2020-02-28 15:41:50

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 0/7] Add support for PCIe controller to work in endpoint mode on R-Car SoCs

This patch series adds support for PCIe controller on rcar to work in
endpoint mode, this also extends the epf framework to handle base region
for mapping PCI address locally.

Note:
The cadence/rockchip/designware endpoint drivers are build tested only.

Changes for v5:
1] Rebased the patches on next branch of https://git.kernel.org/pub/scm/
linux/kernel/git/helgaas/pci.git
2] Fixed review comments reported by Kishon while fetching the matching
window in function pci_epc_get_matching_window()
3] Fixed review comments reported by Bjorn
a] Split patch up first patch so that its easier to review and incremental
b] Fixed typos
4] Included Reviewed tag from Rob for the dt-binding patch
5] Fixed issue reported by Nathan for assigning variable to itself

Changes for v4:
1] Fixed dtb_check error reported by Rob
2] Fixed review comments reported by Kishon
a] Dropped pci_epc_find_best_fit_window()
b] Fixed initializing mem ptr in __pci_epc_mem_init()
c] Dropped map_size from pci_epc_mem_window structure

Changes for v3:
1] Fixed review comments from Bjorn and Kishon.
3] Converted to DT schema

Changes for v2:
1] Fixed review comments from Biju for dt-bindings to include an example
for a tested platform.
2] Fixed review comments from Kishon to extend the features of outbound
regions in epf framework.
3] Added support to parse outbound-ranges in OF.

Lad Prabhakar (7):
PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c
PCI: rcar: Move shareable code to a common file
PCI: rcar: Fix calculating mask for PCIEPAMR register
PCI: endpoint: Add support to handle multiple base for mapping
outbound memory
dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint
controller
PCI: rcar: Add support for rcar PCIe controller in endpoint mode
misc: pci_endpoint_test: Add Device ID for RZ/G2E PCIe controller

.../devicetree/bindings/pci/rcar-pci-ep.yaml | 76 ++
arch/arm64/configs/defconfig | 2 +-
drivers/misc/pci_endpoint_test.c | 3 +
drivers/pci/controller/Kconfig | 15 +-
drivers/pci/controller/Makefile | 3 +-
drivers/pci/controller/cadence/pcie-cadence-ep.c | 7 +-
drivers/pci/controller/dwc/pcie-designware-ep.c | 29 +-
drivers/pci/controller/pcie-rcar-ep.c | 490 ++++++++
drivers/pci/controller/pcie-rcar-host.c | 1053 +++++++++++++++++
drivers/pci/controller/pcie-rcar.c | 1229 +-------------------
drivers/pci/controller/pcie-rcar.h | 129 ++
drivers/pci/controller/pcie-rockchip-ep.c | 7 +-
drivers/pci/endpoint/pci-epc-mem.c | 167 ++-
include/linux/pci-epc.h | 39 +-
14 files changed, 1985 insertions(+), 1264 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
create mode 100644 drivers/pci/controller/pcie-rcar-ep.c
create mode 100644 drivers/pci/controller/pcie-rcar-host.c
create mode 100644 drivers/pci/controller/pcie-rcar.h

--
2.7.4


2020-02-28 15:42:13

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 1/7] PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c

This commit renames pcie-rcar.c to pcie-rcar-host.c in preparation for
adding support for endpoint mode. CONFIG_PCIE_RCAR is also renamed to
CONFIG_PCIE_RCAR_HOST to match the driver name accordingly.

In addition to this defconfig file has also been updated to match the new
config option.

Signed-off-by: Lad Prabhakar <[email protected]>
---
arch/arm64/configs/defconfig | 2 +-
drivers/pci/controller/Kconfig | 7 ++++---
drivers/pci/controller/Makefile | 2 +-
drivers/pci/controller/{pcie-rcar.c => pcie-rcar-host.c} | 0
4 files changed, 6 insertions(+), 5 deletions(-)
rename drivers/pci/controller/{pcie-rcar.c => pcie-rcar-host.c} (100%)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 0f21288..7a34fce 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -185,7 +185,7 @@ CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=y
CONFIG_PCI_AARDVARK=y
CONFIG_PCI_TEGRA=y
-CONFIG_PCIE_RCAR=y
+CONFIG_PCIE_RCAR_HOST=y
CONFIG_PCI_HOST_GENERIC=y
CONFIG_PCI_XGENE=y
CONFIG_PCIE_ALTERA=y
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index f84e5ff..37e0ea7 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -54,12 +54,13 @@ config PCI_RCAR_GEN2
There are 3 internal PCI controllers available with a single
built-in EHCI/OHCI host controller present on each one.

-config PCIE_RCAR
- bool "Renesas R-Car PCIe controller"
+config PCIE_RCAR_HOST
+ bool "Renesas R-Car PCIe host controller"
depends on ARCH_RENESAS || COMPILE_TEST
depends on PCI_MSI_IRQ_DOMAIN
help
- Say Y here if you want PCIe controller support on R-Car SoCs.
+ Say Y here if you want PCIe controller support on R-Car SoCs in host
+ mode.

config PCI_HOST_COMMON
bool
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index 01b2502..4ca2da6 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
-obj-$(CONFIG_PCIE_RCAR) += pcie-rcar.o
+obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar-host.o
obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar-host.c
similarity index 100%
rename from drivers/pci/controller/pcie-rcar.c
rename to drivers/pci/controller/pcie-rcar-host.c
--
2.7.4

2020-02-28 15:42:37

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 3/7] PCI: rcar: Fix calculating mask for PCIEPAMR register

The mask value was calculated incorrectly for PCIEPAMR register if the
size was less than 128 bytes. Fix this issue by adding a check on size.

Signed-off-by: Lad Prabhakar <[email protected]>
---
drivers/pci/controller/pcie-rcar.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
index 41275f9..90d47b21 100644
--- a/drivers/pci/controller/pcie-rcar.c
+++ b/drivers/pci/controller/pcie-rcar.c
@@ -75,7 +75,10 @@ void rcar_pcie_set_outbound(int win, void __iomem *base,
* keeps things pretty simple.
*/
size = resource_size(res);
- mask = (roundup_pow_of_two(size) / SZ_128) - 1;
+ if (size > 128)
+ mask = (roundup_pow_of_two(size) / SZ_128) - 1;
+ else
+ mask = 0x0;
rcar_pci_write_reg(base, mask << 7, PCIEPAMR(win));

if (res->flags & IORESOURCE_IO)
--
2.7.4

2020-02-28 15:42:41

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 4/7] PCI: endpoint: Add support to handle multiple base for mapping outbound memory

R-Car PCIe controller has support to map multiple memory regions for
mapping the outbound memory in local system also the controller limits
single allocation for each region (that is, once a chunk is used from the
region it cannot be used to allocate a new one). This features inspires to
add support for handling multiple memory bases in endpoint framework.

With this patch pci_epc_mem_init() now accepts multiple regions, also
page_size for each memory region is passed during initialization so as
to handle single allocation for each region by setting the page_size to
window_size.

Signed-off-by: Lad Prabhakar <[email protected]>
---
drivers/pci/controller/cadence/pcie-cadence-ep.c | 7 +-
drivers/pci/controller/dwc/pcie-designware-ep.c | 29 ++--
drivers/pci/controller/pcie-rockchip-ep.c | 7 +-
drivers/pci/endpoint/pci-epc-mem.c | 167 ++++++++++++++++-------
include/linux/pci-epc.h | 39 ++++--
5 files changed, 169 insertions(+), 80 deletions(-)

diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
index 1c173da..90e32438 100644
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
@@ -401,6 +401,7 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
struct device *dev = ep->pcie.dev;
struct platform_device *pdev = to_platform_device(dev);
struct device_node *np = dev->of_node;
+ struct pci_epc_mem_window mem_window;
struct cdns_pcie *pcie = &ep->pcie;
struct resource *res;
struct pci_epc *epc;
@@ -449,8 +450,10 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
if (of_property_read_u8(np, "max-functions", &epc->max_functions) < 0)
epc->max_functions = 1;

- ret = pci_epc_mem_init(epc, pcie->mem_res->start,
- resource_size(pcie->mem_res));
+ mem_window.phys_base = pcie->mem_res->start;
+ mem_window.size = resource_size(pcie->mem_res);
+ mem_window.page_size = PAGE_SIZE;
+ ret = pci_epc_mem_init(epc, &mem_window, 1);
if (ret < 0) {
dev_err(dev, "failed to initialize the memory space\n");
goto err_init;
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index cfeccd7..b150ef3 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -195,8 +195,7 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no,
}

static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,
- phys_addr_t addr,
- u64 pci_addr, size_t size)
+ phys_addr_t addr, u64 pci_addr, size_t size)
{
int ret;
struct dw_pcie_ep *ep = epc_get_drvdata(epc);
@@ -367,6 +366,7 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
unsigned int aligned_offset;
u16 msg_ctrl, msg_data;
u32 msg_addr_lower, msg_addr_upper, reg;
+ int window = PCI_EPC_DEFAULT_WINDOW;
u64 msg_addr;
bool has_upper;
int ret;
@@ -390,11 +390,11 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
reg = ep->msi_cap + PCI_MSI_DATA_32;
msg_data = dw_pcie_readw_dbi(pci, reg);
}
- aligned_offset = msg_addr_lower & (epc->mem->page_size - 1);
+ aligned_offset = msg_addr_lower & (epc->mem[window]->page_size - 1);
msg_addr = ((u64)msg_addr_upper) << 32 |
(msg_addr_lower & ~aligned_offset);
- ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
- epc->mem->page_size);
+ ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
+ msg_addr, epc->mem[window]->page_size);
if (ret)
return ret;

@@ -416,6 +416,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
u32 reg, msg_data, vec_ctrl;
u64 tbl_addr, msg_addr, reg_u64;
void __iomem *msix_tbl;
+ int window = PCI_EPC_DEFAULT_WINDOW;
int ret;

reg = ep->msix_cap + PCI_MSIX_TABLE;
@@ -452,8 +453,8 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
return -EPERM;
}

- ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
- epc->mem->page_size);
+ ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
+ msg_addr, epc->mem[window]->page_size);
if (ret)
return ret;

@@ -466,10 +467,11 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,

void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
{
+ int window = PCI_EPC_DEFAULT_WINDOW;
struct pci_epc *epc = ep->epc;

pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
- epc->mem->page_size);
+ epc->mem[window]->page_size);

pci_epc_mem_exit(epc);
}
@@ -502,6 +504,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
unsigned int nbars;
unsigned int offset;
struct pci_epc *epc;
+ size_t msi_page_size;
+ struct pci_epc_mem_window mem_window;
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct device *dev = pci->dev;
struct device_node *np = dev->of_node;
@@ -574,15 +578,18 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
if (ret < 0)
epc->max_functions = 1;

- ret = __pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
- ep->page_size);
+ mem_window.phys_base = ep->phys_base;
+ mem_window.size = ep->addr_size;
+ mem_window.page_size = ep->page_size;
+ ret = __pci_epc_mem_init(epc, &mem_window, 1);
if (ret < 0) {
dev_err(dev, "Failed to initialize address space\n");
return ret;
}

+ msi_page_size = epc->mem[PCI_EPC_DEFAULT_WINDOW]->page_size;
ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys,
- epc->mem->page_size);
+ msi_page_size);
if (!ep->msi_mem) {
dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n");
return -ENOMEM;
diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
index d743b0a..5a97390 100644
--- a/drivers/pci/controller/pcie-rockchip-ep.c
+++ b/drivers/pci/controller/pcie-rockchip-ep.c
@@ -562,6 +562,7 @@ static const struct of_device_id rockchip_pcie_ep_of_match[] = {

static int rockchip_pcie_ep_probe(struct platform_device *pdev)
{
+ struct pci_epc_mem_window mem_window;
struct device *dev = &pdev->dev;
struct rockchip_pcie_ep *ep;
struct rockchip_pcie *rockchip;
@@ -614,8 +615,10 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
/* Only enable function 0 by default */
rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG);

- err = pci_epc_mem_init(epc, rockchip->mem_res->start,
- resource_size(rockchip->mem_res));
+ mem_window.phys_base = rockchip->mem_res->start;
+ mem_window.size = resource_size(rockchip->mem_res);
+ mem_window.page_size = PAGE_SIZE;
+ err = pci_epc_mem_init(epc, &mem_window, 1);
if (err < 0) {
dev_err(dev, "failed to initialize the memory space\n");
goto err_uninit_port;
diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c
index d2b174c..6c21957 100644
--- a/drivers/pci/endpoint/pci-epc-mem.c
+++ b/drivers/pci/endpoint/pci-epc-mem.c
@@ -38,57 +38,76 @@ static int pci_epc_mem_get_order(struct pci_epc_mem *mem, size_t size)
/**
* __pci_epc_mem_init() - initialize the pci_epc_mem structure
* @epc: the EPC device that invoked pci_epc_mem_init
- * @phys_base: the physical address of the base
- * @size: the size of the address space
- * @page_size: size of each page
+ * @windows: pointer to windows supported by the device
+ * @num_windows: number of windows device supports
*
* Invoke to initialize the pci_epc_mem structure used by the
* endpoint functions to allocate mapped PCI address.
*/
-int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size,
- size_t page_size)
+int __pci_epc_mem_init(struct pci_epc *epc, struct pci_epc_mem_window *windows,
+ int num_windows)
{
- int ret;
- struct pci_epc_mem *mem;
- unsigned long *bitmap;
+ struct pci_epc_mem *mem = NULL;
+ unsigned long *bitmap = NULL;
unsigned int page_shift;
- int pages;
+ size_t page_size;
int bitmap_size;
-
- if (page_size < PAGE_SIZE)
- page_size = PAGE_SIZE;
-
- page_shift = ilog2(page_size);
- pages = size >> page_shift;
- bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
-
- mem = kzalloc(sizeof(*mem), GFP_KERNEL);
- if (!mem) {
- ret = -ENOMEM;
- goto err;
- }
-
- bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- if (!bitmap) {
- ret = -ENOMEM;
- goto err_mem;
+ int pages;
+ int ret;
+ int i;
+
+ epc->mem_windows = 0;
+
+ if (!windows)
+ return -EINVAL;
+
+ if (num_windows <= 0)
+ return -EINVAL;
+
+ epc->mem = kcalloc(num_windows, sizeof(*mem), GFP_KERNEL);
+ if (!epc->mem)
+ return -EINVAL;
+
+ for (i = 0; i < num_windows; i++) {
+ page_size = windows[i].page_size;
+ if (page_size < PAGE_SIZE)
+ page_size = PAGE_SIZE;
+ page_shift = ilog2(page_size);
+ pages = windows[i].size >> page_shift;
+ bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+
+ mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+ if (!mem) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ if (!bitmap) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ mem->bitmap = bitmap;
+ mem->window.phys_base = windows[i].phys_base;
+ mem->page_size = page_size;
+ mem->pages = pages;
+ mem->window.size = windows[i].size;
+ epc->mem[i] = mem;
}
-
- mem->bitmap = bitmap;
- mem->phys_base = phys_base;
- mem->page_size = page_size;
- mem->pages = pages;
- mem->size = size;
-
- epc->mem = mem;
+ epc->mem_windows = num_windows;

return 0;

err_mem:
- kfree(mem);
+ for (; i >= 0; i--) {
+ mem = epc->mem[i];
+ kfree(mem->bitmap);
+ kfree(mem);
+ }
+ kfree(epc->mem);

-err:
-return ret;
+ return ret;
}
EXPORT_SYMBOL_GPL(__pci_epc_mem_init);

@@ -101,11 +120,21 @@ EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
*/
void pci_epc_mem_exit(struct pci_epc *epc)
{
- struct pci_epc_mem *mem = epc->mem;
+ struct pci_epc_mem *mem;
+ int i;
+
+ if (!epc->mem_windows)
+ return;
+
+ for (i = 0; i <= epc->mem_windows; i++) {
+ mem = epc->mem[i];
+ kfree(mem->bitmap);
+ kfree(mem);
+ }
+ kfree(epc->mem);

epc->mem = NULL;
- kfree(mem->bitmap);
- kfree(mem);
+ epc->mem_windows = 0;
}
EXPORT_SYMBOL_GPL(pci_epc_mem_exit);

@@ -121,20 +150,30 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
phys_addr_t *phys_addr, size_t size)
{
- int pageno;
- void __iomem *virt_addr;
- struct pci_epc_mem *mem = epc->mem;
- unsigned int page_shift = ilog2(mem->page_size);
+ void __iomem *virt_addr = NULL;
+ struct pci_epc_mem *mem;
+ unsigned int page_shift;
+ int pageno = -EINVAL;
int order;
+ int i;

- size = ALIGN(size, mem->page_size);
- order = pci_epc_mem_get_order(mem, size);
+ for (i = 0; i < epc->mem_windows; i++) {
+ mem = epc->mem[i];
+ size = ALIGN(size, mem->page_size);
+ order = pci_epc_mem_get_order(mem, size);
+
+ pageno = bitmap_find_free_region(mem->bitmap, mem->pages,
+ order);
+ if (pageno >= 0)
+ break;
+ }

- pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
if (pageno < 0)
return NULL;

- *phys_addr = mem->phys_base + ((phys_addr_t)pageno << page_shift);
+ page_shift = ilog2(mem->page_size);
+ *phys_addr = mem->window.phys_base +
+ ((phys_addr_t)pageno << page_shift);
virt_addr = ioremap(*phys_addr, size);
if (!virt_addr)
bitmap_release_region(mem->bitmap, pageno, order);
@@ -143,6 +182,23 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
}
EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);

+struct pci_epc_mem *pci_epc_get_matching_window(struct pci_epc *epc,
+ phys_addr_t phys_addr)
+{
+ struct pci_epc_mem *mem;
+ int i;
+
+ for (i = 0; i < epc->mem_windows; i++) {
+ mem = epc->mem[i];
+
+ if (phys_addr >= mem->window.phys_base &&
+ phys_addr < (mem->window.phys_base + mem->window.size))
+ return mem;
+ }
+
+ return NULL;
+}
+
/**
* pci_epc_mem_free_addr() - free the allocated memory address
* @epc: the EPC device on which memory was allocated
@@ -155,13 +211,20 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
void __iomem *virt_addr, size_t size)
{
+ struct pci_epc_mem *mem;
+ unsigned int page_shift;
int pageno;
- struct pci_epc_mem *mem = epc->mem;
- unsigned int page_shift = ilog2(mem->page_size);
int order;

+ mem = pci_epc_get_matching_window(epc, phys_addr);
+ if (!mem) {
+ pr_err("failed to get matching window\n");
+ return;
+ }
+
+ page_shift = ilog2(mem->page_size);
iounmap(virt_addr);
- pageno = (phys_addr - mem->phys_base) >> page_shift;
+ pageno = (phys_addr - mem->window.phys_base) >> page_shift;
size = ALIGN(size, mem->page_size);
order = pci_epc_mem_get_order(mem, size);
bitmap_release_region(mem->bitmap, pageno, order);
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
index 56f1846..dde42e5 100644
--- a/include/linux/pci-epc.h
+++ b/include/linux/pci-epc.h
@@ -64,17 +64,29 @@ struct pci_epc_ops {
struct module *owner;
};

+#define PCI_EPC_DEFAULT_WINDOW 0
+
+/**
+ * struct pci_epc_mem_window - address window of the endpoint controller
+ * @phys_base: physical base address of the PCI address window
+ * @size: the size of the PCI address window
+ * @page_size: size of each page
+ */
+struct pci_epc_mem_window {
+ phys_addr_t phys_base;
+ size_t size;
+ size_t page_size;
+};
+
/**
* struct pci_epc_mem - address space of the endpoint controller
- * @phys_base: physical base address of the PCI address space
- * @size: the size of the PCI address space
+ * @window: address window of the endpoint controller
* @bitmap: bitmap to manage the PCI address space
- * @pages: number of bits representing the address region
* @page_size: size of each page
+ * @pages: number of bits representing the address region
*/
struct pci_epc_mem {
- phys_addr_t phys_base;
- size_t size;
+ struct pci_epc_mem_window window;
unsigned long *bitmap;
size_t page_size;
int pages;
@@ -85,7 +97,8 @@ struct pci_epc_mem {
* @dev: PCI EPC device
* @pci_epf: list of endpoint functions present in this EPC device
* @ops: function pointers for performing endpoint operations
- * @mem: address space of the endpoint controller
+ * @mem: array of address space of the endpoint controller
+ * @mem_windows: number of windows supported by device
* @max_functions: max number of functions that can be configured in this EPC
* @group: configfs group representing the PCI EPC device
* @lock: spinlock to protect pci_epc ops
@@ -94,7 +107,8 @@ struct pci_epc {
struct device dev;
struct list_head pci_epf;
const struct pci_epc_ops *ops;
- struct pci_epc_mem *mem;
+ struct pci_epc_mem **mem;
+ unsigned int mem_windows;
u8 max_functions;
struct config_group *group;
/* spinlock to protect against concurrent access of EP controller */
@@ -128,8 +142,8 @@ struct pci_epc_features {
#define devm_pci_epc_create(dev, ops) \
__devm_pci_epc_create((dev), (ops), THIS_MODULE)

-#define pci_epc_mem_init(epc, phys_addr, size) \
- __pci_epc_mem_init((epc), (phys_addr), (size), PAGE_SIZE)
+#define pci_epc_mem_init(epc, windows, num_windows) \
+ __pci_epc_mem_init((epc), windows, num_windows)

static inline void epc_set_drvdata(struct pci_epc *epc, void *data)
{
@@ -159,8 +173,7 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no,
void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no,
struct pci_epf_bar *epf_bar);
int pci_epc_map_addr(struct pci_epc *epc, u8 func_no,
- phys_addr_t phys_addr,
- u64 pci_addr, size_t size);
+ phys_addr_t phys_addr, u64 pci_addr, size_t size);
void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
phys_addr_t phys_addr);
int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
@@ -178,8 +191,8 @@ unsigned int pci_epc_get_first_free_bar(const struct pci_epc_features
struct pci_epc *pci_epc_get(const char *epc_name);
void pci_epc_put(struct pci_epc *epc);

-int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr, size_t size,
- size_t page_size);
+int __pci_epc_mem_init(struct pci_epc *epc, struct pci_epc_mem_window *window,
+ int num_windows);
void pci_epc_mem_exit(struct pci_epc *epc);
void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
phys_addr_t *phys_addr, size_t size);
--
2.7.4

2020-02-28 15:42:43

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 5/7] dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint controller

This patch adds the bindings for the R-Car PCIe endpoint driver.

Signed-off-by: Lad Prabhakar <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
.../devicetree/bindings/pci/rcar-pci-ep.yaml | 76 ++++++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml

diff --git a/Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml b/Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
new file mode 100644
index 0000000..07cd5a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2020 Renesas Electronics Europe GmbH - https://www.renesas.com/eu/en/
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/rcar-pci-ep.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas R-Car PCIe Endpoint
+
+maintainers:
+ - Lad Prabhakar <[email protected]>
+
+properties:
+ compatible:
+ items:
+ - const: renesas,r8a774c0-pcie-ep
+ - const: renesas,rcar-gen3-pcie-ep
+
+ reg:
+ maxItems: 5
+
+ reg-names:
+ items:
+ - const: apb-base
+ - const: memory0
+ - const: memory1
+ - const: memory2
+ - const: memory3
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: pcie
+
+ max-functions:
+ minimum: 1
+ maximum: 6
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - resets
+ - power-domains
+ - clocks
+ - clock-names
+ - max-functions
+
+examples:
+ - |
+ #include <dt-bindings/clock/r8a774c0-cpg-mssr.h>
+ #include <dt-bindings/power/r8a774c0-sysc.h>
+
+ pcie0_ep: pcie-ep@fe000000 {
+ compatible = "renesas,r8a774c0-pcie-ep",
+ "renesas,rcar-gen3-pcie-ep";
+ reg = <0 0xfe000000 0 0x80000>,
+ <0x0 0xfe100000 0 0x100000>,
+ <0x0 0xfe200000 0 0x200000>,
+ <0x0 0x30000000 0 0x8000000>,
+ <0x0 0x38000000 0 0x8000000>;
+ reg-names = "apb-base", "memory0", "memory1", "memory2", "memory3";
+ resets = <&cpg 319>;
+ power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
+ clocks = <&cpg CPG_MOD 319>;
+ clock-names = "pcie";
+ max-functions = /bits/ 8 <1>;
+ };
--
2.7.4

2020-02-28 15:43:33

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 2/7] PCI: rcar: Move shareable code to a common file

This patch moves sharable code to common file pcie-rcar.c and the #defines
to pcie-rcar.h so that the common code can be reused with endpoint driver.
There are no functional changes with this patch for the host controller
driver.

Signed-off-by: Lad Prabhakar <[email protected]>
---
drivers/pci/controller/Makefile | 2 +-
drivers/pci/controller/pcie-rcar-host.c | 358 ++++++++------------------------
drivers/pci/controller/pcie-rcar.c | 117 +++++++++++
drivers/pci/controller/pcie-rcar.h | 125 +++++++++++
4 files changed, 324 insertions(+), 278 deletions(-)
create mode 100644 drivers/pci/controller/pcie-rcar.c
create mode 100644 drivers/pci/controller/pcie-rcar.h

diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index 4ca2da6..b4ada32 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
-obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar-host.o
+obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
index 759c654..93f22d8 100644
--- a/drivers/pci/controller/pcie-rcar-host.c
+++ b/drivers/pci/controller/pcie-rcar-host.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/*
* PCIe driver for Renesas R-Car SoCs
- * Copyright (C) 2014 Renesas Electronics Europe Ltd
+ * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
*
* Based on:
* arch/sh/drivers/pci/pcie-sh7786.c
@@ -30,104 +30,7 @@
#include <linux/pm_runtime.h>
#include <linux/slab.h>

-#define PCIECAR 0x000010
-#define PCIECCTLR 0x000018
-#define CONFIG_SEND_ENABLE BIT(31)
-#define TYPE0 (0 << 8)
-#define TYPE1 BIT(8)
-#define PCIECDR 0x000020
-#define PCIEMSR 0x000028
-#define PCIEINTXR 0x000400
-#define PCIEPHYSR 0x0007f0
-#define PHYRDY BIT(0)
-#define PCIEMSITXR 0x000840
-
-/* Transfer control */
-#define PCIETCTLR 0x02000
-#define DL_DOWN BIT(3)
-#define CFINIT BIT(0)
-#define PCIETSTR 0x02004
-#define DATA_LINK_ACTIVE BIT(0)
-#define PCIEERRFR 0x02020
-#define UNSUPPORTED_REQUEST BIT(4)
-#define PCIEMSIFR 0x02044
-#define PCIEMSIALR 0x02048
-#define MSIFE BIT(0)
-#define PCIEMSIAUR 0x0204c
-#define PCIEMSIIER 0x02050
-
-/* root port address */
-#define PCIEPRAR(x) (0x02080 + ((x) * 0x4))
-
-/* local address reg & mask */
-#define PCIELAR(x) (0x02200 + ((x) * 0x20))
-#define PCIELAMR(x) (0x02208 + ((x) * 0x20))
-#define LAM_PREFETCH BIT(3)
-#define LAM_64BIT BIT(2)
-#define LAR_ENABLE BIT(1)
-
-/* PCIe address reg & mask */
-#define PCIEPALR(x) (0x03400 + ((x) * 0x20))
-#define PCIEPAUR(x) (0x03404 + ((x) * 0x20))
-#define PCIEPAMR(x) (0x03408 + ((x) * 0x20))
-#define PCIEPTCTLR(x) (0x0340c + ((x) * 0x20))
-#define PAR_ENABLE BIT(31)
-#define IO_SPACE BIT(8)
-
-/* Configuration */
-#define PCICONF(x) (0x010000 + ((x) * 0x4))
-#define PMCAP(x) (0x010040 + ((x) * 0x4))
-#define EXPCAP(x) (0x010070 + ((x) * 0x4))
-#define VCCAP(x) (0x010100 + ((x) * 0x4))
-
-/* link layer */
-#define IDSETR1 0x011004
-#define TLCTLR 0x011048
-#define MACSR 0x011054
-#define SPCHGFIN BIT(4)
-#define SPCHGFAIL BIT(6)
-#define SPCHGSUC BIT(7)
-#define LINK_SPEED (0xf << 16)
-#define LINK_SPEED_2_5GTS (1 << 16)
-#define LINK_SPEED_5_0GTS (2 << 16)
-#define MACCTLR 0x011058
-#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */
-#define SPEED_CHANGE BIT(24)
-#define SCRAMBLE_DISABLE BIT(27)
-#define LTSMDIS BIT(31)
-#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK)
-#define PMSR 0x01105c
-#define MACS2R 0x011078
-#define MACCGSPSETR 0x011084
-#define SPCNGRSN BIT(31)
-
-/* R-Car H1 PHY */
-#define H1_PCIEPHYADRR 0x04000c
-#define WRITE_CMD BIT(16)
-#define PHY_ACK BIT(24)
-#define RATE_POS 12
-#define LANE_POS 8
-#define ADR_POS 0
-#define H1_PCIEPHYDOUTR 0x040014
-
-/* R-Car Gen2 PHY */
-#define GEN2_PCIEPHYADDR 0x780
-#define GEN2_PCIEPHYDATA 0x784
-#define GEN2_PCIEPHYCTRL 0x78c
-
-#define INT_PCI_MSI_NR 32
-
-#define RCONF(x) (PCICONF(0) + (x))
-#define RPMCAP(x) (PMCAP(0) + (x))
-#define REXPCAP(x) (EXPCAP(0) + (x))
-#define RVCCAP(x) (VCCAP(0) + (x))
-
-#define PCIE_CONF_BUS(b) (((b) & 0xff) << 24)
-#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
-#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
-
-#define RCAR_PCI_MAX_RESOURCES 4
-#define MAX_NR_INBOUND_MAPS 6
+#include "pcie-rcar.h"

