blob: 7482005b6796304f108317284d6427024c7c9613 [file] [log] [blame]
Paul Burton30374f92015-01-29 01:27:57 +00001/*
2 * (C) Copyright 2003
3 * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <asm/cacheops.h>
10#include <asm/mipsregs.h>
11
12#ifdef CONFIG_SYS_CACHELINE_SIZE
13
14static inline unsigned long icache_line_size(void)
15{
16 return CONFIG_SYS_CACHELINE_SIZE;
17}
18
19static inline unsigned long dcache_line_size(void)
20{
21 return CONFIG_SYS_CACHELINE_SIZE;
22}
23
24#else /* !CONFIG_SYS_CACHELINE_SIZE */
25
26static inline unsigned long icache_line_size(void)
27{
28 unsigned long conf1, il;
29 conf1 = read_c0_config1();
Daniel Schwierzecka3ab2ae2016-01-12 21:48:26 +010030 il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF;
Paul Burton30374f92015-01-29 01:27:57 +000031 if (!il)
32 return 0;
33 return 2 << il;
34}
35
36static inline unsigned long dcache_line_size(void)
37{
38 unsigned long conf1, dl;
39 conf1 = read_c0_config1();
Daniel Schwierzecka3ab2ae2016-01-12 21:48:26 +010040 dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF;
Paul Burton30374f92015-01-29 01:27:57 +000041 if (!dl)
42 return 0;
43 return 2 << dl;
44}
45
46#endif /* !CONFIG_SYS_CACHELINE_SIZE */
47
48void flush_cache(ulong start_addr, ulong size)
49{
50 unsigned long ilsize = icache_line_size();
51 unsigned long dlsize = dcache_line_size();
52 const void *addr, *aend;
53
54 /* aend will be miscalculated when size is zero, so we return here */
55 if (size == 0)
56 return;
57
58 addr = (const void *)(start_addr & ~(dlsize - 1));
59 aend = (const void *)((start_addr + size - 1) & ~(dlsize - 1));
60
61 if (ilsize == dlsize) {
62 /* flush I-cache & D-cache simultaneously */
63 while (1) {
64 mips_cache(HIT_WRITEBACK_INV_D, addr);
65 mips_cache(HIT_INVALIDATE_I, addr);
66 if (addr == aend)
67 break;
68 addr += dlsize;
69 }
70 return;
71 }
72
73 /* flush D-cache */
74 while (1) {
75 mips_cache(HIT_WRITEBACK_INV_D, addr);
76 if (addr == aend)
77 break;
78 addr += dlsize;
79 }
80
81 /* flush I-cache */
82 addr = (const void *)(start_addr & ~(ilsize - 1));
83 aend = (const void *)((start_addr + size - 1) & ~(ilsize - 1));
84 while (1) {
85 mips_cache(HIT_INVALIDATE_I, addr);
86 if (addr == aend)
87 break;
88 addr += ilsize;
89 }
90}
91
92void flush_dcache_range(ulong start_addr, ulong stop)
93{
94 unsigned long lsize = dcache_line_size();
95 const void *addr = (const void *)(start_addr & ~(lsize - 1));
96 const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
97
Marek Vasutfbb0de02016-01-27 03:13:59 +010098 /* aend will be miscalculated when size is zero, so we return here */
99 if (start_addr == stop)
100 return;
101
Paul Burton30374f92015-01-29 01:27:57 +0000102 while (1) {
103 mips_cache(HIT_WRITEBACK_INV_D, addr);
104 if (addr == aend)
105 break;
106 addr += lsize;
107 }
108}
109
110void invalidate_dcache_range(ulong start_addr, ulong stop)
111{
112 unsigned long lsize = dcache_line_size();
113 const void *addr = (const void *)(start_addr & ~(lsize - 1));
114 const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
115
Marek Vasutfbb0de02016-01-27 03:13:59 +0100116 /* aend will be miscalculated when size is zero, so we return here */
117 if (start_addr == stop)
118 return;
119
Paul Burton30374f92015-01-29 01:27:57 +0000120 while (1) {
121 mips_cache(HIT_INVALIDATE_D, addr);
122 if (addr == aend)
123 break;
124 addr += lsize;
125 }
126}