]>
Commit | Line | Data |
---|---|---|
30374f98 PB |
1 | /* |
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> | |
939a255a | 10 | #ifdef CONFIG_MIPS_L2_CACHE |
4baa0ab6 | 11 | #include <asm/cm.h> |
939a255a | 12 | #endif |
219c2db3 | 13 | #include <asm/io.h> |
30374f98 | 14 | #include <asm/mipsregs.h> |
d8b32697 | 15 | #include <asm/system.h> |
30374f98 | 16 | |
8cb4817d | 17 | DECLARE_GLOBAL_DATA_PTR; |
30374f98 | 18 | |
4baa0ab6 PB |
19 | static void probe_l2(void) |
20 | { | |
21 | #ifdef CONFIG_MIPS_L2_CACHE | |
22 | unsigned long conf2, sl; | |
23 | bool l2c = false; | |
24 | ||
25 | if (!(read_c0_config1() & MIPS_CONF_M)) | |
26 | return; | |
27 | ||
28 | conf2 = read_c0_config2(); | |
29 | ||
30 | if (__mips_isa_rev >= 6) { | |
31 | l2c = conf2 & MIPS_CONF_M; | |
32 | if (l2c) | |
33 | l2c = read_c0_config3() & MIPS_CONF_M; | |
34 | if (l2c) | |
35 | l2c = read_c0_config4() & MIPS_CONF_M; | |
36 | if (l2c) | |
37 | l2c = read_c0_config5() & MIPS_CONF5_L2C; | |
38 | } | |
39 | ||
40 | if (l2c && config_enabled(CONFIG_MIPS_CM)) { | |
41 | gd->arch.l2_line_size = mips_cm_l2_line_size(); | |
42 | } else if (l2c) { | |
43 | /* We don't know how to retrieve L2 config on this system */ | |
44 | BUG(); | |
45 | } else { | |
46 | sl = (conf2 & MIPS_CONF2_SL) >> MIPS_CONF2_SL_SHF; | |
47 | gd->arch.l2_line_size = sl ? (2 << sl) : 0; | |
48 | } | |
49 | #endif | |
50 | } | |
51 | ||
8cb4817d PB |
52 | void mips_cache_probe(void) |
53 | { | |
54 | #ifdef CONFIG_SYS_CACHE_SIZE_AUTO | |
55 | unsigned long conf1, il, dl; | |
30374f98 | 56 | |
30374f98 | 57 | conf1 = read_c0_config1(); |
8cb4817d | 58 | |
a3ab2ae7 | 59 | il = (conf1 & MIPS_CONF1_IL) >> MIPS_CONF1_IL_SHF; |
8cb4817d PB |
60 | dl = (conf1 & MIPS_CONF1_DL) >> MIPS_CONF1_DL_SHF; |
61 | ||
62 | gd->arch.l1i_line_size = il ? (2 << il) : 0; | |
63 | gd->arch.l1d_line_size = dl ? (2 << dl) : 0; | |
64 | #endif | |
4baa0ab6 | 65 | probe_l2(); |
30374f98 PB |
66 | } |
67 | ||
8cb4817d | 68 | static inline unsigned long icache_line_size(void) |
30374f98 | 69 | { |
8cb4817d PB |
70 | #ifdef CONFIG_SYS_CACHE_SIZE_AUTO |
71 | return gd->arch.l1i_line_size; | |
72 | #else | |
73 | return CONFIG_SYS_ICACHE_LINE_SIZE; | |
74 | #endif | |
75 | } | |
37228621 | 76 | |
8cb4817d PB |
77 | static inline unsigned long dcache_line_size(void) |
78 | { | |
79 | #ifdef CONFIG_SYS_CACHE_SIZE_AUTO | |
80 | return gd->arch.l1d_line_size; | |
81 | #else | |
82 | return CONFIG_SYS_DCACHE_LINE_SIZE; | |
83 | #endif | |
30374f98 PB |
84 | } |
85 | ||
4baa0ab6 PB |
86 | static inline unsigned long scache_line_size(void) |
87 | { | |
88 | #ifdef CONFIG_MIPS_L2_CACHE | |
89 | return gd->arch.l2_line_size; | |
90 | #else | |
91 | return 0; | |
92 | #endif | |
93 | } | |
94 | ||
fb64cda5 PB |
95 | #define cache_loop(start, end, lsize, ops...) do { \ |
96 | const void *addr = (const void *)(start & ~(lsize - 1)); \ | |
97 | const void *aend = (const void *)((end - 1) & ~(lsize - 1)); \ | |
98 | const unsigned int cache_ops[] = { ops }; \ | |
99 | unsigned int i; \ | |
100 | \ | |
101 | for (; addr <= aend; addr += lsize) { \ | |
102 | for (i = 0; i < ARRAY_SIZE(cache_ops); i++) \ | |
103 | mips_cache(cache_ops[i], addr); \ | |
104 | } \ | |
105 | } while (0) | |
106 | ||
30374f98 PB |
107 | void flush_cache(ulong start_addr, ulong size) |
108 | { | |
109 | unsigned long ilsize = icache_line_size(); | |
110 | unsigned long dlsize = dcache_line_size(); | |
4baa0ab6 | 111 | unsigned long slsize = scache_line_size(); |
30374f98 PB |
112 | |
113 | /* aend will be miscalculated when size is zero, so we return here */ | |
114 | if (size == 0) | |
115 | return; | |
116 | ||
4baa0ab6 | 117 | if ((ilsize == dlsize) && !slsize) { |
30374f98 | 118 | /* flush I-cache & D-cache simultaneously */ |
fb64cda5 PB |
119 | cache_loop(start_addr, start_addr + size, ilsize, |
120 | HIT_WRITEBACK_INV_D, HIT_INVALIDATE_I); | |
219c2db3 | 121 | goto ops_done; |
30374f98 PB |
122 | } |
123 | ||
124 | /* flush D-cache */ | |
fb64cda5 | 125 | cache_loop(start_addr, start_addr + size, dlsize, HIT_WRITEBACK_INV_D); |
30374f98 | 126 | |
4baa0ab6 PB |
127 | /* flush L2 cache */ |
128 | if (slsize) | |
129 | cache_loop(start_addr, start_addr + size, slsize, | |
130 | HIT_WRITEBACK_INV_SD); | |
131 | ||
30374f98 | 132 | /* flush I-cache */ |
fb64cda5 | 133 | cache_loop(start_addr, start_addr + size, ilsize, HIT_INVALIDATE_I); |
219c2db3 PB |
134 | |
135 | ops_done: | |
136 | /* ensure cache ops complete before any further memory accesses */ | |
137 | sync(); | |
d8b32697 PB |
138 | |
139 | /* ensure the pipeline doesn't contain now-invalid instructions */ | |
140 | instruction_hazard_barrier(); | |
30374f98 PB |
141 | } |
142 | ||
143 | void flush_dcache_range(ulong start_addr, ulong stop) | |
144 | { | |
145 | unsigned long lsize = dcache_line_size(); | |
4baa0ab6 | 146 | unsigned long slsize = scache_line_size(); |
30374f98 | 147 | |
fbb0de08 MV |
148 | /* aend will be miscalculated when size is zero, so we return here */ |
149 | if (start_addr == stop) | |
150 | return; | |
151 | ||
fb64cda5 | 152 | cache_loop(start_addr, stop, lsize, HIT_WRITEBACK_INV_D); |
4baa0ab6 PB |
153 | |
154 | /* flush L2 cache */ | |
155 | if (slsize) | |
156 | cache_loop(start_addr, stop, slsize, HIT_WRITEBACK_INV_SD); | |
219c2db3 PB |
157 | |
158 | /* ensure cache ops complete before any further memory accesses */ | |
159 | sync(); | |
30374f98 PB |
160 | } |
161 | ||
162 | void invalidate_dcache_range(ulong start_addr, ulong stop) | |
163 | { | |
164 | unsigned long lsize = dcache_line_size(); | |
4baa0ab6 | 165 | unsigned long slsize = scache_line_size(); |
30374f98 | 166 | |
fbb0de08 MV |
167 | /* aend will be miscalculated when size is zero, so we return here */ |
168 | if (start_addr == stop) | |
169 | return; | |
170 | ||
4baa0ab6 PB |
171 | /* invalidate L2 cache */ |
172 | if (slsize) | |
173 | cache_loop(start_addr, stop, slsize, HIT_INVALIDATE_SD); | |
174 | ||
a95800e8 | 175 | cache_loop(start_addr, stop, lsize, HIT_INVALIDATE_D); |
219c2db3 PB |
176 | |
177 | /* ensure cache ops complete before any further memory accesses */ | |
178 | sync(); | |
30374f98 | 179 | } |