[brcm47xx] refresh 2.6.23 patches
[openwrt/svn-archive/archive.git] / target / linux / brcm47xx / patches-2.6.23 / 150-cpu_fixes.patch
1 --- a/arch/mips/kernel/genex.S
2 +++ b/arch/mips/kernel/genex.S
3 @@ -51,6 +51,10 @@
4 NESTED(except_vec3_generic, 0, sp)
5 .set push
6 .set noat
7 +#ifdef CONFIG_BCM947XX
8 + nop
9 + nop
10 +#endif
11 #if R5432_CP0_INTERRUPT_WAR
12 mfc0 k0, CP0_INDEX
13 #endif
14 --- a/arch/mips/mm/c-r4k.c
15 +++ b/arch/mips/mm/c-r4k.c
16 @@ -30,6 +30,9 @@
17 #include <asm/cacheflush.h> /* for run_uncached() */
18
19
20 +/* For enabling BCM4710 cache workarounds */
21 +int bcm4710 = 0;
22 +
23 /*
24 * Special Variant of smp_call_function for use by cache functions:
25 *
26 @@ -94,6 +97,9 @@
27 {
28 unsigned long dc_lsize = cpu_dcache_line_size();
29
30 + if (bcm4710)
31 + r4k_blast_dcache_page = blast_dcache_page;
32 + else
33 if (dc_lsize == 0)
34 r4k_blast_dcache_page = (void *)cache_noop;
35 else if (dc_lsize == 16)
36 @@ -108,6 +114,9 @@
37 {
38 unsigned long dc_lsize = cpu_dcache_line_size();
39
40 + if (bcm4710)
41 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
42 + else
43 if (dc_lsize == 0)
44 r4k_blast_dcache_page_indexed = (void *)cache_noop;
45 else if (dc_lsize == 16)
46 @@ -122,6 +131,9 @@
47 {
48 unsigned long dc_lsize = cpu_dcache_line_size();
49
50 + if (bcm4710)
51 + r4k_blast_dcache = blast_dcache;
52 + else
53 if (dc_lsize == 0)
54 r4k_blast_dcache = (void *)cache_noop;
55 else if (dc_lsize == 16)
56 @@ -638,6 +650,8 @@
57 unsigned long addr = (unsigned long) arg;
58
59 R4600_HIT_CACHEOP_WAR_IMPL;
60 + BCM4710_PROTECTED_FILL_TLB(addr);
61 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
62 if (dc_lsize)
63 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
64 if (!cpu_icache_snoops_remote_store && scache_size)
65 @@ -1213,6 +1227,17 @@
66 * silly idea of putting something else there ...
67 */
68 switch (current_cpu_data.cputype) {
69 + case CPU_BCM3302:
70 + {
71 + u32 cm;
72 + cm = read_c0_diag();
73 + /* Enable icache */
74 + cm |= (1 << 31);
75 + /* Enable dcache */
76 + cm |= (1 << 30);
77 + write_c0_diag(cm);
78 + }
79 + break;
80 case CPU_R4000PC:
81 case CPU_R4000SC:
82 case CPU_R4000MC:
83 @@ -1243,6 +1268,15 @@
84 /* Default cache error handler for R4000 and R5000 family */
85 set_uncached_handler (0x100, &except_vec2_generic, 0x80);
86
87 + /* Check if special workarounds are required */
88 +#ifdef CONFIG_BCM947XX
89 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
90 + printk("Enabling BCM4710A0 cache workarounds.\n");
91 + bcm4710 = 1;
92 + } else
93 +#endif
94 + bcm4710 = 0;
95 +
96 probe_pcache();
97 setup_scache();
98
99 @@ -1288,5 +1322,13 @@
100 build_clear_page();
101 build_copy_page();
102 local_r4k___flush_cache_all(NULL);
103 +#ifdef CONFIG_BCM947XX
104 + {
105 + static void (*_coherency_setup)(void);
106 + _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
107 + _coherency_setup();
108 + }
109 +#else
110 coherency_setup();
111 +#endif
112 }
113 --- a/arch/mips/mm/tlbex.c
114 +++ b/arch/mips/mm/tlbex.c
115 @@ -1273,6 +1273,9 @@
116 /* No need for i_nop */
117 }
118
119 +#ifdef CONFIG_BCM947XX
120 + i_nop(&p);
121 +#endif
122 #ifdef CONFIG_64BIT
123 build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
124 #else
125 @@ -1708,6 +1711,9 @@
126 struct reloc **r, unsigned int pte,
127 unsigned int ptr)
128 {
129 +#ifdef CONFIG_BCM947XX
130 + i_nop(p);
131 +#endif
132 #ifdef CONFIG_64BIT
133 build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
134 #else
135 --- a/include/asm-mips/r4kcache.h
136 +++ b/include/asm-mips/r4kcache.h
137 @@ -17,6 +17,20 @@
138 #include <asm/cpu-features.h>
139 #include <asm/mipsmtregs.h>
140
141 +#ifdef CONFIG_BCM947XX
142 +#include <asm/paccess.h>
143 +#include <linux/ssb/ssb.h>
144 +#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)))
145 +
146 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
147 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
148 +#else
149 +#define BCM4710_DUMMY_RREG()
150 +
151 +#define BCM4710_FILL_TLB(addr)
152 +#define BCM4710_PROTECTED_FILL_TLB(addr)
153 +#endif
154 +
155 /*
156 * This macro return a properly sign-extended address suitable as base address
157 * for indexed cache operations. Two issues here:
158 @@ -150,6 +164,7 @@
159 static inline void flush_dcache_line_indexed(unsigned long addr)
160 {
161 __dflush_prologue
162 + BCM4710_DUMMY_RREG();
163 cache_op(Index_Writeback_Inv_D, addr);
164 __dflush_epilogue
165 }
166 @@ -169,6 +184,7 @@
167 static inline void flush_dcache_line(unsigned long addr)
168 {
169 __dflush_prologue
170 + BCM4710_DUMMY_RREG();
171 cache_op(Hit_Writeback_Inv_D, addr);
172 __dflush_epilogue
173 }
174 @@ -176,6 +192,7 @@
175 static inline void invalidate_dcache_line(unsigned long addr)
176 {
177 __dflush_prologue
178 + BCM4710_DUMMY_RREG();
179 cache_op(Hit_Invalidate_D, addr);
180 __dflush_epilogue
181 }
182 @@ -208,6 +225,7 @@
183 */
184 static inline void protected_flush_icache_line(unsigned long addr)
185 {
186 + BCM4710_DUMMY_RREG();
187 protected_cache_op(Hit_Invalidate_I, addr);
188 }
189
190 @@ -219,6 +237,7 @@
191 */
192 static inline void protected_writeback_dcache_line(unsigned long addr)
193 {
194 + BCM4710_DUMMY_RREG();
195 protected_cache_op(Hit_Writeback_Inv_D, addr);
196 }
197
198 @@ -339,8 +358,52 @@
199 : "r" (base), \
200 "i" (op));
201
202 +static inline void blast_dcache(void)
203 +{
204 + unsigned long start = KSEG0;
205 + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
206 + unsigned long end = (start + dcache_size);
207 +
208 + do {
209 + BCM4710_DUMMY_RREG();
210 + cache_op(Index_Writeback_Inv_D, start);
211 + start += current_cpu_data.dcache.linesz;
212 + } while(start < end);
213 +}
214 +
215 +static inline void blast_dcache_page(unsigned long page)
216 +{
217 + unsigned long start = page;
218 + unsigned long end = start + PAGE_SIZE;
219 +
220 + BCM4710_FILL_TLB(start);
221 + do {
222 + BCM4710_DUMMY_RREG();
223 + cache_op(Hit_Writeback_Inv_D, start);
224 + start += current_cpu_data.dcache.linesz;
225 + } while(start < end);
226 +}
227 +
228 +static inline void blast_dcache_page_indexed(unsigned long page)
229 +{
230 + unsigned long start = page;
231 + unsigned long end = start + PAGE_SIZE;
232 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
233 + unsigned long ws_end = current_cpu_data.dcache.ways <<
234 + current_cpu_data.dcache.waybit;
235 + unsigned long ws, addr;
236 + for (ws = 0; ws < ws_end; ws += ws_inc) {
237 + start = page + ws;
238 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
239 + BCM4710_DUMMY_RREG();
240 + cache_op(Index_Writeback_Inv_D, addr);
241 + }
242 + }
243 +}
244 +
245 +
246 /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
247 -#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
248 +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
249 static inline void blast_##pfx##cache##lsize(void) \
250 { \
251 unsigned long start = INDEX_BASE; \
252 @@ -352,6 +415,7 @@
253 \
254 __##pfx##flush_prologue \
255 \
256 + war \
257 for (ws = 0; ws < ws_end; ws += ws_inc) \
258 for (addr = start; addr < end; addr += lsize * 32) \
259 cache##lsize##_unroll32(addr|ws,indexop); \
260 @@ -366,6 +430,7 @@
261 \
262 __##pfx##flush_prologue \
263 \
264 + war \
265 do { \
266 cache##lsize##_unroll32(start,hitop); \
267 start += lsize * 32; \
268 @@ -384,6 +449,8 @@
269 current_cpu_data.desc.waybit; \
270 unsigned long ws, addr; \
271 \
272 + war \
273 + \
274 __##pfx##flush_prologue \
275 \
276 for (ws = 0; ws < ws_end; ws += ws_inc) \
277 @@ -393,28 +460,30 @@
278 __##pfx##flush_epilogue \
279 }
280
281 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
282 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
283 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
284 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
285 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
286 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
287 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
288 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
289 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
290 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
291 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
292 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
293 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
294 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
295 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
296 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
297 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
298 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
299
300 /* build blast_xxx_range, protected_blast_xxx_range */
301 -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
302 +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
303 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
304 unsigned long end) \
305 { \
306 unsigned long lsize = cpu_##desc##_line_size(); \
307 unsigned long addr = start & ~(lsize - 1); \
308 unsigned long aend = (end - 1) & ~(lsize - 1); \
309 + war \
310 \
311 __##pfx##flush_prologue \
312 \
313 while (1) { \
314 + war2 \
315 prot##cache_op(hitop, addr); \
316 if (addr == aend) \
317 break; \
318 @@ -424,13 +493,13 @@
319 __##pfx##flush_epilogue \
320 }
321
322 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
323 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
324 -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
325 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
326 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
327 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
328 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
329 +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
330 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
331 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
332 /* blast_inv_dcache_range */
333 -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
334 -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
335 +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
336 +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
337
338 #endif /* _ASM_R4KCACHE_H */
339 --- a/include/asm-mips/stackframe.h
340 +++ b/include/asm-mips/stackframe.h
341 @@ -350,6 +350,10 @@
342 .macro RESTORE_SP_AND_RET
343 LONG_L sp, PT_R29(sp)
344 .set mips3
345 +#ifdef CONFIG_BCM947XX
346 + nop
347 + nop
348 +#endif
349 eret
350 .set mips0
351 .endm