struct rcar_msi {
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
@@ -155,36 +58,10 @@ struct rcar_pcie {
struct rcar_msi msi;
};

-static void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val,
- unsigned int reg)
-{
- writel(val, pcie->base + reg);
-}
-
-static u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int reg)
-{
- return readl(pcie->base + reg);
-}
-
-enum {
- RCAR_PCI_ACCESS_READ,
- RCAR_PCI_ACCESS_WRITE,
-};
-
-static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
-{
- unsigned int shift = BITS_PER_BYTE * (where & 3);
- u32 val = rcar_pci_read_reg(pcie, where & ~3);
-
- val &= ~(mask << shift);
- val |= data << shift;
- rcar_pci_write_reg(pcie, val, where & ~3);
-}
-
static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
{
unsigned int shift = BITS_PER_BYTE * (where & 3);
- u32 val = rcar_pci_read_reg(pcie, where & ~3);
+ u32 val = rcar_pci_read_reg(pcie->base, where & ~3);

return val >> shift;
}
@@ -221,13 +98,13 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
return PCIBIOS_DEVICE_NOT_FOUND;

if (access_type == RCAR_PCI_ACCESS_READ) {
- *data = rcar_pci_read_reg(pcie, PCICONF(index));
+ *data = rcar_pci_read_reg(pcie->base, PCICONF(index));
} else {
/* Keep an eye out for changes to the root bus number */
if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS))
pcie->root_bus_nr = *data & 0xff;

- rcar_pci_write_reg(pcie, *data, PCICONF(index));
+ rcar_pci_write_reg(pcie->base, *data, PCICONF(index));
}

return PCIBIOS_SUCCESSFUL;
@@ -237,20 +114,23 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
return PCIBIOS_DEVICE_NOT_FOUND;

/* Clear errors */
- rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
+ rcar_pci_write_reg(pcie->base, rcar_pci_read_reg(pcie->base, PCIEERRFR),
+ PCIEERRFR);

/* Set the PIO address */
- rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
+ rcar_pci_write_reg(pcie->base, PCIE_CONF_BUS(bus->number) |
PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);

/* Enable the configuration access */
if (bus->parent->number == pcie->root_bus_nr)
- rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
+ rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE | TYPE0,
+ PCIECCTLR);
else
- rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
+ rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE | TYPE1,
+ PCIECCTLR);

/* Check for errors */
- if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
+ if (rcar_pci_read_reg(pcie->base, PCIEERRFR) & UNSUPPORTED_REQUEST)
return PCIBIOS_DEVICE_NOT_FOUND;

/* Check for master and target aborts */
@@ -259,12 +139,12 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
return PCIBIOS_DEVICE_NOT_FOUND;

if (access_type == RCAR_PCI_ACCESS_READ)
- *data = rcar_pci_read_reg(pcie, PCIECDR);
+ *data = rcar_pci_read_reg(pcie->base, PCIECDR);
else
- rcar_pci_write_reg(pcie, *data, PCIECDR);
+ rcar_pci_write_reg(pcie->base, *data, PCIECDR);

/* Disable the configuration access */
- rcar_pci_write_reg(pcie, 0, PCIECCTLR);
+ rcar_pci_write_reg(pcie->base, 0, PCIECCTLR);

return PCIBIOS_SUCCESSFUL;
}
@@ -332,41 +212,6 @@ static struct pci_ops rcar_pcie_ops = {
.write = rcar_pcie_write_conf,
};

-static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
- struct resource *res)
-{
- /* Setup PCIe address space mappings for each resource */
- resource_size_t size;
- resource_size_t res_start;
- u32 mask;
-
- rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
-
- /*
- * The PAMR mask is calculated in units of 128Bytes, which
- * keeps things pretty simple.
- */
- size = resource_size(res);
- mask = (roundup_pow_of_two(size) / SZ_128) - 1;
- rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
-
- if (res->flags & IORESOURCE_IO)
- res_start = pci_pio_to_address(res->start);
- else
- res_start = res->start;
-
- rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPAUR(win));
- rcar_pci_write_reg(pcie, lower_32_bits(res_start) & ~0x7F,
- PCIEPALR(win));
-
- /* First resource is for IO */
- mask = PAR_ENABLE;
- if (res->flags & IORESOURCE_IO)
- mask |= IO_SPACE;
-
- rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
-}
-
static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
{
struct resource_entry *win;
@@ -382,7 +227,7 @@ static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
switch (resource_type(res)) {
case IORESOURCE_IO:
case IORESOURCE_MEM:
- rcar_pcie_setup_window(i, pci, res);
+ rcar_pcie_set_outbound(i, pci->base, res);
i++;
break;
case IORESOURCE_BUS:
@@ -404,37 +249,38 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
unsigned int timeout = 1000;
u32 macsr;

- if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) != LINK_SPEED_5_0GTS)
+ if ((rcar_pci_read_reg(pcie->base, MACS2R) & LINK_SPEED) !=
+ LINK_SPEED_5_0GTS)
return;

- if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) {
+ if (rcar_pci_read_reg(pcie->base, MACCTLR) & SPEED_CHANGE) {
dev_err(dev, "Speed change already in progress\n");
return;
}

- macsr = rcar_pci_read_reg(pcie, MACSR);
+ macsr = rcar_pci_read_reg(pcie->base, MACSR);
if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS)
goto done;

/* Set target link speed to 5.0 GT/s */
- rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
+ rcar_rmw32(pcie->base, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
PCI_EXP_LNKSTA_CLS_5_0GB);

/* Set speed change reason as intentional factor */
- rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0);
+ rcar_rmw32(pcie->base, MACCGSPSETR, SPCNGRSN, 0);

/* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */
if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL))
- rcar_pci_write_reg(pcie, macsr, MACSR);
+ rcar_pci_write_reg(pcie->base, macsr, MACSR);

/* Start link speed change */
- rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);
+ rcar_rmw32(pcie->base, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);

while (timeout--) {
- macsr = rcar_pci_read_reg(pcie, MACSR);
+ macsr = rcar_pci_read_reg(pcie->base, MACSR);
if (macsr & SPCHGFIN) {
/* Clear the interrupt bits */
- rcar_pci_write_reg(pcie, macsr, MACSR);
+ rcar_pci_write_reg(pcie->base, macsr, MACSR);

if (macsr & SPCHGFAIL)
dev_err(dev, "Speed change failed\n");
@@ -498,7 +344,7 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)
unsigned int timeout = 100;

while (timeout--) {
- if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
+ if (rcar_pci_read_reg(pcie->base, H1_PCIEPHYADRR) & PHY_ACK)
return 0;

udelay(100);
@@ -521,60 +367,31 @@ static void phy_write_reg(struct rcar_pcie *pcie,
((addr & 0xff) << ADR_POS);

/* Set write data */
- rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
- rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
+ rcar_pci_write_reg(pcie->base, data, H1_PCIEPHYDOUTR);
+ rcar_pci_write_reg(pcie->base, phyaddr, H1_PCIEPHYADRR);

/* Ignore errors as they will be dealt with if the data link is down */
phy_wait_for_ack(pcie);

/* Clear command */
- rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
- rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
+ rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYDOUTR);
+ rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYADRR);

/* Ignore errors as they will be dealt with if the data link is down */
phy_wait_for_ack(pcie);
}

-static int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie)
-{
- unsigned int timeout = 10;
-
- while (timeout--) {
- if (rcar_pci_read_reg(pcie, PCIEPHYSR) & PHYRDY)
- return 0;
-
- msleep(5);
- }
-
- return -ETIMEDOUT;
-}
-
-static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
-{
- unsigned int timeout = 10000;
-
- while (timeout--) {
- if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
- return 0;
-
- udelay(5);
- cpu_relax();
- }
-
- return -ETIMEDOUT;
-}
-
static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
{
int err;

/* Begin initialization */
- rcar_pci_write_reg(pcie, 0, PCIETCTLR);
+ rcar_pci_write_reg(pcie->base, 0, PCIETCTLR);

/* Set mode */
- rcar_pci_write_reg(pcie, 1, PCIEMSR);
+ rcar_pci_write_reg(pcie->base, 1, PCIEMSR);

- err = rcar_pcie_wait_for_phyrdy(pcie);
+ err = rcar_pcie_wait_for_phyrdy(pcie->base);
if (err)
return err;

@@ -583,51 +400,51 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
* class to match. Hardware takes care of propagating the IDSETR
* settings, so there is no need to bother with a quirk.
*/
- rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
+ rcar_pci_write_reg(pcie->base, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);

/*
* Setup Secondary Bus Number & Subordinate Bus Number, even though
* they aren't used, to avoid bridge being detected as broken.
*/
- rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
- rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
+ rcar_rmw32(pcie->base, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
+ rcar_rmw32(pcie->base, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);

/* Initialize default capabilities. */
- rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
- rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
- PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
- rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
- PCI_HEADER_TYPE_BRIDGE);
+ rcar_rmw32(pcie->base, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_FLAGS),
+ PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
+ rcar_rmw32(pcie->base, RCONF(PCI_HEADER_TYPE), 0x7f,
+ PCI_HEADER_TYPE_BRIDGE);

/* Enable data link layer active state reporting */
- rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
- PCI_EXP_LNKCAP_DLLLARC);
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
+ PCI_EXP_LNKCAP_DLLLARC);

/* Write out the physical slot number = 0 */
- rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);

/* Set the completion timer timeout to the maximum 50ms. */
- rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50);
+ rcar_rmw32(pcie->base, TLCTLR + 1, 0x3f, 50);

/* Terminate list of capabilities (Next Capability Offset=0) */
- rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0);
+ rcar_rmw32(pcie->base, RVCCAP(0), 0xfff00000, 0);

/* Enable MSI */
if (IS_ENABLED(CONFIG_PCI_MSI))
- rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR);
+ rcar_pci_write_reg(pcie->base, 0x801f0000, PCIEMSITXR);

- rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
+ rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);

/* Finish initialization - establish a PCI Express link */
- rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
+ rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);

/* This will timeout if we don't have a link. */
- err = rcar_pcie_wait_for_dl(pcie);
+ err = rcar_pcie_wait_for_dl(pcie->base);
if (err)
return err;

/* Enable INTx interrupts */
- rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
+ rcar_rmw32(pcie->base, PCIEINTXR, 0, 0xF << 8);

wmb();

@@ -663,16 +480,16 @@ static int rcar_pcie_phy_init_gen2(struct rcar_pcie *pcie)
* These settings come from the R-Car Series, 2nd Generation User's
* Manual, section 50.3.1 (2) Initialization of the physical layer.
*/
- rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR);
- rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA);
- rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
- rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x000f0030, GEN2_PCIEPHYADDR);
+ rcar_pci_write_reg(pcie->base, 0x00381203, GEN2_PCIEPHYDATA);
+ rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);

- rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR);
+ rcar_pci_write_reg(pcie->base, 0x000f0054, GEN2_PCIEPHYADDR);
/* The following value is for DC connection, no termination resistor */
- rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA);
- rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
- rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x13802007, GEN2_PCIEPHYDATA);
+ rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
+ rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);

return 0;
}
@@ -735,7 +552,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
struct device *dev = pcie->dev;
unsigned long reg;

- reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
+ reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);

/* MSI & INTx share an interrupt - we only handle MSI here */
if (!reg)
@@ -746,7 +563,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
unsigned int msi_irq;

/* clear the interrupt */
- rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
+ rcar_pci_write_reg(pcie->base, 1 << index, PCIEMSIFR);

msi_irq = irq_find_mapping(msi->domain, index);
if (msi_irq) {
@@ -760,7 +577,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
}

/* see if there's any more pending in this vector */
- reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
+ reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);
}

return IRQ_HANDLED;
@@ -787,8 +604,8 @@ static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,

irq_set_msi_desc(irq, desc);

- msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
- msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
+ msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) & ~MSIFE;
+ msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
msg.data = hwirq;

pci_write_msi_msg(irq, &msg);
@@ -839,8 +656,8 @@ static int rcar_msi_setup_irqs(struct msi_controller *chip,
desc->nvec_used = nvec;
desc->msi_attrib.multiple = order_base_2(nvec);

- msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
- msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
+ msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) & ~MSIFE;
+ msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
msg.data = hwirq;

pci_write_msi_msg(irq, &msg);
@@ -940,11 +757,11 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
}
base = virt_to_phys((void *)msi->pages);

- rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR);
- rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR);
+ rcar_pci_write_reg(pcie->base, lower_32_bits(base) | MSIFE, PCIEMSIALR);
+ rcar_pci_write_reg(pcie->base, upper_32_bits(base), PCIEMSIAUR);

/* enable all MSI interrupts */
- rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
+ rcar_pci_write_reg(pcie->base, 0xffffffff, PCIEMSIIER);

return 0;

@@ -958,10 +775,10 @@ static void rcar_pcie_teardown_msi(struct rcar_pcie *pcie)
struct rcar_msi *msi = &pcie->msi;

/* Disable all MSI interrupts */
- rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
+ rcar_pci_write_reg(pcie->base, 0, PCIEMSIIER);

/* Disable address decoding of the MSI interrupt, MSIFE */
- rcar_pci_write_reg(pcie, 0, PCIEMSIALR);
+ rcar_pci_write_reg(pcie->base, 0, PCIEMSIALR);

free_pages(msi->pages, 0);

@@ -1054,21 +871,8 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
mask = roundup_pow_of_two(size) - 1;
mask &= ~0xf;

- /*
- * Set up 64-bit inbound regions as the range parser doesn't
- * distinguish between 32 and 64-bit types.
- */
- rcar_pci_write_reg(pcie, lower_32_bits(pci_addr),
- PCIEPRAR(idx));
- rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
- rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags,
- PCIELAMR(idx));
-
- rcar_pci_write_reg(pcie, upper_32_bits(pci_addr),
- PCIEPRAR(idx + 1));
- rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr),
- PCIELAR(idx + 1));
- rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
+ rcar_pcie_set_inbound(pcie->base, cpu_addr, pci_addr,
+ lower_32_bits(mask) | flags, idx, true);

pci_addr += size;
cpu_addr += size;
@@ -1170,7 +974,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
goto err_phy_shutdown;
}

- data = rcar_pci_read_reg(pcie, MACSR);
+ data = rcar_pci_read_reg(pcie->base, MACSR);
dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);

if (IS_ENABLED(CONFIG_PCI_MSI)) {
@@ -1223,14 +1027,14 @@ static int rcar_pcie_resume_noirq(struct device *dev)
{
struct rcar_pcie *pcie = dev_get_drvdata(dev);

- if (rcar_pci_read_reg(pcie, PMSR) &&
- !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
+ if (rcar_pci_read_reg(pcie->base, PMSR) &&
+ !(rcar_pci_read_reg(pcie->base, PCIETCTLR) & DL_DOWN))
return 0;

/* Re-establish the PCIe link */
- rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
- rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
- return rcar_pcie_wait_for_dl(pcie);
+ rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
+ rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);
+ return rcar_pcie_wait_for_dl(pcie->base);
}

static const struct dev_pm_ops rcar_pcie_pm_ops = {
diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
new file mode 100644
index 0000000..41275f9
--- /dev/null
+++ b/drivers/pci/controller/pcie-rcar.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe driver for Renesas R-Car SoCs
+ * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
+ *
+ * Author: Phil Edworthy <[email protected]>
+ */
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include "pcie-rcar.h"
+
+void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int reg)
+{
+ writel(val, base + reg);
+}
+
+u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg)
+{
+ return readl(base + reg);
+}
+
+void rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data)
+{
+ unsigned int shift = BITS_PER_BYTE * (where & 3);
+ u32 val = rcar_pci_read_reg(base, where & ~3);
+
+ val &= ~(mask << shift);
+ val |= data << shift;
+ rcar_pci_write_reg(base, val, where & ~3);
+}
+
+int rcar_pcie_wait_for_phyrdy(void __iomem *base)
+{
+ unsigned int timeout = 10;
+
+ while (timeout--) {
+ if (rcar_pci_read_reg(base, PCIEPHYSR) & PHYRDY)
+ return 0;
+
+ msleep(5);
+ }
+
+ return -ETIMEDOUT;
+}
+
+int rcar_pcie_wait_for_dl(void __iomem *base)
+{
+ unsigned int timeout = 10000;
+
+ while (timeout--) {
+ if ((rcar_pci_read_reg(base, PCIETSTR) & DATA_LINK_ACTIVE))
+ return 0;
+
+ udelay(5);
+ cpu_relax();
+ }
+
+ return -ETIMEDOUT;
+}
+
+void rcar_pcie_set_outbound(int win, void __iomem *base,
+ struct resource *res)
+{
+ /* Setup PCIe address space mappings for each resource */
+ resource_size_t res_start;
+ resource_size_t size;
+ u32 mask;
+
+ rcar_pci_write_reg(base, 0x00000000, PCIEPTCTLR(win));
+
+ /*
+ * The PAMR mask is calculated in units of 128Bytes, which
+ * keeps things pretty simple.
+ */
+ size = resource_size(res);
+ mask = (roundup_pow_of_two(size) / SZ_128) - 1;
+ rcar_pci_write_reg(base, mask << 7, PCIEPAMR(win));
+
+ if (res->flags & IORESOURCE_IO)
+ res_start = pci_pio_to_address(res->start);
+ else
+ res_start = res->start;
+
+ rcar_pci_write_reg(base, upper_32_bits(res_start), PCIEPAUR(win));
+ rcar_pci_write_reg(base, lower_32_bits(res_start) & ~0x7F,
+ PCIEPALR(win));
+
+ /* First resource is for IO */
+ mask = PAR_ENABLE;
+ if (res->flags & IORESOURCE_IO)
+ mask |= IO_SPACE;
+
+ rcar_pci_write_reg(base, mask, PCIEPTCTLR(win));
+}
+
+void rcar_pcie_set_inbound(void __iomem *base,
+ u64 cpu_addr, u64 pci_addr,
+ u64 flags, int idx, bool host)
+{
+ /*
+ * Set up 64-bit inbound regions as the range parser doesn't
+ * distinguish between 32 and 64-bit types.
+ */
+ if (host)
+ rcar_pci_write_reg(base, lower_32_bits(pci_addr),
+ PCIEPRAR(idx));
+ rcar_pci_write_reg(base, lower_32_bits(cpu_addr), PCIELAR(idx));
+ rcar_pci_write_reg(base, flags, PCIELAMR(idx));
+
+ if (host)
+ rcar_pci_write_reg(base, upper_32_bits(pci_addr),
+ PCIEPRAR(idx + 1));
+ rcar_pci_write_reg(base, upper_32_bits(cpu_addr), PCIELAR(idx + 1));
+ rcar_pci_write_reg(base, 0, PCIELAMR(idx + 1));
+}
diff --git a/drivers/pci/controller/pcie-rcar.h b/drivers/pci/controller/pcie-rcar.h
new file mode 100644
index 0000000..b529d806
--- /dev/null
+++ b/drivers/pci/controller/pcie-rcar.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PCIe driver for Renesas R-Car SoCs
+ * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
+ *
+ * Author: Phil Edworthy <[email protected]>
+ */
+
+#ifndef _PCIE_RCAR_H
+#define _PCIE_RCAR_H
+
+#define PCIECAR 0x000010
+#define PCIECCTLR 0x000018
+#define CONFIG_SEND_ENABLE BIT(31)
+#define TYPE0 (0 << 8)
+#define TYPE1 BIT(8)
+#define PCIECDR 0x000020
+#define PCIEMSR 0x000028
+#define PCIEINTXR 0x000400
+#define PCIEPHYSR 0x0007f0
+#define PHYRDY BIT(0)
+#define PCIEMSITXR 0x000840
+
+/* Transfer control */
+#define PCIETCTLR 0x02000
+#define DL_DOWN BIT(3)
+#define CFINIT BIT(0)
+#define PCIETSTR 0x02004
+#define DATA_LINK_ACTIVE BIT(0)
+#define PCIEERRFR 0x02020
+#define UNSUPPORTED_REQUEST BIT(4)
+#define PCIEMSIFR 0x02044
+#define PCIEMSIALR 0x02048
+#define MSIFE BIT(0)
+#define PCIEMSIAUR 0x0204c
+#define PCIEMSIIER 0x02050
+
+/* root port address */
+#define PCIEPRAR(x) (0x02080 + ((x) * 0x4))
+
+/* local address reg & mask */
+#define PCIELAR(x) (0x02200 + ((x) * 0x20))
+#define PCIELAMR(x) (0x02208 + ((x) * 0x20))
+#define LAM_PREFETCH BIT(3)
+#define LAM_64BIT BIT(2)
+#define LAR_ENABLE BIT(1)
+
+/* PCIe address reg & mask */
+#define PCIEPALR(x) (0x03400 + ((x) * 0x20))
+#define PCIEPAUR(x) (0x03404 + ((x) * 0x20))
+#define PCIEPAMR(x) (0x03408 + ((x) * 0x20))
+#define PCIEPTCTLR(x) (0x0340c + ((x) * 0x20))
+#define PAR_ENABLE BIT(31)
+#define IO_SPACE BIT(8)
+
+/* Configuration */
+#define PCICONF(x) (0x010000 + ((x) * 0x4))
+#define PMCAP(x) (0x010040 + ((x) * 0x4))
+#define EXPCAP(x) (0x010070 + ((x) * 0x4))
+#define VCCAP(x) (0x010100 + ((x) * 0x4))
+
+/* link layer */
+#define IDSETR1 0x011004
+#define TLCTLR 0x011048
+#define MACSR 0x011054
+#define SPCHGFIN BIT(4)
+#define SPCHGFAIL BIT(6)
+#define SPCHGSUC BIT(7)
+#define LINK_SPEED (0xf << 16)
+#define LINK_SPEED_2_5GTS (1 << 16)
+#define LINK_SPEED_5_0GTS (2 << 16)
+#define MACCTLR 0x011058
+#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */
+#define SPEED_CHANGE BIT(24)
+#define SCRAMBLE_DISABLE BIT(27)
+#define LTSMDIS BIT(31)
+#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK)
+#define PMSR 0x01105c
+#define MACS2R 0x011078
+#define MACCGSPSETR 0x011084
+#define SPCNGRSN BIT(31)
+
+/* R-Car H1 PHY */
+#define H1_PCIEPHYADRR 0x04000c
+#define WRITE_CMD BIT(16)
+#define PHY_ACK BIT(24)
+#define RATE_POS 12
+#define LANE_POS 8
+#define ADR_POS 0
+#define H1_PCIEPHYDOUTR 0x040014
+
+/* R-Car Gen2 PHY */
+#define GEN2_PCIEPHYADDR 0x780
+#define GEN2_PCIEPHYDATA 0x784
+#define GEN2_PCIEPHYCTRL 0x78c
+
+#define INT_PCI_MSI_NR 32
+
+#define RCONF(x) (PCICONF(0) + (x))
+#define RPMCAP(x) (PMCAP(0) + (x))
+#define REXPCAP(x) (EXPCAP(0) + (x))
+#define RVCCAP(x) (VCCAP(0) + (x))
+
+#define PCIE_CONF_BUS(b) (((b) & 0xff) << 24)
+#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
+#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
+
+#define RCAR_PCI_MAX_RESOURCES 4
+#define MAX_NR_INBOUND_MAPS 6
+
+enum {
+ RCAR_PCI_ACCESS_READ,
+ RCAR_PCI_ACCESS_WRITE,
+};
+
+void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int reg);
+u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg);
+void rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data);
+int rcar_pcie_wait_for_phyrdy(void __iomem *base);
+int rcar_pcie_wait_for_dl(void __iomem *base);
+void rcar_pcie_set_outbound(int win, void __iomem *base, struct resource *res);
+void rcar_pcie_set_inbound(void __iomem *base, u64 cpu_addr, u64 pci_addr,
+ u64 mask, int idx, bool host);
+
+#endif
--
2.7.4

2020-02-28 15:44:09

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 6/7] PCI: rcar: Add support for rcar PCIe controller in endpoint mode

This patch adds support for rcar PCIe controller to work in endpoint mode.

Signed-off-by: Lad Prabhakar <[email protected]>
---
drivers/pci/controller/Kconfig | 8 +
drivers/pci/controller/Makefile | 1 +
drivers/pci/controller/pcie-rcar-ep.c | 490 ++++++++++++++++++++++++++++++++++
drivers/pci/controller/pcie-rcar.h | 4 +
4 files changed, 503 insertions(+)
create mode 100644 drivers/pci/controller/pcie-rcar-ep.c

diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 37e0ea7..9bf4b02 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -62,6 +62,14 @@ config PCIE_RCAR_HOST
Say Y here if you want PCIe controller support on R-Car SoCs in host
mode.

