summaryrefslogtreecommitdiff
path: root/arch/powerpc/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/cpu')
-rw-r--r--arch/powerpc/cpu/mpc85xx/cmd_errata.c6
-rw-r--r--arch/powerpc/cpu/mpc85xx/cpu_init.c37
-rw-r--r--arch/powerpc/cpu/mpc85xx/release.S15
3 files changed, 55 insertions, 3 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index 4e1a54a..858b3f8 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -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)
diff --git a/arch/powerpc/cpu/mpc85xx/cpu_init.c b/arch/powerpc/cpu/mpc85xx/cpu_init.c
index fc6c287..74863b4 100644
--- a/arch/powerpc/cpu/mpc85xx/cpu_init.c
+++ b/arch/powerpc/cpu/mpc85xx/cpu_init.c
@@ -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();
diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S
index 1860684..1555a9b 100644
--- a/arch/powerpc/cpu/mpc85xx/release.S
+++ b/arch/powerpc/cpu/mpc85xx/release.S
@@ -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: