powerpc/p4080ds: fix PCI-e x8 link training down failure
authorYuanquan Chen <B41889@freescale.com>
Mon, 26 Nov 2012 23:49:45 +0000 (23:49 +0000)
committerAndy Fleming <afleming@freescale.com>
Wed, 28 Nov 2012 00:28:07 +0000 (18:28 -0600)
Due to SerDes configuration error, if we set the PCI-e controller link width
as x8 in RCW and add a narrower width(such as x4, x2 or x1) PCI-e device to
PCI-e slot, it fails to train down to the PCI-e device's link width. According
to p4080ds errata PCIe-A003, we reset the PCI-e controller link width to x4 in
u-boot. Then it can train down to x2 or x1 width to make the PCI-e link between
RC and EP.

Signed-off-by: Yuanquan Chen <B41889@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
arch/powerpc/cpu/mpc85xx/cmd_errata.c
arch/powerpc/include/asm/config_mpc85xx.h
drivers/pci/fsl_pci_init.c

index 7d38e1c..e5ecf5d 100644 (file)
@@ -247,6 +247,9 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #ifdef CONFIG_SYS_FSL_ERRATUM_A004580
        /* This work-around is implemented in PBI, so just check for it */
        check_erratum_a4580(svr);
+#endif
+#ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
+       puts("Work-around for Erratum PCIe-A003 enabled\n");
 #endif
        return 0;
 }
index 965d431..0b9638b 100644 (file)
 #define CONFIG_SYS_FSL_ERRATUM_SRIO_A004034
 #define CONFIG_SYS_FSL_ERRATUM_A004849
 #define CONFIG_SYS_FSL_ERRATUM_A004580
+#define CONFIG_SYS_P4080_ERRATUM_PCIE_A003
 
 #elif defined(CONFIG_PPC_P5020) /* also supports P5010 */
 #define CONFIG_SYS_PPC64               /* 64-bit core */
index 48ae163..77ac1f7 100644 (file)
@@ -470,6 +470,28 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
                }
 #endif
 
+#ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003
+               if (enabled == 0) {
+                       serdes_corenet_t *srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR;
+                       temp32 = in_be32(&srds_regs->srdspccr0);
+
+                       if ((temp32 >> 28) == 3) {
+                               int i;
+
+                               out_be32(&srds_regs->srdspccr0, 2 << 28);
+                               setbits_be32(&pci->pdb_stat, 0x08000000);
+                               in_be32(&pci->pdb_stat);
+                               udelay(100);
+                               clrbits_be32(&pci->pdb_stat, 0x08000000);
+                               asm("sync;isync");
+                               for (i=0; i < 100 && ltssm < PCI_LTSSM_L0; i++) {
+                                       pci_hose_read_config_word(hose, dev, PCI_LTSSM, &ltssm);
+                                       udelay(1000);
+                               }
+                               enabled = ltssm >= PCI_LTSSM_L0;
+                       }
+               }
+#endif
                if (!enabled) {
                        /* Let the user know there's no PCIe link */
                        printf("no link, regs @ 0x%lx\n", pci_info->regs);