+config PCIE_RCAR_EP
+ bool "Renesas R-Car PCIe endpoint controller"
+ depends on ARCH_RENESAS || COMPILE_TEST
+ depends on PCI_ENDPOINT
+ help
+ Say Y here if you want PCIe controller support on R-Car SoCs in
+ endpoint mode.
+
config PCI_HOST_COMMON
bool
select PCI_ECAM
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index b4ada32..067bd33 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
+obj-$(CONFIG_PCIE_RCAR_EP) += pcie-rcar.o pcie-rcar-ep.o
obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
diff --git a/drivers/pci/controller/pcie-rcar-ep.c b/drivers/pci/controller/pcie-rcar-ep.c
new file mode 100644
index 0000000..db89bbe
--- /dev/null
+++ b/drivers/pci/controller/pcie-rcar-ep.c
@@ -0,0 +1,490 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe endpoint driver for Renesas R-Car SoCs
+ * Copyright (c) 2020 Renesas Electronics Europe GmbH
+ *
+ * Author: Lad Prabhakar <[email protected]>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/pci-epc.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#include "pcie-rcar.h"
+
+/* Structure representing the PCIe interface */
+struct rcar_pcie {
+ phys_addr_t *ob_addr;
+ struct pci_epc_mem_window *ob_window;
+ struct pci_epc *epc;
+ struct device *dev;
+ void __iomem *base;
+ u8 max_functions;
+ unsigned int bar_to_atu[MAX_NR_INBOUND_MAPS];
+ unsigned long *ib_window_map;
+ u32 num_ib_windows;
+ u32 num_ob_windows;
+};
+
+static void rcar_pcie_ep_hw_init(struct rcar_pcie *pcie)
+{
+ u32 val;
+
+ rcar_pci_write_reg(pcie->base, 0, PCIETCTLR);
+
+ /* Set endpoint mode */
+ rcar_pci_write_reg(pcie->base, 0, PCIEMSR);
+
+ /* Initialize default capabilities. */
+ rcar_rmw32(pcie->base, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_FLAGS),
+ PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ENDPOINT << 4);
+ rcar_rmw32(pcie->base, RCONF(PCI_HEADER_TYPE), 0x7f,
+ PCI_HEADER_TYPE_NORMAL);
+
+ /* Write out the physical slot number = 0 */
+ rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
+
+ val = rcar_pci_read_reg(pcie->base, EXPCAP(1));
+ /* device supports fixed 128 bytes MPSS */
+ val &= ~GENMASK(2, 0);
+ rcar_pci_write_reg(pcie->base, val, EXPCAP(1));
+
+ val = rcar_pci_read_reg(pcie->base, EXPCAP(2));
+ /* read requests size 128 bytes */
+ val &= ~GENMASK(14, 12);
+ /* payload size 128 bytes */
+ val &= ~GENMASK(7, 5);
+ rcar_pci_write_reg(pcie->base, val, EXPCAP(2));
+
+ /* Set target link speed to 5.0 GT/s */
+ rcar_rmw32(pcie->base, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
+ PCI_EXP_LNKSTA_CLS_5_0GB);
+
+ /* Set the completion timer timeout to the maximum 50ms. */
+ rcar_rmw32(pcie->base, TLCTLR + 1, 0x3f, 50);
+
+ /* Terminate list of capabilities (Next Capability Offset=0) */
+ rcar_rmw32(pcie->base, RVCCAP(0), 0xfff00000, 0);
+
+ /* flush modifications */
+ wmb();
+}
+
+static int rcar_pcie_ep_get_window(struct rcar_pcie *pcie, phys_addr_t addr)
+{
+ int i;
+
+ for (i = 0; i < pcie->num_ob_windows; i++)
+ if (pcie->ob_window[i].phys_base == addr)
+ return i;
+
+ return -EINVAL;
+}
+
+static int rcar_pcie_parse_outbound_ranges(struct rcar_pcie *pcie,
+ struct platform_device *pdev)
+{
+ char outbound_name[10];
+ struct resource *res;
+ unsigned int i = 0;
+
+ pcie->num_ob_windows = 0;
+ for (i = 0; i < RCAR_PCI_MAX_RESOURCES; i++) {
+ sprintf(outbound_name, "memory%u", i);
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM,
+ outbound_name);
+ if (!res) {
+ dev_err(pcie->dev, "missing outbound window %u\n", i);
+ return -EINVAL;
+ }
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res),
+ outbound_name)) {
+ dev_err(pcie->dev, "Cannot request memory region %s.\n",
+ outbound_name);
+ return -EIO;
+ }
+
+ pcie->ob_window[i].phys_base = res->start;
+ pcie->ob_window[i].size = resource_size(res);
+ /* controller doesn't support multiple allocation
+ * from same window, so set page_size to window size
+ */
+ pcie->ob_window[i].page_size = resource_size(res);
+ }
+ pcie->num_ob_windows = i;
+
+ return 0;
+}
+
+static int rcar_pcie_ep_get_pdata(struct rcar_pcie *pcie,
+ struct platform_device *pdev)
+{
+ struct pci_epc_mem_window *window;
+ struct device *dev = pcie->dev;
+ struct resource res;
+ int err;
+
+ err = of_address_to_resource(dev->of_node, 0, &res);
+ if (err)
+ return err;
+ pcie->base = devm_ioremap_resource(dev, &res);
+ if (IS_ERR(pcie->base))
+ return PTR_ERR(pcie->base);
+
+ pcie->ob_window = devm_kcalloc(dev, RCAR_PCI_MAX_RESOURCES,
+ sizeof(*window), GFP_KERNEL);
+ if (!pcie->ob_window)
+ return -ENOMEM;
+
+ rcar_pcie_parse_outbound_ranges(pcie, pdev);
+
+ err = of_property_read_u8(dev->of_node, "max-functions",
+ &pcie->max_functions);
+ if (err < 0)
+ pcie->max_functions = 1;
+
+ return 0;
+}
+
+static int rcar_pcie_ep_write_header(struct pci_epc *epc, u8 fn,
+ struct pci_epf_header *hdr)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+ u32 val;
+
+ if (!fn)
+ val = hdr->vendorid;
+ else
+ val = rcar_pci_read_reg(ep->base, IDSETR0);
+ val |= hdr->deviceid << 16;
+ rcar_pci_write_reg(ep->base, val, IDSETR0);
+
+ val = hdr->revid;
+ val |= hdr->progif_code << 8;
+ val |= hdr->subclass_code << 16;
+ val |= hdr->baseclass_code << 24;
+ rcar_pci_write_reg(ep->base, val, IDSETR1);
+
+ if (!fn)
+ val = hdr->subsys_vendor_id;
+ else
+ val = rcar_pci_read_reg(ep->base, SUBIDSETR);
+ val |= hdr->subsys_id << 16;
+ rcar_pci_write_reg(ep->base, val, SUBIDSETR);
+
+ if (hdr->interrupt_pin > PCI_INTERRUPT_INTA)
+ return -EINVAL;
+ val = rcar_pci_read_reg(ep->base, PCICONF(15));
+ val |= (hdr->interrupt_pin << 8);
+ rcar_pci_write_reg(ep->base, val, PCICONF(15));
+
+ return 0;
+}
+
+static int rcar_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no,
+ struct pci_epf_bar *epf_bar)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+ dma_addr_t cpu_addr = epf_bar->phys_addr;
+ int flags = epf_bar->flags | LAR_ENABLE | LAM_64BIT;
+ enum pci_barno bar = epf_bar->barno;
+ u64 size = 1ULL << fls64(epf_bar->size - 1);
+ u32 mask;
+ int idx;
+ int err;
+
+ idx = find_first_zero_bit(ep->ib_window_map, ep->num_ib_windows);
+ if (idx >= ep->num_ib_windows) {
+ dev_err(ep->dev, "no free inbound window\n");
+ return -EINVAL;
+ }
+
+ if ((flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+ flags |= IO_SPACE;
+
+ ep->bar_to_atu[bar] = idx;
+ /* use 64 bit bars */
+ set_bit(idx, ep->ib_window_map);
+ set_bit(idx + 1, ep->ib_window_map);
+
+ if (cpu_addr > 0) {
+ unsigned long nr_zeros = __ffs64(cpu_addr);
+ u64 alignment = 1ULL << nr_zeros;
+
+ size = min(size, alignment);
+ }
+
+ size = min(size, 1ULL << 32);
+
+ mask = roundup_pow_of_two(size) - 1;
+ mask &= ~0xf;
+
+ rcar_pcie_set_inbound(ep->base, cpu_addr,
+ 0x0, mask | flags, idx, false);
+
+ err = rcar_pcie_wait_for_phyrdy(ep->base);
+ if (err) {
+ dev_err(ep->dev, "phy not ready\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void rcar_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn,
+ struct pci_epf_bar *epf_bar)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+ enum pci_barno bar = epf_bar->barno;
+ u32 atu_index = ep->bar_to_atu[bar];
+
+ rcar_pcie_set_inbound(ep->base, 0x0, 0x0, 0x0, bar, false);
+
+ clear_bit(atu_index, ep->ib_window_map);
+ clear_bit(atu_index + 1, ep->ib_window_map);
+}
+
+static int rcar_pcie_ep_map_addr(struct pci_epc *epc, u8 fn,
+ phys_addr_t addr, u64 pci_addr, size_t size)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+ struct resource res;
+ int window;
+ int err;
+
+ /* check if we have a link. */
+ err = rcar_pcie_wait_for_dl(ep->base);
+ if (err) {
+ dev_err(ep->dev, "link not up\n");
+ return err;
+ }
+
+ window = rcar_pcie_ep_get_window(ep, addr);
+ if (window < 0) {
+ dev_err(ep->dev, "failed to get corresponding window\n");
+ return -EINVAL;
+ }
+
+ memset(&res, 0x0, sizeof(res));
+ res.start = pci_addr;
+ res.end = pci_addr + size - 1;
+ res.flags = IORESOURCE_MEM;
+
+ rcar_pcie_set_outbound(window, ep->base, &res);
+
+ ep->ob_addr[window] = addr;
+
+ return 0;
+}
+
+static void rcar_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn,
+ phys_addr_t addr)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+ struct resource res;
+ int idx;
+
+ for (idx = 0; idx < ep->num_ob_windows; idx++)
+ if (ep->ob_addr[idx] == addr)
+ break;
+
+ if (idx >= ep->num_ob_windows)
+ return;
+
+ memset(&res, 0x0, sizeof(res));
+ rcar_pcie_set_outbound(idx, ep->base, &res);
+
+ ep->ob_addr[idx] = 0;
+}
+
+static int rcar_pcie_ep_assert_intx(struct rcar_pcie *ep, u8 fn, u8 intx)
+{
+ u32 val;
+
+ val = rcar_pci_read_reg(ep->base, PCIEMSITXR);
+ if ((val & PCI_MSI_FLAGS_ENABLE)) {
+ dev_err(ep->dev, "MSI is enabled, cannot assert INTx\n");
+ return -EINVAL;
+ }
+
+ val = rcar_pci_read_reg(ep->base, PCICONF(1));
+ if ((val & INTDIS_SHIFT)) {
+ dev_err(ep->dev, "INTx message transmission is disabled\n");
+ return -EINVAL;
+ }
+
+ val = rcar_pci_read_reg(ep->base, PCIEINTXR);
+ if ((val & ASTINTX_SHIFT)) {
+ dev_err(ep->dev, "INTx is already asserted\n");
+ return -EINVAL;
+ }
+
+ val |= ASTINTX_SHIFT;
+ rcar_pci_write_reg(ep->base, val, PCIEINTXR);
+ mdelay(1);
+ val = rcar_pci_read_reg(ep->base, PCIEINTXR);
+ val &= ~ASTINTX_SHIFT;
+ rcar_pci_write_reg(ep->base, val, PCIEINTXR);
+
+ return 0;
+}
+
+static int rcar_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn,
+ enum pci_epc_irq_type type,
+ u16 interrupt_num)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+
+ switch (type) {
+ case PCI_EPC_IRQ_LEGACY:
+ return rcar_pcie_ep_assert_intx(ep, fn, 0);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int rcar_pcie_ep_start(struct pci_epc *epc)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+
+ rcar_pci_write_reg(ep->base, CFINIT, PCIETCTLR);
+
+ return 0;
+}
+
+static void rcar_pcie_ep_stop(struct pci_epc *epc)
+{
+ struct rcar_pcie *ep = epc_get_drvdata(epc);
+
+ rcar_pci_write_reg(ep->base, 0, PCIETCTLR);
+}
+
+static const struct pci_epc_features rcar_pcie_epc_features = {
+ .linkup_notifier = false,
+ .msi_capable = false,
+ .msix_capable = false,
+ /* use 64-bit bars so mark bar1/3/5 as reserved */
+ .reserved_bar = 1 << BAR_1 | 1 << BAR_3 | 1 << BAR_5,
+ .bar_fixed_64bit = (1 << BAR_0) | (1 << BAR_2) | (1 << BAR_4),
+ .bar_fixed_size[0] = 128,
+ .bar_fixed_size[2] = 256,
+ .bar_fixed_size[4] = 256,
+};
+
+static const struct pci_epc_features*
+rcar_pcie_ep_get_features(struct pci_epc *epc, u8 func_no)
+{
+ return &rcar_pcie_epc_features;
+}
+
+static const struct pci_epc_ops rcar_pcie_epc_ops = {
+ .write_header = rcar_pcie_ep_write_header,
+ .set_bar = rcar_pcie_ep_set_bar,
+ .clear_bar = rcar_pcie_ep_clear_bar,
+ .map_addr = rcar_pcie_ep_map_addr,
+ .unmap_addr = rcar_pcie_ep_unmap_addr,
+ .raise_irq = rcar_pcie_ep_raise_irq,
+ .start = rcar_pcie_ep_start,
+ .stop = rcar_pcie_ep_stop,
+ .get_features = rcar_pcie_ep_get_features,
+};
+
+static const struct of_device_id rcar_pcie_ep_of_match[] = {
+ { .compatible = "renesas,r8a774c0-pcie-ep", },
+ { .compatible = "renesas,rcar-gen3-pcie-ep" },
+ { },
+};
+
+static int rcar_pcie_ep_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rcar_pcie *pcie;
+ struct pci_epc *epc;
+ int err;
+
+ pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+ if (!pcie)
+ return -ENOMEM;
+
+ pcie->dev = dev;
+
+ pm_runtime_enable(pcie->dev);
+ err = pm_runtime_get_sync(pcie->dev);
+ if (err < 0) {
+ dev_err(pcie->dev, "pm_runtime_get_sync failed\n");
+ goto err_pm_disable;
+ }
+
+ err = rcar_pcie_ep_get_pdata(pcie, pdev);
+ if (err < 0) {
+ dev_err(dev, "failed to request resources: %d\n", err);
+ goto err_pm_put;
+ }
+
+ pcie->num_ib_windows = MAX_NR_INBOUND_MAPS;
+ pcie->ib_window_map =
+ devm_kcalloc(dev, BITS_TO_LONGS(pcie->num_ib_windows),
+ sizeof(long), GFP_KERNEL);
+ if (!pcie->ib_window_map) {
+ err = -ENOMEM;
+ dev_err(dev, "failed to allocate memory for inbound map\n");
+ goto err_pm_put;
+ }
+
+ pcie->ob_addr = devm_kcalloc(dev, pcie->num_ob_windows,
+ sizeof(*pcie->ob_addr), GFP_KERNEL);
+ if (!pcie->ob_addr) {
+ err = -ENOMEM;
+ dev_err(dev, "failed to allocate memory for outbound memory pointers\n");
+ goto err_pm_put;
+ }
+
+ epc = devm_pci_epc_create(dev, &rcar_pcie_epc_ops);
+ if (IS_ERR(epc)) {
+ dev_err(dev, "failed to create epc device\n");
+ err = PTR_ERR(epc);
+ goto err_pm_put;
+ }
+
+ epc->max_functions = pcie->max_functions;
+ pcie->epc = epc;
+ epc_set_drvdata(epc, pcie);
+
+ err = pci_epc_mem_init(epc, pcie->ob_window, pcie->num_ob_windows);
+ if (err < 0) {
+ dev_err(dev, "failed to initialize the epc memory space\n");
+ goto err_pm_put;
+ }
+
+ rcar_pcie_ep_hw_init(pcie);
+
+ return 0;
+
+err_pm_put:
+ pm_runtime_put(dev);
+
+err_pm_disable:
+ pm_runtime_disable(dev);
+
+ return err;
+}
+
+static struct platform_driver rcar_pcie_ep_driver = {
+ .driver = {
+ .name = "rcar-pcie-ep",
+ .of_match_table = rcar_pcie_ep_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = rcar_pcie_ep_probe,
+};
+builtin_platform_driver(rcar_pcie_ep_driver);
diff --git a/drivers/pci/controller/pcie-rcar.h b/drivers/pci/controller/pcie-rcar.h
index b529d806..5564ca8 100644
--- a/drivers/pci/controller/pcie-rcar.h
+++ b/drivers/pci/controller/pcie-rcar.h
@@ -17,6 +17,7 @@
#define PCIECDR 0x000020
#define PCIEMSR 0x000028
#define PCIEINTXR 0x000400
+#define ASTINTX_SHIFT BIT(16)
#define PCIEPHYSR 0x0007f0
#define PHYRDY BIT(0)
#define PCIEMSITXR 0x000840
@@ -55,12 +56,15 @@

/* Configuration */
#define PCICONF(x) (0x010000 + ((x) * 0x4))
+#define INTDIS_SHIFT BIT(10)
#define PMCAP(x) (0x010040 + ((x) * 0x4))
#define EXPCAP(x) (0x010070 + ((x) * 0x4))
#define VCCAP(x) (0x010100 + ((x) * 0x4))

/* link layer */
+#define IDSETR0 0x011000
#define IDSETR1 0x011004
+#define SUBIDSETR 0x011024
#define TLCTLR 0x011048
#define MACSR 0x011054
#define SPCHGFIN BIT(4)
--
2.7.4

2020-02-28 15:44:12

by Prabhakar

[permalink] [raw]
Subject: [PATCH v5 7/7] misc: pci_endpoint_test: Add Device ID for RZ/G2E PCIe controller

Add RZ/G2E in pci_device_id table so that pci-epf-test can be used for
testing PCIe EP in RZ/G2E.

Signed-off-by: Lad Prabhakar <[email protected]>
---
drivers/misc/pci_endpoint_test.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
index a5e3170..3c84e9a 100644
--- a/drivers/misc/pci_endpoint_test.c
+++ b/drivers/misc/pci_endpoint_test.c
@@ -66,6 +66,8 @@

#define PCI_DEVICE_ID_TI_AM654 0xb00c

+#define PCI_DEVICE_ID_RENESAS_RZG2E 0x002d
+
#define is_am654_pci_dev(pdev) \
((pdev)->device == PCI_DEVICE_ID_TI_AM654)

@@ -797,6 +799,7 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
.driver_data = (kernel_ulong_t)&am654_data
},
+ { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_RZG2E) },
{ }
};
MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
--
2.7.4

2020-03-13 15:48:45

by Prabhakar

[permalink] [raw]
Subject: Re: [PATCH v5 0/7] Add support for PCIe controller to work in endpoint mode on R-Car SoCs

Hi Bjorn/Kishon,

On Fri, Feb 28, 2020 at 3:41 PM Lad Prabhakar
<[email protected]> wrote:
>
> This patch series adds support for PCIe controller on rcar to work in
> endpoint mode, this also extends the epf framework to handle base region
> for mapping PCI address locally.
>
> Note:
> The cadence/rockchip/designware endpoint drivers are build tested only.
>
> Changes for v5:
> 1] Rebased the patches on next branch of https://git.kernel.org/pub/scm/
> linux/kernel/git/helgaas/pci.git
> 2] Fixed review comments reported by Kishon while fetching the matching
> window in function pci_epc_get_matching_window()
> 3] Fixed review comments reported by Bjorn
> a] Split patch up first patch so that its easier to review and incremental
> b] Fixed typos
> 4] Included Reviewed tag from Rob for the dt-binding patch
> 5] Fixed issue reported by Nathan for assigning variable to itself
>
> Changes for v4:
> 1] Fixed dtb_check error reported by Rob
> 2] Fixed review comments reported by Kishon
> a] Dropped pci_epc_find_best_fit_window()
> b] Fixed initializing mem ptr in __pci_epc_mem_init()
> c] Dropped map_size from pci_epc_mem_window structure
>
> Changes for v3:
> 1] Fixed review comments from Bjorn and Kishon.
> 3] Converted to DT schema
>
> Changes for v2:
> 1] Fixed review comments from Biju for dt-bindings to include an example
> for a tested platform.
> 2] Fixed review comments from Kishon to extend the features of outbound
> regions in epf framework.
> 3] Added support to parse outbound-ranges in OF.
>
> Lad Prabhakar (7):
> PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c
> PCI: rcar: Move shareable code to a common file
> PCI: rcar: Fix calculating mask for PCIEPAMR register
> PCI: endpoint: Add support to handle multiple base for mapping
> outbound memory
> dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint
> controller
> PCI: rcar: Add support for rcar PCIe controller in endpoint mode
> misc: pci_endpoint_test: Add Device ID for RZ/G2E PCIe controller
>
Gentle ping.

Cheers,
--Prabhakar Lad

> .../devicetree/bindings/pci/rcar-pci-ep.yaml | 76 ++
> arch/arm64/configs/defconfig | 2 +-
> drivers/misc/pci_endpoint_test.c | 3 +
> drivers/pci/controller/Kconfig | 15 +-
> drivers/pci/controller/Makefile | 3 +-
> drivers/pci/controller/cadence/pcie-cadence-ep.c | 7 +-
> drivers/pci/controller/dwc/pcie-designware-ep.c | 29 +-
> drivers/pci/controller/pcie-rcar-ep.c | 490 ++++++++
> drivers/pci/controller/pcie-rcar-host.c | 1053 +++++++++++++++++
> drivers/pci/controller/pcie-rcar.c | 1229 +-------------------
> drivers/pci/controller/pcie-rcar.h | 129 ++
> drivers/pci/controller/pcie-rockchip-ep.c | 7 +-
> drivers/pci/endpoint/pci-epc-mem.c | 167 ++-
> include/linux/pci-epc.h | 39 +-
> 14 files changed, 1985 insertions(+), 1264 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/pci/rcar-pci-ep.yaml
> create mode 100644 drivers/pci/controller/pcie-rcar-ep.c
> create mode 100644 drivers/pci/controller/pcie-rcar-host.c
> create mode 100644 drivers/pci/controller/pcie-rcar.h
>
> --
> 2.7.4
>

2020-03-16 12:20:05

by Lorenzo Pieralisi

[permalink] [raw]
Subject: Re: [PATCH v5 0/7] Add support for PCIe controller to work in endpoint mode on R-Car SoCs

On Fri, Mar 13, 2020 at 03:46:42PM +0000, Lad, Prabhakar wrote:
> Hi Bjorn/Kishon,
>
> On Fri, Feb 28, 2020 at 3:41 PM Lad Prabhakar
> <[email protected]> wrote:
> >
> > This patch series adds support for PCIe controller on rcar to work in
> > endpoint mode, this also extends the epf framework to handle base region
> > for mapping PCI address locally.
> >
> > Note:
> > The cadence/rockchip/designware endpoint drivers are build tested only.
> >
> > Changes for v5:
> > 1] Rebased the patches on next branch of https://git.kernel.org/pub/scm/
> > linux/kernel/git/helgaas/pci.git
> > 2] Fixed review comments reported by Kishon while fetching the matching
> > window in function pci_epc_get_matching_window()
> > 3] Fixed review comments reported by Bjorn
> > a] Split patch up first patch so that its easier to review and incremental
> > b] Fixed typos
> > 4] Included Reviewed tag from Rob for the dt-binding patch
> > 5] Fixed issue reported by Nathan for assigning variable to itself
> >
> > Changes for v4:
> > 1] Fixed dtb_check error reported by Rob
> > 2] Fixed review comments reported by Kishon
> > a] Dropped pci_epc_find_best_fit_window()
> > b] Fixed initializing mem ptr in __pci_epc_mem_init()
> > c] Dropped map_size from pci_epc_mem_window structure
> >
> > Changes for v3:
> > 1] Fixed review comments from Bjorn and Kishon.
> > 3] Converted to DT schema
> >
> > Changes for v2:
> > 1] Fixed review comments from Biju for dt-bindings to include an example
> > for a tested platform.
> > 2] Fixed review comments from Kishon to extend the features of outbound
> > regions in epf framework.
> > 3] Added support to parse outbound-ranges in OF.
> >
> > Lad Prabhakar (7):
> > PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c
> > PCI: rcar: Move shareable code to a common file
> > PCI: rcar: Fix calculating mask for PCIEPAMR register
> > PCI: endpoint: Add support to handle multiple base for mapping
> > outbound memory
> > dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint
> > controller
> > PCI: rcar: Add support for rcar PCIe controller in endpoint mode
> > misc: pci_endpoint_test: Add Device ID for RZ/G2E PCIe controller
> >
> Gentle ping.

You should ask the R-CAR maintainers first to have a look at your
code and ACK accordingly.

Lorenzo

2020-03-16 12:34:58

by Prabhakar

[permalink] [raw]
Subject: Re: [PATCH v5 0/7] Add support for PCIe controller to work in endpoint mode on R-Car SoCs

Hi Lorenzo,

On Mon, Mar 16, 2020 at 12:19 PM Lorenzo Pieralisi
<[email protected]> wrote:
>
> On Fri, Mar 13, 2020 at 03:46:42PM +0000, Lad, Prabhakar wrote:
> > Hi Bjorn/Kishon,
> >
> > On Fri, Feb 28, 2020 at 3:41 PM Lad Prabhakar
> > <[email protected]> wrote:
> > >
> > > This patch series adds support for PCIe controller on rcar to work in
> > > endpoint mode, this also extends the epf framework to handle base region
> > > for mapping PCI address locally.
> > >
> > > Note:
> > > The cadence/rockchip/designware endpoint drivers are build tested only.
> > >
> > > Changes for v5:
> > > 1] Rebased the patches on next branch of https://git.kernel.org/pub/scm/
> > > linux/kernel/git/helgaas/pci.git
> > > 2] Fixed review comments reported by Kishon while fetching the matching
> > > window in function pci_epc_get_matching_window()
> > > 3] Fixed review comments reported by Bjorn
> > > a] Split patch up first patch so that its easier to review and incremental
> > > b] Fixed typos
> > > 4] Included Reviewed tag from Rob for the dt-binding patch
> > > 5] Fixed issue reported by Nathan for assigning variable to itself
> > >
> > > Changes for v4:
> > > 1] Fixed dtb_check error reported by Rob
> > > 2] Fixed review comments reported by Kishon
> > > a] Dropped pci_epc_find_best_fit_window()
> > > b] Fixed initializing mem ptr in __pci_epc_mem_init()
> > > c] Dropped map_size from pci_epc_mem_window structure
> > >
> > > Changes for v3:
> > > 1] Fixed review comments from Bjorn and Kishon.
> > > 3] Converted to DT schema
> > >
> > > Changes for v2:
> > > 1] Fixed review comments from Biju for dt-bindings to include an example
> > > for a tested platform.
> > > 2] Fixed review comments from Kishon to extend the features of outbound
> > > regions in epf framework.
> > > 3] Added support to parse outbound-ranges in OF.
> > >
> > > Lad Prabhakar (7):
> > > PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c
> > > PCI: rcar: Move shareable code to a common file
> > > PCI: rcar: Fix calculating mask for PCIEPAMR register
> > > PCI: endpoint: Add support to handle multiple base for mapping
> > > outbound memory
> > > dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint
> > > controller
> > > PCI: rcar: Add support for rcar PCIe controller in endpoint mode
> > > misc: pci_endpoint_test: Add Device ID for RZ/G2E PCIe controller
> > >
> > Gentle ping.
>
> You should ask the R-CAR maintainers first to have a look at your
> code and ACK accordingly.
>
Thanks I have pinged the R-CAR maintainers to do the needy.

Cheers,
--Prabhakar

2020-03-17 07:00:01

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 1/7] PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c

Hi Prabhakar-san,

Thank you for the patch!

> From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM

Since your email account is different with the Singed-off-by,
I think you should add your From: tag here like your v2 patch series.

> This commit renames pcie-rcar.c to pcie-rcar-host.c in preparation for
> adding support for endpoint mode. CONFIG_PCIE_RCAR is also renamed to
> CONFIG_PCIE_RCAR_HOST to match the driver name accordingly.
>
> In addition to this defconfig file has also been updated to match the new
> config option.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> ---
> arch/arm64/configs/defconfig | 2 +-
> drivers/pci/controller/Kconfig | 7 ++++---
> drivers/pci/controller/Makefile | 2 +-
> drivers/pci/controller/{pcie-rcar.c => pcie-rcar-host.c} | 0
> 4 files changed, 6 insertions(+), 5 deletions(-)
> rename drivers/pci/controller/{pcie-rcar.c => pcie-rcar-host.c} (100%)
>
> diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
> index 0f21288..7a34fce 100644
> --- a/arch/arm64/configs/defconfig
> +++ b/arch/arm64/configs/defconfig
> @@ -185,7 +185,7 @@ CONFIG_HOTPLUG_PCI=y
> CONFIG_HOTPLUG_PCI_ACPI=y
> CONFIG_PCI_AARDVARK=y
> CONFIG_PCI_TEGRA=y
> -CONFIG_PCIE_RCAR=y
> +CONFIG_PCIE_RCAR_HOST=y

I think you should separate this change.
To avoid this, I have an idea in the Kconfig like below:
- adding PCIE_RCAR_HOST.
- keeping PCIE_RCAR and select PCIE_RCAR_HOST here.
- adding a description in the help of PCIE_RCAR like "This will be removed after defconfig is updated" is better.

The following is a sample. What do you think?
---
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -58,8 +58,18 @@ config PCIE_RCAR
bool "Renesas R-Car PCIe controller"
depends on ARCH_RENESAS || COMPILE_TEST
depends on PCI_MSI_IRQ_DOMAIN
+ select PCIE_RCAR_HOST
help
Say Y here if you want PCIe controller support on R-Car SoCs.
+ This will be removed after defconfig is updated.
+
+config PCIE_RCAR_HOST
+ bool "Renesas R-Car PCIe host controller"
+ depends on ARCH_RENESAS || COMPILE_TEST
+ depends on PCI_MSI_IRQ_DOMAIN
+ help
+ Say Y here if you want PCIe controller support on R-Car SoCs in host
+ mode.

config PCI_HOST_COMMON
bool
---

Best regards,
Yoshihiro Shimoda

> CONFIG_PCI_HOST_GENERIC=y
> CONFIG_PCI_XGENE=y
> CONFIG_PCIE_ALTERA=y
> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> index f84e5ff..37e0ea7 100644
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -54,12 +54,13 @@ config PCI_RCAR_GEN2
> There are 3 internal PCI controllers available with a single
> built-in EHCI/OHCI host controller present on each one.
>
> -config PCIE_RCAR
> - bool "Renesas R-Car PCIe controller"
> +config PCIE_RCAR_HOST
> + bool "Renesas R-Car PCIe host controller"
> depends on ARCH_RENESAS || COMPILE_TEST
> depends on PCI_MSI_IRQ_DOMAIN
> help
> - Say Y here if you want PCIe controller support on R-Car SoCs.
> + Say Y here if you want PCIe controller support on R-Car SoCs in host
> + mode.
>
> config PCI_HOST_COMMON
> bool
> diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
> index 01b2502..4ca2da6 100644
> --- a/drivers/pci/controller/Makefile
> +++ b/drivers/pci/controller/Makefile
> @@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
> obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> -obj-$(CONFIG_PCIE_RCAR) += pcie-rcar.o
> +obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar-host.o
> obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
> obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
> obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
> diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar-host.c
> similarity index 100%
> rename from drivers/pci/controller/pcie-rcar.c
> rename to drivers/pci/controller/pcie-rcar-host.c
> --
> 2.7.4

2020-03-17 07:27:04

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 2/7] PCI: rcar: Move shareable code to a common file

Hi Prabhakar-san,

Thank you for the patch!

