Merge branch 'pci/host/dwc'

- Export dw_pcie_ep_reset_bar(), dw_pcie_link_up() so more drivers can be
  modular (Luca Ceresoli)

- Allow dra7xx host and endpoint drivers to be modules (Luca Ceresoli)

- Enable dra7xx optional external clock if present (Luca Ceresoli)

- Clean up Kconfig dependencies for PCIE_DW_HOST- and PCIE_DW_EP-based
  drivers (Andy Shevchenko)

- Remove visconti redundant dev_err() after platform_get_irq_byname()
  failure (Krzysztof Wilczyński)

- Run dwc .host_init() method before registering MSI interrupt handler so
  we have a chance to deal with pending interrupts left by bootloader
  (Bjorn Andersson)

- Serialize uniphier INTx masking/unmasking (Kunihiko Hayashi)

* pci/host/dwc:
  PCI: uniphier: Serialize INTx masking/unmasking and fix the bit operation
  PCI: dwc: Perform host_init() before registering msi
  PCI: visconti: Remove surplus dev_err() when using platform_get_irq_byname()
  PCI: dwc: Clean up Kconfig dependencies (PCIE_DW_EP)
  PCI: dwc: Clean up Kconfig dependencies (PCIE_DW_HOST)
  PCI: dra7xx: Get an optional clock
  PCI: dra7xx: Remove unused include
  PCI: dra7xx: Make it a kernel module
  PCI: dwc: Export more symbols to allow modular drivers
This commit is contained in:
Bjorn Helgaas 2021-11-05 11:28:49 -05:00
commit 07dd8bbec1
7 changed files with 51 additions and 41 deletions

View File

@ -8,22 +8,20 @@ config PCIE_DW
config PCIE_DW_HOST config PCIE_DW_HOST
bool bool
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW select PCIE_DW
config PCIE_DW_EP config PCIE_DW_EP
bool bool
depends on PCI_ENDPOINT
select PCIE_DW select PCIE_DW
config PCI_DRA7XX config PCI_DRA7XX
bool tristate
config PCI_DRA7XX_HOST config PCI_DRA7XX_HOST
bool "TI DRA7xx PCIe controller Host Mode" tristate "TI DRA7xx PCIe controller Host Mode"
depends on SOC_DRA7XX || COMPILE_TEST depends on SOC_DRA7XX || COMPILE_TEST
depends on PCI_MSI_IRQ_DOMAIN
depends on OF && HAS_IOMEM && TI_PIPE3 depends on OF && HAS_IOMEM && TI_PIPE3
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW_HOST select PCIE_DW_HOST
select PCI_DRA7XX select PCI_DRA7XX
default y if SOC_DRA7XX default y if SOC_DRA7XX
@ -36,10 +34,10 @@ config PCI_DRA7XX_HOST
This uses the DesignWare core. This uses the DesignWare core.
config PCI_DRA7XX_EP config PCI_DRA7XX_EP
bool "TI DRA7xx PCIe controller Endpoint Mode" tristate "TI DRA7xx PCIe controller Endpoint Mode"
depends on SOC_DRA7XX || COMPILE_TEST depends on SOC_DRA7XX || COMPILE_TEST
depends on PCI_ENDPOINT
depends on OF && HAS_IOMEM && TI_PIPE3 depends on OF && HAS_IOMEM && TI_PIPE3
depends on PCI_ENDPOINT
select PCIE_DW_EP select PCIE_DW_EP
select PCI_DRA7XX select PCI_DRA7XX
help help
@ -55,7 +53,7 @@ config PCIE_DW_PLAT
config PCIE_DW_PLAT_HOST config PCIE_DW_PLAT_HOST
bool "Platform bus based DesignWare PCIe Controller - Host mode" bool "Platform bus based DesignWare PCIe Controller - Host mode"
depends on PCI && PCI_MSI_IRQ_DOMAIN depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW_HOST select PCIE_DW_HOST
select PCIE_DW_PLAT select PCIE_DW_PLAT
help help
@ -138,8 +136,8 @@ config PCI_LAYERSCAPE
bool "Freescale Layerscape PCIe controller - Host mode" bool "Freescale Layerscape PCIe controller - Host mode"
depends on OF && (ARM || ARCH_LAYERSCAPE || COMPILE_TEST) depends on OF && (ARM || ARCH_LAYERSCAPE || COMPILE_TEST)
depends on PCI_MSI_IRQ_DOMAIN depends on PCI_MSI_IRQ_DOMAIN
select MFD_SYSCON
select PCIE_DW_HOST select PCIE_DW_HOST
select MFD_SYSCON
help help
Say Y here if you want to enable PCIe controller support on Layerscape Say Y here if you want to enable PCIe controller support on Layerscape
SoCs to work in Host mode. SoCs to work in Host mode.
@ -283,8 +281,8 @@ config PCIE_HISI_STB
config PCI_MESON config PCI_MESON
tristate "MESON PCIe controller" tristate "MESON PCIe controller"
depends on PCI_MSI_IRQ_DOMAIN
default m if ARCH_MESON default m if ARCH_MESON
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW_HOST select PCIE_DW_HOST
help help
Say Y here if you want to enable PCI controller support on Amlogic Say Y here if you want to enable PCI controller support on Amlogic

