[RFC 03/27] PCI: dwc: Allow overriding bridge pci_ops
Rob Herring
robh at kernel.org
Mon Aug 3 17:00:52 EDT 2020
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.
Cc: Jingoo Han <jingoohan1 at gmail.com>
Cc: Gustavo Pimentel <gustavo.pimentel at synopsys.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi at arm.com>
Cc: Bjorn Helgaas <bhelgaas at google.com>
Signed-off-by: Rob Herring <robh at kernel.org>
---
drivers/pci/controller/dwc/pcie-designware-host.c | 15 ++++++++++-----
drivers/pci/controller/dwc/pcie-designware.h | 1 +
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 6232aefbbdb4..7cd8c9528d4c 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -344,6 +344,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (!bridge)
return -ENOMEM;
+ pp->bridge = bridge;
+
ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
&bridge->dma_ranges, NULL);
if (ret)
@@ -450,6 +452,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)
@@ -461,7 +467,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
bridge->dev.parent = dev;
bridge->sysdata = pp;
bridge->busnr = pp->root_bus_nr;
- bridge->ops = &dw_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
@@ -667,11 +672,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);
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 656e00f8fbeb..bad3cddab28e 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -201,6 +201,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);
};
--
2.25.1
More information about the linux-arm-kernel
mailing list