use radio0 only on the 5312
[openwrt.git] / target / linux / brcm-2.6 / patches / 003-bcm4710_cache_fixes.patch
1 diff -urN linux-2.6.19.ref/arch/mips/kernel/genex.S linux-2.6.19/arch/mips/kernel/genex.S
2 --- linux-2.6.19.ref/arch/mips/kernel/genex.S   2006-11-29 22:57:37.000000000 +0100
3 +++ linux-2.6.19/arch/mips/kernel/genex.S       2006-12-04 21:34:09.000000000 +0100
4 @@ -73,6 +73,10 @@
5         .set    push
6         .set    mips3
7         .set    noat
8 +#ifdef CONFIG_BCM947XX
9 +       nop
10 +       nop
11 +#endif
12         mfc0    k1, CP0_CAUSE
13         li      k0, 31<<2
14         andi    k1, k1, 0x7c
15 diff -urN linux-2.6.19.ref/arch/mips/mm/c-r4k.c linux-2.6.19/arch/mips/mm/c-r4k.c
16 --- linux-2.6.19.ref/arch/mips/mm/c-r4k.c       2006-12-04 21:34:04.000000000 +0100
17 +++ linux-2.6.19/arch/mips/mm/c-r4k.c   2006-12-04 21:34:09.000000000 +0100
18 @@ -13,6 +13,15 @@
19  #include <linux/mm.h>
20  #include <linux/bitops.h>
21  
22 +#ifdef CONFIG_BCM947XX
23 +#include "../bcm947xx/include/typedefs.h"
24 +#include "../bcm947xx/include/sbconfig.h"
25 +#include "../bcm947xx/include/mipsinc.h"
26 +#undef MTC0
27 +#undef MFC0
28 +#undef cache_op
29 +#include <asm/paccess.h>
30 +#endif
31  #include <asm/bcache.h>
32  #include <asm/bootinfo.h>
33  #include <asm/cache.h>
34 @@ -29,6 +38,9 @@
35  #include <asm/cacheflush.h> /* for run_uncached() */
36  
37  
38 +/* For enabling BCM4710 cache workarounds */
39 +int bcm4710 = 0;
40 +
41  /*
42   * Special Variant of smp_call_function for use by cache functions:
43   *
44 @@ -93,6 +105,9 @@
45  {
46         unsigned long  dc_lsize = cpu_dcache_line_size();
47  
48 +       if (bcm4710)
49 +               r4k_blast_dcache_page = blast_dcache_page;
50 +       else
51         if (dc_lsize == 0)
52                 r4k_blast_dcache_page = (void *)cache_noop;
53         else if (dc_lsize == 16)
54 @@ -107,6 +122,9 @@
55  {
56         unsigned long dc_lsize = cpu_dcache_line_size();
57  
58 +       if (bcm4710)
59 +               r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
60 +       else
61         if (dc_lsize == 0)
62                 r4k_blast_dcache_page_indexed = (void *)cache_noop;
63         else if (dc_lsize == 16)
64 @@ -121,6 +139,9 @@
65  {
66         unsigned long dc_lsize = cpu_dcache_line_size();
67  
68 +       if (bcm4710)
69 +               r4k_blast_dcache = blast_dcache;
70 +       else
71         if (dc_lsize == 0)
72                 r4k_blast_dcache = (void *)cache_noop;
73         else if (dc_lsize == 16)
74 @@ -538,6 +559,9 @@
75                 r4k_blast_icache();
76         else
77                 protected_blast_icache_range(start, end);
78 +
79 +       if (bcm4710)
80 +               r4k_flush_cache_all();
81  }
82  
83  static void r4k_flush_icache_range(unsigned long start, unsigned long end)
84 @@ -618,6 +642,8 @@
85         unsigned long addr = (unsigned long) arg;
86  
87         R4600_HIT_CACHEOP_WAR_IMPL;
88 +       BCM4710_PROTECTED_FILL_TLB(addr);
89 +       BCM4710_PROTECTED_FILL_TLB(addr + 4);
90         if (dc_lsize)
91                 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
92         if (!cpu_icache_snoops_remote_store && scache_size)
93 @@ -1135,6 +1161,16 @@
94  static void __init coherency_setup(void)
95  {
96         change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
97 +#ifdef CONFIG_BCM947XX
98 +       if (BCM330X(current_cpu_data.processor_id)) {
99 +               __u32 cm = read_c0_diag();
100 +               /* Enable icache */
101 +               cm |= (1 << 31);
102 +               /* Enable dcache */
103 +               cm |= (1 << 30);
104 +               write_c0_diag(cm);
105 +       }
106 +#endif
107  
108         /*
109          * c0_status.cu=0 specifies that updates by the sc instruction use
110 @@ -1173,6 +1209,15 @@
111  
112         /* Default cache error handler for R4000 and R5000 family */
113         set_uncached_handler (0x100, &except_vec2_generic, 0x80);
114 +       
115 +       /* Check if special workarounds are required */
116 +#ifdef CONFIG_BCM947XX
117 +       if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
118 +               printk("Enabling BCM4710A0 cache workarounds.\n");
119 +               bcm4710 = 1;
120 +       } else
121 +#endif
122 +               bcm4710 = 0;
123  
124         probe_pcache();
125         setup_scache();
126 diff -urN linux-2.6.19.ref/arch/mips/mm/tlbex.c linux-2.6.19/arch/mips/mm/tlbex.c
127 --- linux-2.6.19.ref/arch/mips/mm/tlbex.c       2006-12-04 21:33:48.000000000 +0100
128 +++ linux-2.6.19/arch/mips/mm/tlbex.c   2006-12-04 21:34:09.000000000 +0100
129 @@ -1174,6 +1174,10 @@
130  #endif
131  }
132  
133 +#ifdef CONFIG_BCM947XX
134 +extern int bcm4710;
135 +#endif
136 +
137  static void __init build_r4000_tlb_refill_handler(void)
138  {
139         u32 *p = tlb_handler;
140 @@ -1188,6 +1192,12 @@
141         memset(relocs, 0, sizeof(relocs));
142         memset(final_handler, 0, sizeof(final_handler));
143  
144 +#ifdef CONFIG_BCM947XX
145 +       if (bcm4710) {
146 +               i_nop(&p);
147 +       }
148 +#endif
149 +       
150         /*
151          * create the plain linear handler
152          */
153 diff -urN linux-2.6.19.ref/include/asm-mips/r4kcache.h linux-2.6.19/include/asm-mips/r4kcache.h
154 --- linux-2.6.19.ref/include/asm-mips/r4kcache.h        2006-11-29 22:57:37.000000000 +0100
155 +++ linux-2.6.19/include/asm-mips/r4kcache.h    2006-12-04 21:34:09.000000000 +0100
156 @@ -17,6 +17,18 @@
157  #include <asm/cpu-features.h>
158  #include <asm/mipsmtregs.h>
159  
160 +#ifdef CONFIG_BCM947XX
161 +#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
162 +
163 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
164 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
165 +#else
166 +#define BCM4710_DUMMY_RREG()
167 +
168 +#define BCM4710_FILL_TLB(addr)
169 +#define BCM4710_PROTECTED_FILL_TLB(addr)
170 +#endif
171 +
172  /*
173   * This macro return a properly sign-extended address suitable as base address
174   * for indexed cache operations.  Two issues here:
175 @@ -150,6 +162,7 @@
176  static inline void flush_dcache_line_indexed(unsigned long addr)
177  {
178         __dflush_prologue
179 +       BCM4710_DUMMY_RREG();
180         cache_op(Index_Writeback_Inv_D, addr);
181         __dflush_epilogue
182  }
183 @@ -169,6 +182,7 @@
184  static inline void flush_dcache_line(unsigned long addr)
185  {
186         __dflush_prologue
187 +       BCM4710_DUMMY_RREG();
188         cache_op(Hit_Writeback_Inv_D, addr);
189         __dflush_epilogue
190  }
191 @@ -176,6 +190,7 @@
192  static inline void invalidate_dcache_line(unsigned long addr)
193  {
194         __dflush_prologue
195 +       BCM4710_DUMMY_RREG();
196         cache_op(Hit_Invalidate_D, addr);
197         __dflush_epilogue
198  }
199 @@ -208,6 +223,7 @@
200   */
201  static inline void protected_flush_icache_line(unsigned long addr)
202  {
203 +       BCM4710_DUMMY_RREG();
204         protected_cache_op(Hit_Invalidate_I, addr);
205  }
206  
207 @@ -219,6 +235,7 @@
208   */
209  static inline void protected_writeback_dcache_line(unsigned long addr)
210  {
211 +       BCM4710_DUMMY_RREG();
212         protected_cache_op(Hit_Writeback_Inv_D, addr);
213  }
214  
215 @@ -339,8 +356,52 @@
216                 : "r" (base),                                           \
217                   "i" (op));
218  
219 +static inline void blast_dcache(void)
220 +{
221 +       unsigned long start = KSEG0;
222 +       unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
223 +       unsigned long end = (start + dcache_size);
224 +
225 +       do {
226 +               BCM4710_DUMMY_RREG();
227 +               cache_op(Index_Writeback_Inv_D, start);
228 +               start += current_cpu_data.dcache.linesz;
229 +       } while(start < end);
230 +}
231 +
232 +static inline void blast_dcache_page(unsigned long page)
233 +{
234 +       unsigned long start = page;
235 +       unsigned long end = start + PAGE_SIZE;
236 +
237 +       BCM4710_FILL_TLB(start);
238 +       do {
239 +               BCM4710_DUMMY_RREG();
240 +               cache_op(Hit_Writeback_Inv_D, start);
241 +               start += current_cpu_data.dcache.linesz;
242 +       } while(start < end);
243 +}
244 +
245 +static inline void blast_dcache_page_indexed(unsigned long page)
246 +{
247 +       unsigned long start = page;
248 +       unsigned long end = start + PAGE_SIZE;
249 +       unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
250 +       unsigned long ws_end = current_cpu_data.dcache.ways <<
251 +                              current_cpu_data.dcache.waybit;
252 +       unsigned long ws, addr;
253 +       for (ws = 0; ws < ws_end; ws += ws_inc) {
254 +               start = page + ws;
255 +               for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
256 +                       BCM4710_DUMMY_RREG();
257 +                       cache_op(Index_Writeback_Inv_D, addr);
258 +               }
259 +       }
260 +}
261 +
262 +
263  /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
264 -#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
265 +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
266  static inline void blast_##pfx##cache##lsize(void)                     \
267  {                                                                      \
268         unsigned long start = INDEX_BASE;                               \
269 @@ -352,6 +413,7 @@
270                                                                         \
271         __##pfx##flush_prologue                                         \
272                                                                         \
273 +       war                                                             \
274         for (ws = 0; ws < ws_end; ws += ws_inc)                         \
275                 for (addr = start; addr < end; addr += lsize * 32)      \
276                         cache##lsize##_unroll32(addr|ws,indexop);       \
277 @@ -366,6 +428,7 @@
278                                                                         \
279         __##pfx##flush_prologue                                         \
280                                                                         \
281 +       war                                                             \
282         do {                                                            \
283                 cache##lsize##_unroll32(start,hitop);                   \
284                 start += lsize * 32;                                    \
285 @@ -384,6 +447,8 @@
286                                current_cpu_data.desc.waybit;            \
287         unsigned long ws, addr;                                         \
288                                                                         \
289 +       war                                                             \
290 +                                                                       \
291         __##pfx##flush_prologue                                         \
292                                                                         \
293         for (ws = 0; ws < ws_end; ws += ws_inc)                         \
294 @@ -393,28 +458,30 @@
295         __##pfx##flush_epilogue                                         \
296  }
297  
298 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
299 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
300 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
301 -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
302 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
303 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
304 -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
305 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
306 -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
307 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
308 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
309 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
310 +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
311 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
312 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
313 +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
314 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
315 +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
316  
317  /* build blast_xxx_range, protected_blast_xxx_range */
318 -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
319 +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
320  static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
321                                                     unsigned long end)  \
322  {                                                                      \
323         unsigned long lsize = cpu_##desc##_line_size();                 \
324         unsigned long addr = start & ~(lsize - 1);                      \
325         unsigned long aend = (end - 1) & ~(lsize - 1);                  \
326 +       war                                                             \
327                                                                         \
328         __##pfx##flush_prologue                                         \
329                                                                         \
330         while (1) {                                                     \
331 +               war2                                            \
332                 prot##cache_op(hitop, addr);                            \
333                 if (addr == aend)                                       \
334                         break;                                          \
335 @@ -424,13 +491,13 @@
336         __##pfx##flush_epilogue                                         \
337  }
338  
339 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
340 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
341 -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
342 -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
343 -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
344 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
345 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
346 +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
347 +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
348 +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
349  /* blast_inv_dcache_range */
350 -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
351 -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
352 +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
353 +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
354  
355  #endif /* _ASM_R4KCACHE_H */
356 diff -urN linux-2.6.19.ref/include/asm-mips/stackframe.h linux-2.6.19/include/asm-mips/stackframe.h
357 --- linux-2.6.19.ref/include/asm-mips/stackframe.h      2006-11-29 22:57:37.000000000 +0100
358 +++ linux-2.6.19/include/asm-mips/stackframe.h  2006-12-04 21:34:09.000000000 +0100
359 @@ -334,6 +334,10 @@
360                 .macro  RESTORE_SP_AND_RET
361                 LONG_L  sp, PT_R29(sp)
362                 .set    mips3
363 +#ifdef CONFIG_BCM947XX
364 +               nop
365 +               nop
366 +#endif
367                 eret
368                 .set    mips0
369                 .endm