From c0a4e6b889a702cc2c8375619ce7b093f6b3b1de Mon Sep 17 00:00:00 2001 From: Yuanquan Chen Date: Mon, 26 Nov 2012 23:49:45 +0000 Subject: [PATCH] powerpc/p4080ds: fix PCI-e x8 link training down failure 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 Signed-off-by: Andy Fleming --- arch/powerpc/cpu/mpc85xx/cmd_errata.c | 3 +++ arch/powerpc/include/asm/config_mpc85xx.h | 1 + drivers/pci/fsl_pci_init.c | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c index 7d38e1c3a9..e5ecf5dae5 100644 --- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c +++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c @@ -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; } diff --git a/arch/powerpc/include/asm/config_mpc85xx.h b/arch/powerpc/include/asm/config_mpc85xx.h index 965d4312c7..0b9638bcee 100644 --- a/arch/powerpc/include/asm/config_mpc85xx.h +++ b/arch/powerpc/include/asm/config_mpc85xx.h @@ -421,6 +421,7 @@ #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 */ diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index 48ae16374d..77ac1f7c7b 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -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, <ssm); + 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);