@@ -9,6 +9,7 @@
#include <linux/align.h>
#include <linux/bitfield.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/platform_device.h>
#include "pcie-designware.h"
@@ -294,7 +295,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->phys_base + ep->bus_addr_base;
atu.pci_addr = pci_addr;
atu.size = size;
ret = dw_pcie_ep_outbound_atu(ep, &atu);
@@ -861,6 +862,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;
+ int index;
INIT_LIST_HEAD(&ep->func_list);
@@ -873,6 +875,20 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
return -EINVAL;
ep->phys_base = res->start;
+ ep->bus_addr_base = ep->phys_base;
+
+ if (pci->use_parent_dt_ranges) {
+ index = of_property_match_string(np, "reg-names", "addr_space");
+ if (index < 0)
+ return -EINVAL;
+
+ /*
+ * Get the untranslated bus address from devicetree to use it
+ * as the iATU CPU address in dw_pcie_ep_map_addr().
+ */
+ of_property_read_reg(np, index, &ep->bus_addr_base, NULL);
+ }
+
ep->addr_size = resource_size(res);
if (ep->ops->pre_init)
@@ -410,6 +410,7 @@ struct dw_pcie_ep {
struct list_head func_list;
const struct dw_pcie_ep_ops *ops;
phys_addr_t phys_base;
+ u64 bus_addr_base;
size_t addr_size;
size_t page_size;
u8 bar_to_atu[PCI_STD_NUM_BARS];