[U-Boot] [PATCH 1/4] powerpc/85xx: Implement work-around for P4080 erratum SERDES-A005

From: Timur Tabi timur@freescale.com
SerDes PLL bandwidth default setting is incorrect when no lanes are configured as PCI Express.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- arch/powerpc/cpu/mpc85xx/cmd_errata.c | 3 ++ arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 48 +++++++++++++++++++++++++ arch/powerpc/include/asm/config_mpc85xx.h | 1 + 3 files changed, 52 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c index 0564816..7b9f773 100644 --- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c +++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c @@ -47,6 +47,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #if defined(CONFIG_SYS_P4080_ERRATUM_SERDES9) puts("Work-around for Erratum SERDES9 enabled\n"); #endif +#if defined(CONFIG_SYS_P4080_ERRATUM_SERDES_A005) + puts("Work-around for Erratum SERDES-A005 enabled\n"); +#endif #if defined(CONFIG_SYS_P4080_ERRATUM_CPU22) puts("Work-around for Erratum CPU22 enabled\n"); #endif diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index d39f963..edacdb8 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -386,6 +386,52 @@ static void p4080_erratum_serdes8(serdes_corenet_t *regs, ccsr_gur_t *gur, } #endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A005 +/* + * If PCIe is not selected as a protocol for any lanes driven by a given PLL, + * that PLL should have SRDSBnPLLCR1[PLLBW_SEL] = 0. + */ +static void p4080_erratum_serdes_a005(serdes_corenet_t *regs, unsigned int cfg) +{ + enum srds_prtcl device; + + switch (cfg) { + case 0x13: + case 0x16: + /* + * If SRDS_PRTCL = 0x13 or 0x16, set SRDSB1PLLCR1[PLLBW_SEL] + * to 0. + */ + clrbits_be32(®s->bank[FSL_SRDS_BANK_1].pllcr1, + SRDS_PLLCR1_PLL_BWSEL); + break; + case 0x19: + /* + * If SRDS_PRTCL = 0x19, set SRDSB1PLLCR1[PLLBW_SEL] to 0 and + * SRDSB3PLLCR1[PLLBW_SEL] to 1. + */ + clrbits_be32(®s->bank[FSL_SRDS_BANK_1].pllcr1, + SRDS_PLLCR1_PLL_BWSEL); + setbits_be32(®s->bank[FSL_SRDS_BANK_3].pllcr1, + SRDS_PLLCR1_PLL_BWSEL); + break; + } + + /* + * Set SRDSBnPLLCR1[PLLBW_SEL] to 0 for each bank that selects XAUI + * before XAUI is initialized. + */ + for (device = XAUI_FM1; device <= XAUI_FM2; device++) { + if (is_serdes_configured(device)) { + int bank = serdes_get_bank_by_device(cfg, device); + + clrbits_be32(®s->bank[bank].pllcr1, + SRDS_PLLCR1_PLL_BWSEL); + } + } +} +#endif + void fsl_serdes_init(void) { ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); @@ -570,6 +616,8 @@ void fsl_serdes_init(void) puts("\n"); #endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A005 + p4080_erratum_serdes_a005(srds_regs, cfg); #endif
for (idx = 0; idx < SRDS_MAX_BANK; idx++) { diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h index d71c3fc..207f717 100644 --- a/arch/powerpc/include/asm/config_mpc85xx.h +++ b/arch/powerpc/include/asm/config_mpc85xx.h @@ -315,6 +315,7 @@ #define CONFIG_SYS_P4080_ERRATUM_CPU22 #define CONFIG_SYS_P4080_ERRATUM_SERDES8 #define CONFIG_SYS_P4080_ERRATUM_SERDES9 +#define CONFIG_SYS_P4080_ERRATUM_SERDES_A005
/* P5010 is single core version of P5020 */ #elif defined(CONFIG_PPC_P5010)

From: Timur Tabi timur@freescale.com
The work-around for P4080 erratum SERDES-8 requires all lanes of banks two and three to be disabled (powered down) in the RCW. Display a warning message if this is not the case.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index edacdb8..f5452c0 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -476,6 +476,17 @@ void fsl_serdes_init(void)
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 /* + * Display a warning if banks two and three are not disabled in the RCW, + * since our work-around for SERDES8 depends on these banks being + * disabled at power-on. + */ +#define B2_B3 (FSL_CORENET_RCWSRn_SRDS_LPD_B2 | FSL_CORENET_RCWSRn_SRDS_LPD_B3) + if ((in_be32(&gur->rcwsr[5]) & B2_B3) != B2_B3) { + printf("Warning: SERDES8 requires banks two and " + "three to be disabled in the RCW\n"); + } + + /* * Store the values of the fsl_srds_lpd_b2 and fsl_srds_lpd_b3 * hwconfig options into the srds_lpd_b[] array. See README.p4080ds * for a description of these options.

From: Timur Tabi timur@freescale.com
Part of the SERDES9 erratum work-around is to set some bits in the SerDes TTLCR0 register for lanes configured as XAUI, SGMII, SRIO, or AURORA. The current code does this only for XAUI, so extend it to the other protocols.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 51 ++++++++++++++++-------- arch/powerpc/include/asm/immap_85xx.h | 1 + 2 files changed, 35 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index f5452c0..b44a81e 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -549,6 +549,35 @@ void fsl_serdes_init(void) printf("%s ", serdes_prtcl_str[lane_prtcl]); #endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 + /* + * Set BnTTLCRy0[FLT_SEL] = 000011 and set BnTTLCRy0[17] = 1 for + * each of the SerDes lanes selected as SGMII, XAUI, SRIO, or + * AURORA before the device is initialized. + */ + switch (lane_prtcl) { + case SGMII_FM1_DTSEC1: + case SGMII_FM1_DTSEC2: + case SGMII_FM1_DTSEC3: + case SGMII_FM1_DTSEC4: + case SGMII_FM2_DTSEC1: + case SGMII_FM2_DTSEC2: + case SGMII_FM2_DTSEC3: + case SGMII_FM2_DTSEC4: + case XAUI_FM1: + case XAUI_FM2: + case SRIO1: + case SRIO2: + case AURORA: + clrsetbits_be32(&srds_regs->lane[idx].ttlcr0, + SRDS_TTLCR0_FLT_SEL_MASK, + SRDS_TTLCR0_FLT_SEL_750PPM | + SRDS_TTLCR0_PM_DIS); + default: + break; + } +#endif + #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 switch (lane_prtcl) { case PCIE1: @@ -595,24 +624,12 @@ void fsl_serdes_init(void) FSL_CORENET_DEVDISR2_DTSEC2_4; break; case XAUI_FM1: + serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | + FSL_CORENET_DEVDISR2_10GEC1; + break; case XAUI_FM2: -#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 - /* - * Set BnTTLCRy0[FLT_SEL] = 000011 and set - * BnTTLCRy0[17] = 1 for each of the SerDes lanes - * selected as XAUI on each bank before XAUI is - * initialized. - */ - clrsetbits_be32(&srds_regs->lane[idx].ttlcr0, - SRDS_TTLCR0_FLT_SEL_MASK, - 0x03000000 | SRDS_TTLCR0_PM_DIS); -#endif - if (lane_prtcl == XAUI_FM1) - serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | - FSL_CORENET_DEVDISR2_10GEC1; - else - serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | - FSL_CORENET_DEVDISR2_10GEC2; + serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | + FSL_CORENET_DEVDISR2_10GEC2; break; case AURORA: break; diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h index 5395c7f..f85cee2 100644 --- a/arch/powerpc/include/asm/immap_85xx.h +++ b/arch/powerpc/include/asm/immap_85xx.h @@ -2139,6 +2139,7 @@ typedef struct serdes_corenet { u32 res3; u32 ttlcr0; /* Transition Tracking Loop Ctrl 0 */ #define SRDS_TTLCR0_FLT_SEL_MASK 0x3f000000 +#define SRDS_TTLCR0_FLT_SEL_750PPM 0x03000000 #define SRDS_TTLCR0_PM_DIS 0x00004000 u32 res4[7]; } lane[24];

From: Timur Tabi timur@freescale.com
Bank powerdown through RCW[SRDS_LPD_Bn] for XAUI on FM2 and SGMII on FM1 are swapped.
Erratum SERDES-A001 says that if bank two is kept disabled and after bank three is enabled, then the PLL for bank three won't lock properly. The work-around is to enable and then disable bank two after bank three is disabled.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org --- arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 80 ++++++++++++++++++++----- arch/powerpc/include/asm/config_mpc85xx.h | 1 + 2 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index b44a81e..741a0f8 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -432,6 +432,28 @@ static void p4080_erratum_serdes_a005(serdes_corenet_t *regs, unsigned int cfg) } #endif
+/* + * Wait for the RSTDONE bit to get set, or a one-second timeout. + */ +static void wait_for_rstdone(unsigned int bank) +{ + serdes_corenet_t *srds_regs = + (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; + unsigned long long end_tick; + u32 rstctl; + + /* wait for reset complete or 1-second timeout */ + end_tick = usec2ticks(1000000) + get_ticks(); + do { + rstctl = in_be32(&srds_regs->bank[bank].rstctl); + if (rstctl & SRDS_RSTCTL_RSTDONE) + break; + } while (end_tick > get_ticks()); + + if (!(rstctl & SRDS_RSTCTL_RSTDONE)) + printf("SERDES: timeout resetting bank %u\n", bank); +} + void fsl_serdes_init(void) { ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); @@ -439,7 +461,6 @@ void fsl_serdes_init(void) serdes_corenet_t *srds_regs; int lane, bank, idx; enum srds_prtcl lane_prtcl; - long long end_tick; int have_bank[SRDS_MAX_BANK] = {}; #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 u32 serdes8_devdisr = 0; @@ -451,6 +472,9 @@ void fsl_serdes_init(void) #ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 enum srds_prtcl device; #endif +#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 + int need_serdes_a001; /* TRUE == need work-around for SERDES A001 */ +#endif char buffer[HWCONFIG_BUFFER_SIZE]; char *buf = NULL;
@@ -519,11 +543,32 @@ void fsl_serdes_init(void) have_bank[FSL_SRDS_BANK_3] = 1; #endif
+#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. + */ + need_serdes_a001 = + !have_bank[FSL_SRDS_BANK_2] && have_bank[FSL_SRDS_BANK_3]; +#endif + + /* Power down the banks we're not interested in */ for (bank = 0; bank < SRDS_MAX_BANK; bank++) { if (!have_bank[bank]) { printf("SERDES: bank %d disabled\n", bank + 1); +#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES_A001 + /* + * Erratum SERDES-A001 says bank two needs to be powered + * down after bank three is powered up, so don't power + * down bank two here. + */ + if (!need_serdes_a001 || (bank != FSL_SRDS_BANK_2)) + setbits_be32(&srds_regs->bank[bank].rstctl, + SRDS_RSTCTL_SDPD); +#else setbits_be32(&srds_regs->bank[bank].rstctl, SRDS_RSTCTL_SDPD); +#endif } }
@@ -649,8 +694,6 @@ void fsl_serdes_init(void) #endif
for (idx = 0; idx < SRDS_MAX_BANK; idx++) { - u32 rstctl; - bank = idx;
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES8 @@ -689,20 +732,25 @@ void fsl_serdes_init(void) /* reset banks for errata */ setbits_be32(&srds_regs->bank[bank].rstctl, SRDS_RSTCTL_RST);
- /* wait for reset complete or 1-second timeout */ - end_tick = usec2ticks(1000000) + get_ticks(); - do { - rstctl = in_be32(&srds_regs->bank[bank].rstctl); - if (rstctl & SRDS_RSTCTL_RSTDONE) - break; - } while (end_tick > get_ticks()); - - if (!(rstctl & SRDS_RSTCTL_RSTDONE)) { - printf("SERDES: timeout resetting bank %d\n", - bank + 1); - continue; - } + wait_for_rstdone(bank); + } + +#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 */ + setbits_be32(&srds_regs->bank[FSL_SRDS_BANK_2].rstctl, + SRDS_RSTCTL_SDPD); } +#endif
#ifdef CONFIG_SYS_P4080_ERRATUM_SERDES9 for (device = XAUI_FM1; device <= XAUI_FM2; device++) { diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h index 207f717..41c2d20 100644 --- a/arch/powerpc/include/asm/config_mpc85xx.h +++ b/arch/powerpc/include/asm/config_mpc85xx.h @@ -315,6 +315,7 @@ #define CONFIG_SYS_P4080_ERRATUM_CPU22 #define CONFIG_SYS_P4080_ERRATUM_SERDES8 #define CONFIG_SYS_P4080_ERRATUM_SERDES9 +#define CONFIG_SYS_P4080_ERRATUM_SERDES_A001 #define CONFIG_SYS_P4080_ERRATUM_SERDES_A005
/* P5010 is single core version of P5020 */

Kumar Gala wrote:
The work-around is to enable and then disable bank two after bank three is disabled.
That should say, "after bank three is enabled".

On Apr 22, 2011, at 8:47 AM, Tabi Timur-B04825 wrote:
Kumar Gala wrote:
The work-around is to enable and then disable bank two after bank three is disabled.
That should say, "after bank three is enabled".
Will fix when I apply
- k

On Apr 22, 2011, at 8:34 AM, Kumar Gala wrote:
From: Timur Tabi timur@freescale.com
Bank powerdown through RCW[SRDS_LPD_Bn] for XAUI on FM2 and SGMII on FM1 are swapped.
Erratum SERDES-A001 says that if bank two is kept disabled and after bank three is enabled, then the PLL for bank three won't lock properly. The work-around is to enable and then disable bank two after bank three is disabled.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 80 ++++++++++++++++++++----- arch/powerpc/include/asm/config_mpc85xx.h | 1 + 2 files changed, 65 insertions(+), 16 deletions(-)
applied to 85xx
- k

On Apr 22, 2011, at 8:34 AM, Kumar Gala wrote:
From: Timur Tabi timur@freescale.com
Part of the SERDES9 erratum work-around is to set some bits in the SerDes TTLCR0 register for lanes configured as XAUI, SGMII, SRIO, or AURORA. The current code does this only for XAUI, so extend it to the other protocols.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 51 ++++++++++++++++-------- arch/powerpc/include/asm/immap_85xx.h | 1 + 2 files changed, 35 insertions(+), 17 deletions(-)
applied to 85xx
- k

On Apr 22, 2011, at 8:34 AM, Kumar Gala wrote:
From: Timur Tabi timur@freescale.com
The work-around for P4080 erratum SERDES-8 requires all lanes of banks two and three to be disabled (powered down) in the RCW. Display a warning message if this is not the case.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
applied to 85xx
- k

On Apr 22, 2011, at 8:34 AM, Kumar Gala wrote:
From: Timur Tabi timur@freescale.com
SerDes PLL bandwidth default setting is incorrect when no lanes are configured as PCI Express.
Signed-off-by: Timur Tabi timur@freescale.com Signed-off-by: Kumar Gala galak@kernel.crashing.org
arch/powerpc/cpu/mpc85xx/cmd_errata.c | 3 ++ arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 48 +++++++++++++++++++++++++ arch/powerpc/include/asm/config_mpc85xx.h | 1 + 3 files changed, 52 insertions(+), 0 deletions(-)
applied to 85xx
- k
participants (2)
-
Kumar Gala
-
Tabi Timur-B04825