PCI: dwc: Allow overriding bridge pci_ops
authorRob Herring <robh@kernel.org>
Fri, 21 Aug 2020 03:53:43 +0000 (21:53 -0600)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Mon, 7 Sep 2020 09:30:38 +0000 (10:30 +0100)
In preparation to allow drivers to set their own root and child pci_ops
instead of using the DWC specific config space ops, we need to make
the pci_host_bridge pointer available and move setting the bridge->ops
and bridge->child_ops pointer to before the .host_init() hook.

Link: https://lore.kernel.org/r/20200821035420.380495-4-robh@kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Jingoo Han <jingoohan1@gmail.com>
Cc: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-designware.h

index 1d98554..b626cc7 100644 (file)
@@ -344,6 +344,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
        if (!bridge)
                return -ENOMEM;
 
+       pp->bridge = bridge;
+
        /* Get the I/O and memory ranges from DT */
        resource_list_for_each_entry(win, &bridge->windows) {
                switch (resource_type(win->res)) {
@@ -445,6 +447,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
                }
        }
 
+       /* Set default bus ops */
+       bridge->ops = &dw_pcie_ops;
+       bridge->child_ops = &dw_pcie_ops;
+
        if (pp->ops->host_init) {
                ret = pp->ops->host_init(pp);
                if (ret)
@@ -452,7 +458,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
        }
 
        bridge->sysdata = pp;
-       bridge->ops = &dw_pcie_ops;
 
        ret = pci_scan_root_bus_bridge(bridge);
        if (ret)
@@ -654,11 +659,11 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
        dw_pcie_writel_dbi(pci, PCI_COMMAND, val);
 
        /*
-        * If the platform provides ->rd_other_conf, it means the platform
-        * uses its own address translation component rather than ATU, so
-        * we should not program the ATU here.
+        * If the platform provides its own child bus config accesses, it means
+        * the platform uses its own address translation component rather than
+        * ATU, so we should not program the ATU here.
         */
-       if (!pp->ops->rd_other_conf) {
+       if (pp->bridge->child_ops == &dw_pcie_ops && !pp->ops->rd_other_conf) {
                dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0,
                                          PCIE_ATU_TYPE_MEM, pp->mem_base,
                                          pp->mem_bus_addr, pp->mem_size);
index f911760..8b8ea5f 100644 (file)
@@ -200,6 +200,7 @@ struct pcie_port {
        u32                     num_vectors;
        u32                     irq_mask[MAX_MSI_CTRLS];
        struct pci_bus          *root_bus;
+       struct pci_host_bridge  *bridge;
        raw_spinlock_t          lock;
        DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
 };