1 diff -urN linux.old/arch/mips/kernel/entry.S linux.dev/arch/mips/kernel/entry.S
2 --- linux.old/arch/mips/kernel/entry.S 2005-07-05 16:46:49.000000000 +0200
3 +++ linux.dev/arch/mips/kernel/entry.S 2005-07-06 11:23:55.000000000 +0200
5 * and R4400 SC and MC versions.
7 NESTED(except_vec3_generic, 0, sp)
12 #if R5432_CP0_INTERRUPT_WAR
15 diff -urN 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 2005-07-05 16:46:49.000000000 +0200
17 +++ linux.dev/arch/mips/mm/c-r4k.c 2005-07-06 11:23:55.000000000 +0200
20 #include <linux/bitops.h>
22 +#ifdef CONFIG_BCM4710
23 +#include "../bcm947xx/include/typedefs.h"
24 +#include "../bcm947xx/include/sbconfig.h"
25 +#include <asm/paccess.h>
28 #include <asm/bcache.h>
29 #include <asm/bootinfo.h>
30 #include <asm/cacheops.h>
32 .bc_inv = (void *)no_sc_noop
36 +EXPORT_SYMBOL(bcm4710);
37 struct bcache_ops *bcops = &no_sc_ops;
39 #define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x2010)
41 static inline void r4k_blast_dcache_page_setup(void)
43 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
48 + r4k_blast_dcache_page = blast_dcache_page;
49 + else if (dc_lsize == 16)
50 r4k_blast_dcache_page = blast_dcache16_page;
51 else if (dc_lsize == 32)
52 r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
55 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
59 + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
60 + else if (dc_lsize == 16)
61 r4k_blast_dcache_page_indexed = blast_dcache16_page_indexed;
62 else if (dc_lsize == 32)
63 r4k_blast_dcache_page_indexed = blast_dcache32_page_indexed;
66 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
70 + r4k_blast_dcache = blast_dcache;
71 + else if (dc_lsize == 16)
72 r4k_blast_dcache = blast_dcache16;
73 else if (dc_lsize == 32)
74 r4k_blast_dcache = blast_dcache32;
80 switch (current_cpu_data.cputype) {
84 * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we
85 * only flush the primary caches but R10000 and R12000 behave sane ...
87 - if (current_cpu_data.cputype == CPU_R4000SC ||
88 + if (!bcm4710 && (current_cpu_data.cputype == CPU_R4000SC ||
89 current_cpu_data.cputype == CPU_R4000MC ||
90 current_cpu_data.cputype == CPU_R4400SC ||
91 - current_cpu_data.cputype == CPU_R4400MC)
92 + current_cpu_data.cputype == CPU_R4400MC))
97 unsigned long ic_lsize = current_cpu_data.icache.linesz;
98 unsigned long addr, aend;
100 + addr = start & ~(dc_lsize - 1);
101 + aend = (end - 1) & ~(dc_lsize - 1);
103 if (!cpu_has_ic_fills_f_dc) {
104 if (end - start > dcache_size)
107 - addr = start & ~(dc_lsize - 1);
108 - aend = (end - 1) & ~(dc_lsize - 1);
109 + BCM4710_PROTECTED_FILL_TLB(addr);
110 + BCM4710_PROTECTED_FILL_TLB(aend);
113 /* Hit_Writeback_Inv_D */
115 if (end - start > icache_size)
118 - addr = start & ~(ic_lsize - 1);
119 - aend = (end - 1) & ~(ic_lsize - 1);
121 /* Hit_Invalidate_I */
122 protected_flush_icache_line(addr);
134 if (cpu_has_subset_pcaches) {
135 unsigned long addr = (unsigned long) page_address(page);
137 - r4k_blast_scache_page(addr);
139 + r4k_blast_scache_page(addr);
140 ClearPageDcacheDirty(page);
145 if (!cpu_has_ic_fills_f_dc) {
146 unsigned long addr = (unsigned long) page_address(page);
148 r4k_blast_dcache_page(addr);
149 ClearPageDcacheDirty(page);
152 /* Catch bad driver code */
155 - if (cpu_has_subset_pcaches) {
156 + if (!bcm4710 && cpu_has_subset_pcaches) {
157 unsigned long sc_lsize = current_cpu_data.scache.linesz;
159 if (size >= scache_size) {
161 R4600_HIT_CACHEOP_WAR_IMPL;
162 a = addr & ~(dc_lsize - 1);
163 end = (addr + size - 1) & ~(dc_lsize - 1);
164 + BCM4710_FILL_TLB(a);
165 + BCM4710_FILL_TLB(end);
167 flush_dcache_line(a); /* Hit_Writeback_Inv_D */
170 /* Catch bad driver code */
173 - if (cpu_has_subset_pcaches) {
174 + if (!bcm4710 && (cpu_has_subset_pcaches)) {
175 unsigned long sc_lsize = current_cpu_data.scache.linesz;
177 if (size >= scache_size) {
179 R4600_HIT_CACHEOP_WAR_IMPL;
180 a = addr & ~(dc_lsize - 1);
181 end = (addr + size - 1) & ~(dc_lsize - 1);
182 + BCM4710_FILL_TLB(a);
183 + BCM4710_FILL_TLB(end);
185 flush_dcache_line(a); /* Hit_Writeback_Inv_D */
188 unsigned long dc_lsize = current_cpu_data.dcache.linesz;
190 R4600_HIT_CACHEOP_WAR_IMPL;
191 + BCM4710_PROTECTED_FILL_TLB(addr);
192 + BCM4710_PROTECTED_FILL_TLB(addr + 4);
193 protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
194 protected_flush_icache_line(addr & ~(ic_lsize - 1));
195 if (MIPS4K_ICACHE_REFILL_WAR) {
196 @@ -986,10 +1013,12 @@
200 - probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
201 - sc_present = probe_scache_kseg1(config);
203 - c->options |= MIPS_CPU_CACHE_CDEX_S;
205 + probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
206 + sc_present = probe_scache_kseg1(config);
208 + c->options |= MIPS_CPU_CACHE_CDEX_S;
213 @@ -1041,6 +1070,19 @@
214 static inline void coherency_setup(void)
216 change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
218 +#if defined(CONFIG_BCM4310) || defined(CONFIG_BCM4704) || defined(CONFIG_BCM5365)
219 + if (BCM330X(current_cpu_data.processor_id)) {
222 + cm = read_c0_diag();
223 + /* Enable icache */
225 + /* Enable dcache */
232 * c0_status.cu=0 specifies that updates by the sc instruction use
233 @@ -1073,6 +1115,12 @@
234 memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
235 memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80);
237 + if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & PRID_REV_MASK) == 0) {
238 + printk("Enabling BCM4710A0 cache workarounds.\n");
246 diff -urN linux.old/arch/mips/mm/tlbex-mips32.S linux.dev/arch/mips/mm/tlbex-mips32.S
247 --- linux.old/arch/mips/mm/tlbex-mips32.S 2005-07-05 16:46:49.000000000 +0200
248 +++ linux.dev/arch/mips/mm/tlbex-mips32.S 2005-07-06 11:23:56.000000000 +0200
251 LEAF(except_vec0_r4000)
253 +#ifdef CONFIG_BCM4704
259 diff -urN linux.old/include/asm-mips/r4kcache.h linux.dev/include/asm-mips/r4kcache.h
260 --- linux.old/include/asm-mips/r4kcache.h 2005-07-05 16:46:49.000000000 +0200
261 +++ linux.dev/include/asm-mips/r4kcache.h 2005-07-06 12:52:57.000000000 +0200
264 #include <asm/cacheops.h>
266 +#ifdef CONFIG_BCM4710
267 +#define BCM4710_DUMMY_RREG() (((sbconfig_t *)(KSEG1ADDR(SB_ENUM_BASE + SBCONFIGOFF)))->sbimstate)
269 +#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
270 +#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
272 +#define BCM4710_DUMMY_RREG()
274 +#define BCM4710_FILL_TLB(addr)
275 +#define BCM4710_PROTECTED_FILL_TLB(addr)
278 #define cache_op(op,addr) \
279 __asm__ __volatile__( \
280 " .set noreorder \n" \
283 static inline void flush_icache_line_indexed(unsigned long addr)
285 - cache_op(Index_Invalidate_I, addr);
287 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
289 + for (way = 0; way < current_cpu_data.dcache.ways; way++) {
290 + cache_op(Index_Invalidate_I, addr);
295 static inline void flush_dcache_line_indexed(unsigned long addr)
297 - cache_op(Index_Writeback_Inv_D, addr);
299 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
301 + for (way = 0; way < current_cpu_data.dcache.ways; way++) {
302 + BCM4710_DUMMY_RREG();
303 + cache_op(Index_Writeback_Inv_D, addr);
308 static inline void flush_scache_line_indexed(unsigned long addr)
311 static inline void flush_dcache_line(unsigned long addr)
313 + BCM4710_DUMMY_RREG();
314 cache_op(Hit_Writeback_Inv_D, addr);
319 static inline void protected_writeback_dcache_line(unsigned long addr)
321 + BCM4710_DUMMY_RREG();
322 __asm__ __volatile__(
329 +#define cache_unroll(base,op) \
330 + __asm__ __volatile__(" \
341 +static inline void blast_dcache(void)
343 + unsigned long start = KSEG0;
344 + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
345 + unsigned long end = (start + dcache_size);
347 + while(start < end) {
348 + BCM4710_DUMMY_RREG();
349 + cache_unroll(start,Index_Writeback_Inv_D);
350 + start += current_cpu_data.dcache.linesz;
354 +static inline void blast_dcache_page(unsigned long page)
356 + unsigned long start = page;
357 + unsigned long end = start + PAGE_SIZE;
359 + BCM4710_FILL_TLB(start);
361 + BCM4710_DUMMY_RREG();
362 + cache_unroll(start,Hit_Writeback_Inv_D);
363 + start += current_cpu_data.dcache.linesz;
364 + } while (start < end);
367 +static inline void blast_dcache_page_indexed(unsigned long page)
369 + unsigned long start = page;
370 + unsigned long end = start + PAGE_SIZE;
371 + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
372 + unsigned long ws_end = current_cpu_data.dcache.ways <<
373 + current_cpu_data.dcache.waybit;
374 + unsigned long ws, addr;
376 + for (ws = 0; ws < ws_end; ws += ws_inc) {
378 + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
379 + BCM4710_DUMMY_RREG();
380 + cache_unroll(addr,Index_Writeback_Inv_D);
385 static inline void blast_dcache16(void)
387 unsigned long start = KSEG0;
389 unsigned long ws, addr;
391 for (ws = 0; ws < ws_end; ws += ws_inc)
392 - for (addr = start; addr < end; addr += 0x200)
393 + for (addr = start; addr < end; addr += 0x200) {
394 cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
398 static inline void blast_dcache16_page(unsigned long page)
400 unsigned long ws, addr;
402 for (ws = 0; ws < ws_end; ws += ws_inc)
403 - for (addr = start; addr < end; addr += 0x200)
404 + for (addr = start; addr < end; addr += 0x200) {
405 cache16_unroll32(addr|ws,Index_Writeback_Inv_D);
409 static inline void blast_icache16(void)
411 unsigned long start = page;
412 unsigned long end = start + PAGE_SIZE;
414 + BCM4710_FILL_TLB(start);
416 cache16_unroll32(start,Hit_Invalidate_I);
423 static inline void blast_dcache32(void)
425 unsigned long start = KSEG0;
427 unsigned long ws, addr;
429 for (ws = 0; ws < ws_end; ws += ws_inc)
430 - for (addr = start; addr < end; addr += 0x400)
431 + for (addr = start; addr < end; addr += 0x400) {
432 cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
436 static inline void blast_dcache32_page(unsigned long page)
438 unsigned long ws, addr;
440 for (ws = 0; ws < ws_end; ws += ws_inc)
441 - for (addr = start; addr < end; addr += 0x400)
442 + for (addr = start; addr < end; addr += 0x400) {
443 cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
447 static inline void blast_icache32(void)
449 unsigned long start = page;
450 unsigned long end = start + PAGE_SIZE;
452 + BCM4710_FILL_TLB(start);
454 cache32_unroll32(start,Hit_Invalidate_I);
457 unsigned long start = page;
458 unsigned long end = start + PAGE_SIZE;
460 + BCM4710_FILL_TLB(start);
462 cache64_unroll32(start,Hit_Invalidate_I);
464 diff -urN linux.old/include/asm-mips/stackframe.h linux.dev/include/asm-mips/stackframe.h
465 --- linux.old/include/asm-mips/stackframe.h 2005-07-05 16:46:49.000000000 +0200
466 +++ linux.dev/include/asm-mips/stackframe.h 2005-07-06 11:23:56.000000000 +0200
471 +#if defined(CONFIG_BCM4710) || defined(CONFIG_BCM4704)
473 +#undef RESTORE_SP_AND_RET
474 +#define RESTORE_SP_AND_RET \
475 + lw sp, PT_R29(sp); \
488 diff -urN linux.old/mm/memory.c linux.dev/mm/memory.c
489 --- linux.old/mm/memory.c 2005-04-04 03:42:20.000000000 +0200
490 +++ linux.dev/mm/memory.c 2005-07-06 11:23:56.000000000 +0200
492 flush_page_to_ram(new_page);
493 flush_cache_page(vma, address);
494 establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
495 + flush_icache_page(vma, new_page);