> From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
>
> This patch moves sharable code to common file pcie-rcar.c and the #defines
> to pcie-rcar.h so that the common code can be reused with endpoint driver.
> There are no functional changes with this patch for the host controller
> driver.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> ---
> drivers/pci/controller/Makefile | 2 +-
> drivers/pci/controller/pcie-rcar-host.c | 358 ++++++++------------------------
> drivers/pci/controller/pcie-rcar.c | 117 +++++++++++
> drivers/pci/controller/pcie-rcar.h | 125 +++++++++++
> 4 files changed, 324 insertions(+), 278 deletions(-)
> create mode 100644 drivers/pci/controller/pcie-rcar.c
> create mode 100644 drivers/pci/controller/pcie-rcar.h
>
> diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
> index 4ca2da6..b4ada32 100644
> --- a/drivers/pci/controller/Makefile
> +++ b/drivers/pci/controller/Makefile
> @@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
> obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> -obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar-host.o
> +obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
> obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
> obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
> obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
> diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
> index 759c654..93f22d8 100644
> --- a/drivers/pci/controller/pcie-rcar-host.c
> +++ b/drivers/pci/controller/pcie-rcar-host.c
> @@ -1,7 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0
> /*
> * PCIe driver for Renesas R-Car SoCs
> - * Copyright (C) 2014 Renesas Electronics Europe Ltd
> + * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
> *
> * Based on:
> * arch/sh/drivers/pci/pcie-sh7786.c
> @@ -30,104 +30,7 @@
> #include <linux/pm_runtime.h>
> #include <linux/slab.h>
>
> -#define PCIECAR 0x000010
> -#define PCIECCTLR 0x000018
> -#define CONFIG_SEND_ENABLE BIT(31)
> -#define TYPE0 (0 << 8)
> -#define TYPE1 BIT(8)
> -#define PCIECDR 0x000020
> -#define PCIEMSR 0x000028
> -#define PCIEINTXR 0x000400
> -#define PCIEPHYSR 0x0007f0
> -#define PHYRDY BIT(0)
> -#define PCIEMSITXR 0x000840
> -
> -/* Transfer control */
> -#define PCIETCTLR 0x02000
> -#define DL_DOWN BIT(3)
> -#define CFINIT BIT(0)
> -#define PCIETSTR 0x02004
> -#define DATA_LINK_ACTIVE BIT(0)
> -#define PCIEERRFR 0x02020
> -#define UNSUPPORTED_REQUEST BIT(4)
> -#define PCIEMSIFR 0x02044
> -#define PCIEMSIALR 0x02048
> -#define MSIFE BIT(0)
> -#define PCIEMSIAUR 0x0204c
> -#define PCIEMSIIER 0x02050
> -
> -/* root port address */
> -#define PCIEPRAR(x) (0x02080 + ((x) * 0x4))
> -
> -/* local address reg & mask */
> -#define PCIELAR(x) (0x02200 + ((x) * 0x20))
> -#define PCIELAMR(x) (0x02208 + ((x) * 0x20))
> -#define LAM_PREFETCH BIT(3)
> -#define LAM_64BIT BIT(2)
> -#define LAR_ENABLE BIT(1)
> -
> -/* PCIe address reg & mask */
> -#define PCIEPALR(x) (0x03400 + ((x) * 0x20))
> -#define PCIEPAUR(x) (0x03404 + ((x) * 0x20))
> -#define PCIEPAMR(x) (0x03408 + ((x) * 0x20))
> -#define PCIEPTCTLR(x) (0x0340c + ((x) * 0x20))
> -#define PAR_ENABLE BIT(31)
> -#define IO_SPACE BIT(8)
> -
> -/* Configuration */
> -#define PCICONF(x) (0x010000 + ((x) * 0x4))
> -#define PMCAP(x) (0x010040 + ((x) * 0x4))
> -#define EXPCAP(x) (0x010070 + ((x) * 0x4))
> -#define VCCAP(x) (0x010100 + ((x) * 0x4))
> -
> -/* link layer */
> -#define IDSETR1 0x011004
> -#define TLCTLR 0x011048
> -#define MACSR 0x011054
> -#define SPCHGFIN BIT(4)
> -#define SPCHGFAIL BIT(6)
> -#define SPCHGSUC BIT(7)
> -#define LINK_SPEED (0xf << 16)
> -#define LINK_SPEED_2_5GTS (1 << 16)
> -#define LINK_SPEED_5_0GTS (2 << 16)
> -#define MACCTLR 0x011058
> -#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */
> -#define SPEED_CHANGE BIT(24)
> -#define SCRAMBLE_DISABLE BIT(27)
> -#define LTSMDIS BIT(31)
> -#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK)
> -#define PMSR 0x01105c
> -#define MACS2R 0x011078
> -#define MACCGSPSETR 0x011084
> -#define SPCNGRSN BIT(31)
> -
> -/* R-Car H1 PHY */
> -#define H1_PCIEPHYADRR 0x04000c
> -#define WRITE_CMD BIT(16)
> -#define PHY_ACK BIT(24)
> -#define RATE_POS 12
> -#define LANE_POS 8
> -#define ADR_POS 0
> -#define H1_PCIEPHYDOUTR 0x040014
> -
> -/* R-Car Gen2 PHY */
> -#define GEN2_PCIEPHYADDR 0x780
> -#define GEN2_PCIEPHYDATA 0x784
> -#define GEN2_PCIEPHYCTRL 0x78c
> -
> -#define INT_PCI_MSI_NR 32
> -
> -#define RCONF(x) (PCICONF(0) + (x))
> -#define RPMCAP(x) (PMCAP(0) + (x))
> -#define REXPCAP(x) (EXPCAP(0) + (x))
> -#define RVCCAP(x) (VCCAP(0) + (x))
> -
> -#define PCIE_CONF_BUS(b) (((b) & 0xff) << 24)
> -#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
> -#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
> -
> -#define RCAR_PCI_MAX_RESOURCES 4
> -#define MAX_NR_INBOUND_MAPS 6
> +#include "pcie-rcar.h"
>
> struct rcar_msi {
> DECLARE_BITMAP(used, INT_PCI_MSI_NR);
> @@ -155,36 +58,10 @@ struct rcar_pcie {
> struct rcar_msi msi;
> };
>
> -static void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val,
> - unsigned int reg)
> -{
> - writel(val, pcie->base + reg);
> -}
> -
> -static u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int reg)
> -{
> - return readl(pcie->base + reg);
> -}
> -
> -enum {
> - RCAR_PCI_ACCESS_READ,
> - RCAR_PCI_ACCESS_WRITE,
> -};
> -
> -static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data)
> -{
> - unsigned int shift = BITS_PER_BYTE * (where & 3);
> - u32 val = rcar_pci_read_reg(pcie, where & ~3);
> -
> - val &= ~(mask << shift);
> - val |= data << shift;
> - rcar_pci_write_reg(pcie, val, where & ~3);
> -}
> -
> static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
> {
> unsigned int shift = BITS_PER_BYTE * (where & 3);
> - u32 val = rcar_pci_read_reg(pcie, where & ~3);
> + u32 val = rcar_pci_read_reg(pcie->base, where & ~3);

I'd like to avoid these many changes about "pcie" to "pcie->base" somehow.
My idea is moving declaration of struct rcar_pcie to rcar-pcie.h and use it
from both host and ep codes. According to the patch 6/7, the rcar-pcie-ep.c
also has the same name of struct rcar_pcie and this has the same "base" and "dev.
So, common rcar_pcie should have these members. Remaining members are
contained on renamed structures like "rcar_pcie_host" and "rcar_pcie_ep".
And then, the rcar_pcie_{host,ep} have struct rcar_pcie pcie member.

Best regards,
Yoshihiro Shimoda

> return val >> shift;
> }
> @@ -221,13 +98,13 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> if (access_type == RCAR_PCI_ACCESS_READ) {
> - *data = rcar_pci_read_reg(pcie, PCICONF(index));
> + *data = rcar_pci_read_reg(pcie->base, PCICONF(index));
> } else {
> /* Keep an eye out for changes to the root bus number */
> if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS))
> pcie->root_bus_nr = *data & 0xff;
>
> - rcar_pci_write_reg(pcie, *data, PCICONF(index));
> + rcar_pci_write_reg(pcie->base, *data, PCICONF(index));
> }
>
> return PCIBIOS_SUCCESSFUL;
> @@ -237,20 +114,23 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> /* Clear errors */
> - rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
> + rcar_pci_write_reg(pcie->base, rcar_pci_read_reg(pcie->base, PCIEERRFR),
> + PCIEERRFR);
>
> /* Set the PIO address */
> - rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
> + rcar_pci_write_reg(pcie->base, PCIE_CONF_BUS(bus->number) |
> PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);
>
> /* Enable the configuration access */
> if (bus->parent->number == pcie->root_bus_nr)
> - rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
> + rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE | TYPE0,
> + PCIECCTLR);
> else
> - rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
> + rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE | TYPE1,
> + PCIECCTLR);
>
> /* Check for errors */
> - if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
> + if (rcar_pci_read_reg(pcie->base, PCIEERRFR) & UNSUPPORTED_REQUEST)
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> /* Check for master and target aborts */
> @@ -259,12 +139,12 @@ static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> if (access_type == RCAR_PCI_ACCESS_READ)
> - *data = rcar_pci_read_reg(pcie, PCIECDR);
> + *data = rcar_pci_read_reg(pcie->base, PCIECDR);
> else
> - rcar_pci_write_reg(pcie, *data, PCIECDR);
> + rcar_pci_write_reg(pcie->base, *data, PCIECDR);
>
> /* Disable the configuration access */
> - rcar_pci_write_reg(pcie, 0, PCIECCTLR);
> + rcar_pci_write_reg(pcie->base, 0, PCIECCTLR);
>
> return PCIBIOS_SUCCESSFUL;
> }
> @@ -332,41 +212,6 @@ static struct pci_ops rcar_pcie_ops = {
> .write = rcar_pcie_write_conf,
> };
>
> -static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
> - struct resource *res)
> -{
> - /* Setup PCIe address space mappings for each resource */
> - resource_size_t size;
> - resource_size_t res_start;
> - u32 mask;
> -
> - rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> -
> - /*
> - * The PAMR mask is calculated in units of 128Bytes, which
> - * keeps things pretty simple.
> - */
> - size = resource_size(res);
> - mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> - rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
> -
> - if (res->flags & IORESOURCE_IO)
> - res_start = pci_pio_to_address(res->start);
> - else
> - res_start = res->start;
> -
> - rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPAUR(win));
> - rcar_pci_write_reg(pcie, lower_32_bits(res_start) & ~0x7F,
> - PCIEPALR(win));
> -
> - /* First resource is for IO */
> - mask = PAR_ENABLE;
> - if (res->flags & IORESOURCE_IO)
> - mask |= IO_SPACE;
> -
> - rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
> -}
> -
> static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
> {
> struct resource_entry *win;
> @@ -382,7 +227,7 @@ static int rcar_pcie_setup(struct list_head *resource, struct rcar_pcie *pci)
> switch (resource_type(res)) {
> case IORESOURCE_IO:
> case IORESOURCE_MEM:
> - rcar_pcie_setup_window(i, pci, res);
> + rcar_pcie_set_outbound(i, pci->base, res);
> i++;
> break;
> case IORESOURCE_BUS:
> @@ -404,37 +249,38 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
> unsigned int timeout = 1000;
> u32 macsr;
>
> - if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) != LINK_SPEED_5_0GTS)
> + if ((rcar_pci_read_reg(pcie->base, MACS2R) & LINK_SPEED) !=
> + LINK_SPEED_5_0GTS)
> return;
>
> - if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) {
> + if (rcar_pci_read_reg(pcie->base, MACCTLR) & SPEED_CHANGE) {
> dev_err(dev, "Speed change already in progress\n");
> return;
> }
>
> - macsr = rcar_pci_read_reg(pcie, MACSR);
> + macsr = rcar_pci_read_reg(pcie->base, MACSR);
> if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS)
> goto done;
>
> /* Set target link speed to 5.0 GT/s */
> - rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
> + rcar_rmw32(pcie->base, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
> PCI_EXP_LNKSTA_CLS_5_0GB);
>
> /* Set speed change reason as intentional factor */
> - rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0);
> + rcar_rmw32(pcie->base, MACCGSPSETR, SPCNGRSN, 0);
>
> /* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */
> if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL))
> - rcar_pci_write_reg(pcie, macsr, MACSR);
> + rcar_pci_write_reg(pcie->base, macsr, MACSR);
>
> /* Start link speed change */
> - rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);
> + rcar_rmw32(pcie->base, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);
>
> while (timeout--) {
> - macsr = rcar_pci_read_reg(pcie, MACSR);
> + macsr = rcar_pci_read_reg(pcie->base, MACSR);
> if (macsr & SPCHGFIN) {
> /* Clear the interrupt bits */
> - rcar_pci_write_reg(pcie, macsr, MACSR);
> + rcar_pci_write_reg(pcie->base, macsr, MACSR);
>
> if (macsr & SPCHGFAIL)
> dev_err(dev, "Speed change failed\n");
> @@ -498,7 +344,7 @@ static int phy_wait_for_ack(struct rcar_pcie *pcie)
> unsigned int timeout = 100;
>
> while (timeout--) {
> - if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
> + if (rcar_pci_read_reg(pcie->base, H1_PCIEPHYADRR) & PHY_ACK)
> return 0;
>
> udelay(100);
> @@ -521,60 +367,31 @@ static void phy_write_reg(struct rcar_pcie *pcie,
> ((addr & 0xff) << ADR_POS);
>
> /* Set write data */
> - rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
> - rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
> + rcar_pci_write_reg(pcie->base, data, H1_PCIEPHYDOUTR);
> + rcar_pci_write_reg(pcie->base, phyaddr, H1_PCIEPHYADRR);
>
> /* Ignore errors as they will be dealt with if the data link is down */
> phy_wait_for_ack(pcie);
>
> /* Clear command */
> - rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
> - rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
> + rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYDOUTR);
> + rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYADRR);
>
> /* Ignore errors as they will be dealt with if the data link is down */
> phy_wait_for_ack(pcie);
> }
>
> -static int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie)
> -{
> - unsigned int timeout = 10;
> -
> - while (timeout--) {
> - if (rcar_pci_read_reg(pcie, PCIEPHYSR) & PHYRDY)
> - return 0;
> -
> - msleep(5);
> - }
> -
> - return -ETIMEDOUT;
> -}
> -
> -static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie)
> -{
> - unsigned int timeout = 10000;
> -
> - while (timeout--) {
> - if ((rcar_pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE))
> - return 0;
> -
> - udelay(5);
> - cpu_relax();
> - }
> -
> - return -ETIMEDOUT;
> -}
> -
> static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
> {
> int err;
>
> /* Begin initialization */
> - rcar_pci_write_reg(pcie, 0, PCIETCTLR);
> + rcar_pci_write_reg(pcie->base, 0, PCIETCTLR);
>
> /* Set mode */
> - rcar_pci_write_reg(pcie, 1, PCIEMSR);
> + rcar_pci_write_reg(pcie->base, 1, PCIEMSR);
>
> - err = rcar_pcie_wait_for_phyrdy(pcie);
> + err = rcar_pcie_wait_for_phyrdy(pcie->base);
> if (err)
> return err;
>
> @@ -583,51 +400,51 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
> * class to match. Hardware takes care of propagating the IDSETR
> * settings, so there is no need to bother with a quirk.
> */
> - rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
> + rcar_pci_write_reg(pcie->base, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
>
> /*
> * Setup Secondary Bus Number & Subordinate Bus Number, even though
> * they aren't used, to avoid bridge being detected as broken.
> */
> - rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
> - rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
> + rcar_rmw32(pcie->base, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
> + rcar_rmw32(pcie->base, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
>
> /* Initialize default capabilities. */
> - rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
> - rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
> - PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
> - rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
> - PCI_HEADER_TYPE_BRIDGE);
> + rcar_rmw32(pcie->base, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
> + rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_FLAGS),
> + PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
> + rcar_rmw32(pcie->base, RCONF(PCI_HEADER_TYPE), 0x7f,
> + PCI_HEADER_TYPE_BRIDGE);
>
> /* Enable data link layer active state reporting */
> - rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
> - PCI_EXP_LNKCAP_DLLLARC);
> + rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC,
> + PCI_EXP_LNKCAP_DLLLARC);
>
> /* Write out the physical slot number = 0 */
> - rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
> + rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0);
>
> /* Set the completion timer timeout to the maximum 50ms. */
> - rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50);
> + rcar_rmw32(pcie->base, TLCTLR + 1, 0x3f, 50);
>
> /* Terminate list of capabilities (Next Capability Offset=0) */
> - rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0);
> + rcar_rmw32(pcie->base, RVCCAP(0), 0xfff00000, 0);
>
> /* Enable MSI */
> if (IS_ENABLED(CONFIG_PCI_MSI))
> - rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR);
> + rcar_pci_write_reg(pcie->base, 0x801f0000, PCIEMSITXR);
>
> - rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
> + rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
>
> /* Finish initialization - establish a PCI Express link */
> - rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> + rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);
>
> /* This will timeout if we don't have a link. */
> - err = rcar_pcie_wait_for_dl(pcie);
> + err = rcar_pcie_wait_for_dl(pcie->base);
> if (err)
> return err;
>
> /* Enable INTx interrupts */
> - rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
> + rcar_rmw32(pcie->base, PCIEINTXR, 0, 0xF << 8);
>
> wmb();
>
> @@ -663,16 +480,16 @@ static int rcar_pcie_phy_init_gen2(struct rcar_pcie *pcie)
> * These settings come from the R-Car Series, 2nd Generation User's
> * Manual, section 50.3.1 (2) Initialization of the physical layer.
> */
> - rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR);
> - rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA);
> - rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
> - rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
> + rcar_pci_write_reg(pcie->base, 0x000f0030, GEN2_PCIEPHYADDR);
> + rcar_pci_write_reg(pcie->base, 0x00381203, GEN2_PCIEPHYDATA);
> + rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
> + rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);
>
> - rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR);
> + rcar_pci_write_reg(pcie->base, 0x000f0054, GEN2_PCIEPHYADDR);
> /* The following value is for DC connection, no termination resistor */
> - rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA);
> - rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
> - rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
> + rcar_pci_write_reg(pcie->base, 0x13802007, GEN2_PCIEPHYDATA);
> + rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
> + rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);
>
> return 0;
> }
> @@ -735,7 +552,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
> struct device *dev = pcie->dev;
> unsigned long reg;
>
> - reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
> + reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);
>
> /* MSI & INTx share an interrupt - we only handle MSI here */
> if (!reg)
> @@ -746,7 +563,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
> unsigned int msi_irq;
>
> /* clear the interrupt */
> - rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
> + rcar_pci_write_reg(pcie->base, 1 << index, PCIEMSIFR);
>
> msi_irq = irq_find_mapping(msi->domain, index);
> if (msi_irq) {
> @@ -760,7 +577,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void *data)
> }
>
> /* see if there's any more pending in this vector */
> - reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
> + reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);
> }
>
> return IRQ_HANDLED;
> @@ -787,8 +604,8 @@ static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
>
> irq_set_msi_desc(irq, desc);
>
> - msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
> - msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
> + msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) & ~MSIFE;
> + msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
> msg.data = hwirq;
>
> pci_write_msi_msg(irq, &msg);
> @@ -839,8 +656,8 @@ static int rcar_msi_setup_irqs(struct msi_controller *chip,
> desc->nvec_used = nvec;
> desc->msi_attrib.multiple = order_base_2(nvec);
>
> - msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
> - msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
> + msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) & ~MSIFE;
> + msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
> msg.data = hwirq;
>
> pci_write_msi_msg(irq, &msg);
> @@ -940,11 +757,11 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
> }
> base = virt_to_phys((void *)msi->pages);
>
> - rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR);
> - rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR);
> + rcar_pci_write_reg(pcie->base, lower_32_bits(base) | MSIFE, PCIEMSIALR);
> + rcar_pci_write_reg(pcie->base, upper_32_bits(base), PCIEMSIAUR);
>
> /* enable all MSI interrupts */
> - rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
> + rcar_pci_write_reg(pcie->base, 0xffffffff, PCIEMSIIER);
>
> return 0;
>
> @@ -958,10 +775,10 @@ static void rcar_pcie_teardown_msi(struct rcar_pcie *pcie)
> struct rcar_msi *msi = &pcie->msi;
>
> /* Disable all MSI interrupts */
> - rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
> + rcar_pci_write_reg(pcie->base, 0, PCIEMSIIER);
>
> /* Disable address decoding of the MSI interrupt, MSIFE */
> - rcar_pci_write_reg(pcie, 0, PCIEMSIALR);
> + rcar_pci_write_reg(pcie->base, 0, PCIEMSIALR);
>
> free_pages(msi->pages, 0);
>
> @@ -1054,21 +871,8 @@ static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie,
> mask = roundup_pow_of_two(size) - 1;
> mask &= ~0xf;
>
> - /*
> - * Set up 64-bit inbound regions as the range parser doesn't
> - * distinguish between 32 and 64-bit types.
> - */
> - rcar_pci_write_reg(pcie, lower_32_bits(pci_addr),
> - PCIEPRAR(idx));
> - rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx));
> - rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags,
> - PCIELAMR(idx));
> -
> - rcar_pci_write_reg(pcie, upper_32_bits(pci_addr),
> - PCIEPRAR(idx + 1));
> - rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr),
> - PCIELAR(idx + 1));
> - rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
> + rcar_pcie_set_inbound(pcie->base, cpu_addr, pci_addr,
> + lower_32_bits(mask) | flags, idx, true);
>
> pci_addr += size;
> cpu_addr += size;
> @@ -1170,7 +974,7 @@ static int rcar_pcie_probe(struct platform_device *pdev)
> goto err_phy_shutdown;
> }
>
> - data = rcar_pci_read_reg(pcie, MACSR);
> + data = rcar_pci_read_reg(pcie->base, MACSR);
> dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
>
> if (IS_ENABLED(CONFIG_PCI_MSI)) {
> @@ -1223,14 +1027,14 @@ static int rcar_pcie_resume_noirq(struct device *dev)
> {
> struct rcar_pcie *pcie = dev_get_drvdata(dev);
>
> - if (rcar_pci_read_reg(pcie, PMSR) &&
> - !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
> + if (rcar_pci_read_reg(pcie->base, PMSR) &&
> + !(rcar_pci_read_reg(pcie->base, PCIETCTLR) & DL_DOWN))
> return 0;
>
> /* Re-establish the PCIe link */
> - rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
> - rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> - return rcar_pcie_wait_for_dl(pcie);
> + rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
> + rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);
> + return rcar_pcie_wait_for_dl(pcie->base);
> }
>
> static const struct dev_pm_ops rcar_pcie_pm_ops = {
> diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
> new file mode 100644
> index 0000000..41275f9
> --- /dev/null
> +++ b/drivers/pci/controller/pcie-rcar.c
> @@ -0,0 +1,117 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe driver for Renesas R-Car SoCs
> + * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
> + *
> + * Author: Phil Edworthy <[email protected]>
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/pci.h>
> +
> +#include "pcie-rcar.h"
> +
> +void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int reg)
> +{
> + writel(val, base + reg);
> +}
> +
> +u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg)
> +{
> + return readl(base + reg);
> +}
> +
> +void rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data)
> +{
> + unsigned int shift = BITS_PER_BYTE * (where & 3);
> + u32 val = rcar_pci_read_reg(base, where & ~3);
> +
> + val &= ~(mask << shift);
> + val |= data << shift;
> + rcar_pci_write_reg(base, val, where & ~3);
> +}
> +
> +int rcar_pcie_wait_for_phyrdy(void __iomem *base)
> +{
> + unsigned int timeout = 10;
> +
> + while (timeout--) {
> + if (rcar_pci_read_reg(base, PCIEPHYSR) & PHYRDY)
> + return 0;
> +
> + msleep(5);
> + }
> +
> + return -ETIMEDOUT;
> +}
> +
> +int rcar_pcie_wait_for_dl(void __iomem *base)
> +{
> + unsigned int timeout = 10000;
> +
> + while (timeout--) {
> + if ((rcar_pci_read_reg(base, PCIETSTR) & DATA_LINK_ACTIVE))
> + return 0;
> +
> + udelay(5);
> + cpu_relax();
> + }
> +
> + return -ETIMEDOUT;
> +}
> +
> +void rcar_pcie_set_outbound(int win, void __iomem *base,
> + struct resource *res)
> +{
> + /* Setup PCIe address space mappings for each resource */
> + resource_size_t res_start;
> + resource_size_t size;
> + u32 mask;
> +
> + rcar_pci_write_reg(base, 0x00000000, PCIEPTCTLR(win));
> +
> + /*
> + * The PAMR mask is calculated in units of 128Bytes, which
> + * keeps things pretty simple.
> + */
> + size = resource_size(res);
> + mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> + rcar_pci_write_reg(base, mask << 7, PCIEPAMR(win));
> +
> + if (res->flags & IORESOURCE_IO)
> + res_start = pci_pio_to_address(res->start);
> + else
> + res_start = res->start;
> +
> + rcar_pci_write_reg(base, upper_32_bits(res_start), PCIEPAUR(win));
> + rcar_pci_write_reg(base, lower_32_bits(res_start) & ~0x7F,
> + PCIEPALR(win));
> +
> + /* First resource is for IO */
> + mask = PAR_ENABLE;
> + if (res->flags & IORESOURCE_IO)
> + mask |= IO_SPACE;
> +
> + rcar_pci_write_reg(base, mask, PCIEPTCTLR(win));
> +}
> +
> +void rcar_pcie_set_inbound(void __iomem *base,
> + u64 cpu_addr, u64 pci_addr,
> + u64 flags, int idx, bool host)
> +{
> + /*
> + * Set up 64-bit inbound regions as the range parser doesn't
> + * distinguish between 32 and 64-bit types.
> + */
> + if (host)
> + rcar_pci_write_reg(base, lower_32_bits(pci_addr),
> + PCIEPRAR(idx));
> + rcar_pci_write_reg(base, lower_32_bits(cpu_addr), PCIELAR(idx));
> + rcar_pci_write_reg(base, flags, PCIELAMR(idx));
> +
> + if (host)
> + rcar_pci_write_reg(base, upper_32_bits(pci_addr),
> + PCIEPRAR(idx + 1));
> + rcar_pci_write_reg(base, upper_32_bits(cpu_addr), PCIELAR(idx + 1));
> + rcar_pci_write_reg(base, 0, PCIELAMR(idx + 1));
> +}
> diff --git a/drivers/pci/controller/pcie-rcar.h b/drivers/pci/controller/pcie-rcar.h
> new file mode 100644
> index 0000000..b529d806
> --- /dev/null
> +++ b/drivers/pci/controller/pcie-rcar.h
> @@ -0,0 +1,125 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * PCIe driver for Renesas R-Car SoCs
> + * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
> + *
> + * Author: Phil Edworthy <[email protected]>
> + */
> +
> +#ifndef _PCIE_RCAR_H
> +#define _PCIE_RCAR_H
> +
> +#define PCIECAR 0x000010
> +#define PCIECCTLR 0x000018
> +#define CONFIG_SEND_ENABLE BIT(31)
> +#define TYPE0 (0 << 8)
> +#define TYPE1 BIT(8)
> +#define PCIECDR 0x000020
> +#define PCIEMSR 0x000028
> +#define PCIEINTXR 0x000400
> +#define PCIEPHYSR 0x0007f0
> +#define PHYRDY BIT(0)
> +#define PCIEMSITXR 0x000840
> +
> +/* Transfer control */
> +#define PCIETCTLR 0x02000
> +#define DL_DOWN BIT(3)
> +#define CFINIT BIT(0)
> +#define PCIETSTR 0x02004
> +#define DATA_LINK_ACTIVE BIT(0)
> +#define PCIEERRFR 0x02020
> +#define UNSUPPORTED_REQUEST BIT(4)
> +#define PCIEMSIFR 0x02044
> +#define PCIEMSIALR 0x02048
> +#define MSIFE BIT(0)
> +#define PCIEMSIAUR 0x0204c
> +#define PCIEMSIIER 0x02050
> +
> +/* root port address */
> +#define PCIEPRAR(x) (0x02080 + ((x) * 0x4))
> +
> +/* local address reg & mask */
> +#define PCIELAR(x) (0x02200 + ((x) * 0x20))
> +#define PCIELAMR(x) (0x02208 + ((x) * 0x20))
> +#define LAM_PREFETCH BIT(3)
> +#define LAM_64BIT BIT(2)
> +#define LAR_ENABLE BIT(1)
> +
> +/* PCIe address reg & mask */
> +#define PCIEPALR(x) (0x03400 + ((x) * 0x20))
> +#define PCIEPAUR(x) (0x03404 + ((x) * 0x20))
> +#define PCIEPAMR(x) (0x03408 + ((x) * 0x20))
> +#define PCIEPTCTLR(x) (0x0340c + ((x) * 0x20))
> +#define PAR_ENABLE BIT(31)
> +#define IO_SPACE BIT(8)
> +
> +/* Configuration */
> +#define PCICONF(x) (0x010000 + ((x) * 0x4))
> +#define PMCAP(x) (0x010040 + ((x) * 0x4))
> +#define EXPCAP(x) (0x010070 + ((x) * 0x4))
> +#define VCCAP(x) (0x010100 + ((x) * 0x4))
> +
> +/* link layer */
> +#define IDSETR1 0x011004
> +#define TLCTLR 0x011048
> +#define MACSR 0x011054
> +#define SPCHGFIN BIT(4)
> +#define SPCHGFAIL BIT(6)
> +#define SPCHGSUC BIT(7)
> +#define LINK_SPEED (0xf << 16)
> +#define LINK_SPEED_2_5GTS (1 << 16)
> +#define LINK_SPEED_5_0GTS (2 << 16)
> +#define MACCTLR 0x011058
> +#define MACCTLR_NFTS_MASK GENMASK(23, 16) /* The name is from SH7786 */
> +#define SPEED_CHANGE BIT(24)
> +#define SCRAMBLE_DISABLE BIT(27)
> +#define LTSMDIS BIT(31)
> +#define MACCTLR_INIT_VAL (LTSMDIS | MACCTLR_NFTS_MASK)
> +#define PMSR 0x01105c
> +#define MACS2R 0x011078
> +#define MACCGSPSETR 0x011084
> +#define SPCNGRSN BIT(31)
> +
> +/* R-Car H1 PHY */
> +#define H1_PCIEPHYADRR 0x04000c
> +#define WRITE_CMD BIT(16)
> +#define PHY_ACK BIT(24)
> +#define RATE_POS 12
> +#define LANE_POS 8
> +#define ADR_POS 0
> +#define H1_PCIEPHYDOUTR 0x040014
> +
> +/* R-Car Gen2 PHY */
> +#define GEN2_PCIEPHYADDR 0x780
> +#define GEN2_PCIEPHYDATA 0x784
> +#define GEN2_PCIEPHYCTRL 0x78c
> +
> +#define INT_PCI_MSI_NR 32
> +
> +#define RCONF(x) (PCICONF(0) + (x))
> +#define RPMCAP(x) (PMCAP(0) + (x))
> +#define REXPCAP(x) (EXPCAP(0) + (x))
> +#define RVCCAP(x) (VCCAP(0) + (x))
> +
> +#define PCIE_CONF_BUS(b) (((b) & 0xff) << 24)
> +#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 19)
> +#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 16)
> +
> +#define RCAR_PCI_MAX_RESOURCES 4
> +#define MAX_NR_INBOUND_MAPS 6
> +
> +enum {
> + RCAR_PCI_ACCESS_READ,
> + RCAR_PCI_ACCESS_WRITE,
> +};
> +
> +void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int reg);
> +u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg);
> +void rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data);
> +int rcar_pcie_wait_for_phyrdy(void __iomem *base);
> +int rcar_pcie_wait_for_dl(void __iomem *base);
> +void rcar_pcie_set_outbound(int win, void __iomem *base, struct resource *res);
> +void rcar_pcie_set_inbound(void __iomem *base, u64 cpu_addr, u64 pci_addr,
> + u64 mask, int idx, bool host);
> +
> +#endif
> --
> 2.7.4

