[U-Boot] [PATCH 2/2] powerpc/85xx: Fix the work-arounds for errata SERDES-8 & SERDES-A001 on p4080

Kumar Gala galak at kernel.crashing.org
Fri Jul 1 06:00:45 CEST 2011


From: Timur Tabi <timur at freescale.com>

Erratum SERDES-8 says that the clocks for bank 3 needs to be enabled if
bank 2 is enabled, but this was not being done for SERDES protocols 0xF
and 0x10.  The bank reset that was being done for erratum SERDES4 (a
left-over work-around that was removed in "powerpc/85xx: remove SERDES4
soft-reset work-around") also happened to enable bank 3 (apparently an
undocumented feature).  Now that the reset has been removed, bank 3 was not
being enabled for these two SERDES protocols.

It turns out that every time we call enable_bank(), we do want at least one
lane of the bank enabled, either because the bank is supposed to be enabled,
or because we need the clock from that bank enabled.

For erratum SERDES-A001, we don't want to modify srds_lpd_b[] when we
call enable_bank(), because that array is used elsewhere to determine if
the bank is available.

Also fix an off-by-one error in a printf().

Note that the side effect of these changes is that the work-arounds for these
two errata are now linked.  Specifically, if SERDES-A001 is enabled, then we
need SERDES-8 enabled as well.

Signed-off-by: Timur Tabi <timur at freescale.com>
Acked-by: Ed Swarthout <swarthou at freescale.com>
Acked-by: Scott Wood <scottwood at freescale.com>
Signed-off-by: Kumar Gala <galak at kernel.crashing.org>
---
 arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c |   68 ++++++++++++++++++-------
 1 files changed, 49 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
index e78d32d..4307a4c 100644
--- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
+++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c
@@ -32,6 +32,18 @@
 #include <asm/errno.h>
 #include "fsl_corenet_serdes.h"
 
+/*
+ * The work-arounds for erratum SERDES8 and SERDES-A001 are linked together.
+ * The code is already very complicated as it is, and separating the two
+ * completely would just make things worse.  We try to keep them as separate
+ * as possible, but for now we require SERDES8 if SERDES_A001 is defined.
+ */
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
+#ifndef CONFIG_SYS_P4080_ERRATUM_SERDES8
+#error "CONFIG_SYS_P4080_ERRATUM_SERDES_A001 requires CONFIG_SYS_P4080_ERRATUM_SERDES8"
+#endif
+#endif
+
 static u32 serdes_prtcl_map;
 
 #define HWCONFIG_BUFFER_SIZE	128
@@ -259,9 +271,28 @@ void serdes_reset_rx(enum srds_prtcl device)
 #endif
 
 #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8
+/*
+ * Enable a SERDES bank that was disabled via the RCW
+ *
+ * We only call this function for SERDES8 and SERDES-A001 in cases we really
+ * want to enable the bank, whether we actually want to use the lanes or not,
+ * so make sure at least one lane is enabled.  We're only enabling this one
+ * lane to satisfy errata requirements that the bank be enabled.
+ *
+ * We use a local variable instead of srds_lpd_b[] because we want drivers to
+ * think that the lanes actually are disabled.
+ */
 static void enable_bank(ccsr_gur_t *gur, int bank)
 {
 	u32 rcw5;
+	u32 temp_lpd_b = srds_lpd_b[bank];
+
+	/*
+	 * If we're asked to disable all lanes, just pretend we're doing
+	 * that.
+	 */
+	if (temp_lpd_b == 0xF)
+		temp_lpd_b = 0xE;
 
 	/*
 	 * Enable the lanes SRDS_LPD_Bn.  The RCW bits are read-only in
@@ -270,10 +301,10 @@ static void enable_bank(ccsr_gur_t *gur, int bank)
 	rcw5 = in_be32(gur->rcwsr + 5);
 	if (bank == FSL_SRDS_BANK_2) {
 		rcw5 &= ~FSL_CORENET_RCWSRn_SRDS_LPD_B2;
-		rcw5 |= srds_lpd_b[bank] << 26;
+		rcw5 |= temp_lpd_b << 26;
 	} else if (bank == FSL_SRDS_BANK_3) {
 		rcw5 &= ~FSL_CORENET_RCWSRn_SRDS_LPD_B3;
-		rcw5 |= srds_lpd_b[bank] << 18;
+		rcw5 |= temp_lpd_b << 18;
 	} else {
 		printf("SERDES: enable_bank: bad bank %d\n", bank + 1);
 		return;
@@ -343,8 +374,6 @@ static void p4080_erratum_serdes8(serdes_corenet_t *regs, ccsr_gur_t *gur,
 		 */
 		setbits_be32(&regs->bank[FSL_SRDS_BANK_3].pllcr1,
 			     SRDS_PLLCR1_PLL_BWSEL);
-
-		enable_bank(gur, FSL_SRDS_BANK_3);
 		break;
 
 	case 0x0f:
@@ -379,10 +408,9 @@ static void p4080_erratum_serdes8(serdes_corenet_t *regs, ccsr_gur_t *gur,
 				SRDS_PLLCR0_FRATE_SEL_MASK,
 				SRDS_PLLCR0_FRATE_SEL_6_25);
 		break;
-	default:
-		enable_bank(gur, FSL_SRDS_BANK_3);
 	}
 
