From: Hou Zhiqiang <[email protected]>
This patch set is to recode the Mobiveil driver and add
PCIe support for NXP Layerscape series SoCs integrated
Mobiveil's PCIe Gen4 controller.
Hou Zhiqiang (13):
PCI: mobiveil: Introduce a new structure mobiveil_root_port
PCI: mobiveil: Move the host initialization into a function
PCI: mobiveil: Collect the interrupt related operations into a
function
PCI: mobiveil: Modularize the Mobiveil PCIe Host Bridge IP driver
PCI: mobiveil: Add callback function for interrupt initialization
PCI: mobiveil: Add callback function for link up check
PCI: mobiveil: Allow mobiveil_host_init() to be used to re-init host
PCI: mobiveil: Add 8-bit and 16-bit CSR register accessors
PCI: mobiveil: Add Header Type field check
dt-bindings: PCI: Add NXP Layerscape SoCs PCIe Gen4 controller
PCI: mobiveil: Add PCIe Gen4 RC driver for NXP Layerscape SoCs
arm64: dts: lx2160a: Add PCIe controller DT nodes
arm64: defconfig: Enable CONFIG_PCIE_LAYERSCAPE_GEN4
.../bindings/pci/layerscape-pcie-gen4.txt | 52 ++
MAINTAINERS | 10 +-
.../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 163 +++++
arch/arm64/configs/defconfig | 1 +
drivers/pci/controller/Kconfig | 11 +-
drivers/pci/controller/Makefile | 2 +-
drivers/pci/controller/mobiveil/Kconfig | 33 +
drivers/pci/controller/mobiveil/Makefile | 5 +
.../mobiveil/pcie-layerscape-gen4.c | 267 +++++++++
.../pcie-mobiveil-host.c} | 564 ++++--------------
.../controller/mobiveil/pcie-mobiveil-plat.c | 61 ++
.../pci/controller/mobiveil/pcie-mobiveil.c | 230 +++++++
.../pci/controller/mobiveil/pcie-mobiveil.h | 226 +++++++
13 files changed, 1170 insertions(+), 455 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
create mode 100644 drivers/pci/controller/mobiveil/Kconfig
create mode 100644 drivers/pci/controller/mobiveil/Makefile
create mode 100644 drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
rename drivers/pci/controller/{pcie-mobiveil.c => mobiveil/pcie-mobiveil-host.c} (54%)
create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.c
create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.h
--
2.17.1
From: Hou Zhiqiang <[email protected]>
The Mobiveil PCIe controller can work in either Root Complex
mode or Endpoint mode. So introduce a new structure
mobiveil_root_port, and abstract the RC related members into
it such that the code can be used by both mode.
Signed-off-by: Hou Zhiqiang <[email protected]>
---
V10:
- Refined the subject and change log.
- Added prefix mobiveil to the root port structure.
drivers/pci/controller/pcie-mobiveil.c | 99 ++++++++++++++++----------
1 file changed, 60 insertions(+), 39 deletions(-)
diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
index 3a696ca45bfa..d4de560cd711 100644
--- a/drivers/pci/controller/pcie-mobiveil.c
+++ b/drivers/pci/controller/pcie-mobiveil.c
@@ -3,7 +3,10 @@
* PCIe host controller driver for Mobiveil PCIe Host controller
*
* Copyright (c) 2018 Mobiveil Inc.
+ * Copyright 2019-2020 NXP
+ *
* Author: Subrahmanya Lingappa <[email protected]>
+ * Hou Zhiqiang <[email protected]>
*/
#include <linux/delay.h>
@@ -138,22 +141,27 @@ struct mobiveil_msi { /* MSI information */
DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI);
};
+struct mobiveil_root_port {
+ char root_bus_nr;
+ void __iomem *config_axi_slave_base; /* endpoint config base */
+ struct resource *ob_io_res;
+ int irq;
+ raw_spinlock_t intx_mask_lock;
+ struct irq_domain *intx_domain;
+ struct mobiveil_msi msi;
+ struct pci_host_bridge *bridge;
+};
+
struct mobiveil_pcie {
struct platform_device *pdev;
- void __iomem *config_axi_slave_base; /* endpoint config base */
void __iomem *csr_axi_slave_base; /* root port config base */
void __iomem *apb_csr_base; /* MSI register base */
phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */
- struct irq_domain *intx_domain;
- raw_spinlock_t intx_mask_lock;
- int irq;
int apio_wins;
int ppio_wins;
int ob_wins_configured; /* configured outbound windows */
int ib_wins_configured; /* configured inbound windows */
- struct resource *ob_io_res;
- char root_bus_nr;
- struct mobiveil_msi msi;
+ struct mobiveil_root_port rp;
};
/*
@@ -281,16 +289,17 @@ static bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
static bool mobiveil_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
{
struct mobiveil_pcie *pcie = bus->sysdata;
+ struct mobiveil_root_port *rp = &pcie->rp;
/* Only one device down on each root port */
- if ((bus->number == pcie->root_bus_nr) && (devfn > 0))
+ if ((bus->number == rp->root_bus_nr) && (devfn > 0))
return false;
/*
* Do not read more than one device on the bus directly
* attached to RC
*/
- if ((bus->primary == pcie->root_bus_nr) && (PCI_SLOT(devfn) > 0))
+ if ((bus->primary == rp->root_bus_nr) && (PCI_SLOT(devfn) > 0))
return false;
return true;
@@ -304,13 +313,14 @@ static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus,
unsigned int devfn, int where)
{
struct mobiveil_pcie *pcie = bus->sysdata;
+ struct mobiveil_root_port *rp = &pcie->rp;
u32 value;
if (!mobiveil_pcie_valid_device(bus, devfn))
return NULL;
/* RC config access */
- if (bus->number == pcie->root_bus_nr)
+ if (bus->number == rp->root_bus_nr)
return pcie->csr_axi_slave_base + where;
/*
@@ -325,7 +335,7 @@ static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus,
mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0));
- return pcie->config_axi_slave_base + where;
+ return rp->config_axi_slave_base + where;
}
static struct pci_ops mobiveil_pcie_ops = {
@@ -339,7 +349,8 @@ static void mobiveil_pcie_isr(struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
struct mobiveil_pcie *pcie = irq_desc_get_handler_data(desc);
struct device *dev = &pcie->pdev->dev;
- struct mobiveil_msi *msi = &pcie->msi;
+ struct mobiveil_root_port *rp = &pcie->rp;
+ struct mobiveil_msi *msi = &rp->msi;
u32 msi_data, msi_addr_lo, msi_addr_hi;
u32 intr_status, msi_status;
unsigned long shifted_status;
@@ -365,7 +376,7 @@ static void mobiveil_pcie_isr(struct irq_desc *desc)
shifted_status >>= PAB_INTX_START;
do {
for_each_set_bit(bit, &shifted_status, PCI_NUM_INTX) {
- virq = irq_find_mapping(pcie->intx_domain,
+ virq = irq_find_mapping(rp->intx_domain,
bit + 1);
if (virq)
generic_handle_irq(virq);
@@ -424,15 +435,16 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
struct device *dev = &pcie->pdev->dev;
struct platform_device *pdev = pcie->pdev;
struct device_node *node = dev->of_node;
+ struct mobiveil_root_port *rp = &pcie->rp;
struct resource *res;
/* map config resource */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"config_axi_slave");
- pcie->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
- if (IS_ERR(pcie->config_axi_slave_base))
- return PTR_ERR(pcie->config_axi_slave_base);
- pcie->ob_io_res = res;
+ rp->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
+ if (IS_ERR(rp->config_axi_slave_base))
+ return PTR_ERR(rp->config_axi_slave_base);
+ rp->ob_io_res = res;
/* map csr resource */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -455,9 +467,9 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
pcie->ppio_wins = MAX_PIO_WINDOWS;
- pcie->irq = platform_get_irq(pdev, 0);
- if (pcie->irq <= 0) {
- dev_err(dev, "failed to map IRQ: %d\n", pcie->irq);
+ rp->irq = platform_get_irq(pdev, 0);
+ if (rp->irq <= 0) {
+ dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
return -ENODEV;
}
@@ -564,9 +576,9 @@ static int mobiveil_bringup_link(struct mobiveil_pcie *pcie)
static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
{
phys_addr_t msg_addr = pcie->pcie_reg_base;
- struct mobiveil_msi *msi = &pcie->msi;
+ struct mobiveil_msi *msi = &pcie->rp.msi;
- pcie->msi.num_of_vectors = PCI_NUM_MSI;
+ msi->num_of_vectors = PCI_NUM_MSI;
msi->msi_pages_phys = (phys_addr_t)msg_addr;
writel_relaxed(lower_32_bits(msg_addr),
@@ -579,7 +591,8 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
static int mobiveil_host_init(struct mobiveil_pcie *pcie)
{
- struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
+ struct mobiveil_root_port *rp = &pcie->rp;
+ struct pci_host_bridge *bridge = rp->bridge;
u32 value, pab_ctrl, type;
struct resource_entry *win;
@@ -629,8 +642,8 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
*/
/* config outbound translation window */
- program_ob_windows(pcie, WIN_NUM_0, pcie->ob_io_res->start, 0,
- CFG_WINDOW_TYPE, resource_size(pcie->ob_io_res));
+ program_ob_windows(pcie, WIN_NUM_0, rp->ob_io_res->start, 0,
+ CFG_WINDOW_TYPE, resource_size(rp->ob_io_res));
/* memory inbound translation window */
program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
@@ -667,32 +680,36 @@ static void mobiveil_mask_intx_irq(struct irq_data *data)
{
struct irq_desc *desc = irq_to_desc(data->irq);
struct mobiveil_pcie *pcie;
+ struct mobiveil_root_port *rp;
unsigned long flags;
u32 mask, shifted_val;
pcie = irq_desc_get_chip_data(desc);
+ rp = &pcie->rp;
mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
- raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
+ raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
shifted_val &= ~mask;
mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
- raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
+ raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
}
static void mobiveil_unmask_intx_irq(struct irq_data *data)
{
struct irq_desc *desc = irq_to_desc(data->irq);
struct mobiveil_pcie *pcie;
+ struct mobiveil_root_port *rp;
unsigned long flags;
u32 shifted_val, mask;
pcie = irq_desc_get_chip_data(desc);
+ rp = &pcie->rp;
mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
- raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
+ raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
shifted_val |= mask;
mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
- raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
+ raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
}
static struct irq_chip intx_irq_chip = {
@@ -760,7 +777,7 @@ static int mobiveil_irq_msi_domain_alloc(struct irq_domain *domain,
unsigned int nr_irqs, void *args)
{
struct mobiveil_pcie *pcie = domain->host_data;
- struct mobiveil_msi *msi = &pcie->msi;
+ struct mobiveil_msi *msi = &pcie->rp.msi;
unsigned long bit;
WARN_ON(nr_irqs != 1);
@@ -787,7 +804,7 @@ static void mobiveil_irq_msi_domain_free(struct irq_domain *domain,
{
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(d);
- struct mobiveil_msi *msi = &pcie->msi;
+ struct mobiveil_msi *msi = &pcie->rp.msi;
mutex_lock(&msi->lock);
@@ -808,9 +825,9 @@ static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie)
{
struct device *dev = &pcie->pdev->dev;
struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
- struct mobiveil_msi *msi = &pcie->msi;
+ struct mobiveil_msi *msi = &pcie->rp.msi;
- mutex_init(&pcie->msi.lock);
+ mutex_init(&msi->lock);
msi->dev_domain = irq_domain_add_linear(NULL, msi->num_of_vectors,
&msi_domain_ops, pcie);
if (!msi->dev_domain) {
@@ -834,18 +851,19 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
{
struct device *dev = &pcie->pdev->dev;
struct device_node *node = dev->of_node;
+ struct mobiveil_root_port *rp = &pcie->rp;
int ret;
/* setup INTx */
- pcie->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
- &intx_domain_ops, pcie);
+ rp->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
+ &intx_domain_ops, pcie);
- if (!pcie->intx_domain) {
+ if (!rp->intx_domain) {
dev_err(dev, "Failed to get a INTx IRQ domain\n");
return -ENOMEM;
}
- raw_spin_lock_init(&pcie->intx_mask_lock);
+ raw_spin_lock_init(&rp->intx_mask_lock);
/* setup MSI */
ret = mobiveil_allocate_msi_domains(pcie);
@@ -862,6 +880,7 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
struct pci_bus *child;
struct pci_host_bridge *bridge;
struct device *dev = &pdev->dev;
+ struct mobiveil_root_port *rp;
int ret;
/* allocate the PCIe port */
@@ -870,6 +889,8 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
+ rp = &pcie->rp;
+ rp->bridge = bridge;
pcie->pdev = pdev;
@@ -904,12 +925,12 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
return ret;
}
- irq_set_chained_handler_and_data(pcie->irq, mobiveil_pcie_isr, pcie);
+ irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
/* Initialize bridge */
bridge->dev.parent = dev;
bridge->sysdata = pcie;
- bridge->busnr = pcie->root_bus_nr;
+ bridge->busnr = rp->root_bus_nr;
bridge->ops = &mobiveil_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
--
2.17.1
From: Hou Zhiqiang <[email protected]>
Move the host initialization related operations into a new
routine such that it can be reused by other incoming platform's
PCIe host driver, in which the Mobiveil GPEX is integrated.
Change the subject and change log slightly.
Change the function mobiveil_pcie_host_probe to static.
Add back the comments that was lost in v9.
Signed-off-by: Hou Zhiqiang <[email protected]>
---
V10:
- Refined the subject and change log.
- Changed the mobiveil_pcie_host_probe() to a static function.
- Added back the lost comments.
drivers/pci/controller/pcie-mobiveil.c | 39 +++++++++++++++-----------
1 file changed, 23 insertions(+), 16 deletions(-)
diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
index d4de560cd711..01df04ea5b48 100644
--- a/drivers/pci/controller/pcie-mobiveil.c
+++ b/drivers/pci/controller/pcie-mobiveil.c
@@ -873,27 +873,15 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
return 0;
}
-static int mobiveil_pcie_probe(struct platform_device *pdev)
+static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
{
- struct mobiveil_pcie *pcie;
+ struct mobiveil_root_port *rp = &pcie->rp;
+ struct pci_host_bridge *bridge = rp->bridge;
+ struct device *dev = &pcie->pdev->dev;
struct pci_bus *bus;
struct pci_bus *child;
- struct pci_host_bridge *bridge;
- struct device *dev = &pdev->dev;
- struct mobiveil_root_port *rp;
int ret;
- /* allocate the PCIe port */
- bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
- if (!bridge)
- return -ENOMEM;
-
- pcie = pci_host_bridge_priv(bridge);
- rp = &pcie->rp;
- rp->bridge = bridge;
-
- pcie->pdev = pdev;
-
ret = mobiveil_pcie_parse_dt(pcie);
if (ret) {
dev_err(dev, "Parsing DT failed, ret: %x\n", ret);
@@ -956,6 +944,25 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
return 0;
}
+static int mobiveil_pcie_probe(struct platform_device *pdev)
+{
+ struct mobiveil_pcie *pcie;
+ struct pci_host_bridge *bridge;
+ struct device *dev = &pdev->dev;
+
+ /* allocate the PCIe port */
+ bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
+ if (!bridge)
+ return -ENOMEM;
+
+ pcie = pci_host_bridge_priv(bridge);
+ pcie->rp.bridge = bridge;
+
+ pcie->pdev = pdev;
+
+ return mobiveil_pcie_host_probe(pcie);
+}
+
static const struct of_device_id mobiveil_pcie_of_match[] = {
{.compatible = "mbvl,gpex40-pcie",},
{},
--
2.17.1
From: Hou Zhiqiang <[email protected]>
Collect the interrupt initialization related operations into
a new function such that it is more readable.
Signed-off-by: Hou Zhiqiang <[email protected]>
---
V10:
- Refined the subject and change log.
drivers/pci/controller/pcie-mobiveil.c | 65 +++++++++++++++++---------
1 file changed, 42 insertions(+), 23 deletions(-)
diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
index 01df04ea5b48..9449528bb14f 100644
--- a/drivers/pci/controller/pcie-mobiveil.c
+++ b/drivers/pci/controller/pcie-mobiveil.c
@@ -454,12 +454,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
return PTR_ERR(pcie->csr_axi_slave_base);
pcie->pcie_reg_base = res->start;
- /* map MSI config resource */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr");
- pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
- if (IS_ERR(pcie->apb_csr_base))
- return PTR_ERR(pcie->apb_csr_base);
-
/* read the number of windows requested */
if (of_property_read_u32(node, "apio-wins", &pcie->apio_wins))
pcie->apio_wins = MAX_PIO_WINDOWS;
@@ -467,12 +461,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
pcie->ppio_wins = MAX_PIO_WINDOWS;
- rp->irq = platform_get_irq(pdev, 0);
- if (rp->irq <= 0) {
- dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
- return -ENODEV;
- }
-
return 0;
}
@@ -618,9 +606,6 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
pab_ctrl |= (1 << AMBA_PIO_ENABLE_SHIFT) | (1 << PEX_PIO_ENABLE_SHIFT);
mobiveil_csr_writel(pcie, pab_ctrl, PAB_CTRL);
- mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
- PAB_INTP_AMBA_MISC_ENB);
-
/*
* program PIO Enable Bit to 1 and Config Window Enable Bit to 1 in
* PAB_AXI_PIO_CTRL Register
@@ -670,9 +655,6 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
value |= (PCI_CLASS_BRIDGE_PCI << 16);
mobiveil_csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
- /* setup MSI hardware registers */
- mobiveil_pcie_enable_msi(pcie);
-
return 0;
}
@@ -873,6 +855,46 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
return 0;
}
+static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
+{
+ struct platform_device *pdev = pcie->pdev;
+ struct device *dev = &pdev->dev;
+ struct mobiveil_root_port *rp = &pcie->rp;
+ struct resource *res;
+ int ret;
+
+ /* map MSI config resource */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr");
+ pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
+ if (IS_ERR(pcie->apb_csr_base))
+ return PTR_ERR(pcie->apb_csr_base);
+
+ /* setup MSI hardware registers */
+ mobiveil_pcie_enable_msi(pcie);
+
+ rp->irq = platform_get_irq(pdev, 0);
+ if (rp->irq <= 0) {
+ dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
+ return -ENODEV;
+ }
+
+ /* initialize the IRQ domains */
+ ret = mobiveil_pcie_init_irq_domain(pcie);
+ if (ret) {
+ dev_err(dev, "Failed creating IRQ Domain\n");
+ return ret;
+ }
+
+ irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
+
+ /* Enable interrupts */
+ mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
+ PAB_INTP_AMBA_MISC_ENB);
+
+
+ return 0;
+}
+
static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
{
struct mobiveil_root_port *rp = &pcie->rp;
@@ -906,15 +928,12 @@ static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
return ret;
}
- /* initialize the IRQ domains */
- ret = mobiveil_pcie_init_irq_domain(pcie);
+ ret = mobiveil_pcie_interrupt_init(pcie);
if (ret) {
- dev_err(dev, "Failed creating IRQ Domain\n");
+ dev_err(dev, "Interrupt init failed\n");
return ret;
}
- irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
-
/* Initialize bridge */
bridge->dev.parent = dev;
bridge->sysdata = pcie;
--
2.17.1
From: Hou Zhiqiang <[email protected]>
Modularize the Mobiveil PCIe host driver according to the
abstraction of Root Complex and Endpoint and move it into
a new directory.
Split the RC related routines into pcie-mobiveil-host.c,
and common routines into pcie-mobiveil.c, move the macro
definitions and function declarations into pcie-mobiveil.h,
and the Mobiveil platform reference code into
pcie-mobiveil-plat.c. So that it is easy to reuse the
extracted routines to add a new host driver, which
integrated Mobiveil PCIe GPEX IP.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
---
V10:
- No change
MAINTAINERS | 2 +-
drivers/pci/controller/Kconfig | 11 +-
drivers/pci/controller/Makefile | 2 +-
drivers/pci/controller/mobiveil/Kconfig | 24 ++
drivers/pci/controller/mobiveil/Makefile | 4 +
.../pcie-mobiveil-host.c} | 401 +-----------------
.../controller/mobiveil/pcie-mobiveil-plat.c | 61 +++
.../pci/controller/mobiveil/pcie-mobiveil.c | 227 ++++++++++
.../pci/controller/mobiveil/pcie-mobiveil.h | 178 ++++++++
9 files changed, 499 insertions(+), 411 deletions(-)
create mode 100644 drivers/pci/controller/mobiveil/Kconfig
create mode 100644 drivers/pci/controller/mobiveil/Makefile
rename drivers/pci/controller/{pcie-mobiveil.c => mobiveil/pcie-mobiveil-host.c} (61%)
create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.c
create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.h
diff --git a/MAINTAINERS b/MAINTAINERS
index b8c01ad52bd3..60b4c93914cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12815,7 +12815,7 @@ M: Hou Zhiqiang <[email protected]>
L: [email protected]
S: Supported
F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
-F: drivers/pci/controller/pcie-mobiveil.c
+F: drivers/pci/controller/mobiveil/pcie-mobiveil*
PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
M: Thomas Petazzoni <[email protected]>
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
index 20bf00f587bd..91bfdb784829 100644
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -213,16 +213,6 @@ config PCIE_MEDIATEK
Say Y here if you want to enable PCIe controller support on
MediaTek SoCs.
-config PCIE_MOBIVEIL
- bool "Mobiveil AXI PCIe controller"
- depends on ARCH_ZYNQMP || COMPILE_TEST
- depends on OF
- depends on PCI_MSI_IRQ_DOMAIN
- help
- Say Y here if you want to enable support for the Mobiveil AXI PCIe
- Soft IP. It has up to 8 outbound and inbound windows
- for address translation and it is a PCIe Gen4 IP.
-
config PCIE_TANGO_SMP8759
bool "Tango SMP8759 PCIe controller (DANGEROUS)"
depends on ARCH_TANGO && PCI_MSI && OF
@@ -269,5 +259,6 @@ config PCI_HYPERV_INTERFACE
have a common interface with the Hyper-V PCI frontend driver.
source "drivers/pci/controller/dwc/Kconfig"
+source "drivers/pci/controller/mobiveil/Kconfig"
source "drivers/pci/controller/cadence/Kconfig"
endmenu
diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile
index 01b2502a5323..158c59771824 100644
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -25,12 +25,12 @@ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o
obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
-obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
obj-$(CONFIG_VMD) += vmd.o
obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
obj-y += dwc/
+obj-y += mobiveil/
# The following drivers are for devices that use the generic ACPI
diff --git a/drivers/pci/controller/mobiveil/Kconfig b/drivers/pci/controller/mobiveil/Kconfig
new file mode 100644
index 000000000000..54161d4ddb11
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/Kconfig
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menu "Mobiveil PCIe Core Support"
+ depends on PCI
+
+config PCIE_MOBIVEIL
+ bool
+
+config PCIE_MOBIVEIL_HOST
+ bool
+ depends on PCI_MSI_IRQ_DOMAIN
+ select PCIE_MOBIVEIL
+
+config PCIE_MOBIVEIL_PLAT
+ bool "Mobiveil AXI PCIe controller"
+ depends on ARCH_ZYNQMP || COMPILE_TEST
+ depends on OF
+ select PCIE_MOBIVEIL_HOST
+ help
+ Say Y here if you want to enable support for the Mobiveil AXI PCIe
+ Soft IP. It has up to 8 outbound and inbound windows
+ for address translation and it is a PCIe Gen4 IP.
+
+endmenu
diff --git a/drivers/pci/controller/mobiveil/Makefile b/drivers/pci/controller/mobiveil/Makefile
new file mode 100644
index 000000000000..9fb6d1c6504d
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
+obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o
+obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o
diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
similarity index 61%
rename from drivers/pci/controller/pcie-mobiveil.c
rename to drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
index 9449528bb14f..ea90d2f8692e 100644
--- a/drivers/pci/controller/pcie-mobiveil.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
@@ -9,7 +9,6 @@
* Hou Zhiqiang <[email protected]>
*/
-#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -26,265 +25,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include "../pci.h"
-
-/* register offsets and bit positions */
-
-/*
- * translation tables are grouped into windows, each window registers are
- * grouped into blocks of 4 or 16 registers each
- */
-#define PAB_REG_BLOCK_SIZE 16
-#define PAB_EXT_REG_BLOCK_SIZE 4
-
-#define PAB_REG_ADDR(offset, win) \
- (offset + (win * PAB_REG_BLOCK_SIZE))
-#define PAB_EXT_REG_ADDR(offset, win) \
- (offset + (win * PAB_EXT_REG_BLOCK_SIZE))
-
-#define LTSSM_STATUS 0x0404
-#define LTSSM_STATUS_L0_MASK 0x3f
-#define LTSSM_STATUS_L0 0x2d
-
-#define PAB_CTRL 0x0808
-#define AMBA_PIO_ENABLE_SHIFT 0
-#define PEX_PIO_ENABLE_SHIFT 1
-#define PAGE_SEL_SHIFT 13
-#define PAGE_SEL_MASK 0x3f
-#define PAGE_LO_MASK 0x3ff
-#define PAGE_SEL_OFFSET_SHIFT 10
-
-#define PAB_AXI_PIO_CTRL 0x0840
-#define APIO_EN_MASK 0xf
-
-#define PAB_PEX_PIO_CTRL 0x08c0
-#define PIO_ENABLE_SHIFT 0
-
-#define PAB_INTP_AMBA_MISC_ENB 0x0b0c
-#define PAB_INTP_AMBA_MISC_STAT 0x0b1c
-#define PAB_INTP_INTX_MASK 0x01e0
-#define PAB_INTP_MSI_MASK 0x8
-
-#define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win)
-#define WIN_ENABLE_SHIFT 0
-#define WIN_TYPE_SHIFT 1
-#define WIN_TYPE_MASK 0x3
-#define WIN_SIZE_MASK 0xfffffc00
-
-#define PAB_EXT_AXI_AMAP_SIZE(win) PAB_EXT_REG_ADDR(0xbaf0, win)
-
-#define PAB_EXT_AXI_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0x80a0, win)
-#define PAB_AXI_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x0ba4, win)
-#define AXI_WINDOW_ALIGN_MASK 3
-
-#define PAB_AXI_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x0ba8, win)
-#define PAB_BUS_SHIFT 24
-#define PAB_DEVICE_SHIFT 19
-#define PAB_FUNCTION_SHIFT 16
-
-#define PAB_AXI_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x0bac, win)
-#define PAB_INTP_AXI_PIO_CLASS 0x474
-
-#define PAB_PEX_AMAP_CTRL(win) PAB_REG_ADDR(0x4ba0, win)
-#define AMAP_CTRL_EN_SHIFT 0
-#define AMAP_CTRL_TYPE_SHIFT 1
-#define AMAP_CTRL_TYPE_MASK 3
-
-#define PAB_EXT_PEX_AMAP_SIZEN(win) PAB_EXT_REG_ADDR(0xbef0, win)
-#define PAB_EXT_PEX_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0xb4a0, win)
-#define PAB_PEX_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x4ba4, win)
-#define PAB_PEX_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x4ba8, win)
-#define PAB_PEX_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x4bac, win)
-
-/* starting offset of INTX bits in status register */
-#define PAB_INTX_START 5
-
-/* supported number of MSI interrupts */
-#define PCI_NUM_MSI 16
-
-/* MSI registers */
-#define MSI_BASE_LO_OFFSET 0x04
-#define MSI_BASE_HI_OFFSET 0x08
-#define MSI_SIZE_OFFSET 0x0c
-#define MSI_ENABLE_OFFSET 0x14
-#define MSI_STATUS_OFFSET 0x18
-#define MSI_DATA_OFFSET 0x20
-#define MSI_ADDR_L_OFFSET 0x24
-#define MSI_ADDR_H_OFFSET 0x28
-
-/* outbound and inbound window definitions */
-#define WIN_NUM_0 0
-#define WIN_NUM_1 1
-#define CFG_WINDOW_TYPE 0
-#define IO_WINDOW_TYPE 1
-#define MEM_WINDOW_TYPE 2
-#define IB_WIN_SIZE ((u64)256 * 1024 * 1024 * 1024)
-#define MAX_PIO_WINDOWS 8
-
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES 10
-#define LINK_WAIT_MIN 90000
-#define LINK_WAIT_MAX 100000
-
-#define PAGED_ADDR_BNDRY 0xc00
-#define OFFSET_TO_PAGE_ADDR(off) \
- ((off & PAGE_LO_MASK) | PAGED_ADDR_BNDRY)
-#define OFFSET_TO_PAGE_IDX(off) \
- ((off >> PAGE_SEL_OFFSET_SHIFT) & PAGE_SEL_MASK)
-
-struct mobiveil_msi { /* MSI information */
- struct mutex lock; /* protect bitmap variable */
- struct irq_domain *msi_domain;
- struct irq_domain *dev_domain;
- phys_addr_t msi_pages_phys;
- int num_of_vectors;
- DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI);
-};
-
-struct mobiveil_root_port {
- char root_bus_nr;
- void __iomem *config_axi_slave_base; /* endpoint config base */
- struct resource *ob_io_res;
- int irq;
- raw_spinlock_t intx_mask_lock;
- struct irq_domain *intx_domain;
- struct mobiveil_msi msi;
- struct pci_host_bridge *bridge;
-};
-
-struct mobiveil_pcie {
- struct platform_device *pdev;
- void __iomem *csr_axi_slave_base; /* root port config base */
- void __iomem *apb_csr_base; /* MSI register base */
- phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */
- int apio_wins;
- int ppio_wins;
- int ob_wins_configured; /* configured outbound windows */
- int ib_wins_configured; /* configured inbound windows */
- struct mobiveil_root_port rp;
-};
-
-/*
- * mobiveil_pcie_sel_page - routine to access paged register
- *
- * Registers whose address greater than PAGED_ADDR_BNDRY (0xc00) are paged,
- * for this scheme to work extracted higher 6 bits of the offset will be
- * written to pg_sel field of PAB_CTRL register and rest of the lower 10
- * bits enabled with PAGED_ADDR_BNDRY are used as offset of the register.
- */
-static void mobiveil_pcie_sel_page(struct mobiveil_pcie *pcie, u8 pg_idx)
-{
- u32 val;
-
- val = readl(pcie->csr_axi_slave_base + PAB_CTRL);
- val &= ~(PAGE_SEL_MASK << PAGE_SEL_SHIFT);
- val |= (pg_idx & PAGE_SEL_MASK) << PAGE_SEL_SHIFT;
-
- writel(val, pcie->csr_axi_slave_base + PAB_CTRL);
-}
-
-static void *mobiveil_pcie_comp_addr(struct mobiveil_pcie *pcie, u32 off)
-{
- if (off < PAGED_ADDR_BNDRY) {
- /* For directly accessed registers, clear the pg_sel field */
- mobiveil_pcie_sel_page(pcie, 0);
- return pcie->csr_axi_slave_base + off;
- }
-
- mobiveil_pcie_sel_page(pcie, OFFSET_TO_PAGE_IDX(off));
- return pcie->csr_axi_slave_base + OFFSET_TO_PAGE_ADDR(off);
-}
-
-static int mobiveil_pcie_read(void __iomem *addr, int size, u32 *val)
-{
- if ((uintptr_t)addr & (size - 1)) {
- *val = 0;
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- switch (size) {
- case 4:
- *val = readl(addr);
- break;
- case 2:
- *val = readw(addr);
- break;
- case 1:
- *val = readb(addr);
- break;
- default:
- *val = 0;
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int mobiveil_pcie_write(void __iomem *addr, int size, u32 val)
-{
- if ((uintptr_t)addr & (size - 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- switch (size) {
- case 4:
- writel(val, addr);
- break;
- case 2:
- writew(val, addr);
- break;
- case 1:
- writeb(val, addr);
- break;
- default:
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size)
-{
- void *addr;
- u32 val;
- int ret;
-
- addr = mobiveil_pcie_comp_addr(pcie, off);
-
- ret = mobiveil_pcie_read(addr, size, &val);
- if (ret)
- dev_err(&pcie->pdev->dev, "read CSR address failed\n");
-
- return val;
-}
-
-static void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
- size_t size)
-{
- void *addr;
- int ret;
-
- addr = mobiveil_pcie_comp_addr(pcie, off);
-
- ret = mobiveil_pcie_write(addr, size, val);
- if (ret)
- dev_err(&pcie->pdev->dev, "write CSR address failed\n");
-}
-
-static u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off)
-{
- return mobiveil_csr_read(pcie, off, 0x4);
-}
-
-static void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val, u32 off)
-{
- mobiveil_csr_write(pcie, val, off, 0x4);
-}
-
-static bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
-{
- return (mobiveil_csr_readl(pcie, LTSSM_STATUS) &
- LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0;
-}
+#include "pcie-mobiveil.h"
static bool mobiveil_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
{
@@ -464,103 +205,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
return 0;
}
-static void program_ib_windows(struct mobiveil_pcie *pcie, int win_num,
- u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
-{
- u32 value;
- u64 size64 = ~(size - 1);
-
- if (win_num >= pcie->ppio_wins) {
- dev_err(&pcie->pdev->dev,
- "ERROR: max inbound windows reached !\n");
- return;
- }
-
- value = mobiveil_csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num));
- value &= ~(AMAP_CTRL_TYPE_MASK << AMAP_CTRL_TYPE_SHIFT | WIN_SIZE_MASK);
- value |= type << AMAP_CTRL_TYPE_SHIFT | 1 << AMAP_CTRL_EN_SHIFT |
- (lower_32_bits(size64) & WIN_SIZE_MASK);
- mobiveil_csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num));
-
- mobiveil_csr_writel(pcie, upper_32_bits(size64),
- PAB_EXT_PEX_AMAP_SIZEN(win_num));
-
- mobiveil_csr_writel(pcie, lower_32_bits(cpu_addr),
- PAB_PEX_AMAP_AXI_WIN(win_num));
- mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
- PAB_EXT_PEX_AMAP_AXI_WIN(win_num));
-
- mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
- PAB_PEX_AMAP_PEX_WIN_L(win_num));
- mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
- PAB_PEX_AMAP_PEX_WIN_H(win_num));
-
- pcie->ib_wins_configured++;
-}
-
-/*
- * routine to program the outbound windows
- */
-static void program_ob_windows(struct mobiveil_pcie *pcie, int win_num,
- u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
-{
- u32 value;
- u64 size64 = ~(size - 1);
-
- if (win_num >= pcie->apio_wins) {
- dev_err(&pcie->pdev->dev,
- "ERROR: max outbound windows reached !\n");
- return;
- }
-
- /*
- * program Enable Bit to 1, Type Bit to (00) base 2, AXI Window Size Bit
- * to 4 KB in PAB_AXI_AMAP_CTRL register
- */
- value = mobiveil_csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num));
- value &= ~(WIN_TYPE_MASK << WIN_TYPE_SHIFT | WIN_SIZE_MASK);
- value |= 1 << WIN_ENABLE_SHIFT | type << WIN_TYPE_SHIFT |
- (lower_32_bits(size64) & WIN_SIZE_MASK);
- mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num));
-
- mobiveil_csr_writel(pcie, upper_32_bits(size64),
- PAB_EXT_AXI_AMAP_SIZE(win_num));
-
- /*
- * program AXI window base with appropriate value in
- * PAB_AXI_AMAP_AXI_WIN0 register
- */
- mobiveil_csr_writel(pcie,
- lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK),
- PAB_AXI_AMAP_AXI_WIN(win_num));
- mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
- PAB_EXT_AXI_AMAP_AXI_WIN(win_num));
-
- mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
- PAB_AXI_AMAP_PEX_WIN_L(win_num));
- mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
- PAB_AXI_AMAP_PEX_WIN_H(win_num));
-
- pcie->ob_wins_configured++;
-}
-
-static int mobiveil_bringup_link(struct mobiveil_pcie *pcie)
-{
- int retries;
-
- /* check if the link is up or not */
- for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
- if (mobiveil_pcie_link_up(pcie))
- return 0;
-
- usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX);
- }
-
- dev_err(&pcie->pdev->dev, "link never came up\n");
-
- return -ETIMEDOUT;
-}
-
static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
{
phys_addr_t msg_addr = pcie->pcie_reg_base;
@@ -895,7 +539,7 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
return 0;
}
-static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
+int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
{
struct mobiveil_root_port *rp = &pcie->rp;
struct pci_host_bridge *bridge = rp->bridge;
@@ -962,44 +606,3 @@ static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
return 0;
}
-
-static int mobiveil_pcie_probe(struct platform_device *pdev)
-{
- struct mobiveil_pcie *pcie;
- struct pci_host_bridge *bridge;
- struct device *dev = &pdev->dev;
-
- /* allocate the PCIe port */
- bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
- if (!bridge)
- return -ENOMEM;
-
- pcie = pci_host_bridge_priv(bridge);
- pcie->rp.bridge = bridge;
-
- pcie->pdev = pdev;
-
- return mobiveil_pcie_host_probe(pcie);
-}
-
-static const struct of_device_id mobiveil_pcie_of_match[] = {
- {.compatible = "mbvl,gpex40-pcie",},
- {},
-};
-
-MODULE_DEVICE_TABLE(of, mobiveil_pcie_of_match);
-
-static struct platform_driver mobiveil_pcie_driver = {
- .probe = mobiveil_pcie_probe,
- .driver = {
- .name = "mobiveil-pcie",
- .of_match_table = mobiveil_pcie_of_match,
- .suppress_bind_attrs = true,
- },
-};
-
-builtin_platform_driver(mobiveil_pcie_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Mobiveil PCIe host controller driver");
-MODULE_AUTHOR("Subrahmanya Lingappa <[email protected]>");
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
new file mode 100644
index 000000000000..f6ede66783e7
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Mobiveil PCIe Host controller
+ *
+ * Copyright (c) 2018 Mobiveil Inc.
+ * Copyright 2019 NXP
+ *
+ * Author: Subrahmanya Lingappa <[email protected]>
+ * Hou Zhiqiang <[email protected]>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_pci.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pcie-mobiveil.h"
+
+static int mobiveil_pcie_probe(struct platform_device *pdev)
+{
+ struct mobiveil_pcie *pcie;
+ struct pci_host_bridge *bridge;
+ struct device *dev = &pdev->dev;
+
+ /* allocate the PCIe port */
+ bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
+ if (!bridge)
+ return -ENOMEM;
+
+ pcie = pci_host_bridge_priv(bridge);
+ pcie->rp.bridge = bridge;
+
+ pcie->pdev = pdev;
+
+ return mobiveil_pcie_host_probe(pcie);
+}
+
+static const struct of_device_id mobiveil_pcie_of_match[] = {
+ {.compatible = "mbvl,gpex40-pcie",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, mobiveil_pcie_of_match);
+
+static struct platform_driver mobiveil_pcie_driver = {
+ .probe = mobiveil_pcie_probe,
+ .driver = {
+ .name = "mobiveil-pcie",
+ .of_match_table = mobiveil_pcie_of_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_platform_driver(mobiveil_pcie_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mobiveil PCIe host controller driver");
+MODULE_AUTHOR("Subrahmanya Lingappa <[email protected]>");
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.c b/drivers/pci/controller/mobiveil/pcie-mobiveil.c
new file mode 100644
index 000000000000..2773f823c9ea
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.c
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Mobiveil PCIe Host controller
+ *
+ * Copyright (c) 2018 Mobiveil Inc.
+ * Copyright 2019 NXP
+ *
+ * Author: Subrahmanya Lingappa <[email protected]>
+ * Hou Zhiqiang <[email protected]>
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include "pcie-mobiveil.h"
+
+/*
+ * mobiveil_pcie_sel_page - routine to access paged register
+ *
+ * Registers whose address greater than PAGED_ADDR_BNDRY (0xc00) are paged,
+ * for this scheme to work extracted higher 6 bits of the offset will be
+ * written to pg_sel field of PAB_CTRL register and rest of the lower 10
+ * bits enabled with PAGED_ADDR_BNDRY are used as offset of the register.
+ */
+static void mobiveil_pcie_sel_page(struct mobiveil_pcie *pcie, u8 pg_idx)
+{
+ u32 val;
+
+ val = readl(pcie->csr_axi_slave_base + PAB_CTRL);
+ val &= ~(PAGE_SEL_MASK << PAGE_SEL_SHIFT);
+ val |= (pg_idx & PAGE_SEL_MASK) << PAGE_SEL_SHIFT;
+
+ writel(val, pcie->csr_axi_slave_base + PAB_CTRL);
+}
+
+static void *mobiveil_pcie_comp_addr(struct mobiveil_pcie *pcie, u32 off)
+{
+ if (off < PAGED_ADDR_BNDRY) {
+ /* For directly accessed registers, clear the pg_sel field */
+ mobiveil_pcie_sel_page(pcie, 0);
+ return pcie->csr_axi_slave_base + off;
+ }
+
+ mobiveil_pcie_sel_page(pcie, OFFSET_TO_PAGE_IDX(off));
+ return pcie->csr_axi_slave_base + OFFSET_TO_PAGE_ADDR(off);
+}
+
+static int mobiveil_pcie_read(void __iomem *addr, int size, u32 *val)
+{
+ if ((uintptr_t)addr & (size - 1)) {
+ *val = 0;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ switch (size) {
+ case 4:
+ *val = readl(addr);
+ break;
+ case 2:
+ *val = readw(addr);
+ break;
+ case 1:
+ *val = readb(addr);
+ break;
+ default:
+ *val = 0;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int mobiveil_pcie_write(void __iomem *addr, int size, u32 val)
+{
+ if ((uintptr_t)addr & (size - 1))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ switch (size) {
+ case 4:
+ writel(val, addr);
+ break;
+ case 2:
+ writew(val, addr);
+ break;
+ case 1:
+ writeb(val, addr);
+ break;
+ default:
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size)
+{
+ void *addr;
+ u32 val;
+ int ret;
+
+ addr = mobiveil_pcie_comp_addr(pcie, off);
+
+ ret = mobiveil_pcie_read(addr, size, &val);
+ if (ret)
+ dev_err(&pcie->pdev->dev, "read CSR address failed\n");
+
+ return val;
+}
+
+void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
+ size_t size)
+{
+ void *addr;
+ int ret;
+
+ addr = mobiveil_pcie_comp_addr(pcie, off);
+
+ ret = mobiveil_pcie_write(addr, size, val);
+ if (ret)
+ dev_err(&pcie->pdev->dev, "write CSR address failed\n");
+}
+
+bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
+{
+ return (mobiveil_csr_readl(pcie, LTSSM_STATUS) &
+ LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0;
+}
+
+void program_ib_windows(struct mobiveil_pcie *pcie, int win_num,
+ u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
+{
+ u32 value;
+ u64 size64 = ~(size - 1);
+
+ if (win_num >= pcie->ppio_wins) {
+ dev_err(&pcie->pdev->dev,
+ "ERROR: max inbound windows reached !\n");
+ return;
+ }
+
+ value = mobiveil_csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num));
+ value &= ~(AMAP_CTRL_TYPE_MASK << AMAP_CTRL_TYPE_SHIFT | WIN_SIZE_MASK);
+ value |= type << AMAP_CTRL_TYPE_SHIFT | 1 << AMAP_CTRL_EN_SHIFT |
+ (lower_32_bits(size64) & WIN_SIZE_MASK);
+ mobiveil_csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num));
+
+ mobiveil_csr_writel(pcie, upper_32_bits(size64),
+ PAB_EXT_PEX_AMAP_SIZEN(win_num));
+
+ mobiveil_csr_writel(pcie, lower_32_bits(cpu_addr),
+ PAB_PEX_AMAP_AXI_WIN(win_num));
+ mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
+ PAB_EXT_PEX_AMAP_AXI_WIN(win_num));
+
+ mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
+ PAB_PEX_AMAP_PEX_WIN_L(win_num));
+ mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
+ PAB_PEX_AMAP_PEX_WIN_H(win_num));
+
+ pcie->ib_wins_configured++;
+}
+
+/*
+ * routine to program the outbound windows
+ */
+void program_ob_windows(struct mobiveil_pcie *pcie, int win_num,
+ u64 cpu_addr, u64 pci_addr, u32 type, u64 size)
+{
+ u32 value;
+ u64 size64 = ~(size - 1);
+
+ if (win_num >= pcie->apio_wins) {
+ dev_err(&pcie->pdev->dev,
+ "ERROR: max outbound windows reached !\n");
+ return;
+ }
+
+ /*
+ * program Enable Bit to 1, Type Bit to (00) base 2, AXI Window Size Bit
+ * to 4 KB in PAB_AXI_AMAP_CTRL register
+ */
+ value = mobiveil_csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num));
+ value &= ~(WIN_TYPE_MASK << WIN_TYPE_SHIFT | WIN_SIZE_MASK);
+ value |= 1 << WIN_ENABLE_SHIFT | type << WIN_TYPE_SHIFT |
+ (lower_32_bits(size64) & WIN_SIZE_MASK);
+ mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num));
+
+ mobiveil_csr_writel(pcie, upper_32_bits(size64),
+ PAB_EXT_AXI_AMAP_SIZE(win_num));
+
+ /*
+ * program AXI window base with appropriate value in
+ * PAB_AXI_AMAP_AXI_WIN0 register
+ */
+ mobiveil_csr_writel(pcie,
+ lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK),
+ PAB_AXI_AMAP_AXI_WIN(win_num));
+ mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
+ PAB_EXT_AXI_AMAP_AXI_WIN(win_num));
+
+ mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
+ PAB_AXI_AMAP_PEX_WIN_L(win_num));
+ mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
+ PAB_AXI_AMAP_PEX_WIN_H(win_num));
+
+ pcie->ob_wins_configured++;
+}
+
+int mobiveil_bringup_link(struct mobiveil_pcie *pcie)
+{
+ int retries;
+
+ /* check if the link is up or not */
+ for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ if (mobiveil_pcie_link_up(pcie))
+ return 0;
+
+ usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX);
+ }
+
+ dev_err(&pcie->pdev->dev, "link never came up\n");
+
+ return -ETIMEDOUT;
+}
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
new file mode 100644
index 000000000000..81ffbbd48c08
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PCIe host controller driver for Mobiveil PCIe Host controller
+ *
+ * Copyright (c) 2018 Mobiveil Inc.
+ * Copyright 2019 NXP
+ *
+ * Author: Subrahmanya Lingappa <[email protected]>
+ * Hou Zhiqiang <[email protected]>
+ */
+
+#ifndef _PCIE_MOBIVEIL_H
+#define _PCIE_MOBIVEIL_H
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+#include "../../pci.h"
+
+/* register offsets and bit positions */
+
+/*
+ * translation tables are grouped into windows, each window registers are
+ * grouped into blocks of 4 or 16 registers each
+ */
+#define PAB_REG_BLOCK_SIZE 16
+#define PAB_EXT_REG_BLOCK_SIZE 4
+
+#define PAB_REG_ADDR(offset, win) \
+ (offset + (win * PAB_REG_BLOCK_SIZE))
+#define PAB_EXT_REG_ADDR(offset, win) \
+ (offset + (win * PAB_EXT_REG_BLOCK_SIZE))
+
+#define LTSSM_STATUS 0x0404
+#define LTSSM_STATUS_L0_MASK 0x3f
+#define LTSSM_STATUS_L0 0x2d
+
+#define PAB_CTRL 0x0808
+#define AMBA_PIO_ENABLE_SHIFT 0
+#define PEX_PIO_ENABLE_SHIFT 1
+#define PAGE_SEL_SHIFT 13
+#define PAGE_SEL_MASK 0x3f
+#define PAGE_LO_MASK 0x3ff
+#define PAGE_SEL_OFFSET_SHIFT 10
+
+#define PAB_AXI_PIO_CTRL 0x0840
+#define APIO_EN_MASK 0xf
+
+#define PAB_PEX_PIO_CTRL 0x08c0
+#define PIO_ENABLE_SHIFT 0
+
+#define PAB_INTP_AMBA_MISC_ENB 0x0b0c
+#define PAB_INTP_AMBA_MISC_STAT 0x0b1c
+#define PAB_INTP_INTX_MASK 0x01e0
+#define PAB_INTP_MSI_MASK 0x8
+
+#define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win)
+#define WIN_ENABLE_SHIFT 0
+#define WIN_TYPE_SHIFT 1
+#define WIN_TYPE_MASK 0x3
+#define WIN_SIZE_MASK 0xfffffc00
+
+#define PAB_EXT_AXI_AMAP_SIZE(win) PAB_EXT_REG_ADDR(0xbaf0, win)
+
+#define PAB_EXT_AXI_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0x80a0, win)
+#define PAB_AXI_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x0ba4, win)
+#define AXI_WINDOW_ALIGN_MASK 3
+
+#define PAB_AXI_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x0ba8, win)
+#define PAB_BUS_SHIFT 24
+#define PAB_DEVICE_SHIFT 19
+#define PAB_FUNCTION_SHIFT 16
+
+#define PAB_AXI_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x0bac, win)
+#define PAB_INTP_AXI_PIO_CLASS 0x474
+
+#define PAB_PEX_AMAP_CTRL(win) PAB_REG_ADDR(0x4ba0, win)
+#define AMAP_CTRL_EN_SHIFT 0
+#define AMAP_CTRL_TYPE_SHIFT 1
+#define AMAP_CTRL_TYPE_MASK 3
+
+#define PAB_EXT_PEX_AMAP_SIZEN(win) PAB_EXT_REG_ADDR(0xbef0, win)
+#define PAB_EXT_PEX_AMAP_AXI_WIN(win) PAB_EXT_REG_ADDR(0xb4a0, win)
+#define PAB_PEX_AMAP_AXI_WIN(win) PAB_REG_ADDR(0x4ba4, win)
+#define PAB_PEX_AMAP_PEX_WIN_L(win) PAB_REG_ADDR(0x4ba8, win)
+#define PAB_PEX_AMAP_PEX_WIN_H(win) PAB_REG_ADDR(0x4bac, win)
+
+/* starting offset of INTX bits in status register */
+#define PAB_INTX_START 5
+
+/* supported number of MSI interrupts */
+#define PCI_NUM_MSI 16
+
+/* MSI registers */
+#define MSI_BASE_LO_OFFSET 0x04
+#define MSI_BASE_HI_OFFSET 0x08
+#define MSI_SIZE_OFFSET 0x0c
+#define MSI_ENABLE_OFFSET 0x14
+#define MSI_STATUS_OFFSET 0x18
+#define MSI_DATA_OFFSET 0x20
+#define MSI_ADDR_L_OFFSET 0x24
+#define MSI_ADDR_H_OFFSET 0x28
+
+/* outbound and inbound window definitions */
+#define WIN_NUM_0 0
+#define WIN_NUM_1 1
+#define CFG_WINDOW_TYPE 0
+#define IO_WINDOW_TYPE 1
+#define MEM_WINDOW_TYPE 2
+#define IB_WIN_SIZE ((u64)256 * 1024 * 1024 * 1024)
+#define MAX_PIO_WINDOWS 8
+
+/* Parameters for the waiting for link up routine */
+#define LINK_WAIT_MAX_RETRIES 10
+#define LINK_WAIT_MIN 90000
+#define LINK_WAIT_MAX 100000
+
+#define PAGED_ADDR_BNDRY 0xc00
+#define OFFSET_TO_PAGE_ADDR(off) \
+ ((off & PAGE_LO_MASK) | PAGED_ADDR_BNDRY)
+#define OFFSET_TO_PAGE_IDX(off) \
+ ((off >> PAGE_SEL_OFFSET_SHIFT) & PAGE_SEL_MASK)
+
+struct mobiveil_msi { /* MSI information */
+ struct mutex lock; /* protect bitmap variable */
+ struct irq_domain *msi_domain;
+ struct irq_domain *dev_domain;
+ phys_addr_t msi_pages_phys;
+ int num_of_vectors;
+ DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI);
+};
+
+struct mobiveil_root_port {
+ char root_bus_nr;
+ void __iomem *config_axi_slave_base; /* endpoint config base */
+ struct resource *ob_io_res;
+ int irq;
+ raw_spinlock_t intx_mask_lock;
+ struct irq_domain *intx_domain;
+ struct mobiveil_msi msi;
+ struct pci_host_bridge *bridge;
+};
+
+struct mobiveil_pcie {
+ struct platform_device *pdev;
+ void __iomem *csr_axi_slave_base; /* root port config base */
+ void __iomem *apb_csr_base; /* MSI register base */
+ phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */
+ int apio_wins;
+ int ppio_wins;
+ int ob_wins_configured; /* configured outbound windows */
+ int ib_wins_configured; /* configured inbound windows */
+ struct mobiveil_root_port rp;
+};
+
+int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie);
+bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie);
+int mobiveil_bringup_link(struct mobiveil_pcie *pcie);
+void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr,
+ u64 pci_addr, u32 type, u64 size);
+void program_ib_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr,
+ u64 pci_addr, u32 type, u64 size);
+u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size);
+void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
+ size_t size);
+
+static inline u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off)
+{
+ return mobiveil_csr_read(pcie, off, 0x4);
+}
+
+static inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val,
+ u32 off)
+{
+ mobiveil_csr_write(pcie, val, off, 0x4);
+}
+
+#endif /* _PCIE_MOBIVEIL_H */
--
2.17.1
From: Hou Zhiqiang <[email protected]>
The Mobiveil GPEX internal MSI/INTx controller may not be used
by other platforms in which the Mobiveil GPEX is integrated.
This patch is to allow these platforms to implement their
specific interrupt initialization.
Signed-off-by: Hou Zhiqiang <[email protected]>
---
V10:
- Introduced a helper function mobiveil_pcie_integrated_interrupt_init().
drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 12 +++++++++++-
drivers/pci/controller/mobiveil/pcie-mobiveil.h | 7 +++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
index ea90d2f8692e..53ab8412a1de 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
@@ -499,7 +499,7 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
return 0;
}
-static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
+static int mobiveil_pcie_integrated_interrupt_init(struct mobiveil_pcie *pcie)
{
struct platform_device *pdev = pcie->pdev;
struct device *dev = &pdev->dev;
@@ -539,6 +539,16 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
return 0;
}
+static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
+{
+ struct mobiveil_root_port *rp = &pcie->rp;
+
+ if (rp->ops->interrupt_init)
+ return rp->ops->interrupt_init(pcie);
+
+ return mobiveil_pcie_integrated_interrupt_init(pcie);
+}
+
int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
{
struct mobiveil_root_port *rp = &pcie->rp;
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
index 81ffbbd48c08..0e6b5468c026 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -130,10 +130,17 @@ struct mobiveil_msi { /* MSI information */
DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI);
};
+struct mobiveil_pcie;
+
+struct mobiveil_rp_ops {
+ int (*interrupt_init)(struct mobiveil_pcie *pcie);
+};
+
struct mobiveil_root_port {
char root_bus_nr;
void __iomem *config_axi_slave_base; /* endpoint config base */
struct resource *ob_io_res;
+ struct mobiveil_rp_ops *ops;
int irq;
raw_spinlock_t intx_mask_lock;
struct irq_domain *intx_domain;
--
2.17.1
From: Hou Zhiqiang <[email protected]>
The platforms, in which the Mobiveil GPEX is integrated,
may have their specific mechanism to check link up status.
This patch is to enable these platforms to implement theirs.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
---
V10:
- No change
drivers/pci/controller/mobiveil/pcie-mobiveil.c | 3 +++
drivers/pci/controller/mobiveil/pcie-mobiveil.h | 5 +++++
2 files changed, 8 insertions(+)
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.c b/drivers/pci/controller/mobiveil/pcie-mobiveil.c
index 2773f823c9ea..b9ed2d95641c 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.c
@@ -125,6 +125,9 @@ void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
{
+ if (pcie->ops->link_up)
+ return pcie->ops->link_up(pcie);
+
return (mobiveil_csr_readl(pcie, LTSSM_STATUS) &
LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0;
}
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
index 0e6b5468c026..346bf79a581b 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -148,6 +148,10 @@ struct mobiveil_root_port {
struct pci_host_bridge *bridge;
};
+struct mobiveil_pab_ops {
+ int (*link_up)(struct mobiveil_pcie *pcie);
+};
+
struct mobiveil_pcie {
struct platform_device *pdev;
void __iomem *csr_axi_slave_base; /* root port config base */
@@ -157,6 +161,7 @@ struct mobiveil_pcie {
int ppio_wins;
int ob_wins_configured; /* configured outbound windows */
int ib_wins_configured; /* configured inbound windows */
+ const struct mobiveil_pab_ops *ops;
struct mobiveil_root_port rp;
};
--
2.17.1
From: Hou Zhiqiang <[email protected]>
There are some 8-bit and 16-bit registers in PCIe configuration
space, so add these accessors accordingly.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Minghuan Lian <[email protected]>
Reviewed-by: Subrahmanya Lingappa <[email protected]>
---
V10:
- Changed the return types to reflect the size of the access.
.../pci/controller/mobiveil/pcie-mobiveil.h | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
index 623c5f0c4441..72c62b4d8f7b 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -182,10 +182,33 @@ static inline u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off)
return mobiveil_csr_read(pcie, off, 0x4);
}
+static inline u16 mobiveil_csr_readw(struct mobiveil_pcie *pcie, u32 off)
+{
+ return mobiveil_csr_read(pcie, off, 0x2);
+}
+
+static inline u8 mobiveil_csr_readb(struct mobiveil_pcie *pcie, u32 off)
+{
+ return mobiveil_csr_read(pcie, off, 0x1);
+}
+
+
static inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val,
u32 off)
{
mobiveil_csr_write(pcie, val, off, 0x4);
}
+static inline void mobiveil_csr_writew(struct mobiveil_pcie *pcie, u16 val,
+ u32 off)
+{
+ mobiveil_csr_write(pcie, val, off, 0x2);
+}
+
+static inline void mobiveil_csr_writeb(struct mobiveil_pcie *pcie, u8 val,
+ u32 off)
+{
+ mobiveil_csr_write(pcie, val, off, 0x1);
+}
+
#endif /* _PCIE_MOBIVEIL_H */
--
2.17.1
From: Hou Zhiqiang <[email protected]>
Check the Header Type and exit from the host driver initialization if
it is not in host mode.
Signed-off-by: Hou Zhiqiang <[email protected]>
---
V10:
- New patch separated from #10 of v9.
.../pci/controller/mobiveil/pcie-mobiveil-host.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
index 44dd641fede3..db7028788d91 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
@@ -554,6 +554,16 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
return mobiveil_pcie_integrated_interrupt_init(pcie);
}
+static bool mobiveil_pcie_is_bridge(struct mobiveil_pcie *pcie)
+{
+ u32 header_type;
+
+ header_type = mobiveil_csr_readb(pcie, PCI_HEADER_TYPE);
+ header_type &= 0x7f;
+
+ return header_type == PCI_HEADER_TYPE_BRIDGE;
+}
+
int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
{
struct mobiveil_root_port *rp = &pcie->rp;
@@ -569,6 +579,9 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
return ret;
}
+ if (!mobiveil_pcie_is_bridge(pcie))
+ return -ENODEV;
+
/* parse the host bridge base addresses from the device tree file */
ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
&bridge->dma_ranges, NULL);
--
2.17.1
From: Hou Zhiqiang <[email protected]>
Add PCIe Gen4 controller DT bindings of NXP Layerscape SoCs.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
V10:
- No change
.../bindings/pci/layerscape-pcie-gen4.txt | 52 +++++++++++++++++++
MAINTAINERS | 8 +++
2 files changed, 60 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
diff --git a/Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt b/Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
new file mode 100644
index 000000000000..b40fb5d15d3d
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
@@ -0,0 +1,52 @@
+NXP Layerscape PCIe Gen4 controller
+
+This PCIe controller is based on the Mobiveil PCIe IP and thus inherits all
+the common properties defined in mobiveil-pcie.txt.
+
+Required properties:
+- compatible: should contain the platform identifier such as:
+ "fsl,lx2160a-pcie"
+- reg: base addresses and lengths of the PCIe controller register blocks.
+ "csr_axi_slave": Bridge config registers
+ "config_axi_slave": PCIe controller registers
+- interrupts: A list of interrupt outputs of the controller. Must contain an
+ entry for each entry in the interrupt-names property.
+- interrupt-names: It could include the following entries:
+ "intr": The interrupt that is asserted for controller interrupts
+ "aer": Asserted for aer interrupt when chip support the aer interrupt with
+ none MSI/MSI-X/INTx mode,but there is interrupt line for aer.
+ "pme": Asserted for pme interrupt when chip support the pme interrupt with
+ none MSI/MSI-X/INTx mode,but there is interrupt line for pme.
+- dma-coherent: Indicates that the hardware IP block can ensure the coherency
+ of the data transferred from/to the IP block. This can avoid the software
+ cache flush/invalid actions, and improve the performance significantly.
+- msi-parent : See the generic MSI binding described in
+ Documentation/devicetree/bindings/interrupt-controller/msi.txt.
+
+Example:
+
+ pcie@3400000 {
+ compatible = "fsl,lx2160a-pcie";
+ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
+ 0x80 0x00000000 0x0 0x00001000>; /* configuration space */
+ reg-names = "csr_axi_slave", "config_axi_slave";
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "aer", "pme", "intr";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ apio-wins = <8>;
+ ppio-wins = <8>;
+ dma-coherent;
+ bus-range = <0x0 0xff>;
+ msi-parent = <&its>;
+ ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 60b4c93914cb..6a2350e10c54 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12773,6 +12773,14 @@ L: [email protected]
S: Maintained
F: drivers/pci/controller/dwc/*layerscape*
+PCI DRIVER FOR NXP LAYERSCAPE GEN4 CONTROLLER
+M: Hou Zhiqiang <[email protected]>
+L: [email protected]
+L: [email protected]
+S: Maintained
+F: Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
+F: drivers/pci/controller/mobibeil/pcie-layerscape-gen4.c
+
PCI DRIVER FOR GENERIC OF HOSTS
M: Will Deacon <[email protected]>
L: [email protected]
--
2.17.1
From: Hou Zhiqiang <[email protected]>
Allow the mobiveil_host_init() function to be used to re-init
host controller's PAB and GPEX CSR register block, as NXP
integrated Mobiveil IP has to reset and then re-init the PAB
and GPEX CSR registers upon hot-reset.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Subrahmanya Lingappa <[email protected]>
---
V10:
- Refined the subject and change log.
.../controller/mobiveil/pcie-mobiveil-host.c | 19 ++++++++++++-------
.../pci/controller/mobiveil/pcie-mobiveil.h | 1 +
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
index 53ab8412a1de..44dd641fede3 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
@@ -221,18 +221,23 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
writel_relaxed(1, pcie->apb_csr_base + MSI_ENABLE_OFFSET);
}
-static int mobiveil_host_init(struct mobiveil_pcie *pcie)
+int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit)
{
struct mobiveil_root_port *rp = &pcie->rp;
struct pci_host_bridge *bridge = rp->bridge;
u32 value, pab_ctrl, type;
struct resource_entry *win;
- /* setup bus numbers */
- value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
- value &= 0xff000000;
- value |= 0x00ff0100;
- mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
+ pcie->ib_wins_configured = 0;
+ pcie->ob_wins_configured = 0;
+
+ if (!reinit) {
+ /* setup bus numbers */
+ value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
+ value &= 0xff000000;
+ value |= 0x00ff0100;
+ mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
+ }
/*
* program Bus Master Enable Bit in Command Register in PAB Config
@@ -576,7 +581,7 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
* configure all inbound and outbound windows and prepare the RC for
* config access
*/
- ret = mobiveil_host_init(pcie);
+ ret = mobiveil_host_init(pcie, false);
if (ret) {
dev_err(dev, "Failed to initialize host\n");
return ret;
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
index 346bf79a581b..623c5f0c4441 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -166,6 +166,7 @@ struct mobiveil_pcie {
};
int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie);
+int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit);
bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie);
int mobiveil_bringup_link(struct mobiveil_pcie *pcie);
void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr,
--
2.17.1
From: Hou Zhiqiang <[email protected]>
This PCIe controller is based on the Mobiveil GPEX IP, which is
compatible with the PCI Expressâ„¢ Base Specification, Revision 4.0.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Minghuan Lian <[email protected]>
---
V10:
- Changed the return type of ls_pcie_g4_reinit_hw() to void.
- Moved Header Type check to mobiveil_pcie_host_probe().
drivers/pci/controller/mobiveil/Kconfig | 9 +
drivers/pci/controller/mobiveil/Makefile | 1 +
.../mobiveil/pcie-layerscape-gen4.c | 267 ++++++++++++++++++
.../pci/controller/mobiveil/pcie-mobiveil.h | 16 +-
4 files changed, 291 insertions(+), 2 deletions(-)
create mode 100644 drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
diff --git a/drivers/pci/controller/mobiveil/Kconfig b/drivers/pci/controller/mobiveil/Kconfig
index 54161d4ddb11..7439991ee82c 100644
--- a/drivers/pci/controller/mobiveil/Kconfig
+++ b/drivers/pci/controller/mobiveil/Kconfig
@@ -21,4 +21,13 @@ config PCIE_MOBIVEIL_PLAT
Soft IP. It has up to 8 outbound and inbound windows
for address translation and it is a PCIe Gen4 IP.
+config PCIE_LAYERSCAPE_GEN4
+ bool "Freescale Layerscape PCIe Gen4 controller"
+ depends on PCI
+ depends on OF && (ARM64 || ARCH_LAYERSCAPE)
+ depends on PCI_MSI_IRQ_DOMAIN
+ select PCIE_MOBIVEIL_HOST
+ help
+ Say Y here if you want PCIe Gen4 controller support on
+ Layerscape SoCs.
endmenu
diff --git a/drivers/pci/controller/mobiveil/Makefile b/drivers/pci/controller/mobiveil/Makefile
index 9fb6d1c6504d..99d879de32d6 100644
--- a/drivers/pci/controller/mobiveil/Makefile
+++ b/drivers/pci/controller/mobiveil/Makefile
@@ -2,3 +2,4 @@
obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o
obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o
+obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie-layerscape-gen4.o
diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
new file mode 100644
index 000000000000..f3bd5f5ad229
--- /dev/null
+++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe Gen4 host controller driver for NXP Layerscape SoCs
+ *
+ * Copyright 2019-2020 NXP
+ *
+ * Author: Zhiqiang Hou <[email protected]>
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include "pcie-mobiveil.h"
+
+/* LUT and PF control registers */
+#define PCIE_LUT_OFF 0x80000
+#define PCIE_PF_OFF 0xc0000
+#define PCIE_PF_INT_STAT 0x18
+#define PF_INT_STAT_PABRST BIT(31)
+
+#define PCIE_PF_DBG 0x7fc
+#define PF_DBG_LTSSM_MASK 0x3f
+#define PF_DBG_LTSSM_L0 0x2d /* L0 state */
+#define PF_DBG_WE BIT(31)
+#define PF_DBG_PABR BIT(27)
+
+#define to_ls_pcie_g4(x) platform_get_drvdata((x)->pdev)
+
+struct ls_pcie_g4 {
+ struct mobiveil_pcie pci;
+ struct delayed_work dwork;
+ int irq;
+};
+
+static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32 off)
+{
+ return ioread32(pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
+}
+
+static inline void ls_pcie_g4_lut_writel(struct ls_pcie_g4 *pcie,
+ u32 off, u32 val)
+{
+ iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
+}
+
+static inline u32 ls_pcie_g4_pf_readl(struct ls_pcie_g4 *pcie, u32 off)
+{
+ return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
+}
+
+static inline void ls_pcie_g4_pf_writel(struct ls_pcie_g4 *pcie,
+ u32 off, u32 val)
+{
+ iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
+}
+
+static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci)
+{
+ struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
+ u32 state;
+
+ state = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
+ state = state & PF_DBG_LTSSM_MASK;
+
+ if (state == PF_DBG_LTSSM_L0)
+ return 1;
+
+ return 0;
+}
+
+static void ls_pcie_g4_disable_interrupt(struct ls_pcie_g4 *pcie)
+{
+ struct mobiveil_pcie *mv_pci = &pcie->pci;
+
+ mobiveil_csr_writel(mv_pci, 0, PAB_INTP_AMBA_MISC_ENB);
+}
+
+static void ls_pcie_g4_enable_interrupt(struct ls_pcie_g4 *pcie)
+{
+ struct mobiveil_pcie *mv_pci = &pcie->pci;
+ u32 val;
+
+ /* Clear the interrupt status */
+ mobiveil_csr_writel(mv_pci, 0xffffffff, PAB_INTP_AMBA_MISC_STAT);
+
+ val = PAB_INTP_INTX_MASK | PAB_INTP_MSI | PAB_INTP_RESET |
+ PAB_INTP_PCIE_UE | PAB_INTP_IE_PMREDI | PAB_INTP_IE_EC;
+ mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_ENB);
+}
+
+static int ls_pcie_g4_reinit_hw(struct ls_pcie_g4 *pcie)
+{
+ struct mobiveil_pcie *mv_pci = &pcie->pci;
+ struct device *dev = &mv_pci->pdev->dev;
+ u32 val, act_stat;
+ int to = 100;
+
+ /* Poll for pab_csb_reset to set and PAB activity to clear */
+ do {
+ usleep_range(10, 15);
+ val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_INT_STAT);
+ act_stat = mobiveil_csr_readl(mv_pci, PAB_ACTIVITY_STAT);
+ } while (((val & PF_INT_STAT_PABRST) == 0 || act_stat) && to--);
+ if (to < 0) {
+ dev_err(dev, "Poll PABRST&PABACT timeout\n");
+ return -EIO;
+ }
+
+ /* clear PEX_RESET bit in PEX_PF0_DBG register */
+ val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
+ val |= PF_DBG_WE;
+ ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
+
+ val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
+ val |= PF_DBG_PABR;
+ ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
+
+ val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
+ val &= ~PF_DBG_WE;
+ ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
+
+ mobiveil_host_init(mv_pci, true);
+
+ to = 100;
+ while (!ls_pcie_g4_link_up(mv_pci) && to--)
+ usleep_range(200, 250);
+ if (to < 0) {
+ dev_err(dev, "PCIe link training timeout\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static irqreturn_t ls_pcie_g4_isr(int irq, void *dev_id)
+{
+ struct ls_pcie_g4 *pcie = (struct ls_pcie_g4 *)dev_id;
+ struct mobiveil_pcie *mv_pci = &pcie->pci;
+ u32 val;
+
+ val = mobiveil_csr_readl(mv_pci, PAB_INTP_AMBA_MISC_STAT);
+ if (!val)
+ return IRQ_NONE;
+
+ if (val & PAB_INTP_RESET) {
+ ls_pcie_g4_disable_interrupt(pcie);
+ schedule_delayed_work(&pcie->dwork, msecs_to_jiffies(1));
+ }
+
+ mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_STAT);
+
+ return IRQ_HANDLED;
+}
+
+static int ls_pcie_g4_interrupt_init(struct mobiveil_pcie *mv_pci)
+{
+ struct ls_pcie_g4 *pcie = to_ls_pcie_g4(mv_pci);
+ struct platform_device *pdev = mv_pci->pdev;
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ pcie->irq = platform_get_irq_byname(pdev, "intr");
+ if (pcie->irq < 0) {
+ dev_err(dev, "Can't get 'intr' IRQ, errno = %d\n", pcie->irq);
+ return pcie->irq;
+ }
+ ret = devm_request_irq(dev, pcie->irq, ls_pcie_g4_isr,
+ IRQF_SHARED, pdev->name, pcie);
+ if (ret) {
+ dev_err(dev, "Can't register PCIe IRQ, errno = %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void ls_pcie_g4_reset(struct work_struct *work)
+{
+ struct delayed_work *dwork = container_of(work, struct delayed_work,
+ work);
+ struct ls_pcie_g4 *pcie = container_of(dwork, struct ls_pcie_g4, dwork);
+ struct mobiveil_pcie *mv_pci = &pcie->pci;
+ u16 ctrl;
+
+ ctrl = mobiveil_csr_readw(mv_pci, PCI_BRIDGE_CONTROL);
+ ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
+ mobiveil_csr_writew(mv_pci, ctrl, PCI_BRIDGE_CONTROL);
+
+ if (!ls_pcie_g4_reinit_hw(pcie))
+ return;
+
+ ls_pcie_g4_enable_interrupt(pcie);
+}
+
+static struct mobiveil_rp_ops ls_pcie_g4_rp_ops = {
+ .interrupt_init = ls_pcie_g4_interrupt_init,
+};
+
+static const struct mobiveil_pab_ops ls_pcie_g4_pab_ops = {
+ .link_up = ls_pcie_g4_link_up,
+};
+
+static int __init ls_pcie_g4_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pci_host_bridge *bridge;
+ struct mobiveil_pcie *mv_pci;
+ struct ls_pcie_g4 *pcie;
+ struct device_node *np = dev->of_node;
+ int ret;
+
+ if (!of_parse_phandle(np, "msi-parent", 0)) {
+ dev_err(dev, "Failed to find msi-parent\n");
+ return -EINVAL;
+ }
+
+ bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
+ if (!bridge)
+ return -ENOMEM;
+
+ pcie = pci_host_bridge_priv(bridge);
+ mv_pci = &pcie->pci;
+
+ mv_pci->pdev = pdev;
+ mv_pci->ops = &ls_pcie_g4_pab_ops;
+ mv_pci->rp.ops = &ls_pcie_g4_rp_ops;
+ mv_pci->rp.bridge = bridge;
+
+ platform_set_drvdata(pdev, pcie);
+
+ INIT_DELAYED_WORK(&pcie->dwork, ls_pcie_g4_reset);
+
+ ret = mobiveil_pcie_host_probe(mv_pci);
+ if (ret) {
+ dev_err(dev, "Fail to probe\n");
+ return ret;
+ }
+
+ ls_pcie_g4_enable_interrupt(pcie);
+
+ return 0;
+}
+
+static const struct of_device_id ls_pcie_g4_of_match[] = {
+ { .compatible = "fsl,lx2160a-pcie", },
+ { },
+};
+
+static struct platform_driver ls_pcie_g4_driver = {
+ .driver = {
+ .name = "layerscape-pcie-gen4",
+ .of_match_table = ls_pcie_g4_of_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+builtin_platform_driver_probe(ls_pcie_g4_driver, ls_pcie_g4_probe);
diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
index 72c62b4d8f7b..7b6a403a9fc0 100644
--- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
+++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
@@ -43,6 +43,8 @@
#define PAGE_LO_MASK 0x3ff
#define PAGE_SEL_OFFSET_SHIFT 10
+#define PAB_ACTIVITY_STAT 0x81c
+
#define PAB_AXI_PIO_CTRL 0x0840
#define APIO_EN_MASK 0xf
@@ -51,8 +53,18 @@
#define PAB_INTP_AMBA_MISC_ENB 0x0b0c
#define PAB_INTP_AMBA_MISC_STAT 0x0b1c
-#define PAB_INTP_INTX_MASK 0x01e0
-#define PAB_INTP_MSI_MASK 0x8
+#define PAB_INTP_RESET BIT(1)
+#define PAB_INTP_MSI BIT(3)
+#define PAB_INTP_INTA BIT(5)
+#define PAB_INTP_INTB BIT(6)
+#define PAB_INTP_INTC BIT(7)
+#define PAB_INTP_INTD BIT(8)
+#define PAB_INTP_PCIE_UE BIT(9)
+#define PAB_INTP_IE_PMREDI BIT(29)
+#define PAB_INTP_IE_EC BIT(30)
+#define PAB_INTP_MSI_MASK PAB_INTP_MSI
+#define PAB_INTP_INTX_MASK (PAB_INTP_INTA | PAB_INTP_INTB |\
+ PAB_INTP_INTC | PAB_INTP_INTD)
#define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win)
#define WIN_ENABLE_SHIFT 0
--
2.17.1
From: Hou Zhiqiang <[email protected]>
The LX2160A integrated 6 PCIe Gen4 controllers.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Minghuan Lian <[email protected]>
---
V10:
- No change
.../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 163 ++++++++++++++++++
1 file changed, 163 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index e5ee5591e52b..aee2810d91cc 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -1076,5 +1076,168 @@
};
};
};
+
+ pcie@3400000 {
+ compatible = "fsl,lx2160a-pcie";
+ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
+ 0x80 0x00000000 0x0 0x00001000>; /* configuration space */
+ reg-names = "csr_axi_slave", "config_axi_slave";
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "aer", "pme", "intr";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ apio-wins = <8>;
+ ppio-wins = <8>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pcie@3500000 {
+ compatible = "fsl,lx2160a-pcie";
+ reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */
+ 0x88 0x00000000 0x0 0x00001000>; /* configuration space */
+ reg-names = "csr_axi_slave", "config_axi_slave";
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "aer", "pme", "intr";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ apio-wins = <8>;
+ ppio-wins = <8>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pcie@3600000 {
+ compatible = "fsl,lx2160a-pcie";
+ reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */
+ 0x90 0x00000000 0x0 0x00001000>; /* configuration space */
+ reg-names = "csr_axi_slave", "config_axi_slave";
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "aer", "pme", "intr";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ apio-wins = <256>;
+ ppio-wins = <24>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pcie@3700000 {
+ compatible = "fsl,lx2160a-pcie";
+ reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */
+ 0x98 0x00000000 0x0 0x00001000>; /* configuration space */
+ reg-names = "csr_axi_slave", "config_axi_slave";
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "aer", "pme", "intr";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ apio-wins = <8>;
+ ppio-wins = <8>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pcie@3800000 {
+ compatible = "fsl,lx2160a-pcie";
+ reg = <0x00 0x03800000 0x0 0x00100000 /* controller registers */
+ 0xa0 0x00000000 0x0 0x00001000>; /* configuration space */
+ reg-names = "csr_axi_slave", "config_axi_slave";
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "aer", "pme", "intr";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ apio-wins = <256>;
+ ppio-wins = <24>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pcie@3900000 {
+ compatible = "fsl,lx2160a-pcie";
+ reg = <0x00 0x03900000 0x0 0x00100000 /* controller registers */
+ 0xa8 0x00000000 0x0 0x00001000>; /* configuration space */
+ reg-names = "csr_axi_slave", "config_axi_slave";
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
+ interrupt-names = "aer", "pme", "intr";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ apio-wins = <8>;
+ ppio-wins = <8>;
+ bus-range = <0x0 0xff>;
+ ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+ msi-parent = <&its>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 2 &gic 0 0 GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 3 &gic 0 0 GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+ <0000 0 0 4 &gic 0 0 GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
};
};
--
2.17.1
From: Hou Zhiqiang <[email protected]>
Enable the PCIe Gen4 controller driver for Layerscape SoCs.
Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Minghuan Lian <[email protected]>
---
V10:
- No change
arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 4631a1190719..3bbd14e9dfd5 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -195,6 +195,7 @@ CONFIG_PCI_HOST_THUNDER_ECAM=y
CONFIG_PCIE_ROCKCHIP_HOST=m
CONFIG_PCIE_BRCMSTB=m
CONFIG_PCI_LAYERSCAPE=y
+CONFIG_PCIE_LAYERSCAPE_GEN4=y
CONFIG_PCI_HISI=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_ARMADA_8K=y
--
2.17.1
On Thu, Feb 13, 2020 at 12:06:32PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> The Mobiveil PCIe controller can work in either Root Complex
> mode or Endpoint mode. So introduce a new structure
> mobiveil_root_port, and abstract the RC related members into
> it such that the code can be used by both mode.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
> ---
> V10:
> - Refined the subject and change log.
> - Added prefix mobiveil to the root port structure.
>
> drivers/pci/controller/pcie-mobiveil.c | 99 ++++++++++++++++----------
> 1 file changed, 60 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
> index 3a696ca45bfa..d4de560cd711 100644
> --- a/drivers/pci/controller/pcie-mobiveil.c
> +++ b/drivers/pci/controller/pcie-mobiveil.c
> @@ -3,7 +3,10 @@
> * PCIe host controller driver for Mobiveil PCIe Host controller
> *
> * Copyright (c) 2018 Mobiveil Inc.
> + * Copyright 2019-2020 NXP
> + *
> * Author: Subrahmanya Lingappa <[email protected]>
> + * Hou Zhiqiang <[email protected]>
> */
>
> #include <linux/delay.h>
> @@ -138,22 +141,27 @@ struct mobiveil_msi { /* MSI information */
> DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI);
> };
>
> +struct mobiveil_root_port {
> + char root_bus_nr;
> + void __iomem *config_axi_slave_base; /* endpoint config base */
> + struct resource *ob_io_res;
> + int irq;
> + raw_spinlock_t intx_mask_lock;
> + struct irq_domain *intx_domain;
> + struct mobiveil_msi msi;
> + struct pci_host_bridge *bridge;
> +};
> +
> struct mobiveil_pcie {
> struct platform_device *pdev;
> - void __iomem *config_axi_slave_base; /* endpoint config base */
> void __iomem *csr_axi_slave_base; /* root port config base */
> void __iomem *apb_csr_base; /* MSI register base */
> phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */
> - struct irq_domain *intx_domain;
> - raw_spinlock_t intx_mask_lock;
> - int irq;
> int apio_wins;
> int ppio_wins;
> int ob_wins_configured; /* configured outbound windows */
> int ib_wins_configured; /* configured inbound windows */
> - struct resource *ob_io_res;
> - char root_bus_nr;
> - struct mobiveil_msi msi;
> + struct mobiveil_root_port rp;
> };
>
> /*
> @@ -281,16 +289,17 @@ static bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
> static bool mobiveil_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
> {
> struct mobiveil_pcie *pcie = bus->sysdata;
> + struct mobiveil_root_port *rp = &pcie->rp;
>
> /* Only one device down on each root port */
> - if ((bus->number == pcie->root_bus_nr) && (devfn > 0))
> + if ((bus->number == rp->root_bus_nr) && (devfn > 0))
> return false;
>
> /*
> * Do not read more than one device on the bus directly
> * attached to RC
> */
> - if ((bus->primary == pcie->root_bus_nr) && (PCI_SLOT(devfn) > 0))
> + if ((bus->primary == rp->root_bus_nr) && (PCI_SLOT(devfn) > 0))
> return false;
>
> return true;
> @@ -304,13 +313,14 @@ static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus,
> unsigned int devfn, int where)
> {
> struct mobiveil_pcie *pcie = bus->sysdata;
> + struct mobiveil_root_port *rp = &pcie->rp;
> u32 value;
>
> if (!mobiveil_pcie_valid_device(bus, devfn))
> return NULL;
>
> /* RC config access */
> - if (bus->number == pcie->root_bus_nr)
> + if (bus->number == rp->root_bus_nr)
> return pcie->csr_axi_slave_base + where;
>
> /*
> @@ -325,7 +335,7 @@ static void __iomem *mobiveil_pcie_map_bus(struct pci_bus *bus,
>
> mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0));
>
> - return pcie->config_axi_slave_base + where;
> + return rp->config_axi_slave_base + where;
> }
>
> static struct pci_ops mobiveil_pcie_ops = {
> @@ -339,7 +349,8 @@ static void mobiveil_pcie_isr(struct irq_desc *desc)
> struct irq_chip *chip = irq_desc_get_chip(desc);
> struct mobiveil_pcie *pcie = irq_desc_get_handler_data(desc);
> struct device *dev = &pcie->pdev->dev;
> - struct mobiveil_msi *msi = &pcie->msi;
> + struct mobiveil_root_port *rp = &pcie->rp;
> + struct mobiveil_msi *msi = &rp->msi;
> u32 msi_data, msi_addr_lo, msi_addr_hi;
> u32 intr_status, msi_status;
> unsigned long shifted_status;
> @@ -365,7 +376,7 @@ static void mobiveil_pcie_isr(struct irq_desc *desc)
> shifted_status >>= PAB_INTX_START;
> do {
> for_each_set_bit(bit, &shifted_status, PCI_NUM_INTX) {
> - virq = irq_find_mapping(pcie->intx_domain,
> + virq = irq_find_mapping(rp->intx_domain,
> bit + 1);
> if (virq)
> generic_handle_irq(virq);
> @@ -424,15 +435,16 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
> struct device *dev = &pcie->pdev->dev;
> struct platform_device *pdev = pcie->pdev;
> struct device_node *node = dev->of_node;
> + struct mobiveil_root_port *rp = &pcie->rp;
> struct resource *res;
>
> /* map config resource */
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "config_axi_slave");
> - pcie->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
> - if (IS_ERR(pcie->config_axi_slave_base))
> - return PTR_ERR(pcie->config_axi_slave_base);
> - pcie->ob_io_res = res;
> + rp->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
> + if (IS_ERR(rp->config_axi_slave_base))
> + return PTR_ERR(rp->config_axi_slave_base);
> + rp->ob_io_res = res;
>
> /* map csr resource */
> res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> @@ -455,9 +467,9 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
> if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
> pcie->ppio_wins = MAX_PIO_WINDOWS;
>
> - pcie->irq = platform_get_irq(pdev, 0);
> - if (pcie->irq <= 0) {
> - dev_err(dev, "failed to map IRQ: %d\n", pcie->irq);
> + rp->irq = platform_get_irq(pdev, 0);
> + if (rp->irq <= 0) {
> + dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
> return -ENODEV;
> }
>
> @@ -564,9 +576,9 @@ static int mobiveil_bringup_link(struct mobiveil_pcie *pcie)
> static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
> {
> phys_addr_t msg_addr = pcie->pcie_reg_base;
> - struct mobiveil_msi *msi = &pcie->msi;
> + struct mobiveil_msi *msi = &pcie->rp.msi;
>
> - pcie->msi.num_of_vectors = PCI_NUM_MSI;
> + msi->num_of_vectors = PCI_NUM_MSI;
> msi->msi_pages_phys = (phys_addr_t)msg_addr;
>
> writel_relaxed(lower_32_bits(msg_addr),
> @@ -579,7 +591,8 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
>
> static int mobiveil_host_init(struct mobiveil_pcie *pcie)
> {
> - struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
> + struct mobiveil_root_port *rp = &pcie->rp;
> + struct pci_host_bridge *bridge = rp->bridge;
> u32 value, pab_ctrl, type;
> struct resource_entry *win;
>
> @@ -629,8 +642,8 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
> */
>
> /* config outbound translation window */
> - program_ob_windows(pcie, WIN_NUM_0, pcie->ob_io_res->start, 0,
> - CFG_WINDOW_TYPE, resource_size(pcie->ob_io_res));
> + program_ob_windows(pcie, WIN_NUM_0, rp->ob_io_res->start, 0,
> + CFG_WINDOW_TYPE, resource_size(rp->ob_io_res));
>
> /* memory inbound translation window */
> program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE, IB_WIN_SIZE);
> @@ -667,32 +680,36 @@ static void mobiveil_mask_intx_irq(struct irq_data *data)
> {
> struct irq_desc *desc = irq_to_desc(data->irq);
> struct mobiveil_pcie *pcie;
> + struct mobiveil_root_port *rp;
> unsigned long flags;
> u32 mask, shifted_val;
>
> pcie = irq_desc_get_chip_data(desc);
> + rp = &pcie->rp;
> mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
> - raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
> + raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
> shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
> shifted_val &= ~mask;
> mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
> - raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
> + raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
> }
>
> static void mobiveil_unmask_intx_irq(struct irq_data *data)
> {
> struct irq_desc *desc = irq_to_desc(data->irq);
> struct mobiveil_pcie *pcie;
> + struct mobiveil_root_port *rp;
> unsigned long flags;
> u32 shifted_val, mask;
>
> pcie = irq_desc_get_chip_data(desc);
> + rp = &pcie->rp;
> mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
> - raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
> + raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
> shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
> shifted_val |= mask;
> mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
> - raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
> + raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
> }
>
> static struct irq_chip intx_irq_chip = {
> @@ -760,7 +777,7 @@ static int mobiveil_irq_msi_domain_alloc(struct irq_domain *domain,
> unsigned int nr_irqs, void *args)
> {
> struct mobiveil_pcie *pcie = domain->host_data;
> - struct mobiveil_msi *msi = &pcie->msi;
> + struct mobiveil_msi *msi = &pcie->rp.msi;
> unsigned long bit;
>
> WARN_ON(nr_irqs != 1);
> @@ -787,7 +804,7 @@ static void mobiveil_irq_msi_domain_free(struct irq_domain *domain,
> {
> struct irq_data *d = irq_domain_get_irq_data(domain, virq);
> struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(d);
> - struct mobiveil_msi *msi = &pcie->msi;
> + struct mobiveil_msi *msi = &pcie->rp.msi;
>
> mutex_lock(&msi->lock);
>
> @@ -808,9 +825,9 @@ static int mobiveil_allocate_msi_domains(struct mobiveil_pcie *pcie)
> {
> struct device *dev = &pcie->pdev->dev;
> struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
> - struct mobiveil_msi *msi = &pcie->msi;
> + struct mobiveil_msi *msi = &pcie->rp.msi;
>
> - mutex_init(&pcie->msi.lock);
> + mutex_init(&msi->lock);
> msi->dev_domain = irq_domain_add_linear(NULL, msi->num_of_vectors,
> &msi_domain_ops, pcie);
> if (!msi->dev_domain) {
> @@ -834,18 +851,19 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
> {
> struct device *dev = &pcie->pdev->dev;
> struct device_node *node = dev->of_node;
> + struct mobiveil_root_port *rp = &pcie->rp;
> int ret;
>
> /* setup INTx */
> - pcie->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
> - &intx_domain_ops, pcie);
> + rp->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
> + &intx_domain_ops, pcie);
>
> - if (!pcie->intx_domain) {
> + if (!rp->intx_domain) {
> dev_err(dev, "Failed to get a INTx IRQ domain\n");
> return -ENOMEM;
> }
>
> - raw_spin_lock_init(&pcie->intx_mask_lock);
> + raw_spin_lock_init(&rp->intx_mask_lock);
>
> /* setup MSI */
> ret = mobiveil_allocate_msi_domains(pcie);
> @@ -862,6 +880,7 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
> struct pci_bus *child;
> struct pci_host_bridge *bridge;
> struct device *dev = &pdev->dev;
> + struct mobiveil_root_port *rp;
> int ret;
>
> /* allocate the PCIe port */
> @@ -870,6 +889,8 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
> return -ENOMEM;
>
> pcie = pci_host_bridge_priv(bridge);
> + rp = &pcie->rp;
> + rp->bridge = bridge;
>
> pcie->pdev = pdev;
>
> @@ -904,12 +925,12 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
> return ret;
> }
>
> - irq_set_chained_handler_and_data(pcie->irq, mobiveil_pcie_isr, pcie);
> + irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
>
> /* Initialize bridge */
> bridge->dev.parent = dev;
> bridge->sysdata = pcie;
> - bridge->busnr = pcie->root_bus_nr;
> + bridge->busnr = rp->root_bus_nr;
> bridge->ops = &mobiveil_pcie_ops;
> bridge->map_irq = of_irq_parse_and_map_pci;
> bridge->swizzle_irq = pci_common_swizzle;
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:33PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> Move the host initialization related operations into a new
> routine such that it can be reused by other incoming platform's
> PCIe host driver, in which the Mobiveil GPEX is integrated.
>
> Change the subject and change log slightly.
> Change the function mobiveil_pcie_host_probe to static.
> Add back the comments that was lost in v9.
Are these three lines above supposed to be in the history below the
--- ?
Perhaps Lorenzo can change that when he applies it.
Reviewed-by: Andrew Murray <[email protected]>
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
> ---
> V10:
> - Refined the subject and change log.
> - Changed the mobiveil_pcie_host_probe() to a static function.
> - Added back the lost comments.
>
> drivers/pci/controller/pcie-mobiveil.c | 39 +++++++++++++++-----------
> 1 file changed, 23 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
> index d4de560cd711..01df04ea5b48 100644
> --- a/drivers/pci/controller/pcie-mobiveil.c
> +++ b/drivers/pci/controller/pcie-mobiveil.c
> @@ -873,27 +873,15 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
> return 0;
> }
>
> -static int mobiveil_pcie_probe(struct platform_device *pdev)
> +static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> {
> - struct mobiveil_pcie *pcie;
> + struct mobiveil_root_port *rp = &pcie->rp;
> + struct pci_host_bridge *bridge = rp->bridge;
> + struct device *dev = &pcie->pdev->dev;
> struct pci_bus *bus;
> struct pci_bus *child;
> - struct pci_host_bridge *bridge;
> - struct device *dev = &pdev->dev;
> - struct mobiveil_root_port *rp;
> int ret;
>
> - /* allocate the PCIe port */
> - bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> - if (!bridge)
> - return -ENOMEM;
> -
> - pcie = pci_host_bridge_priv(bridge);
> - rp = &pcie->rp;
> - rp->bridge = bridge;
> -
> - pcie->pdev = pdev;
> -
> ret = mobiveil_pcie_parse_dt(pcie);
> if (ret) {
> dev_err(dev, "Parsing DT failed, ret: %x\n", ret);
> @@ -956,6 +944,25 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
> return 0;
> }
>
> +static int mobiveil_pcie_probe(struct platform_device *pdev)
> +{
> + struct mobiveil_pcie *pcie;
> + struct pci_host_bridge *bridge;
> + struct device *dev = &pdev->dev;
> +
> + /* allocate the PCIe port */
> + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> + if (!bridge)
> + return -ENOMEM;
> +
> + pcie = pci_host_bridge_priv(bridge);
> + pcie->rp.bridge = bridge;
> +
> + pcie->pdev = pdev;
> +
> + return mobiveil_pcie_host_probe(pcie);
> +}
> +
> static const struct of_device_id mobiveil_pcie_of_match[] = {
> {.compatible = "mbvl,gpex40-pcie",},
> {},
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:34PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> Collect the interrupt initialization related operations into
> a new function such that it is more readable.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
> ---
> V10:
> - Refined the subject and change log.
>
> drivers/pci/controller/pcie-mobiveil.c | 65 +++++++++++++++++---------
> 1 file changed, 42 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
> index 01df04ea5b48..9449528bb14f 100644
> --- a/drivers/pci/controller/pcie-mobiveil.c
> +++ b/drivers/pci/controller/pcie-mobiveil.c
> @@ -454,12 +454,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
> return PTR_ERR(pcie->csr_axi_slave_base);
> pcie->pcie_reg_base = res->start;
>
> - /* map MSI config resource */
> - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr");
> - pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
> - if (IS_ERR(pcie->apb_csr_base))
> - return PTR_ERR(pcie->apb_csr_base);
> -
> /* read the number of windows requested */
> if (of_property_read_u32(node, "apio-wins", &pcie->apio_wins))
> pcie->apio_wins = MAX_PIO_WINDOWS;
> @@ -467,12 +461,6 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
> if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
> pcie->ppio_wins = MAX_PIO_WINDOWS;
>
> - rp->irq = platform_get_irq(pdev, 0);
> - if (rp->irq <= 0) {
> - dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
> - return -ENODEV;
> - }
> -
> return 0;
> }
>
> @@ -618,9 +606,6 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
> pab_ctrl |= (1 << AMBA_PIO_ENABLE_SHIFT) | (1 << PEX_PIO_ENABLE_SHIFT);
> mobiveil_csr_writel(pcie, pab_ctrl, PAB_CTRL);
>
> - mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
> - PAB_INTP_AMBA_MISC_ENB);
> -
> /*
> * program PIO Enable Bit to 1 and Config Window Enable Bit to 1 in
> * PAB_AXI_PIO_CTRL Register
> @@ -670,9 +655,6 @@ static int mobiveil_host_init(struct mobiveil_pcie *pcie)
> value |= (PCI_CLASS_BRIDGE_PCI << 16);
> mobiveil_csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
>
> - /* setup MSI hardware registers */
> - mobiveil_pcie_enable_msi(pcie);
> -
> return 0;
> }
>
> @@ -873,6 +855,46 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
> return 0;
> }
>
> +static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
> +{
> + struct platform_device *pdev = pcie->pdev;
> + struct device *dev = &pdev->dev;
> + struct mobiveil_root_port *rp = &pcie->rp;
> + struct resource *res;
> + int ret;
> +
> + /* map MSI config resource */
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apb_csr");
> + pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
> + if (IS_ERR(pcie->apb_csr_base))
> + return PTR_ERR(pcie->apb_csr_base);
> +
> + /* setup MSI hardware registers */
> + mobiveil_pcie_enable_msi(pcie);
> +
> + rp->irq = platform_get_irq(pdev, 0);
> + if (rp->irq <= 0) {
> + dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
> + return -ENODEV;
> + }
> +
> + /* initialize the IRQ domains */
> + ret = mobiveil_pcie_init_irq_domain(pcie);
> + if (ret) {
> + dev_err(dev, "Failed creating IRQ Domain\n");
> + return ret;
> + }
> +
> + irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
> +
> + /* Enable interrupts */
> + mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
> + PAB_INTP_AMBA_MISC_ENB);
> +
> +
> + return 0;
> +}
> +
> static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> {
> struct mobiveil_root_port *rp = &pcie->rp;
> @@ -906,15 +928,12 @@ static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> return ret;
> }
>
> - /* initialize the IRQ domains */
> - ret = mobiveil_pcie_init_irq_domain(pcie);
> + ret = mobiveil_pcie_interrupt_init(pcie);
> if (ret) {
> - dev_err(dev, "Failed creating IRQ Domain\n");
> + dev_err(dev, "Interrupt init failed\n");
> return ret;
> }
>
> - irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
> -
> /* Initialize bridge */
> bridge->dev.parent = dev;
> bridge->sysdata = pcie;
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:36PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> The Mobiveil GPEX internal MSI/INTx controller may not be used
> by other platforms in which the Mobiveil GPEX is integrated.
> This patch is to allow these platforms to implement their
> specific interrupt initialization.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
> ---
> V10:
> - Introduced a helper function mobiveil_pcie_integrated_interrupt_init().
>
> drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 12 +++++++++++-
> drivers/pci/controller/mobiveil/pcie-mobiveil.h | 7 +++++++
> 2 files changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> index ea90d2f8692e..53ab8412a1de 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> @@ -499,7 +499,7 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
> return 0;
> }
>
> -static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
> +static int mobiveil_pcie_integrated_interrupt_init(struct mobiveil_pcie *pcie)
> {
> struct platform_device *pdev = pcie->pdev;
> struct device *dev = &pdev->dev;
> @@ -539,6 +539,16 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
> return 0;
> }
>
> +static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
> +{
> + struct mobiveil_root_port *rp = &pcie->rp;
> +
> + if (rp->ops->interrupt_init)
> + return rp->ops->interrupt_init(pcie);
> +
> + return mobiveil_pcie_integrated_interrupt_init(pcie);
> +}
> +
> int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> {
> struct mobiveil_root_port *rp = &pcie->rp;
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> index 81ffbbd48c08..0e6b5468c026 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> @@ -130,10 +130,17 @@ struct mobiveil_msi { /* MSI information */
> DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI);
> };
>
> +struct mobiveil_pcie;
> +
> +struct mobiveil_rp_ops {
> + int (*interrupt_init)(struct mobiveil_pcie *pcie);
> +};
> +
> struct mobiveil_root_port {
> char root_bus_nr;
> void __iomem *config_axi_slave_base; /* endpoint config base */
> struct resource *ob_io_res;
> + struct mobiveil_rp_ops *ops;
> int irq;
> raw_spinlock_t intx_mask_lock;
> struct irq_domain *intx_domain;
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:38PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> Allow the mobiveil_host_init() function to be used to re-init
> host controller's PAB and GPEX CSR register block, as NXP
> integrated Mobiveil IP has to reset and then re-init the PAB
> and GPEX CSR registers upon hot-reset.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
> Reviewed-by: Subrahmanya Lingappa <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
> ---
> V10:
> - Refined the subject and change log.
>
> .../controller/mobiveil/pcie-mobiveil-host.c | 19 ++++++++++++-------
> .../pci/controller/mobiveil/pcie-mobiveil.h | 1 +
> 2 files changed, 13 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> index 53ab8412a1de..44dd641fede3 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> @@ -221,18 +221,23 @@ static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
> writel_relaxed(1, pcie->apb_csr_base + MSI_ENABLE_OFFSET);
> }
>
> -static int mobiveil_host_init(struct mobiveil_pcie *pcie)
> +int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit)
> {
> struct mobiveil_root_port *rp = &pcie->rp;
> struct pci_host_bridge *bridge = rp->bridge;
> u32 value, pab_ctrl, type;
> struct resource_entry *win;
>
> - /* setup bus numbers */
> - value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
> - value &= 0xff000000;
> - value |= 0x00ff0100;
> - mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
> + pcie->ib_wins_configured = 0;
> + pcie->ob_wins_configured = 0;
> +
> + if (!reinit) {
> + /* setup bus numbers */
> + value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
> + value &= 0xff000000;
> + value |= 0x00ff0100;
> + mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
> + }
>
> /*
> * program Bus Master Enable Bit in Command Register in PAB Config
> @@ -576,7 +581,7 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> * configure all inbound and outbound windows and prepare the RC for
> * config access
> */
> - ret = mobiveil_host_init(pcie);
> + ret = mobiveil_host_init(pcie, false);
> if (ret) {
> dev_err(dev, "Failed to initialize host\n");
> return ret;
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> index 346bf79a581b..623c5f0c4441 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> @@ -166,6 +166,7 @@ struct mobiveil_pcie {
> };
>
> int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie);
> +int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit);
> bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie);
> int mobiveil_bringup_link(struct mobiveil_pcie *pcie);
> void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr,
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:39PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> There are some 8-bit and 16-bit registers in PCIe configuration
> space, so add these accessors accordingly.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
> Reviewed-by: Minghuan Lian <[email protected]>
> Reviewed-by: Subrahmanya Lingappa <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
> ---
> V10:
> - Changed the return types to reflect the size of the access.
>
> .../pci/controller/mobiveil/pcie-mobiveil.h | 23 +++++++++++++++++++
> 1 file changed, 23 insertions(+)
>
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> index 623c5f0c4441..72c62b4d8f7b 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> @@ -182,10 +182,33 @@ static inline u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off)
> return mobiveil_csr_read(pcie, off, 0x4);
> }
>
> +static inline u16 mobiveil_csr_readw(struct mobiveil_pcie *pcie, u32 off)
> +{
> + return mobiveil_csr_read(pcie, off, 0x2);
> +}
> +
> +static inline u8 mobiveil_csr_readb(struct mobiveil_pcie *pcie, u32 off)
> +{
> + return mobiveil_csr_read(pcie, off, 0x1);
> +}
> +
> +
> static inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val,
> u32 off)
> {
> mobiveil_csr_write(pcie, val, off, 0x4);
> }
>
> +static inline void mobiveil_csr_writew(struct mobiveil_pcie *pcie, u16 val,
> + u32 off)
> +{
> + mobiveil_csr_write(pcie, val, off, 0x2);
> +}
> +
> +static inline void mobiveil_csr_writeb(struct mobiveil_pcie *pcie, u8 val,
> + u32 off)
> +{
> + mobiveil_csr_write(pcie, val, off, 0x1);
> +}
> +
> #endif /* _PCIE_MOBIVEIL_H */
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:40PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> Check the Header Type and exit from the host driver initialization if
> it is not in host mode.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
> ---
> V10:
> - New patch separated from #10 of v9.
>
> .../pci/controller/mobiveil/pcie-mobiveil-host.c | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> index 44dd641fede3..db7028788d91 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> @@ -554,6 +554,16 @@ static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
> return mobiveil_pcie_integrated_interrupt_init(pcie);
> }
>
> +static bool mobiveil_pcie_is_bridge(struct mobiveil_pcie *pcie)
> +{
> + u32 header_type;
> +
> + header_type = mobiveil_csr_readb(pcie, PCI_HEADER_TYPE);
> + header_type &= 0x7f;
> +
> + return header_type == PCI_HEADER_TYPE_BRIDGE;
> +}
> +
> int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> {
> struct mobiveil_root_port *rp = &pcie->rp;
> @@ -569,6 +579,9 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> return ret;
> }
>
> + if (!mobiveil_pcie_is_bridge(pcie))
> + return -ENODEV;
> +
> /* parse the host bridge base addresses from the device tree file */
> ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
> &bridge->dma_ranges, NULL);
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:42PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> This PCIe controller is based on the Mobiveil GPEX IP, which is
> compatible with the PCI Expressâ„¢ Base Specification, Revision 4.0.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
> Reviewed-by: Minghuan Lian <[email protected]>
Reviewed-by: Andrew Murray <[email protected]>
> ---
> V10:
> - Changed the return type of ls_pcie_g4_reinit_hw() to void.
> - Moved Header Type check to mobiveil_pcie_host_probe().
>
> drivers/pci/controller/mobiveil/Kconfig | 9 +
> drivers/pci/controller/mobiveil/Makefile | 1 +
> .../mobiveil/pcie-layerscape-gen4.c | 267 ++++++++++++++++++
> .../pci/controller/mobiveil/pcie-mobiveil.h | 16 +-
> 4 files changed, 291 insertions(+), 2 deletions(-)
> create mode 100644 drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
>
> diff --git a/drivers/pci/controller/mobiveil/Kconfig b/drivers/pci/controller/mobiveil/Kconfig
> index 54161d4ddb11..7439991ee82c 100644
> --- a/drivers/pci/controller/mobiveil/Kconfig
> +++ b/drivers/pci/controller/mobiveil/Kconfig
> @@ -21,4 +21,13 @@ config PCIE_MOBIVEIL_PLAT
> Soft IP. It has up to 8 outbound and inbound windows
> for address translation and it is a PCIe Gen4 IP.
>
> +config PCIE_LAYERSCAPE_GEN4
> + bool "Freescale Layerscape PCIe Gen4 controller"
> + depends on PCI
> + depends on OF && (ARM64 || ARCH_LAYERSCAPE)
> + depends on PCI_MSI_IRQ_DOMAIN
> + select PCIE_MOBIVEIL_HOST
> + help
> + Say Y here if you want PCIe Gen4 controller support on
> + Layerscape SoCs.
> endmenu
> diff --git a/drivers/pci/controller/mobiveil/Makefile b/drivers/pci/controller/mobiveil/Makefile
> index 9fb6d1c6504d..99d879de32d6 100644
> --- a/drivers/pci/controller/mobiveil/Makefile
> +++ b/drivers/pci/controller/mobiveil/Makefile
> @@ -2,3 +2,4 @@
> obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
> obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o
> obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o
> +obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie-layerscape-gen4.o
> diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> new file mode 100644
> index 000000000000..f3bd5f5ad229
> --- /dev/null
> +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> @@ -0,0 +1,267 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe Gen4 host controller driver for NXP Layerscape SoCs
> + *
> + * Copyright 2019-2020 NXP
> + *
> + * Author: Zhiqiang Hou <[email protected]>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/interrupt.h>
> +#include <linux/init.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/resource.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +#include "pcie-mobiveil.h"
> +
> +/* LUT and PF control registers */
> +#define PCIE_LUT_OFF 0x80000
> +#define PCIE_PF_OFF 0xc0000
> +#define PCIE_PF_INT_STAT 0x18
> +#define PF_INT_STAT_PABRST BIT(31)
> +
> +#define PCIE_PF_DBG 0x7fc
> +#define PF_DBG_LTSSM_MASK 0x3f
> +#define PF_DBG_LTSSM_L0 0x2d /* L0 state */
> +#define PF_DBG_WE BIT(31)
> +#define PF_DBG_PABR BIT(27)
> +
> +#define to_ls_pcie_g4(x) platform_get_drvdata((x)->pdev)
> +
> +struct ls_pcie_g4 {
> + struct mobiveil_pcie pci;
> + struct delayed_work dwork;
> + int irq;
> +};
> +
> +static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32 off)
> +{
> + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
> +}
> +
> +static inline void ls_pcie_g4_lut_writel(struct ls_pcie_g4 *pcie,
> + u32 off, u32 val)
> +{
> + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
> +}
> +
> +static inline u32 ls_pcie_g4_pf_readl(struct ls_pcie_g4 *pcie, u32 off)
> +{
> + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
> +}
> +
> +static inline void ls_pcie_g4_pf_writel(struct ls_pcie_g4 *pcie,
> + u32 off, u32 val)
> +{
> + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
> +}
> +
> +static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci)
> +{
> + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
> + u32 state;
> +
> + state = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + state = state & PF_DBG_LTSSM_MASK;
> +
> + if (state == PF_DBG_LTSSM_L0)
> + return 1;
> +
> + return 0;
> +}
> +
> +static void ls_pcie_g4_disable_interrupt(struct ls_pcie_g4 *pcie)
> +{
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> +
> + mobiveil_csr_writel(mv_pci, 0, PAB_INTP_AMBA_MISC_ENB);
> +}
> +
> +static void ls_pcie_g4_enable_interrupt(struct ls_pcie_g4 *pcie)
> +{
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + u32 val;
> +
> + /* Clear the interrupt status */
> + mobiveil_csr_writel(mv_pci, 0xffffffff, PAB_INTP_AMBA_MISC_STAT);
> +
> + val = PAB_INTP_INTX_MASK | PAB_INTP_MSI | PAB_INTP_RESET |
> + PAB_INTP_PCIE_UE | PAB_INTP_IE_PMREDI | PAB_INTP_IE_EC;
> + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_ENB);
> +}
> +
> +static int ls_pcie_g4_reinit_hw(struct ls_pcie_g4 *pcie)
> +{
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + struct device *dev = &mv_pci->pdev->dev;
> + u32 val, act_stat;
> + int to = 100;
> +
> + /* Poll for pab_csb_reset to set and PAB activity to clear */
> + do {
> + usleep_range(10, 15);
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_INT_STAT);
> + act_stat = mobiveil_csr_readl(mv_pci, PAB_ACTIVITY_STAT);
> + } while (((val & PF_INT_STAT_PABRST) == 0 || act_stat) && to--);
> + if (to < 0) {
> + dev_err(dev, "Poll PABRST&PABACT timeout\n");
> + return -EIO;
> + }
> +
> + /* clear PEX_RESET bit in PEX_PF0_DBG register */
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + val |= PF_DBG_WE;
> + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> +
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + val |= PF_DBG_PABR;
> + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> +
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + val &= ~PF_DBG_WE;
> + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> +
> + mobiveil_host_init(mv_pci, true);
> +
> + to = 100;
> + while (!ls_pcie_g4_link_up(mv_pci) && to--)
> + usleep_range(200, 250);
> + if (to < 0) {
> + dev_err(dev, "PCIe link training timeout\n");
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> +static irqreturn_t ls_pcie_g4_isr(int irq, void *dev_id)
> +{
> + struct ls_pcie_g4 *pcie = (struct ls_pcie_g4 *)dev_id;
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + u32 val;
> +
> + val = mobiveil_csr_readl(mv_pci, PAB_INTP_AMBA_MISC_STAT);
> + if (!val)
> + return IRQ_NONE;
> +
> + if (val & PAB_INTP_RESET) {
> + ls_pcie_g4_disable_interrupt(pcie);
> + schedule_delayed_work(&pcie->dwork, msecs_to_jiffies(1));
> + }
> +
> + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_STAT);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int ls_pcie_g4_interrupt_init(struct mobiveil_pcie *mv_pci)
> +{
> + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(mv_pci);
> + struct platform_device *pdev = mv_pci->pdev;
> + struct device *dev = &pdev->dev;
> + int ret;
> +
> + pcie->irq = platform_get_irq_byname(pdev, "intr");
> + if (pcie->irq < 0) {
> + dev_err(dev, "Can't get 'intr' IRQ, errno = %d\n", pcie->irq);
> + return pcie->irq;
> + }
> + ret = devm_request_irq(dev, pcie->irq, ls_pcie_g4_isr,
> + IRQF_SHARED, pdev->name, pcie);
> + if (ret) {
> + dev_err(dev, "Can't register PCIe IRQ, errno = %d\n", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static void ls_pcie_g4_reset(struct work_struct *work)
> +{
> + struct delayed_work *dwork = container_of(work, struct delayed_work,
> + work);
> + struct ls_pcie_g4 *pcie = container_of(dwork, struct ls_pcie_g4, dwork);
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + u16 ctrl;
> +
> + ctrl = mobiveil_csr_readw(mv_pci, PCI_BRIDGE_CONTROL);
> + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
> + mobiveil_csr_writew(mv_pci, ctrl, PCI_BRIDGE_CONTROL);
> +
> + if (!ls_pcie_g4_reinit_hw(pcie))
> + return;
> +
> + ls_pcie_g4_enable_interrupt(pcie);
> +}
> +
> +static struct mobiveil_rp_ops ls_pcie_g4_rp_ops = {
> + .interrupt_init = ls_pcie_g4_interrupt_init,
> +};
> +
> +static const struct mobiveil_pab_ops ls_pcie_g4_pab_ops = {
> + .link_up = ls_pcie_g4_link_up,
> +};
> +
> +static int __init ls_pcie_g4_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct pci_host_bridge *bridge;
> + struct mobiveil_pcie *mv_pci;
> + struct ls_pcie_g4 *pcie;
> + struct device_node *np = dev->of_node;
> + int ret;
> +
> + if (!of_parse_phandle(np, "msi-parent", 0)) {
> + dev_err(dev, "Failed to find msi-parent\n");
> + return -EINVAL;
> + }
> +
> + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> + if (!bridge)
> + return -ENOMEM;
> +
> + pcie = pci_host_bridge_priv(bridge);
> + mv_pci = &pcie->pci;
> +
> + mv_pci->pdev = pdev;
> + mv_pci->ops = &ls_pcie_g4_pab_ops;
> + mv_pci->rp.ops = &ls_pcie_g4_rp_ops;
> + mv_pci->rp.bridge = bridge;
> +
> + platform_set_drvdata(pdev, pcie);
> +
> + INIT_DELAYED_WORK(&pcie->dwork, ls_pcie_g4_reset);
> +
> + ret = mobiveil_pcie_host_probe(mv_pci);
> + if (ret) {
> + dev_err(dev, "Fail to probe\n");
> + return ret;
> + }
> +
> + ls_pcie_g4_enable_interrupt(pcie);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id ls_pcie_g4_of_match[] = {
> + { .compatible = "fsl,lx2160a-pcie", },
> + { },
> +};
> +
> +static struct platform_driver ls_pcie_g4_driver = {
> + .driver = {
> + .name = "layerscape-pcie-gen4",
> + .of_match_table = ls_pcie_g4_of_match,
> + .suppress_bind_attrs = true,
> + },
> +};
> +
> +builtin_platform_driver_probe(ls_pcie_g4_driver, ls_pcie_g4_probe);
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> index 72c62b4d8f7b..7b6a403a9fc0 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> @@ -43,6 +43,8 @@
> #define PAGE_LO_MASK 0x3ff
> #define PAGE_SEL_OFFSET_SHIFT 10
>
> +#define PAB_ACTIVITY_STAT 0x81c
> +
> #define PAB_AXI_PIO_CTRL 0x0840
> #define APIO_EN_MASK 0xf
>
> @@ -51,8 +53,18 @@
>
> #define PAB_INTP_AMBA_MISC_ENB 0x0b0c
> #define PAB_INTP_AMBA_MISC_STAT 0x0b1c
> -#define PAB_INTP_INTX_MASK 0x01e0
> -#define PAB_INTP_MSI_MASK 0x8
> +#define PAB_INTP_RESET BIT(1)
> +#define PAB_INTP_MSI BIT(3)
> +#define PAB_INTP_INTA BIT(5)
> +#define PAB_INTP_INTB BIT(6)
> +#define PAB_INTP_INTC BIT(7)
> +#define PAB_INTP_INTD BIT(8)
> +#define PAB_INTP_PCIE_UE BIT(9)
> +#define PAB_INTP_IE_PMREDI BIT(29)
> +#define PAB_INTP_IE_EC BIT(30)
> +#define PAB_INTP_MSI_MASK PAB_INTP_MSI
> +#define PAB_INTP_INTX_MASK (PAB_INTP_INTA | PAB_INTP_INTB |\
> + PAB_INTP_INTC | PAB_INTP_INTD)
>
> #define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win)
> #define WIN_ENABLE_SHIFT 0
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:33PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> Move the host initialization related operations into a new
> routine such that it can be reused by other incoming platform's
> PCIe host driver, in which the Mobiveil GPEX is integrated.
>
> Change the subject and change log slightly.
> Change the function mobiveil_pcie_host_probe to static.
> Add back the comments that was lost in v9.
I removed the paragraph above since it is a leftover and
does not belong in the commit log.
Lorenzo
> Signed-off-by: Hou Zhiqiang <[email protected]>
> ---
> V10:
> - Refined the subject and change log.
> - Changed the mobiveil_pcie_host_probe() to a static function.
> - Added back the lost comments.
>
> drivers/pci/controller/pcie-mobiveil.c | 39 +++++++++++++++-----------
> 1 file changed, 23 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/pci/controller/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
> index d4de560cd711..01df04ea5b48 100644
> --- a/drivers/pci/controller/pcie-mobiveil.c
> +++ b/drivers/pci/controller/pcie-mobiveil.c
> @@ -873,27 +873,15 @@ static int mobiveil_pcie_init_irq_domain(struct mobiveil_pcie *pcie)
> return 0;
> }
>
> -static int mobiveil_pcie_probe(struct platform_device *pdev)
> +static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> {
> - struct mobiveil_pcie *pcie;
> + struct mobiveil_root_port *rp = &pcie->rp;
> + struct pci_host_bridge *bridge = rp->bridge;
> + struct device *dev = &pcie->pdev->dev;
> struct pci_bus *bus;
> struct pci_bus *child;
> - struct pci_host_bridge *bridge;
> - struct device *dev = &pdev->dev;
> - struct mobiveil_root_port *rp;
> int ret;
>
> - /* allocate the PCIe port */
> - bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> - if (!bridge)
> - return -ENOMEM;
> -
> - pcie = pci_host_bridge_priv(bridge);
> - rp = &pcie->rp;
> - rp->bridge = bridge;
> -
> - pcie->pdev = pdev;
> -
> ret = mobiveil_pcie_parse_dt(pcie);
> if (ret) {
> dev_err(dev, "Parsing DT failed, ret: %x\n", ret);
> @@ -956,6 +944,25 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
> return 0;
> }
>
> +static int mobiveil_pcie_probe(struct platform_device *pdev)
> +{
> + struct mobiveil_pcie *pcie;
> + struct pci_host_bridge *bridge;
> + struct device *dev = &pdev->dev;
> +
> + /* allocate the PCIe port */
> + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> + if (!bridge)
> + return -ENOMEM;
> +
> + pcie = pci_host_bridge_priv(bridge);
> + pcie->rp.bridge = bridge;
> +
> + pcie->pdev = pdev;
> +
> + return mobiveil_pcie_host_probe(pcie);
> +}
> +
> static const struct of_device_id mobiveil_pcie_of_match[] = {
> {.compatible = "mbvl,gpex40-pcie",},
> {},
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:42PM +0800, Zhiqiang Hou wrote:
[...]
> +config PCIE_LAYERSCAPE_GEN4
> + bool "Freescale Layerscape PCIe Gen4 controller"
> + depends on PCI
> + depends on OF && (ARM64 || ARCH_LAYERSCAPE)
> + depends on PCI_MSI_IRQ_DOMAIN
> + select PCIE_MOBIVEIL_HOST
> + help
> + Say Y here if you want PCIe Gen4 controller support on
> + Layerscape SoCs.
I queued it as-is. However, I think this Kconfig entry can be
improved to describe on what systems it can apply, if you wish
send me an incremental patch on top of this one to update it.
Thanks,
Lorenzo
> endmenu
> diff --git a/drivers/pci/controller/mobiveil/Makefile b/drivers/pci/controller/mobiveil/Makefile
> index 9fb6d1c6504d..99d879de32d6 100644
> --- a/drivers/pci/controller/mobiveil/Makefile
> +++ b/drivers/pci/controller/mobiveil/Makefile
> @@ -2,3 +2,4 @@
> obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
> obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o
> obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o
> +obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie-layerscape-gen4.o
> diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> new file mode 100644
> index 000000000000..f3bd5f5ad229
> --- /dev/null
> +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> @@ -0,0 +1,267 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe Gen4 host controller driver for NXP Layerscape SoCs
> + *
> + * Copyright 2019-2020 NXP
> + *
> + * Author: Zhiqiang Hou <[email protected]>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/interrupt.h>
> +#include <linux/init.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_irq.h>
> +#include <linux/of_address.h>
> +#include <linux/pci.h>
> +#include <linux/platform_device.h>
> +#include <linux/resource.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +#include "pcie-mobiveil.h"
> +
> +/* LUT and PF control registers */
> +#define PCIE_LUT_OFF 0x80000
> +#define PCIE_PF_OFF 0xc0000
> +#define PCIE_PF_INT_STAT 0x18
> +#define PF_INT_STAT_PABRST BIT(31)
> +
> +#define PCIE_PF_DBG 0x7fc
> +#define PF_DBG_LTSSM_MASK 0x3f
> +#define PF_DBG_LTSSM_L0 0x2d /* L0 state */
> +#define PF_DBG_WE BIT(31)
> +#define PF_DBG_PABR BIT(27)
> +
> +#define to_ls_pcie_g4(x) platform_get_drvdata((x)->pdev)
> +
> +struct ls_pcie_g4 {
> + struct mobiveil_pcie pci;
> + struct delayed_work dwork;
> + int irq;
> +};
> +
> +static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32 off)
> +{
> + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
> +}
> +
> +static inline void ls_pcie_g4_lut_writel(struct ls_pcie_g4 *pcie,
> + u32 off, u32 val)
> +{
> + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
> +}
> +
> +static inline u32 ls_pcie_g4_pf_readl(struct ls_pcie_g4 *pcie, u32 off)
> +{
> + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
> +}
> +
> +static inline void ls_pcie_g4_pf_writel(struct ls_pcie_g4 *pcie,
> + u32 off, u32 val)
> +{
> + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
> +}
> +
> +static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci)
> +{
> + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
> + u32 state;
> +
> + state = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + state = state & PF_DBG_LTSSM_MASK;
> +
> + if (state == PF_DBG_LTSSM_L0)
> + return 1;
> +
> + return 0;
> +}
> +
> +static void ls_pcie_g4_disable_interrupt(struct ls_pcie_g4 *pcie)
> +{
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> +
> + mobiveil_csr_writel(mv_pci, 0, PAB_INTP_AMBA_MISC_ENB);
> +}
> +
> +static void ls_pcie_g4_enable_interrupt(struct ls_pcie_g4 *pcie)
> +{
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + u32 val;
> +
> + /* Clear the interrupt status */
> + mobiveil_csr_writel(mv_pci, 0xffffffff, PAB_INTP_AMBA_MISC_STAT);
> +
> + val = PAB_INTP_INTX_MASK | PAB_INTP_MSI | PAB_INTP_RESET |
> + PAB_INTP_PCIE_UE | PAB_INTP_IE_PMREDI | PAB_INTP_IE_EC;
> + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_ENB);
> +}
> +
> +static int ls_pcie_g4_reinit_hw(struct ls_pcie_g4 *pcie)
> +{
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + struct device *dev = &mv_pci->pdev->dev;
> + u32 val, act_stat;
> + int to = 100;
> +
> + /* Poll for pab_csb_reset to set and PAB activity to clear */
> + do {
> + usleep_range(10, 15);
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_INT_STAT);
> + act_stat = mobiveil_csr_readl(mv_pci, PAB_ACTIVITY_STAT);
> + } while (((val & PF_INT_STAT_PABRST) == 0 || act_stat) && to--);
> + if (to < 0) {
> + dev_err(dev, "Poll PABRST&PABACT timeout\n");
> + return -EIO;
> + }
> +
> + /* clear PEX_RESET bit in PEX_PF0_DBG register */
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + val |= PF_DBG_WE;
> + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> +
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + val |= PF_DBG_PABR;
> + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> +
> + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> + val &= ~PF_DBG_WE;
> + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> +
> + mobiveil_host_init(mv_pci, true);
> +
> + to = 100;
> + while (!ls_pcie_g4_link_up(mv_pci) && to--)
> + usleep_range(200, 250);
> + if (to < 0) {
> + dev_err(dev, "PCIe link training timeout\n");
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> +static irqreturn_t ls_pcie_g4_isr(int irq, void *dev_id)
> +{
> + struct ls_pcie_g4 *pcie = (struct ls_pcie_g4 *)dev_id;
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + u32 val;
> +
> + val = mobiveil_csr_readl(mv_pci, PAB_INTP_AMBA_MISC_STAT);
> + if (!val)
> + return IRQ_NONE;
> +
> + if (val & PAB_INTP_RESET) {
> + ls_pcie_g4_disable_interrupt(pcie);
> + schedule_delayed_work(&pcie->dwork, msecs_to_jiffies(1));
> + }
> +
> + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_STAT);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int ls_pcie_g4_interrupt_init(struct mobiveil_pcie *mv_pci)
> +{
> + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(mv_pci);
> + struct platform_device *pdev = mv_pci->pdev;
> + struct device *dev = &pdev->dev;
> + int ret;
> +
> + pcie->irq = platform_get_irq_byname(pdev, "intr");
> + if (pcie->irq < 0) {
> + dev_err(dev, "Can't get 'intr' IRQ, errno = %d\n", pcie->irq);
> + return pcie->irq;
> + }
> + ret = devm_request_irq(dev, pcie->irq, ls_pcie_g4_isr,
> + IRQF_SHARED, pdev->name, pcie);
> + if (ret) {
> + dev_err(dev, "Can't register PCIe IRQ, errno = %d\n", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static void ls_pcie_g4_reset(struct work_struct *work)
> +{
> + struct delayed_work *dwork = container_of(work, struct delayed_work,
> + work);
> + struct ls_pcie_g4 *pcie = container_of(dwork, struct ls_pcie_g4, dwork);
> + struct mobiveil_pcie *mv_pci = &pcie->pci;
> + u16 ctrl;
> +
> + ctrl = mobiveil_csr_readw(mv_pci, PCI_BRIDGE_CONTROL);
> + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
> + mobiveil_csr_writew(mv_pci, ctrl, PCI_BRIDGE_CONTROL);
> +
> + if (!ls_pcie_g4_reinit_hw(pcie))
> + return;
> +
> + ls_pcie_g4_enable_interrupt(pcie);
> +}
> +
> +static struct mobiveil_rp_ops ls_pcie_g4_rp_ops = {
> + .interrupt_init = ls_pcie_g4_interrupt_init,
> +};
> +
> +static const struct mobiveil_pab_ops ls_pcie_g4_pab_ops = {
> + .link_up = ls_pcie_g4_link_up,
> +};
> +
> +static int __init ls_pcie_g4_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct pci_host_bridge *bridge;
> + struct mobiveil_pcie *mv_pci;
> + struct ls_pcie_g4 *pcie;
> + struct device_node *np = dev->of_node;
> + int ret;
> +
> + if (!of_parse_phandle(np, "msi-parent", 0)) {
> + dev_err(dev, "Failed to find msi-parent\n");
> + return -EINVAL;
> + }
> +
> + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> + if (!bridge)
> + return -ENOMEM;
> +
> + pcie = pci_host_bridge_priv(bridge);
> + mv_pci = &pcie->pci;
> +
> + mv_pci->pdev = pdev;
> + mv_pci->ops = &ls_pcie_g4_pab_ops;
> + mv_pci->rp.ops = &ls_pcie_g4_rp_ops;
> + mv_pci->rp.bridge = bridge;
> +
> + platform_set_drvdata(pdev, pcie);
> +
> + INIT_DELAYED_WORK(&pcie->dwork, ls_pcie_g4_reset);
> +
> + ret = mobiveil_pcie_host_probe(mv_pci);
> + if (ret) {
> + dev_err(dev, "Fail to probe\n");
> + return ret;
> + }
> +
> + ls_pcie_g4_enable_interrupt(pcie);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id ls_pcie_g4_of_match[] = {
> + { .compatible = "fsl,lx2160a-pcie", },
> + { },
> +};
> +
> +static struct platform_driver ls_pcie_g4_driver = {
> + .driver = {
> + .name = "layerscape-pcie-gen4",
> + .of_match_table = ls_pcie_g4_of_match,
> + .suppress_bind_attrs = true,
> + },
> +};
> +
> +builtin_platform_driver_probe(ls_pcie_g4_driver, ls_pcie_g4_probe);
> diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> index 72c62b4d8f7b..7b6a403a9fc0 100644
> --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> @@ -43,6 +43,8 @@
> #define PAGE_LO_MASK 0x3ff
> #define PAGE_SEL_OFFSET_SHIFT 10
>
> +#define PAB_ACTIVITY_STAT 0x81c
> +
> #define PAB_AXI_PIO_CTRL 0x0840
> #define APIO_EN_MASK 0xf
>
> @@ -51,8 +53,18 @@
>
> #define PAB_INTP_AMBA_MISC_ENB 0x0b0c
> #define PAB_INTP_AMBA_MISC_STAT 0x0b1c
> -#define PAB_INTP_INTX_MASK 0x01e0
> -#define PAB_INTP_MSI_MASK 0x8
> +#define PAB_INTP_RESET BIT(1)
> +#define PAB_INTP_MSI BIT(3)
> +#define PAB_INTP_INTA BIT(5)
> +#define PAB_INTP_INTB BIT(6)
> +#define PAB_INTP_INTC BIT(7)
> +#define PAB_INTP_INTD BIT(8)
> +#define PAB_INTP_PCIE_UE BIT(9)
> +#define PAB_INTP_IE_PMREDI BIT(29)
> +#define PAB_INTP_IE_EC BIT(30)
> +#define PAB_INTP_MSI_MASK PAB_INTP_MSI
> +#define PAB_INTP_INTX_MASK (PAB_INTP_INTA | PAB_INTP_INTB |\
> + PAB_INTP_INTC | PAB_INTP_INTD)
>
> #define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0, win)
> #define WIN_ENABLE_SHIFT 0
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:31PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> This patch set is to recode the Mobiveil driver and add
> PCIe support for NXP Layerscape series SoCs integrated
> Mobiveil's PCIe Gen4 controller.
>
> Hou Zhiqiang (13):
> PCI: mobiveil: Introduce a new structure mobiveil_root_port
> PCI: mobiveil: Move the host initialization into a function
> PCI: mobiveil: Collect the interrupt related operations into a
> function
> PCI: mobiveil: Modularize the Mobiveil PCIe Host Bridge IP driver
> PCI: mobiveil: Add callback function for interrupt initialization
> PCI: mobiveil: Add callback function for link up check
> PCI: mobiveil: Allow mobiveil_host_init() to be used to re-init host
> PCI: mobiveil: Add 8-bit and 16-bit CSR register accessors
> PCI: mobiveil: Add Header Type field check
> dt-bindings: PCI: Add NXP Layerscape SoCs PCIe Gen4 controller
> PCI: mobiveil: Add PCIe Gen4 RC driver for NXP Layerscape SoCs
> arm64: dts: lx2160a: Add PCIe controller DT nodes
> arm64: defconfig: Enable CONFIG_PCIE_LAYERSCAPE_GEN4
>
> .../bindings/pci/layerscape-pcie-gen4.txt | 52 ++
> MAINTAINERS | 10 +-
> .../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 163 +++++
> arch/arm64/configs/defconfig | 1 +
> drivers/pci/controller/Kconfig | 11 +-
> drivers/pci/controller/Makefile | 2 +-
> drivers/pci/controller/mobiveil/Kconfig | 33 +
> drivers/pci/controller/mobiveil/Makefile | 5 +
> .../mobiveil/pcie-layerscape-gen4.c | 267 +++++++++
> .../pcie-mobiveil-host.c} | 564 ++++--------------
> .../controller/mobiveil/pcie-mobiveil-plat.c | 61 ++
> .../pci/controller/mobiveil/pcie-mobiveil.c | 230 +++++++
> .../pci/controller/mobiveil/pcie-mobiveil.h | 226 +++++++
> 13 files changed, 1170 insertions(+), 455 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
> create mode 100644 drivers/pci/controller/mobiveil/Kconfig
> create mode 100644 drivers/pci/controller/mobiveil/Makefile
> create mode 100644 drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> rename drivers/pci/controller/{pcie-mobiveil.c => mobiveil/pcie-mobiveil-host.c} (54%)
> create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
> create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.c
> create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.h
I dropped the last two patches since they must be re-routed via arm-soc
(defconfig update and dts), I tweaked most of commit logs and applied
the series to pci/mobiveil, please check everything is in order.
Thanks,
Lorenzo
On Thu, Feb 13, 2020 at 12:06:43PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> The LX2160A integrated 6 PCIe Gen4 controllers.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
> Reviewed-by: Minghuan Lian <[email protected]>
> ---
> V10:
> - No change
>
> .../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 163 ++++++++++++++++++
> 1 file changed, 163 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> index e5ee5591e52b..aee2810d91cc 100644
> --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> @@ -1076,5 +1076,168 @@
> };
> };
> };
> +
> + pcie@3400000 {
The nodes should be sorted in unit-address. That said, they should be
added after ata3: sata@3230000.
> + compatible = "fsl,lx2160a-pcie";
> + reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */
> + 0x80 0x00000000 0x0 0x00001000>; /* configuration space */
> + reg-names = "csr_axi_slave", "config_axi_slave";
> + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
> + <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
> + <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
> + interrupt-names = "aer", "pme", "intr";
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + dma-coherent;
> + apio-wins = <8>;
> + ppio-wins = <8>;
> + bus-range = <0x0 0xff>;
> + ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> + msi-parent = <&its>;
> + #interrupt-cells = <1>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 2 &gic 0 0 GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 3 &gic 0 0 GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 4 &gic 0 0 GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
> + status = "disabled";
> + };
> +
> + pcie@3500000 {
> + compatible = "fsl,lx2160a-pcie";
> + reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */
> + 0x88 0x00000000 0x0 0x00001000>; /* configuration space */
> + reg-names = "csr_axi_slave", "config_axi_slave";
> + interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
> + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
> + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
> + interrupt-names = "aer", "pme", "intr";
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + dma-coherent;
> + apio-wins = <8>;
> + ppio-wins = <8>;
> + bus-range = <0x0 0xff>;
> + ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> + msi-parent = <&its>;
> + #interrupt-cells = <1>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 2 &gic 0 0 GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 3 &gic 0 0 GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 4 &gic 0 0 GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
> + status = "disabled";
> + };
> +
> + pcie@3600000 {
> + compatible = "fsl,lx2160a-pcie";
> + reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */
> + 0x90 0x00000000 0x0 0x00001000>; /* configuration space */
> + reg-names = "csr_axi_slave", "config_axi_slave";
> + interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
> + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
> + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
> + interrupt-names = "aer", "pme", "intr";
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + dma-coherent;
> + apio-wins = <256>;
> + ppio-wins = <24>;
> + bus-range = <0x0 0xff>;
> + ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> + msi-parent = <&its>;
> + #interrupt-cells = <1>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 2 &gic 0 0 GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 3 &gic 0 0 GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 4 &gic 0 0 GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
> + status = "disabled";
> + };
> +
> + pcie@3700000 {
> + compatible = "fsl,lx2160a-pcie";
> + reg = <0x00 0x03700000 0x0 0x00100000 /* controller registers */
> + 0x98 0x00000000 0x0 0x00001000>; /* configuration space */
> + reg-names = "csr_axi_slave", "config_axi_slave";
> + interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
> + <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
> + <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
> + interrupt-names = "aer", "pme", "intr";
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + dma-coherent;
> + apio-wins = <8>;
> + ppio-wins = <8>;
> + bus-range = <0x0 0xff>;
> + ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> + msi-parent = <&its>;
> + #interrupt-cells = <1>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 2 &gic 0 0 GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 3 &gic 0 0 GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 4 &gic 0 0 GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
> + status = "disabled";
> + };
> +
> + pcie@3800000 {
> + compatible = "fsl,lx2160a-pcie";
> + reg = <0x00 0x03800000 0x0 0x00100000 /* controller registers */
> + 0xa0 0x00000000 0x0 0x00001000>; /* configuration space */
> + reg-names = "csr_axi_slave", "config_axi_slave";
> + interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
> + <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
> + <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
> + interrupt-names = "aer", "pme", "intr";
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + dma-coherent;
> + apio-wins = <256>;
> + ppio-wins = <24>;
> + bus-range = <0x0 0xff>;
> + ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> + msi-parent = <&its>;
> + #interrupt-cells = <1>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 2 &gic 0 0 GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 3 &gic 0 0 GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 4 &gic 0 0 GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
> + status = "disabled";
> + };
> +
> + pcie@3900000 {
> + compatible = "fsl,lx2160a-pcie";
> + reg = <0x00 0x03900000 0x0 0x00100000 /* controller registers */
> + 0xa8 0x00000000 0x0 0x00001000>; /* configuration space */
> + reg-names = "csr_axi_slave", "config_axi_slave";
> + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, /* AER interrupt */
> + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, /* PME interrupt */
> + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; /* controller interrupt */
> + interrupt-names = "aer", "pme", "intr";
> + #address-cells = <3>;
> + #size-cells = <2>;
> + device_type = "pci";
> + dma-coherent;
> + apio-wins = <8>;
> + ppio-wins = <8>;
> + bus-range = <0x0 0xff>;
> + ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
> + msi-parent = <&its>;
> + #interrupt-cells = <1>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 2 &gic 0 0 GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 3 &gic 0 0 GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
> + <0000 0 0 4 &gic 0 0 GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
> + status = "disabled";
> + };
> +
Unnecessary newline.
I fixed them up and applied the patch.
Shawn
> };
> };
> --
> 2.17.1
>
On Thu, Feb 13, 2020 at 12:06:44PM +0800, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <[email protected]>
>
> Enable the PCIe Gen4 controller driver for Layerscape SoCs.
>
> Signed-off-by: Hou Zhiqiang <[email protected]>
> Reviewed-by: Minghuan Lian <[email protected]>
Applied, thanks.
Hi Andrew,
Thanks a lot for your review!
Thanks,
Zhiqiang
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020??2??21?? 1:13
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 01/13] PCI: mobiveil: Introduce a new structure
> mobiveil_root_port
>
> On Thu, Feb 13, 2020 at 12:06:32PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > The Mobiveil PCIe controller can work in either Root Complex mode or
> > Endpoint mode. So introduce a new structure mobiveil_root_port, and
> > abstract the RC related members into it such that the code can be used
> > by both mode.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> > ---
> > V10:
> > - Refined the subject and change log.
> > - Added prefix mobiveil to the root port structure.
> >
> > drivers/pci/controller/pcie-mobiveil.c | 99
> > ++++++++++++++++----------
> > 1 file changed, 60 insertions(+), 39 deletions(-)
> >
> > diff --git a/drivers/pci/controller/pcie-mobiveil.c
> > b/drivers/pci/controller/pcie-mobiveil.c
> > index 3a696ca45bfa..d4de560cd711 100644
> > --- a/drivers/pci/controller/pcie-mobiveil.c
> > +++ b/drivers/pci/controller/pcie-mobiveil.c
> > @@ -3,7 +3,10 @@
> > * PCIe host controller driver for Mobiveil PCIe Host controller
> > *
> > * Copyright (c) 2018 Mobiveil Inc.
> > + * Copyright 2019-2020 NXP
> > + *
> > * Author: Subrahmanya Lingappa <[email protected]>
> > + * Hou Zhiqiang <[email protected]>
> > */
> >
> > #include <linux/delay.h>
> > @@ -138,22 +141,27 @@ struct mobiveil_msi { /* MSI
> information */
> > DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI); };
> >
> > +struct mobiveil_root_port {
> > + char root_bus_nr;
> > + void __iomem *config_axi_slave_base; /* endpoint config base */
> > + struct resource *ob_io_res;
> > + int irq;
> > + raw_spinlock_t intx_mask_lock;
> > + struct irq_domain *intx_domain;
> > + struct mobiveil_msi msi;
> > + struct pci_host_bridge *bridge;
> > +};
> > +
> > struct mobiveil_pcie {
> > struct platform_device *pdev;
> > - void __iomem *config_axi_slave_base; /* endpoint config base */
> > void __iomem *csr_axi_slave_base; /* root port config base */
> > void __iomem *apb_csr_base; /* MSI register base */
> > phys_addr_t pcie_reg_base; /* Physical PCIe Controller Base */
> > - struct irq_domain *intx_domain;
> > - raw_spinlock_t intx_mask_lock;
> > - int irq;
> > int apio_wins;
> > int ppio_wins;
> > int ob_wins_configured; /* configured outbound windows */
> > int ib_wins_configured; /* configured inbound windows */
> > - struct resource *ob_io_res;
> > - char root_bus_nr;
> > - struct mobiveil_msi msi;
> > + struct mobiveil_root_port rp;
> > };
> >
> > /*
> > @@ -281,16 +289,17 @@ static bool mobiveil_pcie_link_up(struct
> > mobiveil_pcie *pcie) static bool mobiveil_pcie_valid_device(struct
> > pci_bus *bus, unsigned int devfn) {
> > struct mobiveil_pcie *pcie = bus->sysdata;
> > + struct mobiveil_root_port *rp = &pcie->rp;
> >
> > /* Only one device down on each root port */
> > - if ((bus->number == pcie->root_bus_nr) && (devfn > 0))
> > + if ((bus->number == rp->root_bus_nr) && (devfn > 0))
> > return false;
> >
> > /*
> > * Do not read more than one device on the bus directly
> > * attached to RC
> > */
> > - if ((bus->primary == pcie->root_bus_nr) && (PCI_SLOT(devfn) > 0))
> > + if ((bus->primary == rp->root_bus_nr) && (PCI_SLOT(devfn) > 0))
> > return false;
> >
> > return true;
> > @@ -304,13 +313,14 @@ static void __iomem
> *mobiveil_pcie_map_bus(struct pci_bus *bus,
> > unsigned int devfn, int where) {
> > struct mobiveil_pcie *pcie = bus->sysdata;
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > u32 value;
> >
> > if (!mobiveil_pcie_valid_device(bus, devfn))
> > return NULL;
> >
> > /* RC config access */
> > - if (bus->number == pcie->root_bus_nr)
> > + if (bus->number == rp->root_bus_nr)
> > return pcie->csr_axi_slave_base + where;
> >
> > /*
> > @@ -325,7 +335,7 @@ static void __iomem
> *mobiveil_pcie_map_bus(struct
> > pci_bus *bus,
> >
> > mobiveil_csr_writel(pcie, value,
> PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0));
> >
> > - return pcie->config_axi_slave_base + where;
> > + return rp->config_axi_slave_base + where;
> > }
> >
> > static struct pci_ops mobiveil_pcie_ops = { @@ -339,7 +349,8 @@
> > static void mobiveil_pcie_isr(struct irq_desc *desc)
> > struct irq_chip *chip = irq_desc_get_chip(desc);
> > struct mobiveil_pcie *pcie = irq_desc_get_handler_data(desc);
> > struct device *dev = &pcie->pdev->dev;
> > - struct mobiveil_msi *msi = &pcie->msi;
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > + struct mobiveil_msi *msi = &rp->msi;
> > u32 msi_data, msi_addr_lo, msi_addr_hi;
> > u32 intr_status, msi_status;
> > unsigned long shifted_status;
> > @@ -365,7 +376,7 @@ static void mobiveil_pcie_isr(struct irq_desc *desc)
> > shifted_status >>= PAB_INTX_START;
> > do {
> > for_each_set_bit(bit, &shifted_status, PCI_NUM_INTX) {
> > - virq = irq_find_mapping(pcie->intx_domain,
> > + virq = irq_find_mapping(rp->intx_domain,
> > bit + 1);
> > if (virq)
> > generic_handle_irq(virq);
> > @@ -424,15 +435,16 @@ static int mobiveil_pcie_parse_dt(struct
> mobiveil_pcie *pcie)
> > struct device *dev = &pcie->pdev->dev;
> > struct platform_device *pdev = pcie->pdev;
> > struct device_node *node = dev->of_node;
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > struct resource *res;
> >
> > /* map config resource */
> > res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> > "config_axi_slave");
> > - pcie->config_axi_slave_base = devm_pci_remap_cfg_resource(dev,
> res);
> > - if (IS_ERR(pcie->config_axi_slave_base))
> > - return PTR_ERR(pcie->config_axi_slave_base);
> > - pcie->ob_io_res = res;
> > + rp->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
> > + if (IS_ERR(rp->config_axi_slave_base))
> > + return PTR_ERR(rp->config_axi_slave_base);
> > + rp->ob_io_res = res;
> >
> > /* map csr resource */
> > res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@
> -455,9
> > +467,9 @@ static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
> > if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
> > pcie->ppio_wins = MAX_PIO_WINDOWS;
> >
> > - pcie->irq = platform_get_irq(pdev, 0);
> > - if (pcie->irq <= 0) {
> > - dev_err(dev, "failed to map IRQ: %d\n", pcie->irq);
> > + rp->irq = platform_get_irq(pdev, 0);
> > + if (rp->irq <= 0) {
> > + dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
> > return -ENODEV;
> > }
> >
> > @@ -564,9 +576,9 @@ static int mobiveil_bringup_link(struct
> > mobiveil_pcie *pcie) static void mobiveil_pcie_enable_msi(struct
> > mobiveil_pcie *pcie) {
> > phys_addr_t msg_addr = pcie->pcie_reg_base;
> > - struct mobiveil_msi *msi = &pcie->msi;
> > + struct mobiveil_msi *msi = &pcie->rp.msi;
> >
> > - pcie->msi.num_of_vectors = PCI_NUM_MSI;
> > + msi->num_of_vectors = PCI_NUM_MSI;
> > msi->msi_pages_phys = (phys_addr_t)msg_addr;
> >
> > writel_relaxed(lower_32_bits(msg_addr),
> > @@ -579,7 +591,8 @@ static void mobiveil_pcie_enable_msi(struct
> > mobiveil_pcie *pcie)
> >
> > static int mobiveil_host_init(struct mobiveil_pcie *pcie) {
> > - struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > + struct pci_host_bridge *bridge = rp->bridge;
> > u32 value, pab_ctrl, type;
> > struct resource_entry *win;
> >
> > @@ -629,8 +642,8 @@ static int mobiveil_host_init(struct mobiveil_pcie
> *pcie)
> > */
> >
> > /* config outbound translation window */
> > - program_ob_windows(pcie, WIN_NUM_0, pcie->ob_io_res->start, 0,
> > - CFG_WINDOW_TYPE, resource_size(pcie->ob_io_res));
> > + program_ob_windows(pcie, WIN_NUM_0, rp->ob_io_res->start, 0,
> > + CFG_WINDOW_TYPE, resource_size(rp->ob_io_res));
> >
> > /* memory inbound translation window */
> > program_ib_windows(pcie, WIN_NUM_0, 0, 0, MEM_WINDOW_TYPE,
> > IB_WIN_SIZE); @@ -667,32 +680,36 @@ static void
> > mobiveil_mask_intx_irq(struct irq_data *data) {
> > struct irq_desc *desc = irq_to_desc(data->irq);
> > struct mobiveil_pcie *pcie;
> > + struct mobiveil_root_port *rp;
> > unsigned long flags;
> > u32 mask, shifted_val;
> >
> > pcie = irq_desc_get_chip_data(desc);
> > + rp = &pcie->rp;
> > mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
> > - raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
> > + raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
> > shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
> > shifted_val &= ~mask;
> > mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
> > - raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
> > + raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
> > }
> >
> > static void mobiveil_unmask_intx_irq(struct irq_data *data) {
> > struct irq_desc *desc = irq_to_desc(data->irq);
> > struct mobiveil_pcie *pcie;
> > + struct mobiveil_root_port *rp;
> > unsigned long flags;
> > u32 shifted_val, mask;
> >
> > pcie = irq_desc_get_chip_data(desc);
> > + rp = &pcie->rp;
> > mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
> > - raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
> > + raw_spin_lock_irqsave(&rp->intx_mask_lock, flags);
> > shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
> > shifted_val |= mask;
> > mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
> > - raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
> > + raw_spin_unlock_irqrestore(&rp->intx_mask_lock, flags);
> > }
> >
> > static struct irq_chip intx_irq_chip = { @@ -760,7 +777,7 @@ static
> > int mobiveil_irq_msi_domain_alloc(struct irq_domain *domain,
> > unsigned int nr_irqs, void *args) {
> > struct mobiveil_pcie *pcie = domain->host_data;
> > - struct mobiveil_msi *msi = &pcie->msi;
> > + struct mobiveil_msi *msi = &pcie->rp.msi;
> > unsigned long bit;
> >
> > WARN_ON(nr_irqs != 1);
> > @@ -787,7 +804,7 @@ static void mobiveil_irq_msi_domain_free(struct
> > irq_domain *domain, {
> > struct irq_data *d = irq_domain_get_irq_data(domain, virq);
> > struct mobiveil_pcie *pcie = irq_data_get_irq_chip_data(d);
> > - struct mobiveil_msi *msi = &pcie->msi;
> > + struct mobiveil_msi *msi = &pcie->rp.msi;
> >
> > mutex_lock(&msi->lock);
> >
> > @@ -808,9 +825,9 @@ static int mobiveil_allocate_msi_domains(struct
> > mobiveil_pcie *pcie) {
> > struct device *dev = &pcie->pdev->dev;
> > struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
> > - struct mobiveil_msi *msi = &pcie->msi;
> > + struct mobiveil_msi *msi = &pcie->rp.msi;
> >
> > - mutex_init(&pcie->msi.lock);
> > + mutex_init(&msi->lock);
> > msi->dev_domain = irq_domain_add_linear(NULL,
> msi->num_of_vectors,
> > &msi_domain_ops, pcie);
> > if (!msi->dev_domain) {
> > @@ -834,18 +851,19 @@ static int mobiveil_pcie_init_irq_domain(struct
> > mobiveil_pcie *pcie) {
> > struct device *dev = &pcie->pdev->dev;
> > struct device_node *node = dev->of_node;
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > int ret;
> >
> > /* setup INTx */
> > - pcie->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
> > - &intx_domain_ops, pcie);
> > + rp->intx_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
> > + &intx_domain_ops, pcie);
> >
> > - if (!pcie->intx_domain) {
> > + if (!rp->intx_domain) {
> > dev_err(dev, "Failed to get a INTx IRQ domain\n");
> > return -ENOMEM;
> > }
> >
> > - raw_spin_lock_init(&pcie->intx_mask_lock);
> > + raw_spin_lock_init(&rp->intx_mask_lock);
> >
> > /* setup MSI */
> > ret = mobiveil_allocate_msi_domains(pcie);
> > @@ -862,6 +880,7 @@ static int mobiveil_pcie_probe(struct
> platform_device *pdev)
> > struct pci_bus *child;
> > struct pci_host_bridge *bridge;
> > struct device *dev = &pdev->dev;
> > + struct mobiveil_root_port *rp;
> > int ret;
> >
> > /* allocate the PCIe port */
> > @@ -870,6 +889,8 @@ static int mobiveil_pcie_probe(struct
> platform_device *pdev)
> > return -ENOMEM;
> >
> > pcie = pci_host_bridge_priv(bridge);
> > + rp = &pcie->rp;
> > + rp->bridge = bridge;
> >
> > pcie->pdev = pdev;
> >
> > @@ -904,12 +925,12 @@ static int mobiveil_pcie_probe(struct
> platform_device *pdev)
> > return ret;
> > }
> >
> > - irq_set_chained_handler_and_data(pcie->irq, mobiveil_pcie_isr, pcie);
> > + irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
> >
> > /* Initialize bridge */
> > bridge->dev.parent = dev;
> > bridge->sysdata = pcie;
> > - bridge->busnr = pcie->root_bus_nr;
> > + bridge->busnr = rp->root_bus_nr;
> > bridge->ops = &mobiveil_pcie_ops;
> > bridge->map_irq = of_irq_parse_and_map_pci;
> > bridge->swizzle_irq = pci_common_swizzle;
> > --
> > 2.17.1
> >
Hi Andrew,
Thanks a lot for your review!
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020??2??21?? 1:19
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 02/13] PCI: mobiveil: Move the host initialization
> into a function
>
> On Thu, Feb 13, 2020 at 12:06:33PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > Move the host initialization related operations into a new routine
> > such that it can be reused by other incoming platform's PCIe host
> > driver, in which the Mobiveil GPEX is integrated.
> >
> > Change the subject and change log slightly.
> > Change the function mobiveil_pcie_host_probe to static.
> > Add back the comments that was lost in v9.
>
> Are these three lines above supposed to be in the history below the
> --- ?
Just remove these 3 lines.
Thanks,
Zhiqiang
>
> Perhaps Lorenzo can change that when he applies it.
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
> > ---
> > V10:
> > - Refined the subject and change log.
> > - Changed the mobiveil_pcie_host_probe() to a static function.
> > - Added back the lost comments.
> >
> > drivers/pci/controller/pcie-mobiveil.c | 39
> > +++++++++++++++-----------
> > 1 file changed, 23 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/pci/controller/pcie-mobiveil.c
> > b/drivers/pci/controller/pcie-mobiveil.c
> > index d4de560cd711..01df04ea5b48 100644
> > --- a/drivers/pci/controller/pcie-mobiveil.c
> > +++ b/drivers/pci/controller/pcie-mobiveil.c
> > @@ -873,27 +873,15 @@ static int mobiveil_pcie_init_irq_domain(struct
> mobiveil_pcie *pcie)
> > return 0;
> > }
> >
> > -static int mobiveil_pcie_probe(struct platform_device *pdev)
> > +static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> > {
> > - struct mobiveil_pcie *pcie;
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > + struct pci_host_bridge *bridge = rp->bridge;
> > + struct device *dev = &pcie->pdev->dev;
> > struct pci_bus *bus;
> > struct pci_bus *child;
> > - struct pci_host_bridge *bridge;
> > - struct device *dev = &pdev->dev;
> > - struct mobiveil_root_port *rp;
> > int ret;
> >
> > - /* allocate the PCIe port */
> > - bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> > - if (!bridge)
> > - return -ENOMEM;
> > -
> > - pcie = pci_host_bridge_priv(bridge);
> > - rp = &pcie->rp;
> > - rp->bridge = bridge;
> > -
> > - pcie->pdev = pdev;
> > -
> > ret = mobiveil_pcie_parse_dt(pcie);
> > if (ret) {
> > dev_err(dev, "Parsing DT failed, ret: %x\n", ret); @@ -956,6
> > +944,25 @@ static int mobiveil_pcie_probe(struct platform_device *pdev)
> > return 0;
> > }
> >
> > +static int mobiveil_pcie_probe(struct platform_device *pdev) {
> > + struct mobiveil_pcie *pcie;
> > + struct pci_host_bridge *bridge;
> > + struct device *dev = &pdev->dev;
> > +
> > + /* allocate the PCIe port */
> > + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> > + if (!bridge)
> > + return -ENOMEM;
> > +
> > + pcie = pci_host_bridge_priv(bridge);
> > + pcie->rp.bridge = bridge;
> > +
> > + pcie->pdev = pdev;
> > +
> > + return mobiveil_pcie_host_probe(pcie); }
> > +
> > static const struct of_device_id mobiveil_pcie_of_match[] = {
> > {.compatible = "mbvl,gpex40-pcie",},
> > {},
> > --
> > 2.17.1
> >
Hi Andrew,
Thanks a lot for your review!
Thanks,
Zhiqiang
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020??2??21?? 1:24
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 03/13] PCI: mobiveil: Collect the interrupt related
> operations into a function
>
> On Thu, Feb 13, 2020 at 12:06:34PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > Collect the interrupt initialization related operations into a new
> > function such that it is more readable.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> > ---
> > V10:
> > - Refined the subject and change log.
> >
> > drivers/pci/controller/pcie-mobiveil.c | 65
> > +++++++++++++++++---------
> > 1 file changed, 42 insertions(+), 23 deletions(-)
> >
> > diff --git a/drivers/pci/controller/pcie-mobiveil.c
> > b/drivers/pci/controller/pcie-mobiveil.c
> > index 01df04ea5b48..9449528bb14f 100644
> > --- a/drivers/pci/controller/pcie-mobiveil.c
> > +++ b/drivers/pci/controller/pcie-mobiveil.c
> > @@ -454,12 +454,6 @@ static int mobiveil_pcie_parse_dt(struct
> mobiveil_pcie *pcie)
> > return PTR_ERR(pcie->csr_axi_slave_base);
> > pcie->pcie_reg_base = res->start;
> >
> > - /* map MSI config resource */
> > - res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "apb_csr");
> > - pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
> > - if (IS_ERR(pcie->apb_csr_base))
> > - return PTR_ERR(pcie->apb_csr_base);
> > -
> > /* read the number of windows requested */
> > if (of_property_read_u32(node, "apio-wins", &pcie->apio_wins))
> > pcie->apio_wins = MAX_PIO_WINDOWS;
> > @@ -467,12 +461,6 @@ static int mobiveil_pcie_parse_dt(struct
> mobiveil_pcie *pcie)
> > if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
> > pcie->ppio_wins = MAX_PIO_WINDOWS;
> >
> > - rp->irq = platform_get_irq(pdev, 0);
> > - if (rp->irq <= 0) {
> > - dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
> > - return -ENODEV;
> > - }
> > -
> > return 0;
> > }
> >
> > @@ -618,9 +606,6 @@ static int mobiveil_host_init(struct mobiveil_pcie
> *pcie)
> > pab_ctrl |= (1 << AMBA_PIO_ENABLE_SHIFT) | (1 <<
> PEX_PIO_ENABLE_SHIFT);
> > mobiveil_csr_writel(pcie, pab_ctrl, PAB_CTRL);
> >
> > - mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK |
> PAB_INTP_MSI_MASK),
> > - PAB_INTP_AMBA_MISC_ENB);
> > -
> > /*
> > * program PIO Enable Bit to 1 and Config Window Enable Bit to 1 in
> > * PAB_AXI_PIO_CTRL Register
> > @@ -670,9 +655,6 @@ static int mobiveil_host_init(struct mobiveil_pcie
> *pcie)
> > value |= (PCI_CLASS_BRIDGE_PCI << 16);
> > mobiveil_csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
> >
> > - /* setup MSI hardware registers */
> > - mobiveil_pcie_enable_msi(pcie);
> > -
> > return 0;
> > }
> >
> > @@ -873,6 +855,46 @@ static int mobiveil_pcie_init_irq_domain(struct
> mobiveil_pcie *pcie)
> > return 0;
> > }
> >
> > +static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) {
> > + struct platform_device *pdev = pcie->pdev;
> > + struct device *dev = &pdev->dev;
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > + struct resource *res;
> > + int ret;
> > +
> > + /* map MSI config resource */
> > + res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> "apb_csr");
> > + pcie->apb_csr_base = devm_pci_remap_cfg_resource(dev, res);
> > + if (IS_ERR(pcie->apb_csr_base))
> > + return PTR_ERR(pcie->apb_csr_base);
> > +
> > + /* setup MSI hardware registers */
> > + mobiveil_pcie_enable_msi(pcie);
> > +
> > + rp->irq = platform_get_irq(pdev, 0);
> > + if (rp->irq <= 0) {
> > + dev_err(dev, "failed to map IRQ: %d\n", rp->irq);
> > + return -ENODEV;
> > + }
> > +
> > + /* initialize the IRQ domains */
> > + ret = mobiveil_pcie_init_irq_domain(pcie);
> > + if (ret) {
> > + dev_err(dev, "Failed creating IRQ Domain\n");
> > + return ret;
> > + }
> > +
> > + irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
> > +
> > + /* Enable interrupts */
> > + mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK |
> PAB_INTP_MSI_MASK),
> > + PAB_INTP_AMBA_MISC_ENB);
> > +
> > +
> > + return 0;
> > +}
> > +
> > static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) {
> > struct mobiveil_root_port *rp = &pcie->rp; @@ -906,15 +928,12 @@
> > static int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> > return ret;
> > }
> >
> > - /* initialize the IRQ domains */
> > - ret = mobiveil_pcie_init_irq_domain(pcie);
> > + ret = mobiveil_pcie_interrupt_init(pcie);
> > if (ret) {
> > - dev_err(dev, "Failed creating IRQ Domain\n");
> > + dev_err(dev, "Interrupt init failed\n");
> > return ret;
> > }
> >
> > - irq_set_chained_handler_and_data(rp->irq, mobiveil_pcie_isr, pcie);
> > -
> > /* Initialize bridge */
> > bridge->dev.parent = dev;
> > bridge->sysdata = pcie;
> > --
> > 2.17.1
> >
Hi Andrew,
Thanks a lot for your review!
Thanks,
Zhiqiang
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020??2??21?? 1:25
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 05/13] PCI: mobiveil: Add callback function for
> interrupt initialization
>
> On Thu, Feb 13, 2020 at 12:06:36PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > The Mobiveil GPEX internal MSI/INTx controller may not be used by
> > other platforms in which the Mobiveil GPEX is integrated.
> > This patch is to allow these platforms to implement their specific
> > interrupt initialization.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> > ---
> > V10:
> > - Introduced a helper function mobiveil_pcie_integrated_interrupt_init().
> >
> > drivers/pci/controller/mobiveil/pcie-mobiveil-host.c | 12 +++++++++++-
> > drivers/pci/controller/mobiveil/pcie-mobiveil.h | 7 +++++++
> > 2 files changed, 18 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > index ea90d2f8692e..53ab8412a1de 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > @@ -499,7 +499,7 @@ static int mobiveil_pcie_init_irq_domain(struct
> mobiveil_pcie *pcie)
> > return 0;
> > }
> >
> > -static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie)
> > +static int mobiveil_pcie_integrated_interrupt_init(struct
> > +mobiveil_pcie *pcie)
> > {
> > struct platform_device *pdev = pcie->pdev;
> > struct device *dev = &pdev->dev;
> > @@ -539,6 +539,16 @@ static int mobiveil_pcie_interrupt_init(struct
> mobiveil_pcie *pcie)
> > return 0;
> > }
> >
> > +static int mobiveil_pcie_interrupt_init(struct mobiveil_pcie *pcie) {
> > + struct mobiveil_root_port *rp = &pcie->rp;
> > +
> > + if (rp->ops->interrupt_init)
> > + return rp->ops->interrupt_init(pcie);
> > +
> > + return mobiveil_pcie_integrated_interrupt_init(pcie);
> > +}
> > +
> > int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) {
> > struct mobiveil_root_port *rp = &pcie->rp; diff --git
> > a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > index 81ffbbd48c08..0e6b5468c026 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > @@ -130,10 +130,17 @@ struct mobiveil_msi { /* MSI
> information */
> > DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI); };
> >
> > +struct mobiveil_pcie;
> > +
> > +struct mobiveil_rp_ops {
> > + int (*interrupt_init)(struct mobiveil_pcie *pcie); };
> > +
> > struct mobiveil_root_port {
> > char root_bus_nr;
> > void __iomem *config_axi_slave_base; /* endpoint config base */
> > struct resource *ob_io_res;
> > + struct mobiveil_rp_ops *ops;
> > int irq;
> > raw_spinlock_t intx_mask_lock;
> > struct irq_domain *intx_domain;
> > --
> > 2.17.1
> >
Hi Andrew,
Thanks a lot for your review!
Thanks,
Zhiqiang
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020??2??21?? 1:29
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 07/13] PCI: mobiveil: Allow mobiveil_host_init() to
> be used to re-init host
>
> On Thu, Feb 13, 2020 at 12:06:38PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > Allow the mobiveil_host_init() function to be used to re-init host
> > controller's PAB and GPEX CSR register block, as NXP integrated
> > Mobiveil IP has to reset and then re-init the PAB and GPEX CSR
> > registers upon hot-reset.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
> > Reviewed-by: Subrahmanya Lingappa <[email protected]>
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> > ---
> > V10:
> > - Refined the subject and change log.
> >
> > .../controller/mobiveil/pcie-mobiveil-host.c | 19 ++++++++++++-------
> > .../pci/controller/mobiveil/pcie-mobiveil.h | 1 +
> > 2 files changed, 13 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > index 53ab8412a1de..44dd641fede3 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > @@ -221,18 +221,23 @@ static void mobiveil_pcie_enable_msi(struct
> mobiveil_pcie *pcie)
> > writel_relaxed(1, pcie->apb_csr_base + MSI_ENABLE_OFFSET); }
> >
> > -static int mobiveil_host_init(struct mobiveil_pcie *pcie)
> > +int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit)
> > {
> > struct mobiveil_root_port *rp = &pcie->rp;
> > struct pci_host_bridge *bridge = rp->bridge;
> > u32 value, pab_ctrl, type;
> > struct resource_entry *win;
> >
> > - /* setup bus numbers */
> > - value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
> > - value &= 0xff000000;
> > - value |= 0x00ff0100;
> > - mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
> > + pcie->ib_wins_configured = 0;
> > + pcie->ob_wins_configured = 0;
> > +
> > + if (!reinit) {
> > + /* setup bus numbers */
> > + value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
> > + value &= 0xff000000;
> > + value |= 0x00ff0100;
> > + mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
> > + }
> >
> > /*
> > * program Bus Master Enable Bit in Command Register in PAB Config
> > @@ -576,7 +581,7 @@ int mobiveil_pcie_host_probe(struct mobiveil_pcie
> *pcie)
> > * configure all inbound and outbound windows and prepare the RC for
> > * config access
> > */
> > - ret = mobiveil_host_init(pcie);
> > + ret = mobiveil_host_init(pcie, false);
> > if (ret) {
> > dev_err(dev, "Failed to initialize host\n");
> > return ret;
> > diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > index 346bf79a581b..623c5f0c4441 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > @@ -166,6 +166,7 @@ struct mobiveil_pcie { };
> >
> > int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie);
> > +int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit);
> > bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie); int
> > mobiveil_bringup_link(struct mobiveil_pcie *pcie); void
> > program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64
> > cpu_addr,
> > --
> > 2.17.1
> >
Hi Andrew,
Thanks a lot for your review!
Thanks,
Zhiqiang
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020??2??21?? 1:29
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 08/13] PCI: mobiveil: Add 8-bit and 16-bit CSR
> register accessors
>
> On Thu, Feb 13, 2020 at 12:06:39PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > There are some 8-bit and 16-bit registers in PCIe configuration space,
> > so add these accessors accordingly.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
> > Reviewed-by: Minghuan Lian <[email protected]>
> > Reviewed-by: Subrahmanya Lingappa <[email protected]>
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> > ---
> > V10:
> > - Changed the return types to reflect the size of the access.
> >
> > .../pci/controller/mobiveil/pcie-mobiveil.h | 23
> +++++++++++++++++++
> > 1 file changed, 23 insertions(+)
> >
> > diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > index 623c5f0c4441..72c62b4d8f7b 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > @@ -182,10 +182,33 @@ static inline u32 mobiveil_csr_readl(struct
> mobiveil_pcie *pcie, u32 off)
> > return mobiveil_csr_read(pcie, off, 0x4); }
> >
> > +static inline u16 mobiveil_csr_readw(struct mobiveil_pcie *pcie, u32
> > +off) {
> > + return mobiveil_csr_read(pcie, off, 0x2); }
> > +
> > +static inline u8 mobiveil_csr_readb(struct mobiveil_pcie *pcie, u32
> > +off) {
> > + return mobiveil_csr_read(pcie, off, 0x1); }
> > +
> > +
> > static inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val,
> > u32 off)
> > {
> > mobiveil_csr_write(pcie, val, off, 0x4); }
> >
> > +static inline void mobiveil_csr_writew(struct mobiveil_pcie *pcie, u16 val,
> > + u32 off)
> > +{
> > + mobiveil_csr_write(pcie, val, off, 0x2); }
> > +
> > +static inline void mobiveil_csr_writeb(struct mobiveil_pcie *pcie, u8 val,
> > + u32 off)
> > +{
> > + mobiveil_csr_write(pcie, val, off, 0x1); }
> > +
> > #endif /* _PCIE_MOBIVEIL_H */
> > --
> > 2.17.1
> >
Hi Andrew,
Thanks a lot for your review!
Thanks,
Zhiqiang
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020??2??21?? 1:31
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 09/13] PCI: mobiveil: Add Header Type field check
>
> On Thu, Feb 13, 2020 at 12:06:40PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > Check the Header Type and exit from the host driver initialization if
> > it is not in host mode.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> > ---
> > V10:
> > - New patch separated from #10 of v9.
> >
> > .../pci/controller/mobiveil/pcie-mobiveil-host.c | 13 +++++++++++++
> > 1 file changed, 13 insertions(+)
> >
> > diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > index 44dd641fede3..db7028788d91 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> > @@ -554,6 +554,16 @@ static int mobiveil_pcie_interrupt_init(struct
> mobiveil_pcie *pcie)
> > return mobiveil_pcie_integrated_interrupt_init(pcie);
> > }
> >
> > +static bool mobiveil_pcie_is_bridge(struct mobiveil_pcie *pcie) {
> > + u32 header_type;
> > +
> > + header_type = mobiveil_csr_readb(pcie, PCI_HEADER_TYPE);
> > + header_type &= 0x7f;
> > +
> > + return header_type == PCI_HEADER_TYPE_BRIDGE; }
> > +
> > int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie) {
> > struct mobiveil_root_port *rp = &pcie->rp; @@ -569,6 +579,9 @@ int
> > mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie)
> > return ret;
> > }
> >
> > + if (!mobiveil_pcie_is_bridge(pcie))
> > + return -ENODEV;
> > +
> > /* parse the host bridge base addresses from the device tree file */
> > ret = pci_parse_request_of_pci_ranges(dev, &bridge->windows,
> > &bridge->dma_ranges, NULL);
> > --
> > 2.17.1
> >
Hi Andrew,
Thanks a lot for your review!
Thanks,
Zhiqiang
> -----Original Message-----
> From: Andrew Murray <[email protected]>
> Sent: 2020年2月21日 1:43
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected];
> [email protected]; [email protected]; Mingkai Hu
> <[email protected]>; M.h. Lian <[email protected]>; Xiaowei Bao
> <[email protected]>
> Subject: Re: [PATCHv10 11/13] PCI: mobiveil: Add PCIe Gen4 RC driver for
> NXP Layerscape SoCs
>
> On Thu, Feb 13, 2020 at 12:06:42PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > This PCIe controller is based on the Mobiveil GPEX IP, which is
> > compatible with the PCI Expressâ„¢ Base Specification, Revision 4.0.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
> > Reviewed-by: Minghuan Lian <[email protected]>
>
> Reviewed-by: Andrew Murray <[email protected]>
>
> > ---
> > V10:
> > - Changed the return type of ls_pcie_g4_reinit_hw() to void.
> > - Moved Header Type check to mobiveil_pcie_host_probe().
> >
> > drivers/pci/controller/mobiveil/Kconfig | 9 +
> > drivers/pci/controller/mobiveil/Makefile | 1 +
> > .../mobiveil/pcie-layerscape-gen4.c | 267
> ++++++++++++++++++
> > .../pci/controller/mobiveil/pcie-mobiveil.h | 16 +-
> > 4 files changed, 291 insertions(+), 2 deletions(-) create mode
> > 100644 drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> >
> > diff --git a/drivers/pci/controller/mobiveil/Kconfig
> > b/drivers/pci/controller/mobiveil/Kconfig
> > index 54161d4ddb11..7439991ee82c 100644
> > --- a/drivers/pci/controller/mobiveil/Kconfig
> > +++ b/drivers/pci/controller/mobiveil/Kconfig
> > @@ -21,4 +21,13 @@ config PCIE_MOBIVEIL_PLAT
> > Soft IP. It has up to 8 outbound and inbound windows
> > for address translation and it is a PCIe Gen4 IP.
> >
> > +config PCIE_LAYERSCAPE_GEN4
> > + bool "Freescale Layerscape PCIe Gen4 controller"
> > + depends on PCI
> > + depends on OF && (ARM64 || ARCH_LAYERSCAPE)
> > + depends on PCI_MSI_IRQ_DOMAIN
> > + select PCIE_MOBIVEIL_HOST
> > + help
> > + Say Y here if you want PCIe Gen4 controller support on
> > + Layerscape SoCs.
> > endmenu
> > diff --git a/drivers/pci/controller/mobiveil/Makefile
> > b/drivers/pci/controller/mobiveil/Makefile
> > index 9fb6d1c6504d..99d879de32d6 100644
> > --- a/drivers/pci/controller/mobiveil/Makefile
> > +++ b/drivers/pci/controller/mobiveil/Makefile
> > @@ -2,3 +2,4 @@
> > obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
> > obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o
> > obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o
> > +obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie-layerscape-gen4.o
> > diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> > b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> > new file mode 100644
> > index 000000000000..f3bd5f5ad229
> > --- /dev/null
> > +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> > @@ -0,0 +1,267 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * PCIe Gen4 host controller driver for NXP Layerscape SoCs
> > + *
> > + * Copyright 2019-2020 NXP
> > + *
> > + * Author: Zhiqiang Hou <[email protected]> */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/init.h>
> > +#include <linux/of_pci.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_address.h>
> > +#include <linux/pci.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/resource.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "pcie-mobiveil.h"
> > +
> > +/* LUT and PF control registers */
> > +#define PCIE_LUT_OFF 0x80000
> > +#define PCIE_PF_OFF 0xc0000
> > +#define PCIE_PF_INT_STAT 0x18
> > +#define PF_INT_STAT_PABRST BIT(31)
> > +
> > +#define PCIE_PF_DBG 0x7fc
> > +#define PF_DBG_LTSSM_MASK 0x3f
> > +#define PF_DBG_LTSSM_L0 0x2d /* L0 state */
> > +#define PF_DBG_WE BIT(31)
> > +#define PF_DBG_PABR BIT(27)
> > +
> > +#define to_ls_pcie_g4(x) platform_get_drvdata((x)->pdev)
> > +
> > +struct ls_pcie_g4 {
> > + struct mobiveil_pcie pci;
> > + struct delayed_work dwork;
> > + int irq;
> > +};
> > +
> > +static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32
> > +off) {
> > + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
> > +}
> > +
> > +static inline void ls_pcie_g4_lut_writel(struct ls_pcie_g4 *pcie,
> > + u32 off, u32 val)
> > +{
> > + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off); }
> > +
> > +static inline u32 ls_pcie_g4_pf_readl(struct ls_pcie_g4 *pcie, u32
> > +off) {
> > + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off); }
> > +
> > +static inline void ls_pcie_g4_pf_writel(struct ls_pcie_g4 *pcie,
> > + u32 off, u32 val)
> > +{
> > + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off); }
> > +
> > +static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci) {
> > + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
> > + u32 state;
> > +
> > + state = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + state = state & PF_DBG_LTSSM_MASK;
> > +
> > + if (state == PF_DBG_LTSSM_L0)
> > + return 1;
> > +
> > + return 0;
> > +}
> > +
> > +static void ls_pcie_g4_disable_interrupt(struct ls_pcie_g4 *pcie) {
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > +
> > + mobiveil_csr_writel(mv_pci, 0, PAB_INTP_AMBA_MISC_ENB); }
> > +
> > +static void ls_pcie_g4_enable_interrupt(struct ls_pcie_g4 *pcie) {
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + u32 val;
> > +
> > + /* Clear the interrupt status */
> > + mobiveil_csr_writel(mv_pci, 0xffffffff, PAB_INTP_AMBA_MISC_STAT);
> > +
> > + val = PAB_INTP_INTX_MASK | PAB_INTP_MSI | PAB_INTP_RESET |
> > + PAB_INTP_PCIE_UE | PAB_INTP_IE_PMREDI | PAB_INTP_IE_EC;
> > + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_ENB); }
> > +
> > +static int ls_pcie_g4_reinit_hw(struct ls_pcie_g4 *pcie) {
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + struct device *dev = &mv_pci->pdev->dev;
> > + u32 val, act_stat;
> > + int to = 100;
> > +
> > + /* Poll for pab_csb_reset to set and PAB activity to clear */
> > + do {
> > + usleep_range(10, 15);
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_INT_STAT);
> > + act_stat = mobiveil_csr_readl(mv_pci, PAB_ACTIVITY_STAT);
> > + } while (((val & PF_INT_STAT_PABRST) == 0 || act_stat) && to--);
> > + if (to < 0) {
> > + dev_err(dev, "Poll PABRST&PABACT timeout\n");
> > + return -EIO;
> > + }
> > +
> > + /* clear PEX_RESET bit in PEX_PF0_DBG register */
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + val |= PF_DBG_WE;
> > + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> > +
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + val |= PF_DBG_PABR;
> > + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> > +
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + val &= ~PF_DBG_WE;
> > + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> > +
> > + mobiveil_host_init(mv_pci, true);
> > +
> > + to = 100;
> > + while (!ls_pcie_g4_link_up(mv_pci) && to--)
> > + usleep_range(200, 250);
> > + if (to < 0) {
> > + dev_err(dev, "PCIe link training timeout\n");
> > + return -EIO;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static irqreturn_t ls_pcie_g4_isr(int irq, void *dev_id) {
> > + struct ls_pcie_g4 *pcie = (struct ls_pcie_g4 *)dev_id;
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + u32 val;
> > +
> > + val = mobiveil_csr_readl(mv_pci, PAB_INTP_AMBA_MISC_STAT);
> > + if (!val)
> > + return IRQ_NONE;
> > +
> > + if (val & PAB_INTP_RESET) {
> > + ls_pcie_g4_disable_interrupt(pcie);
> > + schedule_delayed_work(&pcie->dwork, msecs_to_jiffies(1));
> > + }
> > +
> > + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_STAT);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int ls_pcie_g4_interrupt_init(struct mobiveil_pcie *mv_pci) {
> > + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(mv_pci);
> > + struct platform_device *pdev = mv_pci->pdev;
> > + struct device *dev = &pdev->dev;
> > + int ret;
> > +
> > + pcie->irq = platform_get_irq_byname(pdev, "intr");
> > + if (pcie->irq < 0) {
> > + dev_err(dev, "Can't get 'intr' IRQ, errno = %d\n", pcie->irq);
> > + return pcie->irq;
> > + }
> > + ret = devm_request_irq(dev, pcie->irq, ls_pcie_g4_isr,
> > + IRQF_SHARED, pdev->name, pcie);
> > + if (ret) {
> > + dev_err(dev, "Can't register PCIe IRQ, errno = %d\n", ret);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void ls_pcie_g4_reset(struct work_struct *work) {
> > + struct delayed_work *dwork = container_of(work, struct delayed_work,
> > + work);
> > + struct ls_pcie_g4 *pcie = container_of(dwork, struct ls_pcie_g4, dwork);
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + u16 ctrl;
> > +
> > + ctrl = mobiveil_csr_readw(mv_pci, PCI_BRIDGE_CONTROL);
> > + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
> > + mobiveil_csr_writew(mv_pci, ctrl, PCI_BRIDGE_CONTROL);
> > +
> > + if (!ls_pcie_g4_reinit_hw(pcie))
> > + return;
> > +
> > + ls_pcie_g4_enable_interrupt(pcie);
> > +}
> > +
> > +static struct mobiveil_rp_ops ls_pcie_g4_rp_ops = {
> > + .interrupt_init = ls_pcie_g4_interrupt_init, };
> > +
> > +static const struct mobiveil_pab_ops ls_pcie_g4_pab_ops = {
> > + .link_up = ls_pcie_g4_link_up,
> > +};
> > +
> > +static int __init ls_pcie_g4_probe(struct platform_device *pdev) {
> > + struct device *dev = &pdev->dev;
> > + struct pci_host_bridge *bridge;
> > + struct mobiveil_pcie *mv_pci;
> > + struct ls_pcie_g4 *pcie;
> > + struct device_node *np = dev->of_node;
> > + int ret;
> > +
> > + if (!of_parse_phandle(np, "msi-parent", 0)) {
> > + dev_err(dev, "Failed to find msi-parent\n");
> > + return -EINVAL;
> > + }
> > +
> > + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> > + if (!bridge)
> > + return -ENOMEM;
> > +
> > + pcie = pci_host_bridge_priv(bridge);
> > + mv_pci = &pcie->pci;
> > +
> > + mv_pci->pdev = pdev;
> > + mv_pci->ops = &ls_pcie_g4_pab_ops;
> > + mv_pci->rp.ops = &ls_pcie_g4_rp_ops;
> > + mv_pci->rp.bridge = bridge;
> > +
> > + platform_set_drvdata(pdev, pcie);
> > +
> > + INIT_DELAYED_WORK(&pcie->dwork, ls_pcie_g4_reset);
> > +
> > + ret = mobiveil_pcie_host_probe(mv_pci);
> > + if (ret) {
> > + dev_err(dev, "Fail to probe\n");
> > + return ret;
> > + }
> > +
> > + ls_pcie_g4_enable_interrupt(pcie);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id ls_pcie_g4_of_match[] = {
> > + { .compatible = "fsl,lx2160a-pcie", },
> > + { },
> > +};
> > +
> > +static struct platform_driver ls_pcie_g4_driver = {
> > + .driver = {
> > + .name = "layerscape-pcie-gen4",
> > + .of_match_table = ls_pcie_g4_of_match,
> > + .suppress_bind_attrs = true,
> > + },
> > +};
> > +
> > +builtin_platform_driver_probe(ls_pcie_g4_driver, ls_pcie_g4_probe);
> > diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > index 72c62b4d8f7b..7b6a403a9fc0 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > @@ -43,6 +43,8 @@
> > #define PAGE_LO_MASK 0x3ff
> > #define PAGE_SEL_OFFSET_SHIFT 10
> >
> > +#define PAB_ACTIVITY_STAT 0x81c
> > +
> > #define PAB_AXI_PIO_CTRL 0x0840
> > #define APIO_EN_MASK 0xf
> >
> > @@ -51,8 +53,18 @@
> >
> > #define PAB_INTP_AMBA_MISC_ENB 0x0b0c
> > #define PAB_INTP_AMBA_MISC_STAT 0x0b1c
> > -#define PAB_INTP_INTX_MASK 0x01e0
> > -#define PAB_INTP_MSI_MASK 0x8
> > +#define PAB_INTP_RESET BIT(1)
> > +#define PAB_INTP_MSI BIT(3)
> > +#define PAB_INTP_INTA BIT(5)
> > +#define PAB_INTP_INTB BIT(6)
> > +#define PAB_INTP_INTC BIT(7)
> > +#define PAB_INTP_INTD BIT(8)
> > +#define PAB_INTP_PCIE_UE BIT(9)
> > +#define PAB_INTP_IE_PMREDI BIT(29)
> > +#define PAB_INTP_IE_EC BIT(30)
> > +#define PAB_INTP_MSI_MASK PAB_INTP_MSI
> > +#define PAB_INTP_INTX_MASK (PAB_INTP_INTA |
> PAB_INTP_INTB |\
> > + PAB_INTP_INTC | PAB_INTP_INTD)
> >
> > #define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0,
> win)
> > #define WIN_ENABLE_SHIFT 0
> > --
> > 2.17.1
> >
Hi Lorenzo,
Thanks a lot for your comments!
> -----Original Message-----
> From: Lorenzo Pieralisi <[email protected]>
> Sent: 2020??2??21?? 20:18
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected]; [email protected];
> Mingkai Hu <[email protected]>; M.h. Lian <[email protected]>;
> Xiaowei Bao <[email protected]>
> Subject: Re: [PATCHv10 11/13] PCI: mobiveil: Add PCIe Gen4 RC driver for
> NXP Layerscape SoCs
>
> On Thu, Feb 13, 2020 at 12:06:42PM +0800, Zhiqiang Hou wrote:
>
> [...]
>
> > +config PCIE_LAYERSCAPE_GEN4
> > + bool "Freescale Layerscape PCIe Gen4 controller"
> > + depends on PCI
> > + depends on OF && (ARM64 || ARCH_LAYERSCAPE)
> > + depends on PCI_MSI_IRQ_DOMAIN
> > + select PCIE_MOBIVEIL_HOST
> > + help
> > + Say Y here if you want PCIe Gen4 controller support on
> > + Layerscape SoCs.
>
> I queued it as-is. However, I think this Kconfig entry can be improved to
> describe on what systems it can apply, if you wish send me an incremental
> patch on top of this one to update it.
>
Thanks and I'll add the platforms integrated this controller.
Thanks,
Zhiqiang
> Thanks,
> Lorenzo
>
> > endmenu
> > diff --git a/drivers/pci/controller/mobiveil/Makefile
> > b/drivers/pci/controller/mobiveil/Makefile
> > index 9fb6d1c6504d..99d879de32d6 100644
> > --- a/drivers/pci/controller/mobiveil/Makefile
> > +++ b/drivers/pci/controller/mobiveil/Makefile
> > @@ -2,3 +2,4 @@
> > obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
> > obj-$(CONFIG_PCIE_MOBIVEIL_HOST) += pcie-mobiveil-host.o
> > obj-$(CONFIG_PCIE_MOBIVEIL_PLAT) += pcie-mobiveil-plat.o
> > +obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie-layerscape-gen4.o
> > diff --git a/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> > b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> > new file mode 100644
> > index 000000000000..f3bd5f5ad229
> > --- /dev/null
> > +++ b/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> > @@ -0,0 +1,267 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * PCIe Gen4 host controller driver for NXP Layerscape SoCs
> > + *
> > + * Copyright 2019-2020 NXP
> > + *
> > + * Author: Zhiqiang Hou <[email protected]> */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/init.h>
> > +#include <linux/of_pci.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/of_irq.h>
> > +#include <linux/of_address.h>
> > +#include <linux/pci.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/resource.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/regmap.h>
> > +
> > +#include "pcie-mobiveil.h"
> > +
> > +/* LUT and PF control registers */
> > +#define PCIE_LUT_OFF 0x80000
> > +#define PCIE_PF_OFF 0xc0000
> > +#define PCIE_PF_INT_STAT 0x18
> > +#define PF_INT_STAT_PABRST BIT(31)
> > +
> > +#define PCIE_PF_DBG 0x7fc
> > +#define PF_DBG_LTSSM_MASK 0x3f
> > +#define PF_DBG_LTSSM_L0 0x2d /* L0 state */
> > +#define PF_DBG_WE BIT(31)
> > +#define PF_DBG_PABR BIT(27)
> > +
> > +#define to_ls_pcie_g4(x) platform_get_drvdata((x)->pdev)
> > +
> > +struct ls_pcie_g4 {
> > + struct mobiveil_pcie pci;
> > + struct delayed_work dwork;
> > + int irq;
> > +};
> > +
> > +static inline u32 ls_pcie_g4_lut_readl(struct ls_pcie_g4 *pcie, u32
> > +off) {
> > + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off);
> > +}
> > +
> > +static inline void ls_pcie_g4_lut_writel(struct ls_pcie_g4 *pcie,
> > + u32 off, u32 val)
> > +{
> > + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_LUT_OFF + off); }
> > +
> > +static inline u32 ls_pcie_g4_pf_readl(struct ls_pcie_g4 *pcie, u32
> > +off) {
> > + return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off); }
> > +
> > +static inline void ls_pcie_g4_pf_writel(struct ls_pcie_g4 *pcie,
> > + u32 off, u32 val)
> > +{
> > + iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off); }
> > +
> > +static int ls_pcie_g4_link_up(struct mobiveil_pcie *pci) {
> > + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(pci);
> > + u32 state;
> > +
> > + state = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + state = state & PF_DBG_LTSSM_MASK;
> > +
> > + if (state == PF_DBG_LTSSM_L0)
> > + return 1;
> > +
> > + return 0;
> > +}
> > +
> > +static void ls_pcie_g4_disable_interrupt(struct ls_pcie_g4 *pcie) {
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > +
> > + mobiveil_csr_writel(mv_pci, 0, PAB_INTP_AMBA_MISC_ENB); }
> > +
> > +static void ls_pcie_g4_enable_interrupt(struct ls_pcie_g4 *pcie) {
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + u32 val;
> > +
> > + /* Clear the interrupt status */
> > + mobiveil_csr_writel(mv_pci, 0xffffffff, PAB_INTP_AMBA_MISC_STAT);
> > +
> > + val = PAB_INTP_INTX_MASK | PAB_INTP_MSI | PAB_INTP_RESET |
> > + PAB_INTP_PCIE_UE | PAB_INTP_IE_PMREDI | PAB_INTP_IE_EC;
> > + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_ENB); }
> > +
> > +static int ls_pcie_g4_reinit_hw(struct ls_pcie_g4 *pcie) {
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + struct device *dev = &mv_pci->pdev->dev;
> > + u32 val, act_stat;
> > + int to = 100;
> > +
> > + /* Poll for pab_csb_reset to set and PAB activity to clear */
> > + do {
> > + usleep_range(10, 15);
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_INT_STAT);
> > + act_stat = mobiveil_csr_readl(mv_pci, PAB_ACTIVITY_STAT);
> > + } while (((val & PF_INT_STAT_PABRST) == 0 || act_stat) && to--);
> > + if (to < 0) {
> > + dev_err(dev, "Poll PABRST&PABACT timeout\n");
> > + return -EIO;
> > + }
> > +
> > + /* clear PEX_RESET bit in PEX_PF0_DBG register */
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + val |= PF_DBG_WE;
> > + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> > +
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + val |= PF_DBG_PABR;
> > + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> > +
> > + val = ls_pcie_g4_pf_readl(pcie, PCIE_PF_DBG);
> > + val &= ~PF_DBG_WE;
> > + ls_pcie_g4_pf_writel(pcie, PCIE_PF_DBG, val);
> > +
> > + mobiveil_host_init(mv_pci, true);
> > +
> > + to = 100;
> > + while (!ls_pcie_g4_link_up(mv_pci) && to--)
> > + usleep_range(200, 250);
> > + if (to < 0) {
> > + dev_err(dev, "PCIe link training timeout\n");
> > + return -EIO;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static irqreturn_t ls_pcie_g4_isr(int irq, void *dev_id) {
> > + struct ls_pcie_g4 *pcie = (struct ls_pcie_g4 *)dev_id;
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + u32 val;
> > +
> > + val = mobiveil_csr_readl(mv_pci, PAB_INTP_AMBA_MISC_STAT);
> > + if (!val)
> > + return IRQ_NONE;
> > +
> > + if (val & PAB_INTP_RESET) {
> > + ls_pcie_g4_disable_interrupt(pcie);
> > + schedule_delayed_work(&pcie->dwork, msecs_to_jiffies(1));
> > + }
> > +
> > + mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_STAT);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int ls_pcie_g4_interrupt_init(struct mobiveil_pcie *mv_pci) {
> > + struct ls_pcie_g4 *pcie = to_ls_pcie_g4(mv_pci);
> > + struct platform_device *pdev = mv_pci->pdev;
> > + struct device *dev = &pdev->dev;
> > + int ret;
> > +
> > + pcie->irq = platform_get_irq_byname(pdev, "intr");
> > + if (pcie->irq < 0) {
> > + dev_err(dev, "Can't get 'intr' IRQ, errno = %d\n", pcie->irq);
> > + return pcie->irq;
> > + }
> > + ret = devm_request_irq(dev, pcie->irq, ls_pcie_g4_isr,
> > + IRQF_SHARED, pdev->name, pcie);
> > + if (ret) {
> > + dev_err(dev, "Can't register PCIe IRQ, errno = %d\n", ret);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void ls_pcie_g4_reset(struct work_struct *work) {
> > + struct delayed_work *dwork = container_of(work, struct delayed_work,
> > + work);
> > + struct ls_pcie_g4 *pcie = container_of(dwork, struct ls_pcie_g4, dwork);
> > + struct mobiveil_pcie *mv_pci = &pcie->pci;
> > + u16 ctrl;
> > +
> > + ctrl = mobiveil_csr_readw(mv_pci, PCI_BRIDGE_CONTROL);
> > + ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
> > + mobiveil_csr_writew(mv_pci, ctrl, PCI_BRIDGE_CONTROL);
> > +
> > + if (!ls_pcie_g4_reinit_hw(pcie))
> > + return;
> > +
> > + ls_pcie_g4_enable_interrupt(pcie);
> > +}
> > +
> > +static struct mobiveil_rp_ops ls_pcie_g4_rp_ops = {
> > + .interrupt_init = ls_pcie_g4_interrupt_init, };
> > +
> > +static const struct mobiveil_pab_ops ls_pcie_g4_pab_ops = {
> > + .link_up = ls_pcie_g4_link_up,
> > +};
> > +
> > +static int __init ls_pcie_g4_probe(struct platform_device *pdev) {
> > + struct device *dev = &pdev->dev;
> > + struct pci_host_bridge *bridge;
> > + struct mobiveil_pcie *mv_pci;
> > + struct ls_pcie_g4 *pcie;
> > + struct device_node *np = dev->of_node;
> > + int ret;
> > +
> > + if (!of_parse_phandle(np, "msi-parent", 0)) {
> > + dev_err(dev, "Failed to find msi-parent\n");
> > + return -EINVAL;
> > + }
> > +
> > + bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
> > + if (!bridge)
> > + return -ENOMEM;
> > +
> > + pcie = pci_host_bridge_priv(bridge);
> > + mv_pci = &pcie->pci;
> > +
> > + mv_pci->pdev = pdev;
> > + mv_pci->ops = &ls_pcie_g4_pab_ops;
> > + mv_pci->rp.ops = &ls_pcie_g4_rp_ops;
> > + mv_pci->rp.bridge = bridge;
> > +
> > + platform_set_drvdata(pdev, pcie);
> > +
> > + INIT_DELAYED_WORK(&pcie->dwork, ls_pcie_g4_reset);
> > +
> > + ret = mobiveil_pcie_host_probe(mv_pci);
> > + if (ret) {
> > + dev_err(dev, "Fail to probe\n");
> > + return ret;
> > + }
> > +
> > + ls_pcie_g4_enable_interrupt(pcie);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id ls_pcie_g4_of_match[] = {
> > + { .compatible = "fsl,lx2160a-pcie", },
> > + { },
> > +};
> > +
> > +static struct platform_driver ls_pcie_g4_driver = {
> > + .driver = {
> > + .name = "layerscape-pcie-gen4",
> > + .of_match_table = ls_pcie_g4_of_match,
> > + .suppress_bind_attrs = true,
> > + },
> > +};
> > +
> > +builtin_platform_driver_probe(ls_pcie_g4_driver, ls_pcie_g4_probe);
> > diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > index 72c62b4d8f7b..7b6a403a9fc0 100644
> > --- a/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > +++ b/drivers/pci/controller/mobiveil/pcie-mobiveil.h
> > @@ -43,6 +43,8 @@
> > #define PAGE_LO_MASK 0x3ff
> > #define PAGE_SEL_OFFSET_SHIFT 10
> >
> > +#define PAB_ACTIVITY_STAT 0x81c
> > +
> > #define PAB_AXI_PIO_CTRL 0x0840
> > #define APIO_EN_MASK 0xf
> >
> > @@ -51,8 +53,18 @@
> >
> > #define PAB_INTP_AMBA_MISC_ENB 0x0b0c
> > #define PAB_INTP_AMBA_MISC_STAT 0x0b1c
> > -#define PAB_INTP_INTX_MASK 0x01e0
> > -#define PAB_INTP_MSI_MASK 0x8
> > +#define PAB_INTP_RESET BIT(1)
> > +#define PAB_INTP_MSI BIT(3)
> > +#define PAB_INTP_INTA BIT(5)
> > +#define PAB_INTP_INTB BIT(6)
> > +#define PAB_INTP_INTC BIT(7)
> > +#define PAB_INTP_INTD BIT(8)
> > +#define PAB_INTP_PCIE_UE BIT(9)
> > +#define PAB_INTP_IE_PMREDI BIT(29)
> > +#define PAB_INTP_IE_EC BIT(30)
> > +#define PAB_INTP_MSI_MASK PAB_INTP_MSI
> > +#define PAB_INTP_INTX_MASK (PAB_INTP_INTA |
> PAB_INTP_INTB |\
> > + PAB_INTP_INTC | PAB_INTP_INTD)
> >
> > #define PAB_AXI_AMAP_CTRL(win) PAB_REG_ADDR(0x0ba0,
> win)
> > #define WIN_ENABLE_SHIFT 0
> > --
> > 2.17.1
> >
Hi Lorenzo,
> -----Original Message-----
> From: Lorenzo Pieralisi <[email protected]>
> Sent: 2020??2??21?? 20:20
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; Leo Li
> <[email protected]>; [email protected]; [email protected];
> Mingkai Hu <[email protected]>; M.h. Lian <[email protected]>;
> Xiaowei Bao <[email protected]>
> Subject: Re: [PATCHv10 00/13] PCI: Recode Mobiveil driver and add PCIe
> Gen4 driver for NXP Layerscape SoCs
>
> On Thu, Feb 13, 2020 at 12:06:31PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > This patch set is to recode the Mobiveil driver and add PCIe support
> > for NXP Layerscape series SoCs integrated Mobiveil's PCIe Gen4
> > controller.
> >
> > Hou Zhiqiang (13):
> > PCI: mobiveil: Introduce a new structure mobiveil_root_port
> > PCI: mobiveil: Move the host initialization into a function
> > PCI: mobiveil: Collect the interrupt related operations into a
> > function
> > PCI: mobiveil: Modularize the Mobiveil PCIe Host Bridge IP driver
> > PCI: mobiveil: Add callback function for interrupt initialization
> > PCI: mobiveil: Add callback function for link up check
> > PCI: mobiveil: Allow mobiveil_host_init() to be used to re-init host
> > PCI: mobiveil: Add 8-bit and 16-bit CSR register accessors
> > PCI: mobiveil: Add Header Type field check
> > dt-bindings: PCI: Add NXP Layerscape SoCs PCIe Gen4 controller
> > PCI: mobiveil: Add PCIe Gen4 RC driver for NXP Layerscape SoCs
> > arm64: dts: lx2160a: Add PCIe controller DT nodes
> > arm64: defconfig: Enable CONFIG_PCIE_LAYERSCAPE_GEN4
> >
> > .../bindings/pci/layerscape-pcie-gen4.txt | 52 ++
> > MAINTAINERS | 10 +-
> > .../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 163 +++++
> > arch/arm64/configs/defconfig | 1 +
> > drivers/pci/controller/Kconfig | 11 +-
> > drivers/pci/controller/Makefile | 2 +-
> > drivers/pci/controller/mobiveil/Kconfig | 33 +
> > drivers/pci/controller/mobiveil/Makefile | 5 +
> > .../mobiveil/pcie-layerscape-gen4.c | 267 +++++++++
> > .../pcie-mobiveil-host.c} | 564 ++++--------------
> > .../controller/mobiveil/pcie-mobiveil-plat.c | 61 ++
> > .../pci/controller/mobiveil/pcie-mobiveil.c | 230 +++++++
> > .../pci/controller/mobiveil/pcie-mobiveil.h | 226 +++++++
> > 13 files changed, 1170 insertions(+), 455 deletions(-) create mode
> > 100644 Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
> > create mode 100644 drivers/pci/controller/mobiveil/Kconfig
> > create mode 100644 drivers/pci/controller/mobiveil/Makefile
> > create mode 100644
> > drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
> > rename drivers/pci/controller/{pcie-mobiveil.c =>
> > mobiveil/pcie-mobiveil-host.c} (54%) create mode 100644
> > drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
> > create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.c
> > create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.h
>
> I dropped the last two patches since they must be re-routed via arm-soc
> (defconfig update and dts), I tweaked most of commit logs and applied the
> series to pci/mobiveil, please check everything is in order.
Thanks a lot for your help on the commit logs!
Thanks,
Zhiqiang
>
> Thanks,
> Lorenzo
Hi Shawn,
> -----Original Message-----
> From: Shawn Guo <[email protected]>
> Sent: 2020??2??24?? 9:28
> To: Z.q. Hou <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; Leo Li <[email protected]>;
> [email protected]; [email protected];
> [email protected]; Mingkai Hu <[email protected]>; M.h. Lian
> <[email protected]>; Xiaowei Bao <[email protected]>
> Subject: Re: [PATCHv10 12/13] arm64: dts: lx2160a: Add PCIe controller DT
> nodes
>
> On Thu, Feb 13, 2020 at 12:06:43PM +0800, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <[email protected]>
> >
> > The LX2160A integrated 6 PCIe Gen4 controllers.
> >
> > Signed-off-by: Hou Zhiqiang <[email protected]>
> > Reviewed-by: Minghuan Lian <[email protected]>
> > ---
> > V10:
> > - No change
> >
> > .../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 163
> > ++++++++++++++++++
> > 1 file changed, 163 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> > b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> > index e5ee5591e52b..aee2810d91cc 100644
> > --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> > +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
> > @@ -1076,5 +1076,168 @@
> > };
> > };
> > };
> > +
> > + pcie@3400000 {
>
> The nodes should be sorted in unit-address. That said, they should be
> added after ata3: sata@3230000.
>
> > + compatible = "fsl,lx2160a-pcie";
> > + reg = <0x00 0x03400000 0x0 0x00100000 /* controller
> registers */
> > + 0x80 0x00000000 0x0 0x00001000>; /* configuration
> space */
> > + reg-names = "csr_axi_slave", "config_axi_slave";
> > + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* AER
> interrupt */
> > + <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>, /* PME
> interrupt */
> > + <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; /*
> controller interrupt */
> > + interrupt-names = "aer", "pme", "intr";
> > + #address-cells = <3>;
> > + #size-cells = <2>;
> > + device_type = "pci";
> > + dma-coherent;
> > + apio-wins = <8>;
> > + ppio-wins = <8>;
> > + bus-range = <0x0 0xff>;
> > + ranges = <0x82000000 0x0 0x40000000 0x80 0x40000000 0x0
> 0x40000000>; /* non-prefetchable memory */
> > + msi-parent = <&its>;
> > + #interrupt-cells = <1>;
> > + interrupt-map-mask = <0 0 0 7>;
> > + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 109
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 2 &gic 0 0 GIC_SPI 110
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 3 &gic 0 0 GIC_SPI 111
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 4 &gic 0 0 GIC_SPI 112
> IRQ_TYPE_LEVEL_HIGH>;
> > + status = "disabled";
> > + };
> > +
> > + pcie@3500000 {
> > + compatible = "fsl,lx2160a-pcie";
> > + reg = <0x00 0x03500000 0x0 0x00100000 /* controller
> registers */
> > + 0x88 0x00000000 0x0 0x00001000>; /* configuration
> space */
> > + reg-names = "csr_axi_slave", "config_axi_slave";
> > + interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, /* AER
> interrupt */
> > + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>, /* PME
> interrupt */
> > + <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>; /*
> controller interrupt */
> > + interrupt-names = "aer", "pme", "intr";
> > + #address-cells = <3>;
> > + #size-cells = <2>;
> > + device_type = "pci";
> > + dma-coherent;
> > + apio-wins = <8>;
> > + ppio-wins = <8>;
> > + bus-range = <0x0 0xff>;
> > + ranges = <0x82000000 0x0 0x40000000 0x88 0x40000000 0x0
> 0x40000000>; /* non-prefetchable memory */
> > + msi-parent = <&its>;
> > + #interrupt-cells = <1>;
> > + interrupt-map-mask = <0 0 0 7>;
> > + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 114
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 2 &gic 0 0 GIC_SPI 115
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 3 &gic 0 0 GIC_SPI 116
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 4 &gic 0 0 GIC_SPI 117
> IRQ_TYPE_LEVEL_HIGH>;
> > + status = "disabled";
> > + };
> > +
> > + pcie@3600000 {
> > + compatible = "fsl,lx2160a-pcie";
> > + reg = <0x00 0x03600000 0x0 0x00100000 /* controller
> registers */
> > + 0x90 0x00000000 0x0 0x00001000>; /* configuration
> space */
> > + reg-names = "csr_axi_slave", "config_axi_slave";
> > + interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, /* AER
> interrupt */
> > + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, /* PME
> interrupt */
> > + <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; /*
> controller interrupt */
> > + interrupt-names = "aer", "pme", "intr";
> > + #address-cells = <3>;
> > + #size-cells = <2>;
> > + device_type = "pci";
> > + dma-coherent;
> > + apio-wins = <256>;
> > + ppio-wins = <24>;
> > + bus-range = <0x0 0xff>;
> > + ranges = <0x82000000 0x0 0x40000000 0x90 0x40000000 0x0
> 0x40000000>; /* non-prefetchable memory */
> > + msi-parent = <&its>;
> > + #interrupt-cells = <1>;
> > + interrupt-map-mask = <0 0 0 7>;
> > + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 119
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 2 &gic 0 0 GIC_SPI 120
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 3 &gic 0 0 GIC_SPI 121
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 4 &gic 0 0 GIC_SPI 122
> IRQ_TYPE_LEVEL_HIGH>;
> > + status = "disabled";
> > + };
> > +
> > + pcie@3700000 {
> > + compatible = "fsl,lx2160a-pcie";
> > + reg = <0x00 0x03700000 0x0 0x00100000 /* controller
> registers */
> > + 0x98 0x00000000 0x0 0x00001000>; /* configuration
> space */
> > + reg-names = "csr_axi_slave", "config_axi_slave";
> > + interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, /* AER
> interrupt */
> > + <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>, /* PME
> interrupt */
> > + <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>; /*
> controller interrupt */
> > + interrupt-names = "aer", "pme", "intr";
> > + #address-cells = <3>;
> > + #size-cells = <2>;
> > + device_type = "pci";
> > + dma-coherent;
> > + apio-wins = <8>;
> > + ppio-wins = <8>;
> > + bus-range = <0x0 0xff>;
> > + ranges = <0x82000000 0x0 0x40000000 0x98 0x40000000 0x0
> 0x40000000>; /* non-prefetchable memory */
> > + msi-parent = <&its>;
> > + #interrupt-cells = <1>;
> > + interrupt-map-mask = <0 0 0 7>;
> > + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 124
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 2 &gic 0 0 GIC_SPI 125
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 3 &gic 0 0 GIC_SPI 126
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 4 &gic 0 0 GIC_SPI 127
> IRQ_TYPE_LEVEL_HIGH>;
> > + status = "disabled";
> > + };
> > +
> > + pcie@3800000 {
> > + compatible = "fsl,lx2160a-pcie";
> > + reg = <0x00 0x03800000 0x0 0x00100000 /* controller
> registers */
> > + 0xa0 0x00000000 0x0 0x00001000>; /* configuration
> space */
> > + reg-names = "csr_axi_slave", "config_axi_slave";
> > + interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, /* AER
> interrupt */
> > + <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, /* PME
> interrupt */
> > + <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>; /*
> controller interrupt */
> > + interrupt-names = "aer", "pme", "intr";
> > + #address-cells = <3>;
> > + #size-cells = <2>;
> > + device_type = "pci";
> > + dma-coherent;
> > + apio-wins = <256>;
> > + ppio-wins = <24>;
> > + bus-range = <0x0 0xff>;
> > + ranges = <0x82000000 0x0 0x40000000 0xa0 0x40000000 0x0
> 0x40000000>; /* non-prefetchable memory */
> > + msi-parent = <&its>;
> > + #interrupt-cells = <1>;
> > + interrupt-map-mask = <0 0 0 7>;
> > + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 129
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 2 &gic 0 0 GIC_SPI 130
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 3 &gic 0 0 GIC_SPI 131
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 4 &gic 0 0 GIC_SPI 132
> IRQ_TYPE_LEVEL_HIGH>;
> > + status = "disabled";
> > + };
> > +
> > + pcie@3900000 {
> > + compatible = "fsl,lx2160a-pcie";
> > + reg = <0x00 0x03900000 0x0 0x00100000 /* controller
> registers */
> > + 0xa8 0x00000000 0x0 0x00001000>; /* configuration
> space */
> > + reg-names = "csr_axi_slave", "config_axi_slave";
> > + interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, /* AER
> interrupt */
> > + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>, /* PME
> interrupt */
> > + <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; /*
> controller interrupt */
> > + interrupt-names = "aer", "pme", "intr";
> > + #address-cells = <3>;
> > + #size-cells = <2>;
> > + device_type = "pci";
> > + dma-coherent;
> > + apio-wins = <8>;
> > + ppio-wins = <8>;
> > + bus-range = <0x0 0xff>;
> > + ranges = <0x82000000 0x0 0x40000000 0xa8 0x40000000 0x0
> 0x40000000>; /* non-prefetchable memory */
> > + msi-parent = <&its>;
> > + #interrupt-cells = <1>;
> > + interrupt-map-mask = <0 0 0 7>;
> > + interrupt-map = <0000 0 0 1 &gic 0 0 GIC_SPI 104
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 2 &gic 0 0 GIC_SPI 105
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 3 &gic 0 0 GIC_SPI 106
> IRQ_TYPE_LEVEL_HIGH>,
> > + <0000 0 0 4 &gic 0 0 GIC_SPI 107
> IRQ_TYPE_LEVEL_HIGH>;
> > + status = "disabled";
> > + };
> > +
>
> Unnecessary newline.
>
> I fixed them up and applied the patch.
Thanks a lot for your help!
Thanks,
Zhiqiang
>
> Shawn
>
> > };
> > };
> > --
> > 2.17.1
> >