]> git.kernelconcepts.de Git - karo-tx-uboot.git/commitdiff
powerpc/85xx: remove SERDES4 soft-reset work-around
authorTimur Tabi <timur@freescale.com>
Fri, 29 Apr 2011 16:37:43 +0000 (11:37 -0500)
committerKumar Gala <galak@kernel.crashing.org>
Mon, 11 Jul 2011 18:24:21 +0000 (13:24 -0500)
Some P4080 rev1 errata work-arounds, notably erratum SERDES4, required a
bank soft-reset after the bank was configured and enabled, even though
enabling a bank causes it to reset.  Because the reset was required for
multiple errata, it was not properly enclosed in an #ifdef, and so was
not removed with all the other rev1 errata work-arounds.

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 also happened to enable bank 3 (apparently an
undocumented feature).  Simply removing the reset breaks these two
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.

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.

Because this was the only SERDES bank soft-reset, there is no need to
implement a work-around for erratum SERDES-A003.

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

Signed-off-by: Timur Tabi <timur@freescale.com>
Acked-by: Ed Swarthout <swarthou@freescale.com>
Acked-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c

index 741a0f84aace038b425bc8ca0c5d179ac51edd42..4307a4ccbb5349074b2352ef1fa43dcd0ae17c72 100644 (file)
 #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,29 +763,17 @@ 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
 
-               /* reset banks for errata */
-               setbits_be32(&srds_regs->bank[bank].rstctl, SRDS_RSTCTL_RST);
-
                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 */
+               /* 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);
        }