1. Implement fsl_arch_pci64_dma_offset() to return PowerPC PCI64
DMA offset
2. Implement fsl_arch_sys_to_pci() to convert pci_controller
to fsl_pci
3. Implement fsl_arch_fake_pci_bus() to fake pci_controller
and PCI bus.
4. Implement fsl_arch_pci_exclude_device() to call
ppc_md.pci_exclude_device()
5. Implement fsl_arch_pci_sys_register() to initialize pci_controller
according to fsl_pci, add register PCI controller to PowerPC PCI
subsystem.
6. Implement fsl_arch_pci_sys_remove() to remove PCI controller from
PowerPC PCI subsystem.
7. Add mpc83xx_pcie_check_link() because pci-fsl-common dose not
support mpc83xx.

Signed-off-by: Minghuan Lian <minghuan.l...@freescale.com>
---
change log:
v4:
no change
v1-v3:
Derived from http://patchwork.ozlabs.org/patch/278965/

Based on upstream master.
Based on the discussion of RFC version here
http://patchwork.ozlabs.org/patch/274487/

 arch/powerpc/sysdev/fsl_pci.c | 142 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 135 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 0764385..38e8dca 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -62,7 +62,11 @@ static void quirk_fsl_pcie_early(struct pci_dev *dev)
 #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
 
 #define MAX_PHYS_ADDR_BITS     40
-static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS;
+
+u64 fsl_arch_pci64_dma_offset(void)
+{
+       return 1ull << MAX_PHYS_ADDR_BITS;
+}
 
 static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
 {
@@ -77,17 +81,44 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 
dma_mask)
        if ((dev->bus == &pci_bus_type) &&
            dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
                set_dma_ops(dev, &dma_direct_ops);
-               set_dma_offset(dev, pci64_dma_offset);
+               set_dma_offset(dev, fsl_arch_pci64_dma_offset());
        }
 
        *dev->dma_mask = dma_mask;
        return 0;
 }
 
+struct fsl_pci *fsl_arch_sys_to_pci(void *sys)
+{
+       struct pci_controller *hose = sys;
+       struct fsl_pci *pci = hose->private_data;
+
+       /* Update the first bus number */
+       if (pci->first_busno != hose->first_busno)
+               pci->first_busno = hose->first_busno;
+
+       return pci;
+}
+
+struct pci_bus *fsl_arch_fake_pci_bus(struct fsl_pci *pci, int busnr)
+{
+       static struct pci_bus bus;
+       static struct pci_controller hose;
+
+       bus.number = busnr;
+       bus.sysdata = &hose;
+       hose.private_data = pci;
+       bus.ops = pci->ops;
+
+       return &bus;
+}
+
 void fsl_pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
-       int i, is_pcie = 0, no_link;
+       bool is_pcie, no_link;
+       int i;
+       struct fsl_pci *pci = fsl_arch_sys_to_pci(hose);
 
        /* The root complex bridge comes up with bogus resources,
         * we copy the PHB ones in.
@@ -97,9 +128,8 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus)
         * tricky.
         */
 
-       if (fsl_pcie_bus_fixup)
-               is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
-       no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK);
+       is_pcie = pci->is_pcie;
+       no_link = !fsl_pci_check_link(pci);
 
        if (bus->parent == hose->bus && (is_pcie || no_link)) {
                for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) {
@@ -121,6 +151,94 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus)
        }
 }
 
+int fsl_arch_pci_exclude_device(struct fsl_pci *pci, u8 bus, u8 devfn)
+{
+       struct pci_controller *hose = pci->sys;
+
+       if (!hose)
+               return PCIBIOS_SUCCESSFUL;
+
+       if (ppc_md.pci_exclude_device)
+               if (ppc_md.pci_exclude_device(hose, bus, devfn))
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+int fsl_arch_pci_sys_register(struct fsl_pci *pci)
+{
+       struct pci_controller *hose;
+
+       pci_add_flags(PCI_REASSIGN_ALL_BUS);
+       hose = pcibios_alloc_controller(pci->dn);
+       if (!hose)
+               return -ENOMEM;
+
+       /* set platform device as the parent */
+       hose->private_data = pci;
+       hose->parent = pci->dev;
+       hose->first_busno = pci->first_busno;
+       hose->last_busno = pci->last_busno;
+       hose->ops = pci->ops;
+
+#ifdef CONFIG_PPC32
+       /* On 32 bits, limit I/O space to 16MB */
+       if (pci->pci_io_size > 0x01000000)
+               pci->pci_io_size = 0x01000000;
+
+       /* 32 bits needs to map IOs here */
+       hose->io_base_virt = ioremap(pci->io_base_phys + pci->io_resource.start,
+                                    pci->pci_io_size);
+
+       /* Expect trouble if pci_addr is not 0 */
+       if (fsl_pci_primary == pci->dn)
+               isa_io_base = (unsigned long)hose->io_base_virt;
+#endif /* CONFIG_PPC32 */
+
+       hose->pci_io_size = pci->io_resource.start + pci->pci_io_size;
+       hose->io_base_phys = pci->io_base_phys;
+       hose->io_resource = pci->io_resource;
+
+       memcpy(hose->mem_offset, pci->mem_offset, sizeof(hose->mem_offset));
+       memcpy(hose->mem_resources, pci->mem_resources,
+               sizeof(hose->mem_resources));
+       hose->dma_window_base_cur = pci->dma_window_base_cur;
+       hose->dma_window_size = pci->dma_window_size;
+
+       pci->sys = hose;
+
+       /*
+        * Install our own dma_set_mask handler to fixup dma_ops
+        * and dma_offset when memory is more than dma window size
+        */
+       if (pci->is_pcie && memblock_end_of_DRAM() > hose->dma_window_size)
+               ppc_md.dma_set_mask = fsl_pci_dma_set_mask;
+
+#ifdef CONFIG_SWIOTLB
+       /*
+        * if we couldn't map all of DRAM via the dma windows
+        * we need SWIOTLB to handle buffers located outside of
+        * dma capable memory region
+        */
+       if (memblock_end_of_DRAM() - 1 > hose->dma_window_base_cur +
+                       hose->dma_window_size)
+               ppc_swiotlb_enable = 1;
+#endif
+
+       mpc85xx_pci_err_probe(to_platform_device(pci->dev));
+       return 0;
+}
+
+void fsl_arch_pci_sys_remove(struct fsl_pci *pci)
+{
+       struct pci_controller *hose = pci->sys;
+
+       if (!hose)
+               return;
+
+       pcibios_free_controller(hose);
+}
+
 #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
 
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID,
@@ -261,6 +379,16 @@ static struct pci_ops mpc83xx_pcie_ops = {
        .write = mpc83xx_pcie_write_config,
 };
 
+static int mpc83xx_pcie_check_link(struct pci_controller *hose)
+{
+       u32 val = 0;
+
+       early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
+       if (val < PCIE_LTSSM_L0)
+               return 1;
+       return 0;
+}
+
 static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
                                     struct resource *reg)
 {
@@ -295,7 +423,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 (mpc83xx_pcie_check_link(hose))
                hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
 
        return 0;
-- 
1.8.1.2


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to