aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-10-07 19:03:53 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-10-29 14:08:43 -0400
commitc9941158fd8a539a56b0e8a4740ec1f6beb23ea3 (patch)
tree73e3868737061e1d5b0b61c182ea443e3ccd94e3 /arch/mips
parent468ffde46d429fbd291b0ef43a06afe9c837629f (diff)
MIPS: Octeon: Apply CN63XXP1 errata workarounds.
The CN63XXP1 needs a couple of workarounds to ensure memory is not written in unexpected ways. All PREF with hints in the range 0-4,6-24 are replaced with PREF 28. We pass a flag to the assembler to cover compiler generated code, and patch uasm for the dynamically generated code. The write buffer threshold is reduced to 4. Signed-off-by: David Daney <ddaney@caviumnetworks.com> Patchwork: http://patchwork.linux-mips.org/patch/1672/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Makefile1
-rw-r--r--arch/mips/cavium-octeon/Kconfig11
-rw-r--r--arch/mips/cavium-octeon/setup.c42
-rw-r--r--arch/mips/mm/uasm.c20
4 files changed, 69 insertions, 5 deletions
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 1a81240102c5..7c1102e41fe2 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -156,6 +156,7 @@ cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += $(call cc-option,-march=octeon) -Wa,--trap
156ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON)))) 156ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON))))
157cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon 157cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
158endif 158endif
159cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1
159 160
160cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) 161cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
161cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,) 162cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 475156b0c807..caae22858163 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -3,6 +3,17 @@ config CAVIUM_OCTEON_SPECIFIC_OPTIONS
3 depends on CPU_CAVIUM_OCTEON 3 depends on CPU_CAVIUM_OCTEON
4 default "y" 4 default "y"
5 5
6config CAVIUM_CN63XXP1
7 bool "Enable CN63XXP1 errata worarounds"
8 depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
9 default "n"
10 help
11 The CN63XXP1 chip requires build time workarounds to
12 function reliably, select this option to enable them. These
13 workarounds will cause a slight decrease in performance on
14 non-CN63XXP1 hardware, so it is recommended to select "n"
15 unless it is known the workarounds are needed.
16
6config CAVIUM_OCTEON_2ND_KERNEL 17config CAVIUM_OCTEON_2ND_KERNEL
7 bool "Build the kernel to be used as a 2nd kernel on the same chip" 18 bool "Build the kernel to be used as a 2nd kernel on the same chip"
8 depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS 19 depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index c072b24f4853..b0c3686c96dd 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -356,8 +356,18 @@ void octeon_user_io_init(void)
356 cvmmemctl.s.wbfltime = 0; 356 cvmmemctl.s.wbfltime = 0;
357 /* R/W If set, do not put Istream in the L2 cache. */ 357 /* R/W If set, do not put Istream in the L2 cache. */
358 cvmmemctl.s.istrnol2 = 0; 358 cvmmemctl.s.istrnol2 = 0;
359 /* R/W The write buffer threshold. */ 359
360 cvmmemctl.s.wbthresh = 10; 360 /*
361 * R/W The write buffer threshold. As per erratum Core-14752
362 * for CN63XX, a sc/scd might fail if the write buffer is
363 * full. Lowering WBTHRESH greatly lowers the chances of the
364 * write buffer ever being full and triggering the erratum.
365 */
366 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X))
367 cvmmemctl.s.wbthresh = 4;
368 else
369 cvmmemctl.s.wbthresh = 10;
370
361 /* R/W If set, CVMSEG is available for loads/stores in 371 /* R/W If set, CVMSEG is available for loads/stores in
362 * kernel/debug mode. */ 372 * kernel/debug mode. */
363#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0 373#if CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
@@ -375,14 +385,13 @@ void octeon_user_io_init(void)
375 * is max legal value. */ 385 * is max legal value. */
376 cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE; 386 cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE;
377 387
388 write_c0_cvmmemctl(cvmmemctl.u64);
378 389
379 if (smp_processor_id() == 0) 390 if (smp_processor_id() == 0)
380 pr_notice("CVMSEG size: %d cache lines (%d bytes)\n", 391 pr_notice("CVMSEG size: %d cache lines (%d bytes)\n",
381 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE, 392 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE,
382 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128); 393 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128);
383 394
384 write_c0_cvmmemctl(cvmmemctl.u64);
385
386 /* Move the performance counter interrupts to IRQ 6 */ 395 /* Move the performance counter interrupts to IRQ 6 */
387 cvmctl = read_c0_cvmctl(); 396 cvmctl = read_c0_cvmctl();
388 cvmctl &= ~(7 << 7); 397 cvmctl &= ~(7 << 7);
@@ -758,6 +767,31 @@ EXPORT_SYMBOL(prom_putchar);
758 767
759void prom_free_prom_memory(void) 768void prom_free_prom_memory(void)
760{ 769{
770 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) {
771 /* Check for presence of Core-14449 fix. */
772 u32 insn;
773 u32 *foo;
774
775 foo = &insn;
776
777 asm volatile("# before" : : : "memory");
778 prefetch(foo);
779 asm volatile(
780 ".set push\n\t"
781 ".set noreorder\n\t"
782 "bal 1f\n\t"
783 "nop\n"
784 "1:\tlw %0,-12($31)\n\t"
785 ".set pop\n\t"
786 : "=r" (insn) : : "$31", "memory");
787
788 if ((insn >> 26) != 0x33)
789 panic("No PREF instruction at Core-14449 probe point.\n");
790
791 if (((insn >> 16) & 0x1f) != 28)
792 panic("Core-14449 WAR not in place (%04x).\n"
793 "Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).\n", insn);
794 }
761#ifdef CONFIG_CAVIUM_DECODE_RSL 795#ifdef CONFIG_CAVIUM_DECODE_RSL
762 cvmx_interrupt_rsl_enable(); 796 cvmx_interrupt_rsl_enable();
763 797
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index d2647a4e012b..23afdebc8e5c 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -405,7 +405,6 @@ I_u1u2u3(_mfc0)
405I_u1u2u3(_mtc0) 405I_u1u2u3(_mtc0)
406I_u2u1u3(_ori) 406I_u2u1u3(_ori)
407I_u3u1u2(_or) 407I_u3u1u2(_or)
408I_u2s3u1(_pref)
409I_0(_rfe) 408I_0(_rfe)
410I_u2s3u1(_sc) 409I_u2s3u1(_sc)
411I_u2s3u1(_scd) 410I_u2s3u1(_scd)
@@ -427,6 +426,25 @@ I_u1(_syscall);
427I_u1u2s3(_bbit0); 426I_u1u2s3(_bbit0);
428I_u1u2s3(_bbit1); 427I_u1u2s3(_bbit1);
429 428
429#ifdef CONFIG_CPU_CAVIUM_OCTEON
430#include <asm/octeon/octeon.h>
431void __uasminit uasm_i_pref(u32 **buf, unsigned int a, signed int b,
432 unsigned int c)
433{
434 if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) && a <= 24 && a != 5)
435 /*
436 * As per erratum Core-14449, replace prefetches 0-4,
437 * 6-24 with 'pref 28'.
438 */
439 build_insn(buf, insn_pref, c, 28, b);
440 else
441 build_insn(buf, insn_pref, c, a, b);
442}
443UASM_EXPORT_SYMBOL(uasm_i_pref);
444#else
445I_u2s3u1(_pref)
446#endif
447
430/* Handle labels. */ 448/* Handle labels. */
431void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) 449void __uasminit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
432{ 450{