2020-03-17 07:32:02

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 3/7] PCI: rcar: Fix calculating mask for PCIEPAMR register

Hi Prabhakar-san,

Thank you for the patch!

> From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
>
> The mask value was calculated incorrectly for PCIEPAMR register if the
> size was less than 128 bytes. Fix this issue by adding a check on size.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> ---
> drivers/pci/controller/pcie-rcar.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
> index 41275f9..90d47b21 100644
> --- a/drivers/pci/controller/pcie-rcar.c
> +++ b/drivers/pci/controller/pcie-rcar.c
> @@ -75,7 +75,10 @@ void rcar_pcie_set_outbound(int win, void __iomem *base,
> * keeps things pretty simple.
> */
> size = resource_size(res);
> - mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> + if (size > 128)
> + mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> + else
> + mask = 0x0;
> rcar_pci_write_reg(base, mask << 7, PCIEPAMR(win));

This patch seems OK. I think rebasing is needed though. Anyway,

Reviewed-by: Yoshihiro Shimoda <[email protected]>

Best regards,
Yoshihiro Shimoda

> if (res->flags & IORESOURCE_IO)
> --
> 2.7.4

2020-03-17 08:13:17

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 4/7] PCI: endpoint: Add support to handle multiple base for mapping outbound memory

Hi Prabhakar-san,

Thank you for the patch!

> From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
>
> R-Car PCIe controller has support to map multiple memory regions for
> mapping the outbound memory in local system also the controller limits
> single allocation for each region (that is, once a chunk is used from the
> region it cannot be used to allocate a new one). This features inspires to
> add support for handling multiple memory bases in endpoint framework.
>
> With this patch pci_epc_mem_init() now accepts multiple regions, also
> page_size for each memory region is passed during initialization so as
> to handle single allocation for each region by setting the page_size to
> window_size.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> ---
> drivers/pci/controller/cadence/pcie-cadence-ep.c | 7 +-
> drivers/pci/controller/dwc/pcie-designware-ep.c | 29 ++--
> drivers/pci/controller/pcie-rockchip-ep.c | 7 +-
> drivers/pci/endpoint/pci-epc-mem.c | 167 ++++++++++++++++-------

I could not apply this patch on the latest pci.git / next branch.
So, you need to rebase.

> include/linux/pci-epc.h | 39 ++++--
> 5 files changed, 169 insertions(+), 80 deletions(-)
>
> diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> index 1c173da..90e32438 100644
> --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> @@ -401,6 +401,7 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
> struct device *dev = ep->pcie.dev;
> struct platform_device *pdev = to_platform_device(dev);
> struct device_node *np = dev->of_node;
> + struct pci_epc_mem_window mem_window;
> struct cdns_pcie *pcie = &ep->pcie;
> struct resource *res;
> struct pci_epc *epc;
> @@ -449,8 +450,10 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
> if (of_property_read_u8(np, "max-functions", &epc->max_functions) < 0)
> epc->max_functions = 1;
>
> - ret = pci_epc_mem_init(epc, pcie->mem_res->start,
> - resource_size(pcie->mem_res));
> + mem_window.phys_base = pcie->mem_res->start;
> + mem_window.size = resource_size(pcie->mem_res);
> + mem_window.page_size = PAGE_SIZE;
> + ret = pci_epc_mem_init(epc, &mem_window, 1);

I'm not sure my idea is acceptable or not but,
I think we can have compatible API for single window like below.
- In this patch, pci_epc_mem_init() and __pci_epc_mem_init() become the same behavior.
So, for example, pci_epc_mem_init() is for simple, and __pci_epc_mem_init() is multiple windows.
-- In this case, pci_epc_mem_init() should have page_size argument.
- The original "mem" in the pci_epc can be the default window instead of
PCI_EPC_DEFAULT_WINDOW.

