PPC405EX CHIP_21 erratum
authorSteven A. Falco <sfalco@harris.com>
Thu, 5 May 2011 14:08:35 +0000 (10:08 -0400)
committerStefan Roese <sr@denx.de>
Thu, 12 May 2011 14:10:51 +0000 (16:10 +0200)
APM errata CHIP_21 for the 405EX/EXr (from the rev 1.09 document dated
4/27/11) states that rev D processors may wake up with the wrong feature
set.  This patch implements the APM-proposed workaround.

To enable this patch for your board, add the appropriate define for your
CPU to your board header file.  See kilauea.h for more information.  The
following variants are supported:

#define CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY
#define CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY
#define CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY
#define CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY

Please note that if you select the wrong define, your board will not
boot, and JTAG will be required to recover.

Tested on custom boards using:

CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY  <sfalco@harris.com>
CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY     <eibach@gdsys.de>

Signed-off-by: Steve Falco <sfalco@harris.com>
Acked-by: Dirk Eibach <eibach@gdsys.de>
Signed-off-by: Stefan Roese <sr@denx.de>
arch/powerpc/cpu/ppc4xx/cpu_init.c
arch/powerpc/include/asm/ppc405ex.h
arch/powerpc/include/asm/processor.h
include/configs/kilauea.h

index bf208adfe6f5cb3351fd7a6f8f56849e2ddcb305..970a8c1e2dc2c8e8bfc60184a1d1698ef3301d60 100644 (file)
@@ -221,6 +221,66 @@ void reconfigure_pll(u32 new_cpu_freq)
 #endif
 }
 
+#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
+void
+chip_21_errata(void)
+{
+       /*
+        * See rev 1.09 of the 405EX/405EXr errata.  CHIP_21 says that
+        * sometimes reading the PVR and/or SDR0_ECID results in incorrect
+        * values.  Since the rev-D chip uses the SDR0_ECID bits to control
+        * internal features, that means the second PCIe or ethernet of an EX
+        * variant could fail to work.  Also, security features of both EX and
+        * EXr might be incorrectly disabled.
+        *
+        * The suggested workaround is as follows (covering rev-C and rev-D):
+        *
+        * 1.Read the PVR and SDR0_ECID3.
+        *
+        * 2.If the PVR matches an expected Revision C PVR value AND if
+        * SDR0_ECID3[12:15] is different from PVR[28:31], then processor is
+        * Revision C: continue executing the initialization code (no reset
+        * required).  else go to step 3.
+        *
+        * 3.If the PVR matches an expected Revision D PVR value AND if
+        * SDR0_ECID3[10:11] matches its expected value, then continue
+        * executing initialization code, no reset required.  else write
+        * DBCR0[RST] = 0b11 to generate a SysReset.
+        */
+
+       u32 pvr;
+       u32 pvr_28_31;
+       u32 ecid3;
+       u32 ecid3_10_11;
+       u32 ecid3_12_15;
+
+       /* Step 1: */
+       pvr = get_pvr();
+       mfsdr(SDR0_ECID3, ecid3);
+
+       /* Step 2: */
+       pvr_28_31 = pvr & 0xf;
+       ecid3_10_11 = (ecid3 >> 20) & 0x3;
+       ecid3_12_15 = (ecid3 >> 16) & 0xf;
+       if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_C) &&
+                       (pvr_28_31 != ecid3_12_15)) {
+               /* No reset required. */
+               return;
+       }
+
+       /* Step 3: */
+       if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_D) &&
+                       (ecid3_10_11 == CONFIG_405EX_CHIP21_ECID3_REV_D)) {
+               /* No reset required. */
+               return;
+       }
+
+       /* Reset required. */
+       __asm__ __volatile__ ("sync; isync");
+       mtspr(SPRN_DBCR0, 0x30000000);
+}
+#endif
+
 /*
  * Breath some life into the CPU...
  *
@@ -235,6 +295,10 @@ cpu_init_f (void)
        u32 val;
 #endif
 
+#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA
+       chip_21_errata();
+#endif
+
        reconfigure_pll(CONFIG_SYS_PLL_RECONFIG);
 
 #if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && \
index 36d3149b8c3841f41592055b59213be012abe033..80703858166fc50ea06527366877ec24d7ecaf2d 100644 (file)
 #define SDR0_PFC1              0x4101
 #define SDR0_MFR               0x4300  /* SDR0_MFR reg */
 
+#define SDR0_ECID0             0x0080
+#define SDR0_ECID1             0x0081
+#define SDR0_ECID2             0x0082
+#define SDR0_ECID3             0x0083
+
 #define SDR0_SDCS_SDD          (0x80000000 >> 31)
 
 #define SDR0_SRST_DMC          (0x80000000 >> 10)
index f5bf4dd4fd40af7884ce79e50c10e96ddec5fba4..c5b03b49951b2142fd5c7f68c6ec2ed3014a08f7 100644 (file)
 #define PVR_5200       0x80822011
 #define PVR_5200B      0x80822014
 
+/*
+ * 405EX/EXr CHIP_21 Errata
+ */
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C  PVR_405EX1_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D  PVR_405EX1_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D        0x0
+#endif
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C  PVR_405EX2_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D  PVR_405EX2_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D        0x1
+#endif
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C  PVR_405EXR1_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D  PVR_405EXR1_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D        0x2
+#endif
+
+#ifdef CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY
+#define CONFIG_SYS_4xx_CHIP_21_ERRATA
+#define CONFIG_405EX_CHIP21_PVR_REV_C  PVR_405EXR2_RC
+#define CONFIG_405EX_CHIP21_PVR_REV_D  PVR_405EXR2_RD
+#define CONFIG_405EX_CHIP21_ECID3_REV_D        0x3
+#endif
+
 /*
  * System Version Register
  */
index 031f8fb4ec991a37eae9f3476d873fadfc0fe474..e66aadf97e0c9c41908689937c0ab64fd6837579 100644 (file)
 #define CONFIG_SYS_TEXT_BASE   0xFFFA0000
 #endif
 
+/*
+ * CHIP_21 errata - you must set this to match your exact CPU, else your
+ * board will not boot.  DO NOT enable this unless you have JTAG available
+ * for recovery, in the event you get it wrong.
+ *
+ * Kilauea uses the 405EX, while Haleakala uses the 405EXr.  Either board
+ * may be equipped for security or not.  You must look at the CPU part
+ * number to be sure what you have.
+ */
+/* #define CONFIG_SYS_4xx_CHIP_21_405EX_NO_SECURITY */
+/* #define CONFIG_SYS_4xx_CHIP_21_405EX_SECURITY */
+/* #define CONFIG_SYS_4xx_CHIP_21_405EXr_NO_SECURITY */
+/* #define CONFIG_SYS_4xx_CHIP_21_405EXr_SECURITY */
+
 /*
  * Include common defines/options for all AMCC eval boards
  */