[RFC PATCH v4 01/38] dmaengine: dw-edma: Export helper to get integrated register window

Koichiro Den <[email protected]>
Newsgroups dev.linux.lists.ntb,dev.linux.lists.iommu,org.kernel.vger.dmaengine,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel,org.kernel.vger.linux-kselftest,org.kernel.vger.linux-pci,org.kernel.vger.linux-renesas-soc,org.kernel.vger.netdev
Message-ID <[email protected]>
Some DesignWare PCIe endpoint controllers integrate a DesignWare eDMA
instance. Remote-eDMA providers (e.g. vNTB) need to expose the eDMA
register block to the host through a memory window so the host can
ioremap it and run dw_edma_probe() against the remote view.

Record the physical base and size of the eDMA register aperture and
export dw_edma_get_reg_window() so higher-level code can query the
register window associated with a given PCI EPC device.

Signed-off-by: Koichiro Den <[email protected]>
---
 drivers/pci/controller/dwc/pcie-designware.c | 26 ++++++++++++++++++++
 include/linux/dma/edma.h                     | 25 +++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 345365ea97c7..ad18b84c9f71 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -162,8 +162,12 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
 			pci->edma.reg_base = devm_ioremap_resource(pci->dev, res);
 			if (IS_ERR(pci->edma.reg_base))
 				return PTR_ERR(pci->edma.reg_base);
+			pci->edma.reg_phys = res->start;
+			pci->edma.reg_size = resource_size(res);
 		} else if (pci->atu_size >= 2 * DEFAULT_DBI_DMA_OFFSET) {
 			pci->edma.reg_base = pci->atu_base + DEFAULT_DBI_DMA_OFFSET;
+			pci->edma.reg_phys = pci->atu_phys_addr + DEFAULT_DBI_DMA_OFFSET;
+			pci->edma.reg_size = pci->atu_size - DEFAULT_DBI_DMA_OFFSET;
 		}
 	}
 
@@ -1257,3 +1261,25 @@ resource_size_t dw_pcie_parent_bus_offset(struct dw_pcie *pci,
 
 	return cpu_phys_addr - reg_addr;
 }
+
+int dw_edma_get_reg_window(struct pci_epc *epc, phys_addr_t *phys,
+			   resource_size_t *sz)
+{
+	struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+	struct dw_pcie *pci;
+
+	if (!ep)
+		return -ENODEV;
+
+	pci = to_dw_pcie_from_ep(ep);
+	if (!pci->edma.reg_size)
+		return -ENODEV;
+
+	if (phys)
+		*phys = pci->edma.reg_phys;
+	if (sz)
+		*sz = pci->edma.reg_size;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dw_edma_get_reg_window);
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 270b5458aecf..ffad10ff2cd6 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -83,6 +83,8 @@ struct dw_edma_chip {
 	u32			flags;
 
 	void __iomem		*reg_base;
+	phys_addr_t		reg_phys;
+	resource_size_t		reg_size;
 
 	u16			ll_wr_cnt;
 	u16			ll_rd_cnt;
@@ -115,4 +117,27 @@ static inline int dw_edma_remove(struct dw_edma_chip *chip)
 }
 #endif /* CONFIG_DW_EDMA */
 
+struct pci_epc;
+
+#if IS_REACHABLE(CONFIG_PCIE_DW)
+/**
+ * dw_edma_get_reg_window - get eDMA register base and size
+ * @epc:  the EPC device with which the eDMA instance is integrated
+ * @phys: the output parameter that returns the register base address
+ * @sz:   the output parameter that returns the register space size
+ *
+ * Remote eDMA users (e.g. NTB) may need to expose the integrated DW eDMA
+ * register block through a memory window. This helper returns the physical
+ * base and size for a given DesignWare EP controller.
+ */
+int dw_edma_get_reg_window(struct pci_epc *epc, phys_addr_t *phys,
+			   resource_size_t *sz);
+#else
+static inline int dw_edma_get_reg_window(struct pci_epc *epc, phys_addr_t *phys,
+					 resource_size_t *sz)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_PCIE_DW */
+
 #endif /* _DW_EDMA_H */
-- 
2.51.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.