> if (ret < 0) {
> dev_err(dev, "failed to initialize the memory space\n");
> goto err_init;
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index cfeccd7..b150ef3 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -195,8 +195,7 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no,
> }
>
> static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,
> - phys_addr_t addr,
> - u64 pci_addr, size_t size)
> + phys_addr_t addr, u64 pci_addr, size_t size)
> {
> int ret;
> struct dw_pcie_ep *ep = epc_get_drvdata(epc);
> @@ -367,6 +366,7 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
> unsigned int aligned_offset;
> u16 msg_ctrl, msg_data;
> u32 msg_addr_lower, msg_addr_upper, reg;
> + int window = PCI_EPC_DEFAULT_WINDOW;
> u64 msg_addr;
> bool has_upper;
> int ret;
> @@ -390,11 +390,11 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
> reg = ep->msi_cap + PCI_MSI_DATA_32;
> msg_data = dw_pcie_readw_dbi(pci, reg);
> }
> - aligned_offset = msg_addr_lower & (epc->mem->page_size - 1);
> + aligned_offset = msg_addr_lower & (epc->mem[window]->page_size - 1);
> msg_addr = ((u64)msg_addr_upper) << 32 |
> (msg_addr_lower & ~aligned_offset);
> - ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
> - epc->mem->page_size);
> + ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
> + msg_addr, epc->mem[window]->page_size);
> if (ret)
> return ret;
>
> @@ -416,6 +416,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
> u32 reg, msg_data, vec_ctrl;
> u64 tbl_addr, msg_addr, reg_u64;
> void __iomem *msix_tbl;
> + int window = PCI_EPC_DEFAULT_WINDOW;
> int ret;
>
> reg = ep->msix_cap + PCI_MSIX_TABLE;
> @@ -452,8 +453,8 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
> return -EPERM;
> }
>
> - ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr,
> - epc->mem->page_size);
> + ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
> + msg_addr, epc->mem[window]->page_size);
> if (ret)
> return ret;
>
> @@ -466,10 +467,11 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
>
> void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
> {
> + int window = PCI_EPC_DEFAULT_WINDOW;
> struct pci_epc *epc = ep->epc;
>
> pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
> - epc->mem->page_size);
> + epc->mem[window]->page_size);
>
> pci_epc_mem_exit(epc);
> }
> @@ -502,6 +504,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> unsigned int nbars;
> unsigned int offset;
> struct pci_epc *epc;
> + size_t msi_page_size;
> + struct pci_epc_mem_window mem_window;
> struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> struct device *dev = pci->dev;
> struct device_node *np = dev->of_node;
> @@ -574,15 +578,18 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> if (ret < 0)
> epc->max_functions = 1;
>
> - ret = __pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
> - ep->page_size);
> + mem_window.phys_base = ep->phys_base;
> + mem_window.size = ep->addr_size;
> + mem_window.page_size = ep->page_size;
> + ret = __pci_epc_mem_init(epc, &mem_window, 1);
> if (ret < 0) {
> dev_err(dev, "Failed to initialize address space\n");
> return ret;
> }
>
> + msi_page_size = epc->mem[PCI_EPC_DEFAULT_WINDOW]->page_size;
> ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys,
> - epc->mem->page_size);
> + msi_page_size);
> if (!ep->msi_mem) {
> dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n");
> return -ENOMEM;
> diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
> index d743b0a..5a97390 100644
> --- a/drivers/pci/controller/pcie-rockchip-ep.c
> +++ b/drivers/pci/controller/pcie-rockchip-ep.c
> @@ -562,6 +562,7 @@ static const struct of_device_id rockchip_pcie_ep_of_match[] = {
>
> static int rockchip_pcie_ep_probe(struct platform_device *pdev)
> {
> + struct pci_epc_mem_window mem_window;
> struct device *dev = &pdev->dev;
> struct rockchip_pcie_ep *ep;
> struct rockchip_pcie *rockchip;
> @@ -614,8 +615,10 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
> /* Only enable function 0 by default */
> rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG);
>
> - err = pci_epc_mem_init(epc, rockchip->mem_res->start,
> - resource_size(rockchip->mem_res));
> + mem_window.phys_base = rockchip->mem_res->start;
> + mem_window.size = resource_size(rockchip->mem_res);
> + mem_window.page_size = PAGE_SIZE;
> + err = pci_epc_mem_init(epc, &mem_window, 1);
> if (err < 0) {
> dev_err(dev, "failed to initialize the memory space\n");
> goto err_uninit_port;
> diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c
> index d2b174c..6c21957 100644
> --- a/drivers/pci/endpoint/pci-epc-mem.c
> +++ b/drivers/pci/endpoint/pci-epc-mem.c
> @@ -38,57 +38,76 @@ static int pci_epc_mem_get_order(struct pci_epc_mem *mem, size_t size)
> /**
> * __pci_epc_mem_init() - initialize the pci_epc_mem structure
> * @epc: the EPC device that invoked pci_epc_mem_init
> - * @phys_base: the physical address of the base
> - * @size: the size of the address space
> - * @page_size: size of each page
> + * @windows: pointer to windows supported by the device
> + * @num_windows: number of windows device supports
> *
> * Invoke to initialize the pci_epc_mem structure used by the
> * endpoint functions to allocate mapped PCI address.
> */
> -int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size,
> - size_t page_size)
> +int __pci_epc_mem_init(struct pci_epc *epc, struct pci_epc_mem_window *windows,
> + int num_windows)
> {
> - int ret;
> - struct pci_epc_mem *mem;
> - unsigned long *bitmap;
> + struct pci_epc_mem *mem = NULL;
> + unsigned long *bitmap = NULL;
> unsigned int page_shift;
> - int pages;
> + size_t page_size;
> int bitmap_size;
> -
> - if (page_size < PAGE_SIZE)
> - page_size = PAGE_SIZE;
> -
> - page_shift = ilog2(page_size);
> - pages = size >> page_shift;
> - bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
> -
> - mem = kzalloc(sizeof(*mem), GFP_KERNEL);
> - if (!mem) {
> - ret = -ENOMEM;
> - goto err;
> - }
> -
> - bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> - if (!bitmap) {
> - ret = -ENOMEM;
> - goto err_mem;
> + int pages;
> + int ret;
> + int i;
> +
> + epc->mem_windows = 0;
> +
> + if (!windows)
> + return -EINVAL;
> +
> + if (num_windows <= 0)
> + return -EINVAL;
> +
> + epc->mem = kcalloc(num_windows, sizeof(*mem), GFP_KERNEL);
> + if (!epc->mem)
> + return -EINVAL;
> +
> + for (i = 0; i < num_windows; i++) {
> + page_size = windows[i].page_size;
> + if (page_size < PAGE_SIZE)
> + page_size = PAGE_SIZE;
> + page_shift = ilog2(page_size);
> + pages = windows[i].size >> page_shift;
> + bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
> +
> + mem = kzalloc(sizeof(*mem), GFP_KERNEL);
> + if (!mem) {
> + ret = -ENOMEM;
> + goto err_mem;
> + }
> +
> + bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> + if (!bitmap) {
> + ret = -ENOMEM;
> + goto err_mem;
> + }
> +
> + mem->bitmap = bitmap;
> + mem->window.phys_base = windows[i].phys_base;

I could not understand why the window member is needed.
I think original members (just phys_base and size) are enough.
Also, this function doesn't store the page_size to mem->window.page_size.

> + mem->page_size = page_size;
> + mem->pages = pages;
> + mem->window.size = windows[i].size;
> + epc->mem[i] = mem;
> }
> -
> - mem->bitmap = bitmap;
> - mem->phys_base = phys_base;
> - mem->page_size = page_size;
> - mem->pages = pages;
> - mem->size = size;
> -
> - epc->mem = mem;
> + epc->mem_windows = num_windows;
>
> return 0;
>
> err_mem:
> - kfree(mem);
> + for (; i >= 0; i--) {
> + mem = epc->mem[i];
> + kfree(mem->bitmap);

If bitmap cannot be allocated, the epc->mem[i] is NULL.
So, freeing mem->bitmap anyway is not good.

> + kfree(mem);
> + }
> + kfree(epc->mem);
>
> -err:
> -return ret;
> + return ret;
> }
> EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
>
> @@ -101,11 +120,21 @@ EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
> */
> void pci_epc_mem_exit(struct pci_epc *epc)
> {
> - struct pci_epc_mem *mem = epc->mem;
> + struct pci_epc_mem *mem;
> + int i;
> +
> + if (!epc->mem_windows)
> + return;
> +
> + for (i = 0; i <= epc->mem_windows; i++) {
> + mem = epc->mem[i];
> + kfree(mem->bitmap);
> + kfree(mem);
> + }
> + kfree(epc->mem);
>
> epc->mem = NULL;
> - kfree(mem->bitmap);
> - kfree(mem);
> + epc->mem_windows = 0;
> }
> EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
>
> @@ -121,20 +150,30 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
> void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
> phys_addr_t *phys_addr, size_t size)
> {
> - int pageno;
> - void __iomem *virt_addr;
> - struct pci_epc_mem *mem = epc->mem;
> - unsigned int page_shift = ilog2(mem->page_size);
> + void __iomem *virt_addr = NULL;
> + struct pci_epc_mem *mem;
> + unsigned int page_shift;
> + int pageno = -EINVAL;
> int order;
> + int i;
>
> - size = ALIGN(size, mem->page_size);
> - order = pci_epc_mem_get_order(mem, size);
> + for (i = 0; i < epc->mem_windows; i++) {
> + mem = epc->mem[i];
> + size = ALIGN(size, mem->page_size);
> + order = pci_epc_mem_get_order(mem, size);
> +
> + pageno = bitmap_find_free_region(mem->bitmap, mem->pages,
> + order);
> + if (pageno >= 0)
> + break;
> + }
>
> - pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
> if (pageno < 0)
> return NULL;
>
> - *phys_addr = mem->phys_base + ((phys_addr_t)pageno << page_shift);
> + page_shift = ilog2(mem->page_size);
> + *phys_addr = mem->window.phys_base +
> + ((phys_addr_t)pageno << page_shift);
> virt_addr = ioremap(*phys_addr, size);
> if (!virt_addr)
> bitmap_release_region(mem->bitmap, pageno, order);
> @@ -143,6 +182,23 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
> }
> EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
>
> +struct pci_epc_mem *pci_epc_get_matching_window(struct pci_epc *epc,
> + phys_addr_t phys_addr)
> +{
> + struct pci_epc_mem *mem;
> + int i;
> +
> + for (i = 0; i < epc->mem_windows; i++) {
> + mem = epc->mem[i];
> +
> + if (phys_addr >= mem->window.phys_base &&
> + phys_addr < (mem->window.phys_base + mem->window.size))
> + return mem;
> + }
> +
> + return NULL;
> +}
> +
> /**
> * pci_epc_mem_free_addr() - free the allocated memory address
> * @epc: the EPC device on which memory was allocated
> @@ -155,13 +211,20 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
> void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
> void __iomem *virt_addr, size_t size)
> {
> + struct pci_epc_mem *mem;
> + unsigned int page_shift;
> int pageno;
> - struct pci_epc_mem *mem = epc->mem;
> - unsigned int page_shift = ilog2(mem->page_size);
> int order;
>
> + mem = pci_epc_get_matching_window(epc, phys_addr);
> + if (!mem) {
> + pr_err("failed to get matching window\n");
> + return;
> + }
> +
> + page_shift = ilog2(mem->page_size);
> iounmap(virt_addr);
> - pageno = (phys_addr - mem->phys_base) >> page_shift;
> + pageno = (phys_addr - mem->window.phys_base) >> page_shift;
> size = ALIGN(size, mem->page_size);
> order = pci_epc_mem_get_order(mem, size);
> bitmap_release_region(mem->bitmap, pageno, order);
> diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
> index 56f1846..dde42e5 100644
> --- a/include/linux/pci-epc.h
> +++ b/include/linux/pci-epc.h
> @@ -64,17 +64,29 @@ struct pci_epc_ops {
> struct module *owner;
> };
>
> +#define PCI_EPC_DEFAULT_WINDOW 0
> +
> +/**
> + * struct pci_epc_mem_window - address window of the endpoint controller
> + * @phys_base: physical base address of the PCI address window
> + * @size: the size of the PCI address window
> + * @page_size: size of each page
> + */
> +struct pci_epc_mem_window {
> + phys_addr_t phys_base;
> + size_t size;
> + size_t page_size;
> +};
> +
> /**
> * struct pci_epc_mem - address space of the endpoint controller
> - * @phys_base: physical base address of the PCI address space
> - * @size: the size of the PCI address space
> + * @window: address window of the endpoint controller
> * @bitmap: bitmap to manage the PCI address space
> - * @pages: number of bits representing the address region
> * @page_size: size of each page
> + * @pages: number of bits representing the address region
> */
> struct pci_epc_mem {
> - phys_addr_t phys_base;
> - size_t size;
> + struct pci_epc_mem_window window;
> unsigned long *bitmap;
> size_t page_size;
> int pages;
> @@ -85,7 +97,8 @@ struct pci_epc_mem {
> * @dev: PCI EPC device
> * @pci_epf: list of endpoint functions present in this EPC device
> * @ops: function pointers for performing endpoint operations
> - * @mem: address space of the endpoint controller

If my idea is acceptable, this should be "default address space ...".

> + * @mem: array of address space of the endpoint controller

And, this should be difference name.

> + * @mem_windows: number of windows supported by device

Perhaps, num_windows?

> * @max_functions: max number of functions that can be configured in this EPC
> * @group: configfs group representing the PCI EPC device
> * @lock: spinlock to protect pci_epc ops
> @@ -94,7 +107,8 @@ struct pci_epc {
> struct device dev;
> struct list_head pci_epf;
> const struct pci_epc_ops *ops;
> - struct pci_epc_mem *mem;
> + struct pci_epc_mem **mem;
> + unsigned int mem_windows;
> u8 max_functions;
> struct config_group *group;
> /* spinlock to protect against concurrent access of EP controller */
> @@ -128,8 +142,8 @@ struct pci_epc_features {
> #define devm_pci_epc_create(dev, ops) \
> __devm_pci_epc_create((dev), (ops), THIS_MODULE)
>
> -#define pci_epc_mem_init(epc, phys_addr, size) \
> - __pci_epc_mem_init((epc), (phys_addr), (size), PAGE_SIZE)
> +#define pci_epc_mem_init(epc, windows, num_windows) \
> + __pci_epc_mem_init((epc), windows, num_windows)

As I mentioned above, pci_epc_mem_init() and __ pci_epc_mem_init() are the same behavior.

> static inline void epc_set_drvdata(struct pci_epc *epc, void *data)
> {
> @@ -159,8 +173,7 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no,
> void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no,
> struct pci_epf_bar *epf_bar);
> int pci_epc_map_addr(struct pci_epc *epc, u8 func_no,
> - phys_addr_t phys_addr,
> - u64 pci_addr, size_t size);
> + phys_addr_t phys_addr, u64 pci_addr, size_t size);

Perhaps, this is not needed to change?

Best regards,
Yoshihiro Shimoda

> void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
> phys_addr_t phys_addr);
> int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
> @@ -178,8 +191,8 @@ unsigned int pci_epc_get_first_free_bar(const struct pci_epc_features
> struct pci_epc *pci_epc_get(const char *epc_name);
> void pci_epc_put(struct pci_epc *epc);
>
> -int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr, size_t size,
> - size_t page_size);
> +int __pci_epc_mem_init(struct pci_epc *epc, struct pci_epc_mem_window *window,
> + int num_windows);
> void pci_epc_mem_exit(struct pci_epc *epc);
> void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
> phys_addr_t *phys_addr, size_t size);
> --
> 2.7.4

2020-03-17 08:27:41

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 5/7] dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint controller

Hi Prabhakar-san,

Thank you for the patch!

> From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
>
> This patch adds the bindings for the R-Car PCIe endpoint driver.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> Reviewed-by: Rob Herring <[email protected]>

Reviewed-by: Yoshihiro Shimoda <[email protected]>

Best regards,
Yoshihiro Shimoda

2020-03-17 08:28:29

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: RE: [PATCH v5 1/7] PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c

Hi Yoshihiro-San,

Thank you for the review.

> -----Original Message-----
> From: Yoshihiro Shimoda <[email protected]>
> Sent: 17 March 2020 06:59
> To: Lad Prabhakar <[email protected]>
> Cc: Andrew Murray <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; Bjorn Helgaas <[email protected]>; Rob
> Herring <[email protected]>; Mark Rutland <[email protected]>;
> Catalin Marinas <[email protected]>; Will Deacon <[email protected]>;
> Kishon Vijay Abraham I <[email protected]>; Lorenzo Pieralisi
> <[email protected]>; Arnd Bergmann <[email protected]>; Greg
> Kroah-Hartman <[email protected]>; Jingoo Han
> <[email protected]>; Gustavo Pimentel
> <[email protected]>; Marek Vasut
> <[email protected]>; Shawn Lin <shawn.lin@rock-
> chips.com>; Heiko Stuebner <[email protected]>; Prabhakar Mahadev Lad
> <[email protected]>
> Subject: RE: [PATCH v5 1/7] PCI: rcar: Rename pcie-rcar.c to pcie-rcar-host.c
>
> Hi Prabhakar-san,
>
> Thank you for the patch!
>
> > From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
>
> Since your email account is different with the Singed-off-by, I think you
> should add your From: tag here like your v2 patch series.
>
> > This commit renames pcie-rcar.c to pcie-rcar-host.c in preparation for
> > adding support for endpoint mode. CONFIG_PCIE_RCAR is also renamed to
> > CONFIG_PCIE_RCAR_HOST to match the driver name accordingly.
> >
> > In addition to this defconfig file has also been updated to match the
> > new config option.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-
> [email protected]>
> > ---
> > arch/arm64/configs/defconfig | 2 +-
> > drivers/pci/controller/Kconfig | 7 ++++---
> > drivers/pci/controller/Makefile | 2 +-
> > drivers/pci/controller/{pcie-rcar.c => pcie-rcar-host.c} | 0
> > 4 files changed, 6 insertions(+), 5 deletions(-) rename
> > drivers/pci/controller/{pcie-rcar.c => pcie-rcar-host.c} (100%)
> >
> > diff --git a/arch/arm64/configs/defconfig
> > b/arch/arm64/configs/defconfig index 0f21288..7a34fce 100644
> > --- a/arch/arm64/configs/defconfig
> > +++ b/arch/arm64/configs/defconfig
> > @@ -185,7 +185,7 @@ CONFIG_HOTPLUG_PCI=y
> CONFIG_HOTPLUG_PCI_ACPI=y
> > CONFIG_PCI_AARDVARK=y CONFIG_PCI_TEGRA=y -
> CONFIG_PCIE_RCAR=y
> > +CONFIG_PCIE_RCAR_HOST=y
>
> I think you should separate this change.
> To avoid this, I have an idea in the Kconfig like below:
> - adding PCIE_RCAR_HOST.
> - keeping PCIE_RCAR and select PCIE_RCAR_HOST here.
> - adding a description in the help of PCIE_RCAR like "This will be removed
> after defconfig is updated" is better.
>
> The following is a sample. What do you think?
Sound like a plan will do that, I will just append the description "This will be removed
after defconfig is updated" to PCIE_RCAR config option.

Cheers,
--Prabhakar

> ---
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -58,8 +58,18 @@ config PCIE_RCAR
> bool "Renesas R-Car PCIe controller"
> depends on ARCH_RENESAS || COMPILE_TEST
> depends on PCI_MSI_IRQ_DOMAIN
> +select PCIE_RCAR_HOST
> help
> Say Y here if you want PCIe controller support on R-Car SoCs.
> + This will be removed after defconfig is updated.
> +
> +config PCIE_RCAR_HOST
> +bool "Renesas R-Car PCIe host controller"
> +depends on ARCH_RENESAS || COMPILE_TEST
> +depends on PCI_MSI_IRQ_DOMAIN
> +help
> + Say Y here if you want PCIe controller support on R-Car SoCs in host
> + mode.
>
> config PCI_HOST_COMMON
> bool
> ---
>
> Best regards,
> Yoshihiro Shimoda
>
> > CONFIG_PCI_HOST_GENERIC=y
> > CONFIG_PCI_XGENE=y
> > CONFIG_PCIE_ALTERA=y
> > diff --git a/drivers/pci/controller/Kconfig
> > b/drivers/pci/controller/Kconfig index f84e5ff..37e0ea7 100644
> > --- a/drivers/pci/controller/Kconfig
> > +++ b/drivers/pci/controller/Kconfig
> > @@ -54,12 +54,13 @@ config PCI_RCAR_GEN2
> > There are 3 internal PCI controllers available with a single
> > built-in EHCI/OHCI host controller present on each one.
> >
> > -config PCIE_RCAR
> > -bool "Renesas R-Car PCIe controller"
> > +config PCIE_RCAR_HOST
> > +bool "Renesas R-Car PCIe host controller"
> > depends on ARCH_RENESAS || COMPILE_TEST
> > depends on PCI_MSI_IRQ_DOMAIN
> > help
> > - Say Y here if you want PCIe controller support on R-Car SoCs.
> > + Say Y here if you want PCIe controller support on R-Car SoCs in host
> > + mode.
> >
> > config PCI_HOST_COMMON
> > bool
> > diff --git a/drivers/pci/controller/Makefile
> > b/drivers/pci/controller/Makefile index 01b2502..4ca2da6 100644
> > --- a/drivers/pci/controller/Makefile
> > +++ b/drivers/pci/controller/Makefile
> > @@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> > obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
> > obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> > obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> > -obj-$(CONFIG_PCIE_RCAR) += pcie-rcar.o
> > +obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar-host.o
> > obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
> > obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
> > obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o diff --git
> > a/drivers/pci/controller/pcie-rcar.c
> > b/drivers/pci/controller/pcie-rcar-host.c
> > similarity index 100%
> > rename from drivers/pci/controller/pcie-rcar.c
> > rename to drivers/pci/controller/pcie-rcar-host.c
> > --
> > 2.7.4



Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

2020-03-17 08:31:24

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: RE: [PATCH v5 2/7] PCI: rcar: Move shareable code to a common file

Hi Yoshihiro-san,

Thank you for the review.

> -----Original Message-----
> From: Yoshihiro Shimoda <[email protected]>
> Sent: 17 March 2020 07:23
> To: Lad Prabhakar <[email protected]>
> Cc: Andrew Murray <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; Prabhakar Mahadev Lad <prabhakar.mahadev-
> [email protected]>; Bjorn Helgaas <[email protected]>; Rob
> Herring <[email protected]>; Mark Rutland <[email protected]>;
> Catalin Marinas <[email protected]>; Will Deacon <[email protected]>;
> Kishon Vijay Abraham I <[email protected]>; Lorenzo Pieralisi
> <[email protected]>; Arnd Bergmann <[email protected]>; Greg
> Kroah-Hartman <[email protected]>; Jingoo Han
> <[email protected]>; Gustavo Pimentel
> <[email protected]>; Marek Vasut
> <[email protected]>; Shawn Lin <shawn.lin@rock-
> chips.com>; Heiko Stuebner <[email protected]>
> Subject: RE: [PATCH v5 2/7] PCI: rcar: Move shareable code to a common file
>
> Hi Prabhakar-san,
>
> Thank you for the patch!
>
> > From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
> >
> > This patch moves sharable code to common file pcie-rcar.c and the
> > #defines to pcie-rcar.h so that the common code can be reused with
> endpoint driver.
> > There are no functional changes with this patch for the host
> > controller driver.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-
> [email protected]>
> > ---
> > drivers/pci/controller/Makefile | 2 +-
> > drivers/pci/controller/pcie-rcar-host.c | 358 ++++++++------------------------
> > drivers/pci/controller/pcie-rcar.c | 117 +++++++++++
> > drivers/pci/controller/pcie-rcar.h | 125 +++++++++++
> > 4 files changed, 324 insertions(+), 278 deletions(-) create mode
> > 100644 drivers/pci/controller/pcie-rcar.c
> > create mode 100644 drivers/pci/controller/pcie-rcar.h
> >
> > diff --git a/drivers/pci/controller/Makefile
> > b/drivers/pci/controller/Makefile index 4ca2da6..b4ada32 100644
> > --- a/drivers/pci/controller/Makefile
> > +++ b/drivers/pci/controller/Makefile
> > @@ -7,7 +7,7 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
> > obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
> > obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> > obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> > -obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar-host.o
> > +obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
> > obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
> > obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
> > obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o diff --git
> > a/drivers/pci/controller/pcie-rcar-host.c
> > b/drivers/pci/controller/pcie-rcar-host.c
> > index 759c654..93f22d8 100644
> > --- a/drivers/pci/controller/pcie-rcar-host.c
> > +++ b/drivers/pci/controller/pcie-rcar-host.c
> > @@ -1,7 +1,7 @@
> > // SPDX-License-Identifier: GPL-2.0
> > /*
> > * PCIe driver for Renesas R-Car SoCs
> > - * Copyright (C) 2014 Renesas Electronics Europe Ltd
> > + * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
> > *
> > * Based on:
> > * arch/sh/drivers/pci/pcie-sh7786.c @@ -30,104 +30,7 @@ #include
> > <linux/pm_runtime.h> #include <linux/slab.h>
> >
> > -#define PCIECAR0x000010
> > -#define PCIECCTLR0x000018
> > -#define CONFIG_SEND_ENABLEBIT(31)
> > -#define TYPE0(0 << 8)
> > -#define TYPE1BIT(8)
> > -#define PCIECDR0x000020
> > -#define PCIEMSR0x000028
> > -#define PCIEINTXR0x000400
> > -#define PCIEPHYSR0x0007f0
> > -#define PHYRDYBIT(0)
> > -#define PCIEMSITXR0x000840
> > -
> > -/* Transfer control */
> > -#define PCIETCTLR0x02000
> > -#define DL_DOWNBIT(3)
> > -#define CFINITBIT(0)
> > -#define PCIETSTR0x02004
> > -#define DATA_LINK_ACTIVEBIT(0)
> > -#define PCIEERRFR0x02020
> > -#define UNSUPPORTED_REQUESTBIT(4)
> > -#define PCIEMSIFR0x02044
> > -#define PCIEMSIALR0x02048
> > -#define MSIFEBIT(0)
> > -#define PCIEMSIAUR0x0204c
> > -#define PCIEMSIIER0x02050
> > -
> > -/* root port address */
> > -#define PCIEPRAR(x)(0x02080 + ((x) * 0x4))
> > -
> > -/* local address reg & mask */
> > -#define PCIELAR(x)(0x02200 + ((x) * 0x20))
> > -#define PCIELAMR(x)(0x02208 + ((x) * 0x20))
> > -#define LAM_PREFETCHBIT(3)
> > -#define LAM_64BITBIT(2)
> > -#define LAR_ENABLEBIT(1)
> > -
> > -/* PCIe address reg & mask */
> > -#define PCIEPALR(x)(0x03400 + ((x) * 0x20))
> > -#define PCIEPAUR(x)(0x03404 + ((x) * 0x20))
> > -#define PCIEPAMR(x)(0x03408 + ((x) * 0x20))
> > -#define PCIEPTCTLR(x)(0x0340c + ((x) * 0x20))
> > -#define PAR_ENABLEBIT(31)
> > -#define IO_SPACEBIT(8)
> > -
> > -/* Configuration */
> > -#define PCICONF(x)(0x010000 + ((x) * 0x4))
> > -#define PMCAP(x)(0x010040 + ((x) * 0x4))
> > -#define EXPCAP(x)(0x010070 + ((x) * 0x4))
> > -#define VCCAP(x)(0x010100 + ((x) * 0x4))
> > -
> > -/* link layer */
> > -#define IDSETR10x011004
> > -#define TLCTLR0x011048
> > -#define MACSR0x011054
> > -#define SPCHGFINBIT(4)
> > -#define SPCHGFAILBIT(6)
> > -#define SPCHGSUCBIT(7)
> > -#define LINK_SPEED(0xf << 16)
> > -#define LINK_SPEED_2_5GTS(1 << 16)
> > -#define LINK_SPEED_5_0GTS(2 << 16)
> > -#define MACCTLR0x011058
> > -#define MACCTLR_NFTS_MASKGENMASK(23, 16)/* The name
> is from SH7786 */
> > -#define SPEED_CHANGEBIT(24)
> > -#define SCRAMBLE_DISABLEBIT(27)
> > -#define LTSMDISBIT(31)
> > -#define MACCTLR_INIT_VAL(LTSMDIS | MACCTLR_NFTS_MASK)
> > -#define PMSR0x01105c
> > -#define MACS2R0x011078
> > -#define MACCGSPSETR0x011084
> > -#define SPCNGRSNBIT(31)
> > -
> > -/* R-Car H1 PHY */
> > -#define H1_PCIEPHYADRR0x04000c
> > -#define WRITE_CMDBIT(16)
> > -#define PHY_ACKBIT(24)
> > -#define RATE_POS12
> > -#define LANE_POS8
> > -#define ADR_POS0
> > -#define H1_PCIEPHYDOUTR0x040014
> > -
> > -/* R-Car Gen2 PHY */
> > -#define GEN2_PCIEPHYADDR0x780
> > -#define GEN2_PCIEPHYDATA0x784
> > -#define GEN2_PCIEPHYCTRL0x78c
> > -
> > -#define INT_PCI_MSI_NR32
> > -
> > -#define RCONF(x)(PCICONF(0) + (x))
> > -#define RPMCAP(x)(PMCAP(0) + (x))
> > -#define REXPCAP(x)(EXPCAP(0) + (x))
> > -#define RVCCAP(x)(VCCAP(0) + (x))
> > -
> > -#define PCIE_CONF_BUS(b)(((b) & 0xff) << 24)
> > -#define PCIE_CONF_DEV(d)(((d) & 0x1f) << 19)
> > -#define PCIE_CONF_FUNC(f)(((f) & 0x7) << 16)
> > -
> > -#define RCAR_PCI_MAX_RESOURCES4
> > -#define MAX_NR_INBOUND_MAPS6
> > +#include "pcie-rcar.h"
> >
> > struct rcar_msi {
> > DECLARE_BITMAP(used, INT_PCI_MSI_NR); @@ -155,36 +58,10 @@
> struct
> > rcar_pcie {
> > structrcar_msi msi;
> > };
> >
> > -static void rcar_pci_write_reg(struct rcar_pcie *pcie, u32 val,
> > - unsigned int reg)
> > -{
> > -writel(val, pcie->base + reg);
> > -}
> > -
> > -static u32 rcar_pci_read_reg(struct rcar_pcie *pcie, unsigned int
> > reg) -{
> > -return readl(pcie->base + reg);
> > -}
> > -
> > -enum {
> > -RCAR_PCI_ACCESS_READ,
> > -RCAR_PCI_ACCESS_WRITE,
> > -};
> > -
> > -static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask,
> > u32 data) -{
> > -unsigned int shift = BITS_PER_BYTE * (where & 3);
> > -u32 val = rcar_pci_read_reg(pcie, where & ~3);
> > -
> > -val &= ~(mask << shift);
> > -val |= data << shift;
> > -rcar_pci_write_reg(pcie, val, where & ~3);
> > -}
> > -
> > static u32 rcar_read_conf(struct rcar_pcie *pcie, int where) {
> > unsigned int shift = BITS_PER_BYTE * (where & 3);
> > -u32 val = rcar_pci_read_reg(pcie, where & ~3);
> > +u32 val = rcar_pci_read_reg(pcie->base, where & ~3);
>
> I'd like to avoid these many changes about "pcie" to "pcie->base" somehow.
> My idea is moving declaration of struct rcar_pcie to rcar-pcie.h and use it
> from both host and ep codes. According to the patch 6/7, the rcar-pcie-ep.c
> also has the same name of struct rcar_pcie and this has the same "base" and
> "dev.
> So, common rcar_pcie should have these members. Remaining members are
> contained on renamed structures like "rcar_pcie_host" and "rcar_pcie_ep".
> And then, the rcar_pcie_{host,ep} have struct rcar_pcie pcie member.
>
Agreed will do that.

Cheers,
--Prabhakar

> Best regards,
> Yoshihiro Shimoda
>
> > return val >> shift;
> > }
> > @@ -221,13 +98,13 @@ static int rcar_pcie_config_access(struct rcar_pcie
> *pcie,
> > return PCIBIOS_DEVICE_NOT_FOUND;
> >
> > if (access_type == RCAR_PCI_ACCESS_READ) {
> > -*data = rcar_pci_read_reg(pcie, PCICONF(index));
> > +*data = rcar_pci_read_reg(pcie->base,
> PCICONF(index));
> > } else {
> > /* Keep an eye out for changes to the root bus
> number */
> > if (pci_is_root_bus(bus) && (reg ==
> PCI_PRIMARY_BUS))
> > pcie->root_bus_nr = *data & 0xff;
> >
> > -rcar_pci_write_reg(pcie, *data, PCICONF(index));
> > +rcar_pci_write_reg(pcie->base, *data,
> PCICONF(index));
> > }
> >
> > return PCIBIOS_SUCCESSFUL;
> > @@ -237,20 +114,23 @@ static int rcar_pcie_config_access(struct rcar_pcie
> *pcie,
> > return PCIBIOS_DEVICE_NOT_FOUND;
> >
> > /* Clear errors */
> > -rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR),
> PCIEERRFR);
> > +rcar_pci_write_reg(pcie->base, rcar_pci_read_reg(pcie->base,
> PCIEERRFR),
> > + PCIEERRFR);
> >
> > /* Set the PIO address */
> > -rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
> > +rcar_pci_write_reg(pcie->base, PCIE_CONF_BUS(bus->number) |
> > PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg,
> PCIECAR);
> >
> > /* Enable the configuration access */
> > if (bus->parent->number == pcie->root_bus_nr)
> > -rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0,
> PCIECCTLR);
> > +rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE |
> TYPE0,
> > + PCIECCTLR);
> > else
> > -rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1,
> PCIECCTLR);
> > +rcar_pci_write_reg(pcie->base, CONFIG_SEND_ENABLE |
> TYPE1,
> > + PCIECCTLR);
> >
> > /* Check for errors */
> > -if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
> > +if (rcar_pci_read_reg(pcie->base, PCIEERRFR) &
> UNSUPPORTED_REQUEST)
> > return PCIBIOS_DEVICE_NOT_FOUND;
> >
> > /* Check for master and target aborts */ @@ -259,12 +139,12 @@
> > static int rcar_pcie_config_access(struct rcar_pcie *pcie,
> > return PCIBIOS_DEVICE_NOT_FOUND;
> >
> > if (access_type == RCAR_PCI_ACCESS_READ)
> > -*data = rcar_pci_read_reg(pcie, PCIECDR);
> > +*data = rcar_pci_read_reg(pcie->base, PCIECDR);
> > else
> > -rcar_pci_write_reg(pcie, *data, PCIECDR);
> > +rcar_pci_write_reg(pcie->base, *data, PCIECDR);
> >
> > /* Disable the configuration access */
> > -rcar_pci_write_reg(pcie, 0, PCIECCTLR);
> > +rcar_pci_write_reg(pcie->base, 0, PCIECCTLR);
> >
> > return PCIBIOS_SUCCESSFUL;
> > }
> > @@ -332,41 +212,6 @@ static struct pci_ops rcar_pcie_ops = {
> > .write= rcar_pcie_write_conf,
> > };
> >
> > -static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
> > - struct resource *res)
> > -{
> > -/* Setup PCIe address space mappings for each resource */
> > -resource_size_t size;
> > -resource_size_t res_start;
> > -u32 mask;
> > -
> > -rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
> > -
> > -/*
> > - * The PAMR mask is calculated in units of 128Bytes, which
> > - * keeps things pretty simple.
> > - */
> > -size = resource_size(res);
> > -mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> > -rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
> > -
> > -if (res->flags & IORESOURCE_IO)
> > -res_start = pci_pio_to_address(res->start);
> > -else
> > -res_start = res->start;
> > -
> > -rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPAUR(win));
> > -rcar_pci_write_reg(pcie, lower_32_bits(res_start) & ~0x7F,
> > - PCIEPALR(win));
> > -
> > -/* First resource is for IO */
> > -mask = PAR_ENABLE;
> > -if (res->flags & IORESOURCE_IO)
> > -mask |= IO_SPACE;
> > -
> > -rcar_pci_write_reg(pcie, mask, PCIEPTCTLR(win));
> > -}
> > -
> > static int rcar_pcie_setup(struct list_head *resource, struct
> > rcar_pcie *pci) {
> > struct resource_entry *win;
> > @@ -382,7 +227,7 @@ static int rcar_pcie_setup(struct list_head
> *resource, struct rcar_pcie *pci)
> > switch (resource_type(res)) {
> > case IORESOURCE_IO:
> > case IORESOURCE_MEM:
> > -rcar_pcie_setup_window(i, pci, res);
> > +rcar_pcie_set_outbound(i, pci->base, res);
> > i++;
> > break;
> > case IORESOURCE_BUS:
> > @@ -404,37 +249,38 @@ static void rcar_pcie_force_speedup(struct
> rcar_pcie *pcie)
> > unsigned int timeout = 1000;
> > u32 macsr;
> >
> > -if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) !=
> LINK_SPEED_5_0GTS)
> > +if ((rcar_pci_read_reg(pcie->base, MACS2R) & LINK_SPEED) !=
> > +LINK_SPEED_5_0GTS)
> > return;
> >
> > -if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) {
> > +if (rcar_pci_read_reg(pcie->base, MACCTLR) & SPEED_CHANGE) {
> > dev_err(dev, "Speed change already in progress\n");
> > return;
> > }
> >
> > -macsr = rcar_pci_read_reg(pcie, MACSR);
> > +macsr = rcar_pci_read_reg(pcie->base, MACSR);
> > if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS)
> > goto done;
> >
> > /* Set target link speed to 5.0 GT/s */
> > -rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
> > +rcar_rmw32(pcie->base, EXPCAP(12), PCI_EXP_LNKSTA_CLS,
> > PCI_EXP_LNKSTA_CLS_5_0GB);
> >
> > /* Set speed change reason as intentional factor */
> > -rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0);
> > +rcar_rmw32(pcie->base, MACCGSPSETR, SPCNGRSN, 0);
> >
> > /* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */
> > if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL))
> > -rcar_pci_write_reg(pcie, macsr, MACSR);
> > +rcar_pci_write_reg(pcie->base, macsr, MACSR);
> >
> > /* Start link speed change */
> > -rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE);
> > +rcar_rmw32(pcie->base, MACCTLR, SPEED_CHANGE,
> SPEED_CHANGE);
> >
> > while (timeout--) {
> > -macsr = rcar_pci_read_reg(pcie, MACSR);
> > +macsr = rcar_pci_read_reg(pcie->base, MACSR);
> > if (macsr & SPCHGFIN) {
> > /* Clear the interrupt bits */
> > -rcar_pci_write_reg(pcie, macsr, MACSR);
> > +rcar_pci_write_reg(pcie->base, macsr, MACSR);
> >
> > if (macsr & SPCHGFAIL)
> > dev_err(dev, "Speed change failed\n"); @@
> -498,7 +344,7 @@ static
> > int phy_wait_for_ack(struct rcar_pcie *pcie)
> > unsigned int timeout = 100;
> >
> > while (timeout--) {
> > -if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK)
> > +if (rcar_pci_read_reg(pcie->base, H1_PCIEPHYADRR) &
> PHY_ACK)
> > return 0;
> >
> > udelay(100);
> > @@ -521,60 +367,31 @@ static void phy_write_reg(struct rcar_pcie *pcie,
> > ((addr & 0xff) << ADR_POS);
> >
> > /* Set write data */
> > -rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR);
> > -rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR);
> > +rcar_pci_write_reg(pcie->base, data, H1_PCIEPHYDOUTR);
> > +rcar_pci_write_reg(pcie->base, phyaddr, H1_PCIEPHYADRR);
> >
> > /* Ignore errors as they will be dealt with if the data link is down */
> > phy_wait_for_ack(pcie);
> >
> > /* Clear command */
> > -rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR);
> > -rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR);
> > +rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYDOUTR);
> > +rcar_pci_write_reg(pcie->base, 0, H1_PCIEPHYADRR);
> >
> > /* Ignore errors as they will be dealt with if the data link is down */
> > phy_wait_for_ack(pcie);
> > }
> >
> > -static int rcar_pcie_wait_for_phyrdy(struct rcar_pcie *pcie) -{
> > -unsigned int timeout = 10;
> > -
> > -while (timeout--) {
> > -if (rcar_pci_read_reg(pcie, PCIEPHYSR) & PHYRDY)
> > -return 0;
> > -
> > -msleep(5);
> > -}
> > -
> > -return -ETIMEDOUT;
> > -}
> > -
> > -static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie) -{
> > -unsigned int timeout = 10000;
> > -
> > -while (timeout--) {
> > -if ((rcar_pci_read_reg(pcie, PCIETSTR) &
> DATA_LINK_ACTIVE))
> > -return 0;
> > -
> > -udelay(5);
> > -cpu_relax();
> > -}
> > -
> > -return -ETIMEDOUT;
> > -}
> > -
> > static int rcar_pcie_hw_init(struct rcar_pcie *pcie) {
> > int err;
> >
> > /* Begin initialization */
> > -rcar_pci_write_reg(pcie, 0, PCIETCTLR);
> > +rcar_pci_write_reg(pcie->base, 0, PCIETCTLR);
> >
> > /* Set mode */
> > -rcar_pci_write_reg(pcie, 1, PCIEMSR);
> > +rcar_pci_write_reg(pcie->base, 1, PCIEMSR);
> >
> > -err = rcar_pcie_wait_for_phyrdy(pcie);
> > +err = rcar_pcie_wait_for_phyrdy(pcie->base);
> > if (err)
> > return err;
> >
> > @@ -583,51 +400,51 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
> > * class to match. Hardware takes care of propagating the IDSETR
> > * settings, so there is no need to bother with a quirk.
> > */
> > -rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1);
> > +rcar_pci_write_reg(pcie->base, PCI_CLASS_BRIDGE_PCI << 16,
> IDSETR1);
> >
> > /*
> > * Setup Secondary Bus Number & Subordinate Bus Number, even
> though
> > * they aren't used, to avoid bridge being detected as broken.
> > */
> > -rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
> > -rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
> > +rcar_rmw32(pcie->base, RCONF(PCI_SECONDARY_BUS), 0xff, 1);
> > +rcar_rmw32(pcie->base, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1);
> >
> > /* Initialize default capabilities. */
> > -rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
> > -rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
> > -PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
> > -rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
> > -PCI_HEADER_TYPE_BRIDGE);
> > +rcar_rmw32(pcie->base, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
> > +rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_FLAGS),
> > + PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
> > +rcar_rmw32(pcie->base, RCONF(PCI_HEADER_TYPE), 0x7f,
> > + PCI_HEADER_TYPE_BRIDGE);
> >
> > /* Enable data link layer active state reporting */
> > -rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP),
> PCI_EXP_LNKCAP_DLLLARC,
> > -PCI_EXP_LNKCAP_DLLLARC);
> > +rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_LNKCAP),
> PCI_EXP_LNKCAP_DLLLARC,
> > + PCI_EXP_LNKCAP_DLLLARC);
> >
> > /* Write out the physical slot number = 0 */
> > -rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP),
> PCI_EXP_SLTCAP_PSN, 0);
> > +rcar_rmw32(pcie->base, REXPCAP(PCI_EXP_SLTCAP),
> PCI_EXP_SLTCAP_PSN,
> > +0);
> >
> > /* Set the completion timer timeout to the maximum 50ms. */
> > -rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50);
> > +rcar_rmw32(pcie->base, TLCTLR + 1, 0x3f, 50);
> >
> > /* Terminate list of capabilities (Next Capability Offset=0) */
> > -rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0);
> > +rcar_rmw32(pcie->base, RVCCAP(0), 0xfff00000, 0);
> >
> > /* Enable MSI */
> > if (IS_ENABLED(CONFIG_PCI_MSI))
> > -rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR);
> > +rcar_pci_write_reg(pcie->base, 0x801f0000, PCIEMSITXR);
> >
> > -rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
> > +rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
> >
> > /* Finish initialization - establish a PCI Express link */
> > -rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> > +rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);
> >
> > /* This will timeout if we don't have a link. */
> > -err = rcar_pcie_wait_for_dl(pcie);
> > +err = rcar_pcie_wait_for_dl(pcie->base);
> > if (err)
> > return err;
> >
> > /* Enable INTx interrupts */
> > -rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8);
> > +rcar_rmw32(pcie->base, PCIEINTXR, 0, 0xF << 8);
> >
> > wmb();
> >
> > @@ -663,16 +480,16 @@ static int rcar_pcie_phy_init_gen2(struct
> rcar_pcie *pcie)
> > * These settings come from the R-Car Series, 2nd Generation User's
> > * Manual, section 50.3.1 (2) Initialization of the physical layer.
> > */
> > -rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR);
> > -rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA);
> > -rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
> > -rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
> > +rcar_pci_write_reg(pcie->base, 0x000f0030, GEN2_PCIEPHYADDR);
> > +rcar_pci_write_reg(pcie->base, 0x00381203, GEN2_PCIEPHYDATA);
> > +rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
> > +rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);
> >
> > -rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR);
> > +rcar_pci_write_reg(pcie->base, 0x000f0054, GEN2_PCIEPHYADDR);
> > /* The following value is for DC connection, no termination resistor
> */
> > -rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA);
> > -rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL);
> > -rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL);
> > +rcar_pci_write_reg(pcie->base, 0x13802007, GEN2_PCIEPHYDATA);
> > +rcar_pci_write_reg(pcie->base, 0x00000001, GEN2_PCIEPHYCTRL);
> > +rcar_pci_write_reg(pcie->base, 0x00000006, GEN2_PCIEPHYCTRL);
> >
> > return 0;
> > }
> > @@ -735,7 +552,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void
> *data)
> > struct device *dev = pcie->dev;
> > unsigned long reg;
> >
> > -reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
> > +reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);
> >
> > /* MSI & INTx share an interrupt - we only handle MSI here */
> > if (!reg)
> > @@ -746,7 +563,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void
> *data)
> > unsigned int msi_irq;
> >
> > /* clear the interrupt */
> > -rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR);
> > +rcar_pci_write_reg(pcie->base, 1 << index, PCIEMSIFR);
> >
> > msi_irq = irq_find_mapping(msi->domain, index);
> > if (msi_irq) {
> > @@ -760,7 +577,7 @@ static irqreturn_t rcar_pcie_msi_irq(int irq, void
> *data)
> > }
> >
> > /* see if there's any more pending in this vector */
> > -reg = rcar_pci_read_reg(pcie, PCIEMSIFR);
> > +reg = rcar_pci_read_reg(pcie->base, PCIEMSIFR);
> > }
> >
> > return IRQ_HANDLED;
> > @@ -787,8 +604,8 @@ static int rcar_msi_setup_irq(struct
> > msi_controller *chip, struct pci_dev *pdev,
> >
> > irq_set_msi_desc(irq, desc);
> >
> > -msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
> > -msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
> > +msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) &
> ~MSIFE;
> > +msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
> > msg.data = hwirq;
> >
> > pci_write_msi_msg(irq, &msg);
> > @@ -839,8 +656,8 @@ static int rcar_msi_setup_irqs(struct msi_controller
> *chip,
> > desc->nvec_used = nvec;
> > desc->msi_attrib.multiple = order_base_2(nvec);
> >
> > -msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE;
> > -msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR);
> > +msg.address_lo = rcar_pci_read_reg(pcie->base, PCIEMSIALR) &
> ~MSIFE;
> > +msg.address_hi = rcar_pci_read_reg(pcie->base, PCIEMSIAUR);
> > msg.data = hwirq;
> >
> > pci_write_msi_msg(irq, &msg);
> > @@ -940,11 +757,11 @@ static int rcar_pcie_enable_msi(struct rcar_pcie
> *pcie)
> > }
> > base = virt_to_phys((void *)msi->pages);
> >
> > -rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR);
> > -rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR);
> > +rcar_pci_write_reg(pcie->base, lower_32_bits(base) | MSIFE,
> PCIEMSIALR);
> > +rcar_pci_write_reg(pcie->base, upper_32_bits(base), PCIEMSIAUR);
> >
> > /* enable all MSI interrupts */
> > -rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER);
> > +rcar_pci_write_reg(pcie->base, 0xffffffff, PCIEMSIIER);
> >
> > return 0;
> >
> > @@ -958,10 +775,10 @@ static void rcar_pcie_teardown_msi(struct
> rcar_pcie *pcie)
> > struct rcar_msi *msi = &pcie->msi;
> >
> > /* Disable all MSI interrupts */
> > -rcar_pci_write_reg(pcie, 0, PCIEMSIIER);
> > +rcar_pci_write_reg(pcie->base, 0, PCIEMSIIER);
> >
> > /* Disable address decoding of the MSI interrupt, MSIFE */
> > -rcar_pci_write_reg(pcie, 0, PCIEMSIALR);
> > +rcar_pci_write_reg(pcie->base, 0, PCIEMSIALR);
> >
> > free_pages(msi->pages, 0);
> >
> > @@ -1054,21 +871,8 @@ static int rcar_pcie_inbound_ranges(struct
> rcar_pcie *pcie,
> > mask = roundup_pow_of_two(size) - 1;
> > mask &= ~0xf;
> >
> > -/*
> > - * Set up 64-bit inbound regions as the range parser doesn't
> > - * distinguish between 32 and 64-bit types.
> > - */
> > -rcar_pci_write_reg(pcie, lower_32_bits(pci_addr),
> > - PCIEPRAR(idx));
> > -rcar_pci_write_reg(pcie, lower_32_bits(cpu_addr),
> PCIELAR(idx));
> > -rcar_pci_write_reg(pcie, lower_32_bits(mask) | flags,
> > - PCIELAMR(idx));
> > -
> > -rcar_pci_write_reg(pcie, upper_32_bits(pci_addr),
> > - PCIEPRAR(idx + 1));
> > -rcar_pci_write_reg(pcie, upper_32_bits(cpu_addr),
> > - PCIELAR(idx + 1));
> > -rcar_pci_write_reg(pcie, 0, PCIELAMR(idx + 1));
> > +rcar_pcie_set_inbound(pcie->base, cpu_addr, pci_addr,
> > + lower_32_bits(mask) | flags, idx, true);
> >
> > pci_addr += size;
> > cpu_addr += size;
> > @@ -1170,7 +974,7 @@ static int rcar_pcie_probe(struct platform_device
> *pdev)
> > goto err_phy_shutdown;
> > }
> >
> > -data = rcar_pci_read_reg(pcie, MACSR);
> > +data = rcar_pci_read_reg(pcie->base, MACSR);
> > dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f);
> >
> > if (IS_ENABLED(CONFIG_PCI_MSI)) {
> > @@ -1223,14 +1027,14 @@ static int rcar_pcie_resume_noirq(struct
> > device *dev) {
> > struct rcar_pcie *pcie = dev_get_drvdata(dev);
> >
> > -if (rcar_pci_read_reg(pcie, PMSR) &&
> > - !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN))
> > +if (rcar_pci_read_reg(pcie->base, PMSR) &&
> > + !(rcar_pci_read_reg(pcie->base, PCIETCTLR) & DL_DOWN))
> > return 0;
> >
> > /* Re-establish the PCIe link */
> > -rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
> > -rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
> > -return rcar_pcie_wait_for_dl(pcie);
> > +rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
> > +rcar_pci_write_reg(pcie->base, CFINIT, PCIETCTLR);
> > +return rcar_pcie_wait_for_dl(pcie->base);
> > }
> >
> > static const struct dev_pm_ops rcar_pcie_pm_ops = { diff --git
> > a/drivers/pci/controller/pcie-rcar.c
> > b/drivers/pci/controller/pcie-rcar.c
> > new file mode 100644
> > index 0000000..41275f9
> > --- /dev/null
> > +++ b/drivers/pci/controller/pcie-rcar.c
> > @@ -0,0 +1,117 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * PCIe driver for Renesas R-Car SoCs
> > + * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
> > + *
> > + * Author: Phil Edworthy <[email protected]> */
> > +
> > +#include <linux/delay.h>
> > +#include <linux/pci.h>
> > +
> > +#include "pcie-rcar.h"
> > +
> > +void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int
> > +reg) {
> > +writel(val, base + reg);
> > +}
> > +
> > +u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg) {
> > +return readl(base + reg);
> > +}
> > +
> > +void rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data) {
> > +unsigned int shift = BITS_PER_BYTE * (where & 3);
> > +u32 val = rcar_pci_read_reg(base, where & ~3);
> > +
> > +val &= ~(mask << shift);
> > +val |= data << shift;
> > +rcar_pci_write_reg(base, val, where & ~3); }
> > +
> > +int rcar_pcie_wait_for_phyrdy(void __iomem *base) {
> > +unsigned int timeout = 10;
> > +
> > +while (timeout--) {
> > +if (rcar_pci_read_reg(base, PCIEPHYSR) & PHYRDY)
> > +return 0;
> > +
> > +msleep(5);
> > +}
> > +
> > +return -ETIMEDOUT;
> > +}
> > +
> > +int rcar_pcie_wait_for_dl(void __iomem *base) {
> > +unsigned int timeout = 10000;
> > +
> > +while (timeout--) {
> > +if ((rcar_pci_read_reg(base, PCIETSTR) &
> DATA_LINK_ACTIVE))
> > +return 0;
> > +
> > +udelay(5);
> > +cpu_relax();
> > +}
> > +
> > +return -ETIMEDOUT;
> > +}
> > +
> > +void rcar_pcie_set_outbound(int win, void __iomem *base,
> > + struct resource *res)
> > +{
> > +/* Setup PCIe address space mappings for each resource */
> > +resource_size_t res_start;
> > +resource_size_t size;
> > +u32 mask;
> > +
> > +rcar_pci_write_reg(base, 0x00000000, PCIEPTCTLR(win));
> > +
> > +/*
> > + * The PAMR mask is calculated in units of 128Bytes, which
> > + * keeps things pretty simple.
> > + */
> > +size = resource_size(res);
> > +mask = (roundup_pow_of_two(size) / SZ_128) - 1;
> > +rcar_pci_write_reg(base, mask << 7, PCIEPAMR(win));
> > +
> > +if (res->flags & IORESOURCE_IO)
> > +res_start = pci_pio_to_address(res->start);
> > +else
> > +res_start = res->start;
> > +
> > +rcar_pci_write_reg(base, upper_32_bits(res_start), PCIEPAUR(win));
> > +rcar_pci_write_reg(base, lower_32_bits(res_start) & ~0x7F,
> > + PCIEPALR(win));
> > +
> > +/* First resource is for IO */
> > +mask = PAR_ENABLE;
> > +if (res->flags & IORESOURCE_IO)
> > +mask |= IO_SPACE;
> > +
> > +rcar_pci_write_reg(base, mask, PCIEPTCTLR(win)); }
> > +
> > +void rcar_pcie_set_inbound(void __iomem *base,
> > + u64 cpu_addr, u64 pci_addr,
> > + u64 flags, int idx, bool host)
> > +{
> > +/*
> > + * Set up 64-bit inbound regions as the range parser doesn't
> > + * distinguish between 32 and 64-bit types.
> > + */
> > +if (host)
> > +rcar_pci_write_reg(base, lower_32_bits(pci_addr),
> > + PCIEPRAR(idx));
> > +rcar_pci_write_reg(base, lower_32_bits(cpu_addr), PCIELAR(idx));
> > +rcar_pci_write_reg(base, flags, PCIELAMR(idx));
> > +
> > +if (host)
> > +rcar_pci_write_reg(base, upper_32_bits(pci_addr),
> > + PCIEPRAR(idx + 1));
> > +rcar_pci_write_reg(base, upper_32_bits(cpu_addr), PCIELAR(idx +
> 1));
> > +rcar_pci_write_reg(base, 0, PCIELAMR(idx + 1)); }
> > diff --git a/drivers/pci/controller/pcie-rcar.h
> > b/drivers/pci/controller/pcie-rcar.h
> > new file mode 100644
> > index 0000000..b529d806
> > --- /dev/null
> > +++ b/drivers/pci/controller/pcie-rcar.h
> > @@ -0,0 +1,125 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/*
> > + * PCIe driver for Renesas R-Car SoCs
> > + * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
> > + *
> > + * Author: Phil Edworthy <[email protected]> */
> > +
> > +#ifndef _PCIE_RCAR_H
> > +#define _PCIE_RCAR_H
> > +
> > +#define PCIECAR0x000010
> > +#define PCIECCTLR0x000018
> > +#define CONFIG_SEND_ENABLEBIT(31)
> > +#define TYPE0(0 << 8)
> > +#define TYPE1BIT(8)
> > +#define PCIECDR0x000020
> > +#define PCIEMSR0x000028
> > +#define PCIEINTXR0x000400
> > +#define PCIEPHYSR0x0007f0
> > +#define PHYRDYBIT(0)
> > +#define PCIEMSITXR0x000840
> > +
> > +/* Transfer control */
> > +#define PCIETCTLR0x02000
> > +#define DL_DOWNBIT(3)
> > +#define CFINITBIT(0)
> > +#define PCIETSTR0x02004
> > +#define DATA_LINK_ACTIVEBIT(0)
> > +#define PCIEERRFR0x02020
> > +#define UNSUPPORTED_REQUESTBIT(4)
> > +#define PCIEMSIFR0x02044
> > +#define PCIEMSIALR0x02048
> > +#define MSIFEBIT(0)
> > +#define PCIEMSIAUR0x0204c
> > +#define PCIEMSIIER0x02050
> > +
> > +/* root port address */
> > +#define PCIEPRAR(x)(0x02080 + ((x) * 0x4))
> > +
> > +/* local address reg & mask */
> > +#define PCIELAR(x)(0x02200 + ((x) * 0x20))
> > +#define PCIELAMR(x)(0x02208 + ((x) * 0x20))
> > +#define LAM_PREFETCHBIT(3)
> > +#define LAM_64BITBIT(2)
> > +#define LAR_ENABLEBIT(1)
> > +
> > +/* PCIe address reg & mask */
> > +#define PCIEPALR(x)(0x03400 + ((x) * 0x20))
> > +#define PCIEPAUR(x)(0x03404 + ((x) * 0x20))
> > +#define PCIEPAMR(x)(0x03408 + ((x) * 0x20))
> > +#define PCIEPTCTLR(x)(0x0340c + ((x) * 0x20))
> > +#define PAR_ENABLEBIT(31)
> > +#define IO_SPACEBIT(8)
> > +
> > +/* Configuration */
> > +#define PCICONF(x)(0x010000 + ((x) * 0x4))
> > +#define PMCAP(x)(0x010040 + ((x) * 0x4))
> > +#define EXPCAP(x)(0x010070 + ((x) * 0x4))
> > +#define VCCAP(x)(0x010100 + ((x) * 0x4))
> > +
> > +/* link layer */
> > +#define IDSETR10x011004
> > +#define TLCTLR0x011048
> > +#define MACSR0x011054
> > +#define SPCHGFINBIT(4)
> > +#define SPCHGFAILBIT(6)
> > +#define SPCHGSUCBIT(7)
> > +#define LINK_SPEED(0xf << 16)
> > +#define LINK_SPEED_2_5GTS(1 << 16)
> > +#define LINK_SPEED_5_0GTS(2 << 16)
> > +#define MACCTLR0x011058
> > +#define MACCTLR_NFTS_MASKGENMASK(23, 16)/* The name
> is from SH7786 */
> > +#define SPEED_CHANGEBIT(24)
> > +#define SCRAMBLE_DISABLEBIT(27)
> > +#define LTSMDISBIT(31)
> > +#define MACCTLR_INIT_VAL(LTSMDIS | MACCTLR_NFTS_MASK)
> > +#define PMSR0x01105c
> > +#define MACS2R0x011078
> > +#define MACCGSPSETR0x011084
> > +#define SPCNGRSNBIT(31)
> > +
> > +/* R-Car H1 PHY */
> > +#define H1_PCIEPHYADRR0x04000c
> > +#define WRITE_CMDBIT(16)
> > +#define PHY_ACKBIT(24)
> > +#define RATE_POS12
> > +#define LANE_POS8
> > +#define ADR_POS0
> > +#define H1_PCIEPHYDOUTR0x040014
> > +
> > +/* R-Car Gen2 PHY */
> > +#define GEN2_PCIEPHYADDR0x780
> > +#define GEN2_PCIEPHYDATA0x784
> > +#define GEN2_PCIEPHYCTRL0x78c
> > +
> > +#define INT_PCI_MSI_NR32
> > +
> > +#define RCONF(x)(PCICONF(0) + (x))
> > +#define RPMCAP(x)(PMCAP(0) + (x))
> > +#define REXPCAP(x)(EXPCAP(0) + (x))
> > +#define RVCCAP(x)(VCCAP(0) + (x))
> > +
> > +#define PCIE_CONF_BUS(b)(((b) & 0xff) << 24)
> > +#define PCIE_CONF_DEV(d)(((d) & 0x1f) << 19)
> > +#define PCIE_CONF_FUNC(f)(((f) & 0x7) << 16)
> > +
> > +#define RCAR_PCI_MAX_RESOURCES4
> > +#define MAX_NR_INBOUND_MAPS6
> > +
> > +enum {
> > +RCAR_PCI_ACCESS_READ,
> > +RCAR_PCI_ACCESS_WRITE,
> > +};
> > +
> > +void rcar_pci_write_reg(void __iomem *base, u32 val, unsigned int
> > +reg);
> > +u32 rcar_pci_read_reg(void __iomem *base, unsigned int reg); void
> > +rcar_rmw32(void __iomem *base, int where, u32 mask, u32 data); int
> > +rcar_pcie_wait_for_phyrdy(void __iomem *base); int
> > +rcar_pcie_wait_for_dl(void __iomem *base); void
> > +rcar_pcie_set_outbound(int win, void __iomem *base, struct resource
> > +*res); void rcar_pcie_set_inbound(void __iomem *base, u64 cpu_addr,
> u64 pci_addr,
> > + u64 mask, int idx, bool host);
> > +
> > +#endif
> > --
> > 2.7.4



Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

