From: Timur Tabi <ti...@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 <ti...@freescale.com>
Signed-off-by: Kumar Gala <ga...@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 */
-- 
1.7.3.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to