View File

@ -7,6 +7,7 @@
* Authors: Kishon Vijay Abraham I <kishon@ti.com> * Authors: Kishon Vijay Abraham I <kishon@ti.com>
*/ */
#include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
@ -14,7 +15,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/module.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/of_pci.h> #include <linux/of_pci.h>
@ -90,6 +91,7 @@ struct dra7xx_pcie {
int phy_count; /* DT phy-names count */ int phy_count; /* DT phy-names count */
struct phy **phy; struct phy **phy;
struct irq_domain *irq_domain; struct irq_domain *irq_domain;
struct clk *clk;
enum dw_pcie_device_mode mode; enum dw_pcie_device_mode mode;
}; };
@ -607,6 +609,7 @@ static const struct of_device_id of_dra7xx_pcie_match[] = {
}, },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, of_dra7xx_pcie_match);
/* /*
* dra7xx_pcie_unaligned_memaccess: workaround for AM572x/AM571x Errata i870 * dra7xx_pcie_unaligned_memaccess: workaround for AM572x/AM571x Errata i870
@ -740,6 +743,15 @@ static int dra7xx_pcie_probe(struct platform_device *pdev)
if (!link) if (!link)
return -ENOMEM; return -ENOMEM;
dra7xx->clk = devm_clk_get_optional(dev, NULL);
if (IS_ERR(dra7xx->clk))
return dev_err_probe(dev, PTR_ERR(dra7xx->clk),
"clock request failed");
ret = clk_prepare_enable(dra7xx->clk);
if (ret)
return ret;
for (i = 0; i < phy_count; i++) { for (i = 0; i < phy_count; i++) {
snprintf(name, sizeof(name), "pcie-phy%d", i); snprintf(name, sizeof(name), "pcie-phy%d", i);
phy[i] = devm_phy_get(dev, name); phy[i] = devm_phy_get(dev, name);
@ -925,6 +937,8 @@ static void dra7xx_pcie_shutdown(struct platform_device *pdev)
pm_runtime_disable(dev); pm_runtime_disable(dev);
dra7xx_pcie_disable_phy(dra7xx); dra7xx_pcie_disable_phy(dra7xx);
clk_disable_unprepare(dra7xx->clk);
} }
static const struct dev_pm_ops dra7xx_pcie_pm_ops = { static const struct dev_pm_ops dra7xx_pcie_pm_ops = {
@ -943,4 +957,8 @@ static struct platform_driver dra7xx_pcie_driver = {
}, },
.shutdown = dra7xx_pcie_shutdown, .shutdown = dra7xx_pcie_shutdown,
}; };
builtin_platform_driver(dra7xx_pcie_driver); module_platform_driver(dra7xx_pcie_driver);
MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
MODULE_DESCRIPTION("PCIe controller driver for TI DRA7xx SoCs");
MODULE_LICENSE("GPL v2");

View File

@ -83,6 +83,7 @@ void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
for (func_no = 0; func_no < funcs; func_no++) for (func_no = 0; func_no < funcs; func_no++)
__dw_pcie_ep_reset_bar(pci, func_no, bar, 0); __dw_pcie_ep_reset_bar(pci, func_no, bar, 0);
} }
EXPORT_SYMBOL_GPL(dw_pcie_ep_reset_bar);
static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no, static u8 __dw_pcie_ep_find_next_cap(struct dw_pcie_ep *ep, u8 func_no,
u8 cap_ptr, u8 cap) u8 cap_ptr, u8 cap)

View File

@ -335,6 +335,16 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (pci->link_gen < 1) if (pci->link_gen < 1)
pci->link_gen = of_pci_get_max_link_speed(np); pci->link_gen = of_pci_get_max_link_speed(np);
/* Set default bus ops */
bridge->ops = &dw_pcie_ops;
bridge->child_ops = &dw_child_pcie_ops;
if (pp->ops->host_init) {
ret = pp->ops->host_init(pp);
if (ret)
return ret;
}
if (pci_msi_enabled()) { if (pci_msi_enabled()) {
pp->has_msi_ctrl = !(pp->ops->msi_host_init || pp->has_msi_ctrl = !(pp->ops->msi_host_init ||
of_property_read_bool(np, "msi-parent") || of_property_read_bool(np, "msi-parent") ||
@ -388,15 +398,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
} }
} }
/* Set default bus ops */
bridge->ops = &dw_pcie_ops;
bridge->child_ops = &dw_child_pcie_ops;
if (pp->ops->host_init) {
ret = pp->ops->host_init(pp);
if (ret)
goto err_free_msi;
}
dw_pcie_iatu_detect(pci); dw_pcie_iatu_detect(pci);
dw_pcie_setup_rc(pp); dw_pcie_setup_rc(pp);