2020-03-17 10:00:26

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 6/7] PCI: rcar: Add support for rcar PCIe controller in endpoint mode

Hi Prabhakar-san,

Thank you for the patch!

> From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
>
> This patch adds support for rcar PCIe controller to work in endpoint mode.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> ---
> drivers/pci/controller/Kconfig | 8 +
> drivers/pci/controller/Makefile | 1 +
> drivers/pci/controller/pcie-rcar-ep.c | 490 ++++++++++++++++++++++++++++++++++
> drivers/pci/controller/pcie-rcar.h | 4 +
> 4 files changed, 503 insertions(+)
> create mode 100644 drivers/pci/controller/pcie-rcar-ep.c
>
> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> index 37e0ea7..9bf4b02 100644
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -62,6 +62,14 @@ config PCIE_RCAR_HOST
> Say Y here if you want PCIe controller support on R-Car SoCs in host
> mode.
>
> +config PCIE_RCAR_EP
> + bool "Renesas R-Car PCIe endpoint controller"
> + depends on ARCH_RENESAS || COMPILE_TEST
> + depends on PCI_ENDPOINT
> + help
> + Say Y here if you want PCIe controller support on R-Car SoCs in
> + endpoint mode.
> +
> config PCI_HOST_COMMON
> bool
> select PCI_ECAM
> diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
> index b4ada32..067bd33 100644
> --- a/drivers/pci/controller/Makefile
> +++ b/drivers/pci/controller/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
> obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
> +obj-$(CONFIG_PCIE_RCAR_EP) += pcie-rcar.o pcie-rcar-ep.o
> obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
> obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
> obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
> diff --git a/drivers/pci/controller/pcie-rcar-ep.c b/drivers/pci/controller/pcie-rcar-ep.c
> new file mode 100644
> index 0000000..db89bbe
> --- /dev/null
> +++ b/drivers/pci/controller/pcie-rcar-ep.c
> @@ -0,0 +1,490 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe endpoint driver for Renesas R-Car SoCs
> + * Copyright (c) 2020 Renesas Electronics Europe GmbH
> + *
> + * Author: Lad Prabhakar <[email protected]>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci.h>
> +#include <linux/pci-epc.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +
> +#include "pcie-rcar.h"
> +
> +/* Structure representing the PCIe interface */
> +struct rcar_pcie {
> + phys_addr_t *ob_addr;

I think "ob_mapped_addr" is better.

> + struct pci_epc_mem_window *ob_window;

I think we can get these windows from "array of address space of
the endpoint controller" in struct pci_epc. If so, we can remove
this member.

> + struct pci_epc *epc;

This member can be removed like pcie-cadence-ep.c because
this is not used except saving the epc value from devm_pci_epc_create().

<snip>
> +static int rcar_pcie_ep_start(struct pci_epc *epc)
> +{
> + struct rcar_pcie *ep = epc_get_drvdata(epc);
> +
> + rcar_pci_write_reg(ep->base, CFINIT, PCIETCTLR);

The following setting is needed before CFINIT like host.

rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);

> +
> + return 0;
> +}
> +
> +static void rcar_pcie_ep_stop(struct pci_epc *epc)
> +{
> + struct rcar_pcie *ep = epc_get_drvdata(epc);
> +
> + rcar_pci_write_reg(ep->base, 0, PCIETCTLR);
> +}
> +
> +static const struct pci_epc_features rcar_pcie_epc_features = {
> + .linkup_notifier = false,
> + .msi_capable = false,
> + .msix_capable = false,
> + /* use 64-bit bars so mark bar1/3/5 as reserved */
> + .reserved_bar = 1 << BAR_1 | 1 << BAR_3 | 1 << BAR_5,
> + .bar_fixed_64bit = (1 << BAR_0) | (1 << BAR_2) | (1 << BAR_4),

These parentheses are not needed like .reserved_bar.

<snip>
> + err = pci_epc_mem_init(epc, pcie->ob_window, pcie->num_ob_windows);
> + if (err < 0) {
> + dev_err(dev, "failed to initialize the epc memory space\n");
> + goto err_pm_put;
> + }
> +
> + rcar_pcie_ep_hw_init(pcie);

I'm not sure, but I wonder if we should call this hw init before pci_epc_mem_init().

<snip>
> +builtin_platform_driver(rcar_pcie_ep_driver);
> diff --git a/drivers/pci/controller/pcie-rcar.h b/drivers/pci/controller/pcie-rcar.h
> index b529d806..5564ca8 100644
> --- a/drivers/pci/controller/pcie-rcar.h
> +++ b/drivers/pci/controller/pcie-rcar.h
> @@ -17,6 +17,7 @@
> #define PCIECDR 0x000020
> #define PCIEMSR 0x000028
> #define PCIEINTXR 0x000400
> +#define ASTINTX_SHIFT BIT(16)

Just "ASTINTX" is better.

> #define PCIEPHYSR 0x0007f0
> #define PHYRDY BIT(0)
> #define PCIEMSITXR 0x000840
> @@ -55,12 +56,15 @@
>
> /* Configuration */
> #define PCICONF(x) (0x010000 + ((x) * 0x4))
> +#define INTDIS_SHIFT BIT(10)

Same here (we can remove "_SHIFT").

Best regards,
Yoshihiro Shimoda

> #define PMCAP(x) (0x010040 + ((x) * 0x4))
> #define EXPCAP(x) (0x010070 + ((x) * 0x4))
> #define VCCAP(x) (0x010100 + ((x) * 0x4))
>
> /* link layer */
> +#define IDSETR0 0x011000
> #define IDSETR1 0x011004
> +#define SUBIDSETR 0x011024
> #define TLCTLR 0x011048
> #define MACSR 0x011054
> #define SPCHGFIN BIT(4)
> --
> 2.7.4

2020-03-17 10:04:26

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: RE: [PATCH v5 4/7] PCI: endpoint: Add support to handle multiple base for mapping outbound memory

Hi Yoshihiro-san,

Thank you for the review,

> -----Original Message-----
> From: Yoshihiro Shimoda <[email protected]>
> Sent: 17 March 2020 08:12
> To: Lad Prabhakar <[email protected]>
> Cc: Andrew Murray <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; Prabhakar Mahadev Lad <prabhakar.mahadev-
> [email protected]>; Bjorn Helgaas <[email protected]>; Rob
> Herring <[email protected]>; Mark Rutland <[email protected]>;
> Catalin Marinas <[email protected]>; Will Deacon <[email protected]>;
> Kishon Vijay Abraham I <[email protected]>; Lorenzo Pieralisi
> <[email protected]>; Arnd Bergmann <[email protected]>; Greg
> Kroah-Hartman <[email protected]>; Jingoo Han
> <[email protected]>; Gustavo Pimentel
> <[email protected]>; Marek Vasut
> <[email protected]>; Shawn Lin <shawn.lin@rock-
> chips.com>; Heiko Stuebner <[email protected]>
> Subject: RE: [PATCH v5 4/7] PCI: endpoint: Add support to handle multiple
> base for mapping outbound memory
>
> Hi Prabhakar-san,
>
> Thank you for the patch!
>
> > From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
> >
> > R-Car PCIe controller has support to map multiple memory regions for
> > mapping the outbound memory in local system also the controller limits
> > single allocation for each region (that is, once a chunk is used from
> > the region it cannot be used to allocate a new one). This features
> > inspires to add support for handling multiple memory bases in endpoint
> framework.
> >
> > With this patch pci_epc_mem_init() now accepts multiple regions, also
> > page_size for each memory region is passed during initialization so as
> > to handle single allocation for each region by setting the page_size
> > to window_size.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-
> [email protected]>
> > ---
> > drivers/pci/controller/cadence/pcie-cadence-ep.c | 7 +-
> > drivers/pci/controller/dwc/pcie-designware-ep.c | 29 ++--
> > drivers/pci/controller/pcie-rockchip-ep.c | 7 +-
> > drivers/pci/endpoint/pci-epc-mem.c | 167 ++++++++++++++++-----
> --
>
> I could not apply this patch on the latest pci.git / next branch.
> So, you need to rebase.
>
Yes it needs rebasing on https://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/log/?h=pci/endpoint

> > include/linux/pci-epc.h | 39 ++++--
> > 5 files changed, 169 insertions(+), 80 deletions(-)
> >
> > diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > index 1c173da..90e32438 100644
> > --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c
> > @@ -401,6 +401,7 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
> > struct device *dev = ep->pcie.dev;
> > struct platform_device *pdev = to_platform_device(dev);
> > struct device_node *np = dev->of_node;
> > +struct pci_epc_mem_window mem_window;
> > struct cdns_pcie *pcie = &ep->pcie;
> > struct resource *res;
> > struct pci_epc *epc;
> > @@ -449,8 +450,10 @@ int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
> > if (of_property_read_u8(np, "max-functions", &epc-
> >max_functions) < 0)
> > epc->max_functions = 1;
> >
> > -ret = pci_epc_mem_init(epc, pcie->mem_res->start,
> > - resource_size(pcie->mem_res));
> > +mem_window.phys_base = pcie->mem_res->start;
> > +mem_window.size = resource_size(pcie->mem_res);
> > +mem_window.page_size = PAGE_SIZE;
> > +ret = pci_epc_mem_init(epc, &mem_window, 1);
>
> I'm not sure my idea is acceptable or not but, I think we can have compatible
> API for single window like below.
> - In this patch, pci_epc_mem_init() and __pci_epc_mem_init() become the
> same behavior.
> So, for example, pci_epc_mem_init() is for simple, and
> __pci_epc_mem_init() is multiple windows.
> -- In this case, pci_epc_mem_init() should have page_size argument.
> - The original "mem" in the pci_epc can be the default window instead of
> PCI_EPC_DEFAULT_WINDOW.
>
OK

> > if (ret < 0) {
> > dev_err(dev, "failed to initialize the memory space\n");
> > goto err_init;
> > diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > index cfeccd7..b150ef3 100644
> > --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> > +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> > @@ -195,8 +195,7 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc
> > *epc, u8 func_no, }
> >
> > static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,
> > - phys_addr_t addr,
> > - u64 pci_addr, size_t size)
> > + phys_addr_t addr, u64 pci_addr, size_t size)
> > {
> > int ret;
> > struct dw_pcie_ep *ep = epc_get_drvdata(epc); @@ -367,6 +366,7
> @@
> > int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no,
> > unsigned int aligned_offset;
> > u16 msg_ctrl, msg_data;
> > u32 msg_addr_lower, msg_addr_upper, reg;
> > +int window = PCI_EPC_DEFAULT_WINDOW;
> > u64 msg_addr;
> > bool has_upper;
> > int ret;
> > @@ -390,11 +390,11 @@ int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep
> *ep, u8 func_no,
> > reg = ep->msi_cap + PCI_MSI_DATA_32;
> > msg_data = dw_pcie_readw_dbi(pci, reg);
> > }
> > -aligned_offset = msg_addr_lower & (epc->mem->page_size - 1);
> > +aligned_offset = msg_addr_lower & (epc->mem[window]-
> >page_size - 1);
> > msg_addr = ((u64)msg_addr_upper) << 32 |
> > (msg_addr_lower & ~aligned_offset);
> > -ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
> msg_addr,
> > - epc->mem->page_size);
> > +ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
> > + msg_addr, epc->mem[window]-
> >page_size);
> > if (ret)
> > return ret;
> >
> > @@ -416,6 +416,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep
> *ep, u8 func_no,
> > u32 reg, msg_data, vec_ctrl;
> > u64 tbl_addr, msg_addr, reg_u64;
> > void __iomem *msix_tbl;
> > +int window = PCI_EPC_DEFAULT_WINDOW;
> > int ret;
> >
> > reg = ep->msix_cap + PCI_MSIX_TABLE; @@ -452,8 +453,8 @@ int
> > dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
> > return -EPERM;
> > }
> >
> > -ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
> msg_addr,
> > - epc->mem->page_size);
> > +ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys,
> > + msg_addr, epc->mem[window]-
> >page_size);
> > if (ret)
> > return ret;
> >
> > @@ -466,10 +467,11 @@ int dw_pcie_ep_raise_msix_irq(struct
> dw_pcie_ep
> > *ep, u8 func_no,
> >
> > void dw_pcie_ep_exit(struct dw_pcie_ep *ep) {
> > +int window = PCI_EPC_DEFAULT_WINDOW;
> > struct pci_epc *epc = ep->epc;
> >
> > pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
> > - epc->mem->page_size);
> > + epc->mem[window]->page_size);
> >
> > pci_epc_mem_exit(epc);
> > }
> > @@ -502,6 +504,8 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
> > unsigned int nbars;
> > unsigned int offset;
> > struct pci_epc *epc;
> > +size_t msi_page_size;
> > +struct pci_epc_mem_window mem_window;
> > struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
> > struct device *dev = pci->dev;
> > struct device_node *np = dev->of_node; @@ -574,15 +578,18 @@
> int
> > dw_pcie_ep_init(struct dw_pcie_ep *ep)
> > if (ret < 0)
> > epc->max_functions = 1;
> >
> > -ret = __pci_epc_mem_init(epc, ep->phys_base, ep->addr_size,
> > - ep->page_size);
> > +mem_window.phys_base = ep->phys_base;
> > +mem_window.size = ep->addr_size;
> > +mem_window.page_size = ep->page_size;
> > +ret = __pci_epc_mem_init(epc, &mem_window, 1);
> > if (ret < 0) {
> > dev_err(dev, "Failed to initialize address space\n");
> > return ret;
> > }
> >
> > +msi_page_size = epc->mem[PCI_EPC_DEFAULT_WINDOW]-
> >page_size;
> > ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep-
> >msi_mem_phys,
> > - epc->mem->page_size);
> > + msi_page_size);
> > if (!ep->msi_mem) {
> > dev_err(dev, "Failed to reserve memory for MSI/MSI-X\n");
> > return -ENOMEM;
> > diff --git a/drivers/pci/controller/pcie-rockchip-ep.c
> > b/drivers/pci/controller/pcie-rockchip-ep.c
> > index d743b0a..5a97390 100644
> > --- a/drivers/pci/controller/pcie-rockchip-ep.c
> > +++ b/drivers/pci/controller/pcie-rockchip-ep.c
> > @@ -562,6 +562,7 @@ static const struct of_device_id
> > rockchip_pcie_ep_of_match[] = {
> >
> > static int rockchip_pcie_ep_probe(struct platform_device *pdev) {
> > +struct pci_epc_mem_window mem_window;
> > struct device *dev = &pdev->dev;
> > struct rockchip_pcie_ep *ep;
> > struct rockchip_pcie *rockchip;
> > @@ -614,8 +615,10 @@ static int rockchip_pcie_ep_probe(struct
> platform_device *pdev)
> > /* Only enable function 0 by default */
> > rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG);
> >
> > -err = pci_epc_mem_init(epc, rockchip->mem_res->start,
> > - resource_size(rockchip->mem_res));
> > +mem_window.phys_base = rockchip->mem_res->start;
> > +mem_window.size = resource_size(rockchip->mem_res);
> > +mem_window.page_size = PAGE_SIZE;
> > +err = pci_epc_mem_init(epc, &mem_window, 1);
> > if (err < 0) {
> > dev_err(dev, "failed to initialize the memory space\n");
> > goto err_uninit_port;
> > diff --git a/drivers/pci/endpoint/pci-epc-mem.c
> > b/drivers/pci/endpoint/pci-epc-mem.c
> > index d2b174c..6c21957 100644
> > --- a/drivers/pci/endpoint/pci-epc-mem.c
> > +++ b/drivers/pci/endpoint/pci-epc-mem.c
> > @@ -38,57 +38,76 @@ static int pci_epc_mem_get_order(struct
> > pci_epc_mem *mem, size_t size)
> > /**
> > * __pci_epc_mem_init() - initialize the pci_epc_mem structure
> > * @epc: the EPC device that invoked pci_epc_mem_init
> > - * @phys_base: the physical address of the base
> > - * @size: the size of the address space
> > - * @page_size: size of each page
> > + * @windows: pointer to windows supported by the device
> > + * @num_windows: number of windows device supports
> > *
> > * Invoke to initialize the pci_epc_mem structure used by the
> > * endpoint functions to allocate mapped PCI address.
> > */
> > -int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base,
> size_t size,
> > - size_t page_size)
> > +int __pci_epc_mem_init(struct pci_epc *epc, struct
> pci_epc_mem_window *windows,
> > + int num_windows)
> > {
> > -int ret;
> > -struct pci_epc_mem *mem;
> > -unsigned long *bitmap;
> > +struct pci_epc_mem *mem = NULL;
> > +unsigned long *bitmap = NULL;
> > unsigned int page_shift;
> > -int pages;
> > +size_t page_size;
> > int bitmap_size;
> > -
> > -if (page_size < PAGE_SIZE)
> > -page_size = PAGE_SIZE;
> > -
> > -page_shift = ilog2(page_size);
> > -pages = size >> page_shift;
> > -bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
> > -
> > -mem = kzalloc(sizeof(*mem), GFP_KERNEL);
> > -if (!mem) {
> > -ret = -ENOMEM;
> > -goto err;
> > -}
> > -
> > -bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> > -if (!bitmap) {
> > -ret = -ENOMEM;
> > -goto err_mem;
> > +int pages;
> > +int ret;
> > +int i;
> > +
> > +epc->mem_windows = 0;
> > +
> > +if (!windows)
> > +return -EINVAL;
> > +
> > +if (num_windows <= 0)
> > +return -EINVAL;
> > +
> > +epc->mem = kcalloc(num_windows, sizeof(*mem), GFP_KERNEL);
> > +if (!epc->mem)
> > +return -EINVAL;
> > +
> > +for (i = 0; i < num_windows; i++) {
> > +page_size = windows[i].page_size;
> > +if (page_size < PAGE_SIZE)
> > +page_size = PAGE_SIZE;
> > +page_shift = ilog2(page_size);
> > +pages = windows[i].size >> page_shift;
> > +bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
> > +
> > +mem = kzalloc(sizeof(*mem), GFP_KERNEL);
> > +if (!mem) {
> > +ret = -ENOMEM;
> > +goto err_mem;
> > +}
> > +
> > +bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> > +if (!bitmap) {
> > +ret = -ENOMEM;
> > +goto err_mem;
> > +}
> > +
> > +mem->bitmap = bitmap;
> > +mem->window.phys_base = windows[i].phys_base;
>
> I could not understand why the window member is needed.
> I think original members (just phys_base and size) are enough.
> Also, this function doesn't store the page_size to mem->window.page_size.
>
Because, for example on RZ/Gx platforms, following are the windows on endpoint device
where the root's address can be mapped, but where as on other platforms atm there
exists just single window to map. Also on RZ/Gx platforms if a window is allocated say of
size 1K, rest of the window cannot be used for other allocations.

1: 0xfe000000 0 0x80000
2: 0xfe100000 0 0x100000
3: 0xfe200000 0 0x200000
4: 0x30000000 0 0x8000000
5: 0x38000000 0 0x8000000

Struct pci_epc_mem_window, represents the above windows.

window.page_size is set by endpoint controller drivers as done in this patch.

> > +mem->page_size = page_size;
> > +mem->pages = pages;
> > +mem->window.size = windows[i].size;
> > +epc->mem[i] = mem;
> > }
> > -
> > -mem->bitmap = bitmap;
> > -mem->phys_base = phys_base;
> > -mem->page_size = page_size;
> > -mem->pages = pages;
> > -mem->size = size;
> > -
> > -epc->mem = mem;
> > +epc->mem_windows = num_windows;
> >
> > return 0;
> >
> > err_mem:
> > -kfree(mem);
> > +for (; i >= 0; i--) {
> > +mem = epc->mem[i];
> > +kfree(mem->bitmap);
>
> If bitmap cannot be allocated, the epc->mem[i] is NULL.
> So, freeing mem->bitmap anyway is not good.
>
Agreed shall fix it.

> > +kfree(mem);
> > +}
> > +kfree(epc->mem);
> >
> > -err:
> > -return ret;
> > +return ret;
> > }
> > EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
> >
> > @@ -101,11 +120,21 @@ EXPORT_SYMBOL_GPL(__pci_epc_mem_init);
> > */
> > void pci_epc_mem_exit(struct pci_epc *epc) {
> > -struct pci_epc_mem *mem = epc->mem;
> > +struct pci_epc_mem *mem;
> > +int i;
> > +
> > +if (!epc->mem_windows)
> > +return;
> > +
> > +for (i = 0; i <= epc->mem_windows; i++) {
> > +mem = epc->mem[i];
> > +kfree(mem->bitmap);
> > +kfree(mem);
> > +}
> > +kfree(epc->mem);
> >
> > epc->mem = NULL;
> > -kfree(mem->bitmap);
> > -kfree(mem);
> > +epc->mem_windows = 0;
> > }
> > EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
> >
> > @@ -121,20 +150,30 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
> > void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
> > phys_addr_t *phys_addr, size_t size) {
> > -int pageno;
> > -void __iomem *virt_addr;
> > -struct pci_epc_mem *mem = epc->mem;
> > -unsigned int page_shift = ilog2(mem->page_size);
> > +void __iomem *virt_addr = NULL;
> > +struct pci_epc_mem *mem;
> > +unsigned int page_shift;
> > +int pageno = -EINVAL;
> > int order;
> > +int i;
> >
> > -size = ALIGN(size, mem->page_size);
> > -order = pci_epc_mem_get_order(mem, size);
> > +for (i = 0; i < epc->mem_windows; i++) {
> > +mem = epc->mem[i];
> > +size = ALIGN(size, mem->page_size);
> > +order = pci_epc_mem_get_order(mem, size);
> > +
> > +pageno = bitmap_find_free_region(mem->bitmap, mem-
> >pages,
> > + order);
> > +if (pageno >= 0)
> > +break;
> > +}
> >
> > -pageno = bitmap_find_free_region(mem->bitmap, mem->pages,
> order);
> > if (pageno < 0)
> > return NULL;
> >
> > -*phys_addr = mem->phys_base + ((phys_addr_t)pageno <<
> page_shift);
> > +page_shift = ilog2(mem->page_size);
> > +*phys_addr = mem->window.phys_base +
> > + ((phys_addr_t)pageno << page_shift);
> > virt_addr = ioremap(*phys_addr, size);
> > if (!virt_addr)
> > bitmap_release_region(mem->bitmap, pageno, order); @@
> -143,6
> > +182,23 @@ void __iomem *pci_epc_mem_alloc_addr(struct pci_epc
> *epc,
> > } EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
> >
> > +struct pci_epc_mem *pci_epc_get_matching_window(struct pci_epc
> *epc,
> > +phys_addr_t phys_addr)
> > +{
> > +struct pci_epc_mem *mem;
> > +int i;
> > +
> > +for (i = 0; i < epc->mem_windows; i++) {
> > +mem = epc->mem[i];
> > +
> > +if (phys_addr >= mem->window.phys_base &&
> > + phys_addr < (mem->window.phys_base + mem-
> >window.size))
> > +return mem;
> > +}
> > +
> > +return NULL;
> > +}
> > +
> > /**
> > * pci_epc_mem_free_addr() - free the allocated memory address
> > * @epc: the EPC device on which memory was allocated @@ -155,13
> > +211,20 @@ EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
> > void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t
> phys_addr,
> > void __iomem *virt_addr, size_t size) {
> > +struct pci_epc_mem *mem;
> > +unsigned int page_shift;
> > int pageno;
> > -struct pci_epc_mem *mem = epc->mem;
> > -unsigned int page_shift = ilog2(mem->page_size);
> > int order;
> >
> > +mem = pci_epc_get_matching_window(epc, phys_addr);
> > +if (!mem) {
> > +pr_err("failed to get matching window\n");
> > +return;
> > +}
> > +
> > +page_shift = ilog2(mem->page_size);
> > iounmap(virt_addr);
> > -pageno = (phys_addr - mem->phys_base) >> page_shift;
> > +pageno = (phys_addr - mem->window.phys_base) >> page_shift;
> > size = ALIGN(size, mem->page_size);
> > order = pci_epc_mem_get_order(mem, size);
> > bitmap_release_region(mem->bitmap, pageno, order); diff --git
> > a/include/linux/pci-epc.h b/include/linux/pci-epc.h index
> > 56f1846..dde42e5 100644
> > --- a/include/linux/pci-epc.h
> > +++ b/include/linux/pci-epc.h
> > @@ -64,17 +64,29 @@ struct pci_epc_ops {
> > struct module *owner;
> > };
> >
> > +#define PCI_EPC_DEFAULT_WINDOW 0
> > +
> > +/**
> > + * struct pci_epc_mem_window - address window of the endpoint
> > +controller
> > + * @phys_base: physical base address of the PCI address window
> > + * @size: the size of the PCI address window
> > + * @page_size: size of each page
> > + */
> > +struct pci_epc_mem_window {
> > +phys_addr_tphys_base;
> > +size_tsize;
> > +size_tpage_size;
> > +};
> > +
> > /**
> > * struct pci_epc_mem - address space of the endpoint controller
> > - * @phys_base: physical base address of the PCI address space
> > - * @size: the size of the PCI address space
> > + * @window: address window of the endpoint controller
> > * @bitmap: bitmap to manage the PCI address space
> > - * @pages: number of bits representing the address region
> > * @page_size: size of each page
> > + * @pages: number of bits representing the address region
> > */
> > struct pci_epc_mem {
> > -phys_addr_tphys_base;
> > -size_tsize;
> > +struct pci_epc_mem_window window;
> > unsigned long*bitmap;
> > size_tpage_size;
> > intpages;
> > @@ -85,7 +97,8 @@ struct pci_epc_mem {
> > * @dev: PCI EPC device
> > * @pci_epf: list of endpoint functions present in this EPC device
> > * @ops: function pointers for performing endpoint operations
> > - * @mem: address space of the endpoint controller
>
> If my idea is acceptable, this should be "default address space ...".
>
Could you please elaborate more on how you would like the structures to be organized.

> > + * @mem: array of address space of the endpoint controller
>
> And, this should be difference name.
>
OK

> > + * @mem_windows: number of windows supported by device
>
> Perhaps, num_windows?
>
OK

> > * @max_functions: max number of functions that can be configured in
> this EPC
> > * @group: configfs group representing the PCI EPC device
> > * @lock: spinlock to protect pci_epc ops @@ -94,7 +107,8 @@ struct
> > pci_epc {
> > struct devicedev;
> > struct list_headpci_epf;
> > const struct pci_epc_ops*ops;
> > -struct pci_epc_mem*mem;
> > +struct pci_epc_mem**mem;
> > +unsigned intmem_windows;
> > u8max_functions;
> > struct config_group*group;
> > /* spinlock to protect against concurrent access of EP controller */
> > @@ -128,8 +142,8 @@ struct pci_epc_features {
> > #define devm_pci_epc_create(dev, ops) \
> > __devm_pci_epc_create((dev), (ops), THIS_MODULE)
> >
> > -#define pci_epc_mem_init(epc, phys_addr, size)\
> > -__pci_epc_mem_init((epc), (phys_addr), (size), PAGE_SIZE)
> > +#define pci_epc_mem_init(epc, windows, num_windows)\
> > +__pci_epc_mem_init((epc), windows, num_windows)
>
> As I mentioned above, pci_epc_mem_init() and __ pci_epc_mem_init() are
> the same behavior.
>
> > static inline void epc_set_drvdata(struct pci_epc *epc, void *data)
> > { @@ -159,8 +173,7 @@ int pci_epc_set_bar(struct pci_epc *epc, u8
> > func_no, void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no,
> > struct pci_epf_bar *epf_bar); int
> pci_epc_map_addr(struct
> > pci_epc *epc, u8 func_no,
> > - phys_addr_t phys_addr,
> > - u64 pci_addr, size_t size);
> > + phys_addr_t phys_addr, u64 pci_addr, size_t size);
>
> Perhaps, this is not needed to change?
>
Yes my bad.

Cheers,
--Prabhakar

> Best regards,
> Yoshihiro Shimoda
>
> > void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no,
> > phys_addr_t phys_addr);
> > int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 interrupts);
> > @@ -178,8 +191,8 @@ unsigned int pci_epc_get_first_free_bar(const
> > struct pci_epc_features struct pci_epc *pci_epc_get(const char
> > *epc_name); void pci_epc_put(struct pci_epc *epc);
> >
> > -int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr,
> size_t size,
> > - size_t page_size);
> > +int __pci_epc_mem_init(struct pci_epc *epc, struct
> pci_epc_mem_window *window,
> > + int num_windows);
> > void pci_epc_mem_exit(struct pci_epc *epc); void __iomem
> > *pci_epc_mem_alloc_addr(struct pci_epc *epc,
> > phys_addr_t *phys_addr, size_t size);
> > --
> > 2.7.4



Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

2020-03-17 10:15:42

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: RE: [PATCH v5 6/7] PCI: rcar: Add support for rcar PCIe controller in endpoint mode

Hi Yoshihiro-san,

Thank you for the review,

> -----Original Message-----
> From: Yoshihiro Shimoda <[email protected]>
> Sent: 17 March 2020 09:59
> To: Lad Prabhakar <[email protected]>
> Cc: Andrew Murray <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; Prabhakar Mahadev Lad <prabhakar.mahadev-
> [email protected]>; Bjorn Helgaas <[email protected]>; Rob
> Herring <[email protected]>; Mark Rutland <[email protected]>;
> Catalin Marinas <[email protected]>; Will Deacon <[email protected]>;
> Kishon Vijay Abraham I <[email protected]>; Lorenzo Pieralisi
> <[email protected]>; Arnd Bergmann <[email protected]>; Greg
> Kroah-Hartman <[email protected]>; Jingoo Han
> <[email protected]>; Gustavo Pimentel
> <[email protected]>; Marek Vasut
> <[email protected]>; Shawn Lin <shawn.lin@rock-
> chips.com>; Heiko Stuebner <[email protected]>
> Subject: RE: [PATCH v5 6/7] PCI: rcar: Add support for rcar PCIe controller in
> endpoint mode
>
> Hi Prabhakar-san,
>
> Thank you for the patch!
>
> > From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
> >
> > This patch adds support for rcar PCIe controller to work in endpoint mode.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-
> [email protected]>
> > ---
> > drivers/pci/controller/Kconfig | 8 +
> > drivers/pci/controller/Makefile | 1 +
> > drivers/pci/controller/pcie-rcar-ep.c | 490
> ++++++++++++++++++++++++++++++++++
> > drivers/pci/controller/pcie-rcar.h | 4 +
> > 4 files changed, 503 insertions(+)
> > create mode 100644 drivers/pci/controller/pcie-rcar-ep.c
> >
> > diff --git a/drivers/pci/controller/Kconfig
> > b/drivers/pci/controller/Kconfig index 37e0ea7..9bf4b02 100644
> > --- a/drivers/pci/controller/Kconfig
> > +++ b/drivers/pci/controller/Kconfig
> > @@ -62,6 +62,14 @@ config PCIE_RCAR_HOST
> > Say Y here if you want PCIe controller support on R-Car SoCs in host
> > mode.
> >
> > +config PCIE_RCAR_EP
> > +bool "Renesas R-Car PCIe endpoint controller"
> > +depends on ARCH_RENESAS || COMPILE_TEST
> > +depends on PCI_ENDPOINT
> > +help
> > + Say Y here if you want PCIe controller support on R-Car SoCs in
> > + endpoint mode.
> > +
> > config PCI_HOST_COMMON
> > bool
> > select PCI_ECAM
> > diff --git a/drivers/pci/controller/Makefile
> > b/drivers/pci/controller/Makefile index b4ada32..067bd33 100644
> > --- a/drivers/pci/controller/Makefile
> > +++ b/drivers/pci/controller/Makefile
> > @@ -8,6 +8,7 @@ obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
> > obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
> > obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
> > obj-$(CONFIG_PCIE_RCAR_HOST) += pcie-rcar.o pcie-rcar-host.o
> > +obj-$(CONFIG_PCIE_RCAR_EP) += pcie-rcar.o pcie-rcar-ep.o
> > obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
> > obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
> > obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o diff --git
> > a/drivers/pci/controller/pcie-rcar-ep.c
> > b/drivers/pci/controller/pcie-rcar-ep.c
> > new file mode 100644
> > index 0000000..db89bbe
> > --- /dev/null
> > +++ b/drivers/pci/controller/pcie-rcar-ep.c
> > @@ -0,0 +1,490 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * PCIe endpoint driver for Renesas R-Car SoCs
> > + * Copyright (c) 2020 Renesas Electronics Europe GmbH
> > + *
> > + * Author: Lad Prabhakar <[email protected]>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/delay.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_pci.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/pci.h>
> > +#include <linux/pci-epc.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +
> > +#include "pcie-rcar.h"
> > +
> > +/* Structure representing the PCIe interface */ struct rcar_pcie {
> > +phys_addr_t*ob_addr;
>
> I think "ob_mapped_addr" is better.
>
OK will rename that.

> > +struct pci_epc_mem_window *ob_window;
>
> I think we can get these windows from "array of address space of the
> endpoint controller" in struct pci_epc. If so, we can remove this member.
>
I shall see if this can be dropped.

> > +struct pci_epc*epc;
>
> This member can be removed like pcie-cadence-ep.c because this is not used
> except saving the epc value from devm_pci_epc_create().
>
OK will drop it.

> <snip>
> > +static int rcar_pcie_ep_start(struct pci_epc *epc) {
> > +struct rcar_pcie *ep = epc_get_drvdata(epc);
> > +
> > +rcar_pci_write_reg(ep->base, CFINIT, PCIETCTLR);
>
> The following setting is needed before CFINIT like host.
>
> rcar_pci_write_reg(pcie->base, MACCTLR_INIT_VAL, MACCTLR);
>
I shall add this as part of rcar_pcie_ep_hw_init()

> > +
> > +return 0;
> > +}
> > +
> > +static void rcar_pcie_ep_stop(struct pci_epc *epc) {
> > +struct rcar_pcie *ep = epc_get_drvdata(epc);
> > +
> > +rcar_pci_write_reg(ep->base, 0, PCIETCTLR); }
> > +
> > +static const struct pci_epc_features rcar_pcie_epc_features = {
> > +.linkup_notifier = false,
> > +.msi_capable = false,
> > +.msix_capable = false,
> > +/* use 64-bit bars so mark bar1/3/5 as reserved */
> > +.reserved_bar = 1 << BAR_1 | 1 << BAR_3 | 1 << BAR_5,
> > +.bar_fixed_64bit = (1 << BAR_0) | (1 << BAR_2) | (1 << BAR_4),
>
> These parentheses are not needed like .reserved_bar.
>
Agreed.

> <snip>
> > +err = pci_epc_mem_init(epc, pcie->ob_window, pcie-
> >num_ob_windows);
> > +if (err < 0) {
> > +dev_err(dev, "failed to initialize the epc memory space\n");
> > +goto err_pm_put;
> > +}
> > +
> > +rcar_pcie_ep_hw_init(pcie);
>
> I'm not sure, but I wonder if we should call this hw init before
> pci_epc_mem_init().
>
Ideally shouldn't matter because in pci_epc_mem_init(), we just tell the framework
our windows properties. But shall move hw_init() before mem_init().

> <snip>
> > +builtin_platform_driver(rcar_pcie_ep_driver);
> > diff --git a/drivers/pci/controller/pcie-rcar.h
> > b/drivers/pci/controller/pcie-rcar.h
> > index b529d806..5564ca8 100644
> > --- a/drivers/pci/controller/pcie-rcar.h
> > +++ b/drivers/pci/controller/pcie-rcar.h
> > @@ -17,6 +17,7 @@
> > #define PCIECDR0x000020
> > #define PCIEMSR0x000028
> > #define PCIEINTXR0x000400
> > +#define ASTINTX_SHIFTBIT(16)
>
> Just "ASTINTX" is better.
>
Shall replace it.

> > #define PCIEPHYSR0x0007f0
> > #define PHYRDYBIT(0)
> > #define PCIEMSITXR0x000840
> > @@ -55,12 +56,15 @@
> >
> > /* Configuration */
> > #define PCICONF(x)(0x010000 + ((x) * 0x4))
> > +#define INTDIS_SHIFTBIT(10)
>
> Same here (we can remove "_SHIFT").
>
OK.

Cheers,
--Prabhakar

> Best regards,
> Yoshihiro Shimoda
>
> > #define PMCAP(x)(0x010040 + ((x) * 0x4))
> > #define EXPCAP(x)(0x010070 + ((x) * 0x4))
> > #define VCCAP(x)(0x010100 + ((x) * 0x4))
> >
> > /* link layer */
> > +#define IDSETR00x011000
> > #define IDSETR10x011004
> > +#define SUBIDSETR0x011024
> > #define TLCTLR0x011048
> > #define MACSR0x011054
> > #define SPCHGFINBIT(4)
> > --
> > 2.7.4



Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

2020-03-17 10:18:46

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: RE: [PATCH v5 5/7] dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint controller

Hi Yoshihiro-san,

> -----Original Message-----
> From: Yoshihiro Shimoda <[email protected]>
> Sent: 17 March 2020 08:26
> To: Lad Prabhakar <[email protected]>
> Cc: Andrew Murray <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; Prabhakar Mahadev Lad <prabhakar.mahadev-
> [email protected]>; Rob Herring <[email protected]>; Bjorn Helgaas
> <[email protected]>; Rob Herring <[email protected]>; Mark Rutland
> <[email protected]>; Catalin Marinas <[email protected]>; Will
> Deacon <[email protected]>; Kishon Vijay Abraham I <[email protected]>;
> Lorenzo Pieralisi <[email protected]>; Arnd Bergmann
> <[email protected]>; Greg Kroah-Hartman <[email protected]>;
> Jingoo Han <[email protected]>; Gustavo Pimentel
> <[email protected]>; Marek Vasut
> <[email protected]>; Shawn Lin <shawn.lin@rock-
> chips.com>; Heiko Stuebner <[email protected]>
> Subject: RE: [PATCH v5 5/7] dt-bindings: PCI: rcar: Add bindings for R-Car PCIe
> endpoint controller
>
> Hi Prabhakar-san,
>
> Thank you for the patch!
>
> > From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
> >
> > This patch adds the bindings for the R-Car PCIe endpoint driver.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-
> [email protected]>
> > Reviewed-by: Rob Herring <[email protected]>
>
> Reviewed-by: Yoshihiro Shimoda <[email protected]>
>
Thank you for the review. Shall I add this file under "PCI DRIVER FOR RENESAS R-CAR"
In MAINTAINERS file as a separate patch ?

Cheers,
--Prabhakar

> Best regards,
> Yoshihiro Shimoda



Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

2020-03-17 10:33:23

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 7/7] misc: pci_endpoint_test: Add Device ID for RZ/G2E PCIe controller

Hi Prabhakar-san,

Thank you for the patch!

> From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
>
> Add RZ/G2E in pci_device_id table so that pci-epf-test can be used for
> testing PCIe EP in RZ/G2E.
>
> Signed-off-by: Lad Prabhakar <[email protected]>
> ---
> drivers/misc/pci_endpoint_test.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
> index a5e3170..3c84e9a 100644
> --- a/drivers/misc/pci_endpoint_test.c
> +++ b/drivers/misc/pci_endpoint_test.c
> @@ -66,6 +66,8 @@
>
> #define PCI_DEVICE_ID_TI_AM654 0xb00c
>
> +#define PCI_DEVICE_ID_RENESAS_RZG2E 0x002d

This define should be in include/linux/pci_ids.h, and adding
the define should be separated.
Also, I think "R8A774C0" is better than "RZG2E".

Best regards,
Yoshihiro Shimoda

> #define is_am654_pci_dev(pdev) \
> ((pdev)->device == PCI_DEVICE_ID_TI_AM654)
>
> @@ -797,6 +799,7 @@ static const struct pci_device_id pci_endpoint_test_tbl[] = {
> { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
> .driver_data = (kernel_ulong_t)&am654_data
> },
> + { PCI_DEVICE(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_RZG2E) },
> { }
> };
> MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
> --
> 2.7.4

2020-03-17 10:36:56

by Prabhakar Mahadev Lad

[permalink] [raw]
Subject: RE: [PATCH v5 7/7] misc: pci_endpoint_test: Add Device ID for RZ/G2E PCIe controller

Hi Yoshihiro,

Thank you for the review.

> -----Original Message-----
> From: Yoshihiro Shimoda <[email protected]>
> Sent: 17 March 2020 10:32
> To: Lad Prabhakar <[email protected]>
> Cc: Andrew Murray <[email protected]>; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; Prabhakar Mahadev Lad <prabhakar.mahadev-
> [email protected]>; Bjorn Helgaas <[email protected]>; Rob
> Herring <[email protected]>; Mark Rutland <[email protected]>;
> Catalin Marinas <[email protected]>; Will Deacon <[email protected]>;
> Kishon Vijay Abraham I <[email protected]>; Lorenzo Pieralisi
> <[email protected]>; Arnd Bergmann <[email protected]>; Greg
> Kroah-Hartman <[email protected]>; Jingoo Han
> <[email protected]>; Gustavo Pimentel
> <[email protected]>; Marek Vasut
> <[email protected]>; Shawn Lin <shawn.lin@rock-
> chips.com>; Heiko Stuebner <[email protected]>
> Subject: RE: [PATCH v5 7/7] misc: pci_endpoint_test: Add Device ID for
> RZ/G2E PCIe controller
>
> Hi Prabhakar-san,
>
> Thank you for the patch!
>
> > From: Lad Prabhakar, Sent: Saturday, February 29, 2020 12:41 AM
> >
> > Add RZ/G2E in pci_device_id table so that pci-epf-test can be used for
> > testing PCIe EP in RZ/G2E.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-
> [email protected]>
> > ---
> > drivers/misc/pci_endpoint_test.c | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/misc/pci_endpoint_test.c
> > b/drivers/misc/pci_endpoint_test.c
> > index a5e3170..3c84e9a 100644
> > --- a/drivers/misc/pci_endpoint_test.c
> > +++ b/drivers/misc/pci_endpoint_test.c
> > @@ -66,6 +66,8 @@
> >
> > #define PCI_DEVICE_ID_TI_AM6540xb00c
> >
> > +#define PCI_DEVICE_ID_RENESAS_RZG2E0x002d
>
> This define should be in include/linux/pci_ids.h, and adding the define
> should be separated.
> Also, I think "R8A774C0" is better than "RZG2E".
>
Agreed will add it under PCI_VENDOR_ID_RENESAS.

Cheers,
--Prabhakar

> Best regards,
> Yoshihiro Shimoda
>
> > #define is_am654_pci_dev(pdev)\
> > ((pdev)->device == PCI_DEVICE_ID_TI_AM654)
> >
> > @@ -797,6 +799,7 @@ static const struct pci_device_id
> pci_endpoint_test_tbl[] = {
> > { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654),
> > .driver_data = (kernel_ulong_t)&am654_data
> > },
> > +{ PCI_DEVICE(PCI_VENDOR_ID_RENESAS,
> PCI_DEVICE_ID_RENESAS_RZG2E) },
> > { }
> > };
> > MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
> > --
> > 2.7.4



Renesas Electronics Europe GmbH, Geschaeftsfuehrer/President: Carsten Jauch, Sitz der Gesellschaft/Registered office: Duesseldorf, Arcadiastrasse 10, 40472 Duesseldorf, Germany, Handelsregister/Commercial Register: Duesseldorf, HRB 3708 USt-IDNr./Tax identification no.: DE 119353406 WEEE-Reg.-Nr./WEEE reg. no.: DE 14978647

2020-03-17 11:17:00

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 5/7] dt-bindings: PCI: rcar: Add bindings for R-Car PCIe endpoint controller

Hi Prabhakar-san,

> From: Prabhakar Mahadev Lad, Sent: Tuesday, March 17, 2020 7:18 PM
<snip>
> > > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-
> > [email protected]>
> > > Reviewed-by: Rob Herring <[email protected]>
> >
> > Reviewed-by: Yoshihiro Shimoda <[email protected]>
> >
> Thank you for the review. Shall I add this file under "PCI DRIVER FOR RENESAS R-CAR"
> In MAINTAINERS file as a separate patch ?

That's a nice idea! I think we should add the following like for dt-binding:

F: Documentation/devicetree/bindings/pci/*rcar*

Best regards,
Yoshihiro Shimoda

> Cheers,
> --Prabhakar
>
> > Best regards,
> > Yoshihiro Shimoda

2020-03-17 11:21:16

by Yoshihiro Shimoda

[permalink] [raw]
Subject: RE: [PATCH v5 4/7] PCI: endpoint: Add support to handle multiple base for mapping outbound memory

Hi Prabhakar-san,

Just in my opinion though, automatically adding new line of email client
should be disabled or setting larger characters.
# In my side, I change the setting as 132 characters on Outlook :)

> From: Prabhakar Mahadev Lad, Sent: Tuesday, March 17, 2020 7:04 PM
<snip>
> > > -int __pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base,
> > size_t size,
> > > - size_t page_size)
> > > +int __pci_epc_mem_init(struct pci_epc *epc, struct
> > pci_epc_mem_window *windows,
> > > + int num_windows)
> > > {
> > > - int ret;
> > > - struct pci_epc_mem *mem;
> > > - unsigned long *bitmap;
> > > + struct pci_epc_mem *mem = NULL;
> > > + unsigned long *bitmap = NULL;
> > > unsigned int page_shift;
> > > - int pages;
> > > + size_t page_size;
> > > int bitmap_size;
> > > -
> > > - if (page_size < PAGE_SIZE)
> > > - page_size = PAGE_SIZE;
> > > -
> > > - page_shift = ilog2(page_size);
> > > - pages = size >> page_shift;
> > > - bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
> > > -
> > > - mem = kzalloc(sizeof(*mem), GFP_KERNEL);
> > > - if (!mem) {
> > > - ret = -ENOMEM;
> > > - goto err;
> > > - }
> > > -
> > > - bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> > > - if (!bitmap) {
> > > - ret = -ENOMEM;
> > > - goto err_mem;
> > > + int pages;
> > > + int ret;
> > > + int i;
> > > +
> > > + epc->mem_windows = 0;
> > > +
> > > + if (!windows)
> > > + return -EINVAL;
> > > +
> > > + if (num_windows <= 0)
> > > + return -EINVAL;
> > > +
> > > + epc->mem = kcalloc(num_windows, sizeof(*mem), GFP_KERNEL);
> > > + if (!epc->mem)
> > > + return -EINVAL;
> > > +
> > > + for (i = 0; i < num_windows; i++) {
> > > + page_size = windows[i].page_size;
> > > + if (page_size < PAGE_SIZE)
> > > + page_size = PAGE_SIZE;
> > > + page_shift = ilog2(page_size);
> > > + pages = windows[i].size >> page_shift;
> > > + bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
> > > +
> > > + mem = kzalloc(sizeof(*mem), GFP_KERNEL);
> > > + if (!mem) {
> > > + ret = -ENOMEM;
> > > + goto err_mem;
> > > + }
> > > +
> > > + bitmap = kzalloc(bitmap_size, GFP_KERNEL);
> > > + if (!bitmap) {
> > > + ret = -ENOMEM;
> > > + goto err_mem;
> > > + }
> > > +
> > > + mem->bitmap = bitmap;
> > > + mem->window.phys_base = windows[i].phys_base;
> >
> > I could not understand why the window member is needed.
> > I think original members (just phys_base and size) are enough.
> > Also, this function doesn't store the page_size to mem->window.page_size.

I'm sorry, but I meant the window member is in the left side (mem->window.phys_base).
In other words, this patch changes the struct pci_epc_mem like below, but
I'm thinking this change is not needed because struct pci_epc will have
multiple windows as "array of address space of the endpoint controller".
---
struct pci_epc_mem {
- phys_addr_t phys_base;
- size_t size;
+ struct pci_epc_mem_window window;
---

> Because, for example on RZ/Gx platforms, following are the windows on endpoint device
> where the root's address can be mapped, but where as on other platforms atm there
> exists just single window to map. Also on RZ/Gx platforms if a window is allocated say of
> size 1K, rest of the window cannot be used for other allocations.
>
> 1: 0xfe000000 0 0x80000
> 2: 0xfe100000 0 0x100000
> 3: 0xfe200000 0 0x200000
> 4: 0x30000000 0 0x8000000
> 5: 0x38000000 0 0x8000000
>
> Struct pci_epc_mem_window, represents the above windows.

Yes, I understood it.

> window.page_size is set by endpoint controller drivers as done in this patch.

I meant the left side. No one change the mem->window.page_size so that
the value seems to be 0. Of course, for now, this is no problem because
no one uses this value though.

<snip>
> > > /**
> > > * struct pci_epc_mem - address space of the endpoint controller
> > > - * @phys_base: physical base address of the PCI address space
> > > - * @size: the size of the PCI address space
> > > + * @window: address window of the endpoint controller
> > > * @bitmap: bitmap to manage the PCI address space
> > > - * @pages: number of bits representing the address region
> > > * @page_size: size of each page
> > > + * @pages: number of bits representing the address region
> > > */
> > > struct pci_epc_mem {
> > > - phys_addr_t phys_base;
> > > - size_t size;
> > > + struct pci_epc_mem_window window;
> > > unsigned long *bitmap;
> > > size_t page_size;
> > > int pages;
> > > @@ -85,7 +97,8 @@ struct pci_epc_mem {
> > > * @dev: PCI EPC device
> > > * @pci_epf: list of endpoint functions present in this EPC device
> > > * @ops: function pointers for performing endpoint operations
> > > - * @mem: address space of the endpoint controller
> >
> > If my idea is acceptable, this should be "default address space ...".
> >
> Could you please elaborate more on how you would like the structures to be organized.

* @mem: default address space of the endpoint controller.

And, if I assumed the "array of address space of the endpoint controller"
is renamed as struct pci_epc_mem **windows and when __pci_epc_mem_init() is succeeded,
the function should set the mem value right before return as the first window like below.

+ epc->mem = epc->windows[0];
+ epc->num_windows = num_windows;

return 0;

Best regards,
Yoshihiro Shimoda