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