Some systems (such as i.MX8QXP) have different CPU and PCI addresses, requiring address translation. If 'addr_space' is missing, retrieve the address translation information from the 'ranges' property in the device tree. This allows support for systems where CPU and PCI addresses differ without relying solely on 'addr_space'. Update the driver to use 'ranges' from the device tree when 'addr_space' is not provided, keeping compatibility with existed systems. Signed-off-by: Frank Li <Frank.Li@xxxxxxx> --- drivers/pci/controller/dwc/pcie-designware-ep.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index feac1a435f764..1b013d2fe694a 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -294,7 +294,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no, atu.func_no = func_no; atu.type = PCIE_ATU_TYPE_MEM; - atu.cpu_addr = addr; + atu.cpu_addr = addr + ep->range.bus_addr - ep->range.cpu_addr; atu.pci_addr = pci_addr; atu.size = size; ret = dw_pcie_ep_outbound_atu(ep, &atu); @@ -861,6 +861,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) struct device *dev = pci->dev; struct platform_device *pdev = to_platform_device(dev); struct device_node *np = dev->of_node; + struct of_pci_range_parser parser; INIT_LIST_HEAD(&ep->func_list); @@ -869,11 +870,21 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) return ret; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); - if (!res) - return -EINVAL; + if (!res) { + ret = of_pci_range_parser_init(&parser, np); + if (ret) + return ret; + + for_each_of_pci_range(&parser, &ep->range) + if ((ep->range.flags & IORESOURCE_TYPE_BITS) == IORESOURCE_MEM) + break; - ep->range.cpu_addr = ep->range.pci_addr = res->start; - ep->range.size = resource_size(res); + if (!ep->range.size) + return -EINVAL; + } else { + ep->range.cpu_addr = ep->range.bus_addr = res->start; + ep->range.size = resource_size(res); + } if (ep->ops->pre_init) ep->ops->pre_init(ep); -- 2.34.1