powerpc/85xx: Add support for FSL PCIe controller v3.0
authorRoy ZANG <tie-fei.zang@freescale.com>
Fri, 21 Sep 2012 04:12:52 +0000 (04:12 +0000)
committerKumar Gala <galak@kernel.crashing.org>
Tue, 5 Mar 2013 23:10:27 +0000 (17:10 -0600)
The T4240 utilizes a new PCIe controller block that has some minor
programming model differences from previous versions.

The major one that impacts initialization is how we determine the link
state.  On the 3.x controllers we have a memory mapped SoC register
instead of a PCI config register that reports the link state.

Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_pci.h

index 682084dba19bb17a51ed8e5cb3dcfc1902e3dbeb..3271177239b99abd794a35fce8a074145d038bee 100644 (file)
@@ -54,13 +54,35 @@ static void quirk_fsl_pcie_header(struct pci_dev *dev)
        return;
 }
 
-static int __init fsl_pcie_check_link(struct pci_controller *hose)
+static int __init fsl_pcie_check_link(struct pci_controller *hose,
+                                 struct resource *rsrc)
 {
+       struct ccsr_pci __iomem *pci = NULL;
        u32 val;
 
+       /* for PCIe IP rev 3.0 or greater use CSR0 for link state */
+       if (rsrc) {
+               pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
+                   (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
+               pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+               if (!pci) {
+                       dev_err(hose->parent, "Unable to map PCIe registers\n");
+                       return -ENOMEM;
+               }
+               if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_3_0) {
+                       val = (in_be32(&pci->pex_csr0) & PEX_CSR0_LTSSM_MASK)
+                                       >> PEX_CSR0_LTSSM_SHIFT;
+                       if (val != PEX_CSR0_LTSSM_L0)
+                               return 1;
+                       iounmap(pci);
+                       return 0;
+               }
+               iounmap(pci);
+       }
        early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
        if (val < PCIE_LTSSM_L0)
                return 1;
+
        return 0;
 }
 
@@ -483,7 +505,7 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
        if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
                hose->indirect_type |= PPC_INDIRECT_TYPE_EXT_REG |
                        PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
-               if (fsl_pcie_check_link(hose))
+               if (fsl_pcie_check_link(hose, &rsrc))
                        hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
        }
 
@@ -685,7 +707,7 @@ static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
        out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
        out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
 
-       if (fsl_pcie_check_link(hose))
+       if (fsl_pcie_check_link(hose, NULL))
                hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
 
        return 0;
@@ -836,6 +858,7 @@ static const struct of_device_id pci_ids[] = {
        { .compatible = "fsl,qoriq-pcie-v2.2", },
        { .compatible = "fsl,qoriq-pcie-v2.3", },
        { .compatible = "fsl,qoriq-pcie-v2.4", },
+       { .compatible = "fsl,qoriq-pcie-v3.0", },
 
        /*
         * The following entries are for compatibility with older device
index c495c00c8740a938ad079749ff62adc3b22bc229..c81bf4407b5e14d76f47ab9225e93ee7d2fadfeb 100644 (file)
@@ -17,6 +17,7 @@
 #define PCIE_LTSSM     0x0404          /* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0  0x16            /* L0 state */
 #define PCIE_IP_REV_2_2                0x02080202 /* PCIE IP block version Rev2.2 */
+#define PCIE_IP_REV_3_0                0x02080300 /* PCIE IP block version Rev3.0 */
 #define PIWAR_EN               0x80000000      /* Enable */
 #define PIWAR_PF               0x20000000      /* prefetch */
 #define PIWAR_TGI_LOCAL                0x00f00000      /* target - local memory */
@@ -89,6 +90,16 @@ struct ccsr_pci {
        __be32  pex_err_cap_r1;         /* 0x.e2c - PCIE error capture register 0 */
        __be32  pex_err_cap_r2;         /* 0x.e30 - PCIE error capture register 0 */
        __be32  pex_err_cap_r3;         /* 0x.e34 - PCIE error capture register 0 */
+       u8      res_e38[200];
+       __be32  pdb_stat;               /* 0x.f00 - PCIE Debug Status */
+       u8      res_f04[16];
+       __be32  pex_csr0;               /* 0x.f14 - PEX Control/Status register 0*/
+#define PEX_CSR0_LTSSM_MASK    0xFC
+#define PEX_CSR0_LTSSM_SHIFT   2
+#define PEX_CSR0_LTSSM_L0      0x11
+       __be32  pex_csr1;               /* 0x.f18 - PEX Control/Status register 1*/
+       u8      res_f1c[228];
+
 };
 
 extern int fsl_add_bridge(struct platform_device *pdev, int is_primary);