+	enable_bank(gur, FSL_SRDS_BANK_3);
 }
 #endif
 
@@ -451,7 +479,7 @@ static void wait_for_rstdone(unsigned int bank)
 	} while (end_tick > get_ticks());
 
 	if (!(rstctl & SRDS_RSTCTL_RSTDONE))
-		printf("SERDES: timeout resetting bank %u\n", bank);
+		printf("SERDES: timeout resetting bank %u\n", bank + 1);
 }
 
 void fsl_serdes_init(void)
@@ -523,6 +551,14 @@ void fsl_serdes_init(void)
 			srds_lpd_b[bank] =
 				simple_strtoul(srds_lpd_arg, NULL, 0) & 0xf;
 	}
+
+	if ((cfg == 0xf) || (cfg == 0x10)) {
+		/*
+		 * For SERDES protocols 0xF and 0x10, force bank 3 to be
+		 * disabled, because it is not supported.
+		 */
+		srds_lpd_b[FSL_SRDS_BANK_3] = 0xF;
+	}
 #endif
 
 	/* Look for banks with all lanes disabled, and power down the bank. */
@@ -546,7 +582,10 @@ void fsl_serdes_init(void)
 #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
 	/*
 	 * The work-aroud for erratum SERDES-A001 is needed only if bank two
-	 * is disabled and bank three is enabled.
+	 * is disabled and bank three is enabled.  The converse is also true,
+	 * but SERDES8 ensures that bank 3 is always enabled if bank 2 is
+	 * enabled, so there's no point in complicating the code to handle
+	 * that situation.
 	 */
 	need_serdes_a001 =
 		!have_bank[FSL_SRDS_BANK_2] && have_bank[FSL_SRDS_BANK_3];
@@ -724,7 +763,7 @@ void fsl_serdes_init(void)
 			p4080_erratum_serdes8(srds_regs, gur, serdes8_devdisr,
 					      serdes8_devdisr2, cfg);
 		} else if (idx == 2) {
-			/* Eable bank two now that bank three is enabled. */
+			/* Enable bank two now that bank three is enabled. */
 			enable_bank(gur, FSL_SRDS_BANK_2);
 		}
 #endif
@@ -734,16 +773,7 @@ void fsl_serdes_init(void)
 
 #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001
 	if (need_serdes_a001) {
-		/*
-		 * Bank three has been enabled, so enable bank two and then
-		 * disable it.
-		 */
-		srds_lpd_b[FSL_SRDS_BANK_2] = 0;
-		enable_bank(gur, FSL_SRDS_BANK_2);
-
-		wait_for_rstdone(FSL_SRDS_BANK_2);
-
-		/* Disable bank 2 */
+		/* Bank 3 has been enabled, so now we can disable bank 2 */
 		setbits_be32(&srds_regs->bank[FSL_SRDS_BANK_2].rstctl,
 			     SRDS_RSTCTL_SDPD);
 	}
-- 
1.7.3.4



More information about the U-Boot mailing list