powerpc/mpc85xx: Make NMG_CPU_A011 workaround conditional
authorYork Sun <yorksun@freescale.com>
Wed, 8 Aug 2012 18:04:53 +0000 (18:04 +0000)
committerAndy Fleming <afleming@freescale.com>
Thu, 23 Aug 2012 15:24:13 +0000 (10:24 -0500)
This erratum applies to the following SoCs:
P4080 rev 1.0, 2.0, fixed in rev 3.0
P2041 rev 1.0, 1.1, fixed in rev 2.0
P3041 rev 1.0, 1.1, fixed in rev 2.0.

Workaround for erratum NMG_CPU_A011 is enabled by default. This workaround
may degrade performance. P4080 erratum CPU22 shares the same workaround.
So it is always enabled for P4080. For other SoCs, it can be disabled by
hwconfig with syntax:

fsl_cpu_a011:disable

Signed-off-by: York Sun <yorksun@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
arch/powerpc/cpu/mpc85xx/cmd_errata.c
arch/powerpc/cpu/mpc85xx/cpu_init.c
arch/powerpc/cpu/mpc85xx/release.S
arch/powerpc/include/asm/config_mpc85xx.h

index 4e1a54ad0c546bae30398189b8d0b458cb2ad908..858b3f8260e6394078870dc6593ab0391aad44e1 100644 (file)
@@ -27,6 +27,9 @@
 
 static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+       extern int enable_cpu_a011_workaround;
+#endif
        __maybe_unused u32 svr = get_svr();
 
 #if defined(CONFIG_FSL_SATA_V2) && defined(CONFIG_FSL_SATA_ERRATUM_A001)
@@ -56,8 +59,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        /*
         * NMG_CPU_A011 applies to P4080 rev 1.0, 2.0, fixed in 3.0
         * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1
+        * The SVR has been checked by cpu_init_r().
         */
-       if (SVR_SOC_VER(svr) != SVR_P4080 || SVR_MAJ(svr) < 3)
+       if (enable_cpu_a011_workaround)
                puts("Work-around for Erratum CPU-A011 enabled\n");
 #endif
 #if defined(CONFIG_SYS_FSL_ERRATUM_CPU_A003999)
index fc6c2877d253bde572fcf7dec8660b39e91479aa..74863b4a1a12246b9e8d823eea5cb82c7bd2cc28 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/fsl_law.h>
 #include <asm/fsl_serdes.h>
 #include <asm/fsl_srio.h>
+#include <hwconfig.h>
 #include <linux/compiler.h>
 #include "mp.h"
 #ifdef CONFIG_SYS_QE_FMAN_FW_IN_NAND
@@ -47,6 +48,8 @@
 
 #include "../../../../drivers/block/fsl_sata.h"
 
+#define HWCONFIG_BUFFER_SIZE 128
+
 DECLARE_GLOBAL_DATA_PTR;
 
 #ifdef CONFIG_QE
@@ -311,11 +314,41 @@ int cpu_init_r(void)
 #if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) || \
        defined(CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011)
        /*
+        * CPU22 and NMG_CPU_A011 share the same workaround.
         * CPU22 applies to P4080 rev 1.0, 2.0, fixed in 3.0
         * NMG_CPU_A011 applies to P4080 rev 1.0, 2.0, fixed in 3.0
-        * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1
+        * also applies to P3041 rev 1.0, 1.1, P2041 rev 1.0, 1.1, both
+        * fixed in 2.0. NMG_CPU_A011 is activated by default and can
+        * be disabled by hwconfig with syntax:
+        *
+        * fsl_cpu_a011:disable
         */
-       if (SVR_SOC_VER(svr) != SVR_P4080 || SVR_MAJ(svr) < 3) {
+       extern int enable_cpu_a011_workaround;
+#ifdef CONFIG_SYS_P4080_ERRATUM_CPU22
+       enable_cpu_a011_workaround = (SVR_MAJ(svr) < 3);
+#else
+       char buffer[HWCONFIG_BUFFER_SIZE];
+       char *buf = NULL;
+       int n, res;
+
+       n = getenv_f("hwconfig", buffer, sizeof(buffer));
+       if (n > 0)
+               buf = buffer;
+
+       res = hwconfig_arg_cmp_f("fsl_cpu_a011", "disable", buf);
+       if (res > 0)
+               enable_cpu_a011_workaround = 0;
+       else {
+               if (n >= HWCONFIG_BUFFER_SIZE) {
+                       printf("fsl_cpu_a011 was not found. hwconfig variable "
+                               "may be too long\n");
+               }
+               enable_cpu_a011_workaround =
+                       (SVR_SOC_VER(svr) == SVR_P4080 && SVR_MAJ(svr) < 3) ||
+                       (SVR_SOC_VER(svr) != SVR_P4080 && SVR_MAJ(svr) < 2);
+       }
+#endif
+       if (enable_cpu_a011_workaround) {
                flush_dcache();
                mtspr(L1CSR2, (mfspr(L1CSR2) | L1CSR2_DCWS));
                sync();
index 1860684c11adf56a75c12677fa45912f93378d06..1555a9ba6781957a3a646e77b99f8655835ea1a3 100644 (file)
@@ -163,6 +163,12 @@ __secondary_start_page:
        cmpw    r3,r5
        bge     2f
 1:
+#ifdef CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
+       lis     r3,toreset(enable_cpu_a011_workaround)@ha
+       lwz     r3,toreset(enable_cpu_a011_workaround)@l(r3)
+       cmpwi   r3,0
+       beq     2f
+#endif
        mfspr   r3,L1CSR2
        oris    r3,r3,(L1CSR2_DCWS)@h
        mtspr   L1CSR2,r3
@@ -346,6 +352,15 @@ __bootpg_addr:
 __spin_table:
        .space CONFIG_MAX_CPUS*ENTRY_SIZE
 
+       /*
+        * This variable is set by cpu_init_r() after parsing hwconfig
+        * to enable workaround for erratum NMG_CPU_A011.
+        */
+       .align L1_CACHE_SHIFT
+       .global enable_cpu_a011_workaround
+enable_cpu_a011_workaround:
+       .long   1
+
        /* Fill in the empty space.  The actual reset vector is
         * the last word of the page */
 __secondary_start_code_end:
index b6c44bb11d1a6c8e8e54b5ccd32681ba2af35719..7e61f71f11af5dcdee880539ee151e67651d711d 100644 (file)
 #define CONFIG_SYS_FSL_USB2_PHY_ENABLE
 #define CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
 #define CONFIG_SYS_FSL_ERRATUM_ESDHC111
+#define CONFIG_SYS_FSL_ERRATUM_NMG_CPU_A011
 #define CONFIG_SYS_FSL_ERRATUM_CPU_A003999
 #define CONFIG_SYS_FSL_ERRATUM_DDR_A003474
 #define CONFIG_SYS_FSL_SRIO_MAX_PORTS  2