View File

@ -538,6 +538,7 @@ int dw_pcie_link_up(struct dw_pcie *pci)
return ((val & PCIE_PORT_DEBUG1_LINK_UP) && return ((val & PCIE_PORT_DEBUG1_LINK_UP) &&
(!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING))); (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING)));
} }
EXPORT_SYMBOL_GPL(dw_pcie_link_up);
void dw_pcie_upconfig_setup(struct dw_pcie *pci) void dw_pcie_upconfig_setup(struct dw_pcie *pci)
{ {

View File

@ -168,30 +168,21 @@ static void uniphier_pcie_irq_enable(struct uniphier_pcie_priv *priv)
writel(PCL_RCV_INTX_ALL_ENABLE, priv->base + PCL_RCV_INTX); writel(PCL_RCV_INTX_ALL_ENABLE, priv->base + PCL_RCV_INTX);
} }
static void uniphier_pcie_irq_ack(struct irq_data *d)
{
struct pcie_port *pp = irq_data_get_irq_chip_data(d);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
u32 val;
val = readl(priv->base + PCL_RCV_INTX);
val &= ~PCL_RCV_INTX_ALL_STATUS;
val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_STATUS_SHIFT);
writel(val, priv->base + PCL_RCV_INTX);
}
static void uniphier_pcie_irq_mask(struct irq_data *d) static void uniphier_pcie_irq_mask(struct irq_data *d)
{ {
struct pcie_port *pp = irq_data_get_irq_chip_data(d); struct pcie_port *pp = irq_data_get_irq_chip_data(d);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
unsigned long flags;
u32 val; u32 val;
raw_spin_lock_irqsave(&pp->lock, flags);
val = readl(priv->base + PCL_RCV_INTX); val = readl(priv->base + PCL_RCV_INTX);
val &= ~PCL_RCV_INTX_ALL_MASK;
val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT); val |= BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT);
writel(val, priv->base + PCL_RCV_INTX); writel(val, priv->base + PCL_RCV_INTX);
raw_spin_unlock_irqrestore(&pp->lock, flags);
} }
static void uniphier_pcie_irq_unmask(struct irq_data *d) static void uniphier_pcie_irq_unmask(struct irq_data *d)
@ -199,17 +190,20 @@ static void uniphier_pcie_irq_unmask(struct irq_data *d)
struct pcie_port *pp = irq_data_get_irq_chip_data(d); struct pcie_port *pp = irq_data_get_irq_chip_data(d);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci); struct uniphier_pcie_priv *priv = to_uniphier_pcie(pci);
unsigned long flags;
u32 val; u32 val;
raw_spin_lock_irqsave(&pp->lock, flags);
val = readl(priv->base + PCL_RCV_INTX); val = readl(priv->base + PCL_RCV_INTX);
val &= ~PCL_RCV_INTX_ALL_MASK;
val &= ~BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT); val &= ~BIT(irqd_to_hwirq(d) + PCL_RCV_INTX_MASK_SHIFT);
writel(val, priv->base + PCL_RCV_INTX); writel(val, priv->base + PCL_RCV_INTX);
raw_spin_unlock_irqrestore(&pp->lock, flags);
} }
static struct irq_chip uniphier_pcie_irq_chip = { static struct irq_chip uniphier_pcie_irq_chip = {
.name = "PCI", .name = "PCI",
.irq_ack = uniphier_pcie_irq_ack,
.irq_mask = uniphier_pcie_irq_mask, .irq_mask = uniphier_pcie_irq_mask,
.irq_unmask = uniphier_pcie_irq_unmask, .irq_unmask = uniphier_pcie_irq_unmask,
}; };

View File

@ -279,13 +279,10 @@ static int visconti_add_pcie_port(struct visconti_pcie *pcie,
{ {
struct dw_pcie *pci = &pcie->pci; struct dw_pcie *pci = &pcie->pci;
struct pcie_port *pp = &pci->pp; struct pcie_port *pp = &pci->pp;
struct device *dev = &pdev->dev;
pp->irq = platform_get_irq_byname(pdev, "intr"); pp->irq = platform_get_irq_byname(pdev, "intr");
if (pp->irq < 0) { if (pp->irq < 0)
dev_err(dev, "Interrupt intr is missing");
return pp->irq; return pp->irq;
}
pp->ops = &visconti_pcie_host_ops; pp->ops = &visconti_pcie_host_ops;