From ad002661c2e559ee3ec523b00e23948407968cd7 Mon Sep 17 00:00:00 2001 From: Krishna Chaitanya Chundru Date: Fri, 28 Nov 2025 16:44:17 +0530 Subject: [PATCH] PCI: qcom: Enable iATU mapping for memory & IO regions Signed-off-by: Krishna Chaitanya Chundru --- .../pci/controller/dwc/pcie-designware-host.c | 24 ++++++++++++++----- drivers/pci/controller/dwc/pcie-designware.c | 3 +++ drivers/pci/controller/dwc/pcie-designware.h | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index e92513c5bda5..a60f1539fadc 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -36,6 +36,7 @@ static struct pci_ops dw_child_pcie_ops; #define IS_256MB_ALIGNED(x) IS_ALIGNED(x, SZ_256M) +static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp); static const struct msi_parent_ops dw_pcie_msi_parent_ops = { .required_flags = DW_PCIE_MSI_FLAGS_REQUIRED, .supported_flags = DW_PCIE_MSI_FLAGS_SUPPORTED, @@ -427,13 +428,17 @@ static int dw_pcie_config_ecam_iatu(struct dw_pcie_rp *pp) bus = resource_list_first_type(&pp->bridge->windows, IORESOURCE_BUS); + ret = dw_pcie_iatu_setup(pp); + if (ret) + return ret; + /* * Root bus under the host bridge doesn't require any iATU configuration * as DBI region will be used to access root bus config space. * Immediate bus under Root Bus, needs type 0 iATU configuration and * remaining buses need type 1 iATU configuration. */ - atu.index = 0; + atu.index = pp->ob_atu_index; atu.type = PCIE_ATU_TYPE_CFG0; atu.parent_bus_addr = pp->cfg0_base + SZ_1M; /* 1MiB is to cover 1 (bus) * 32 (devices) * 8 (functions) */ @@ -443,19 +448,26 @@ static int dw_pcie_config_ecam_iatu(struct dw_pcie_rp *pp) if (ret) return ret; + bus_range_max = resource_size(bus->res); if (bus_range_max < 2) return 0; + pp->ob_atu_index++; + /* Configure remaining buses in type 1 iATU configuration */ - atu.index = 1; + atu.index = pp->ob_atu_index; atu.type = PCIE_ATU_TYPE_CFG1; atu.parent_bus_addr = pp->cfg0_base + SZ_2M; atu.size = (SZ_1M * bus_range_max) - SZ_2M; atu.ctrl2 = PCIE_ATU_CFG_SHIFT_MODE_ENABLE; - return dw_pcie_prog_outbound_atu(pci, &atu); + ret = dw_pcie_prog_outbound_atu(pci, &atu); + if (!ret) + pp->ob_atu_index++; + + return ret; } static int dw_pcie_create_ecam_window(struct dw_pcie_rp *pp, struct resource *res) @@ -942,7 +954,7 @@ static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) dev_warn(pci->dev, "Ranges exceed outbound iATU size (%d)\n", pci->num_ob_windows); - pp->msg_atu_index = i; + pp->ob_atu_index = i; i = 0; resource_list_for_each_entry(entry, &pp->bridge->dma_ranges) { @@ -1113,7 +1125,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci) void __iomem *mem; int ret; - if (pci->num_ob_windows <= pci->pp.msg_atu_index) + if (pci->num_ob_windows <= pci->pp.ob_atu_index) return -ENOSPC; if (!pci->pp.msg_res) @@ -1123,7 +1135,7 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci) atu.routing = PCIE_MSG_TYPE_R_BC; atu.type = PCIE_ATU_TYPE_MSG; atu.size = resource_size(pci->pp.msg_res); - atu.index = pci->pp.msg_atu_index; + atu.index = pci->pp.ob_atu_index; atu.parent_bus_addr = pci->pp.msg_res->start - pci->parent_bus_offset; diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index c644216995f6..d27b469b417b 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -478,6 +478,9 @@ int dw_pcie_prog_outbound_atu(struct dw_pcie *pci, limit_addr = parent_bus_addr + atu->size - 1; + if (atu->index > pci->num_ob_windows) + return -ENOSPC; + if ((limit_addr & ~pci->region_limit) != (parent_bus_addr & ~pci->region_limit) || !IS_ALIGNED(parent_bus_addr, pci->region_align) || !IS_ALIGNED(atu->pci_addr, pci->region_align) || !atu->size) { diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index e995f692a1ec..69d0bd8b3c57 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -423,8 +423,8 @@ struct dw_pcie_rp { struct pci_host_bridge *bridge; raw_spinlock_t lock; DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); + int ob_atu_index; bool use_atu_msg; - int msg_atu_index; struct resource *msg_res; bool use_linkup_irq; struct pci_eq_presets presets; -- 2.34.1