Commit 3bb0356b authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/host-designware' into next

* pci/host-designware:
  PCI: dwc: Remove dependency of designware on CONFIG_PCI
  PCI: dwc: Add CONFIG_PCIE_DW_HOST to enable PCI dwc host
  PCI: dwc: Split pcie-designware.c into host and core files
  PCI: dwc: designware: Fix style errors in pcie-designware.c
  PCI: dwc: designware: Parse "num-lanes" property in dw_pcie_setup_rc()
  PCI: dwc: all: Split struct pcie_port into host-only and core structures
  PCI: dwc: designware: Get device pointer at the start of dw_pcie_host_init()
  PCI: dwc: all: Rename cfg_read/cfg_write to read/write
  PCI: dwc: all: Use platform_set_drvdata() to save private data
  PCI: dwc: designware: Move register defines to designware header file
  PCI: dwc: Use PTR_ERR_OR_ZERO to simplify code
  PCI: dra7xx: Group PHY API invocations
  PCI: dra7xx: Enable MSI and legacy interrupts simultaneously
  PCI: dra7xx: Add support to force RC to work in GEN1 mode
  PCI: dra7xx: Simplify probe code with devm_gpiod_get_optional()
  PCI: Move DesignWare IP support to new drivers/pci/dwc/ directory
  PCI: designware: Check for iATU unroll only on platforms that use ATU
parents 4c2ae32d 7a2b3f02
......@@ -9429,7 +9429,7 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/pci/pci-armada8k.txt
F: drivers/pci/host/pcie-armada8k.c
F: drivers/pci/dwc/pcie-armada8k.c
PCI DRIVER FOR APPLIEDMICRO XGENE
M: Tanmay Inamdar <tinamdar@apm.com>
......@@ -9447,7 +9447,7 @@ L: linuxppc-dev@lists.ozlabs.org
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: drivers/pci/host/*layerscape*
F: drivers/pci/dwc/*layerscape*
PCI DRIVER FOR IMX6
M: Richard Zhu <hongxing.zhu@nxp.com>
......@@ -9456,14 +9456,14 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
F: drivers/pci/host/*imx6*
F: drivers/pci/dwc/*imx6*
PCI DRIVER FOR TI KEYSTONE
M: Murali Karicheri <m-karicheri2@ti.com>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/pci/host/*keystone*
F: drivers/pci/dwc/*keystone*
PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC support)
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
......@@ -9495,7 +9495,7 @@ L: linux-omap@vger.kernel.org
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/ti-pci.txt
F: drivers/pci/host/pci-dra7xx.c
F: drivers/pci/dwc/pci-dra7xx.c
PCI DRIVER FOR RENESAS R-CAR
M: Simon Horman <horms@verge.net.au>
......@@ -9510,7 +9510,7 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
F: drivers/pci/host/pci-exynos.c
F: drivers/pci/dwc/pci-exynos.c
PCI DRIVER FOR SYNOPSIS DESIGNWARE
M: Jingoo Han <jingoohan1@gmail.com>
......@@ -9518,7 +9518,7 @@ M: Joao Pinto <Joao.Pinto@synopsys.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/designware-pcie.txt
F: drivers/pci/host/*designware*
F: drivers/pci/dwc/*designware*
PCI DRIVER FOR GENERIC OF HOSTS
M: Will Deacon <will.deacon@arm.com>
......@@ -9539,7 +9539,7 @@ PCIE DRIVER FOR ST SPEAR13XX
M: Pratyush Anand <pratyush.anand@gmail.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: drivers/pci/host/*spear*
F: drivers/pci/dwc/*spear*
PCI MSI DRIVER FOR ALTERA MSI IP
M: Ley Foon Tan <lftan@altera.com>
......@@ -9564,7 +9564,7 @@ L: linux-arm-kernel@axis.com
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/axis,artpec*
F: drivers/pci/host/*artpec*
F: drivers/pci/dwc/*artpec*
PCIE DRIVER FOR HISILICON
M: Zhou Wang <wangzhou1@hisilicon.com>
......@@ -9572,7 +9572,7 @@ M: Gabriele Paoloni <gabriele.paoloni@huawei.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
F: drivers/pci/host/pcie-hisi.c
F: drivers/pci/dwc/pcie-hisi.c
PCIE DRIVER FOR ROCKCHIP
M: Shawn Lin <shawn.lin@rock-chips.com>
......@@ -9588,7 +9588,7 @@ M: Stanimir Varbanov <svarbanov@mm-sol.com>
L: linux-pci@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: drivers/pci/host/*qcom*
F: drivers/pci/dwc/*qcom*
PCIE DRIVER FOR CAVIUM THUNDERX
M: David Daney <david.daney@cavium.com>
......
......@@ -15,6 +15,9 @@ obj-$(CONFIG_PINCTRL) += pinctrl/
obj-$(CONFIG_GPIOLIB) += gpio/
obj-y += pwm/
obj-$(CONFIG_PCI) += pci/
# PCI dwc controller drivers
obj-y += pci/dwc/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_RAPIDIO) += rapidio/
obj-y += video/
......
......@@ -132,4 +132,5 @@ config PCI_HYPERV
PCI devices from a PCI backend to support PCI driver domains.
source "drivers/pci/hotplug/Kconfig"
source "drivers/pci/dwc/Kconfig"
source "drivers/pci/host/Kconfig"
menu "DesignWare PCI Core Support"
config PCIE_DW
bool
config PCIE_DW_HOST
bool
depends on PCI
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
config PCI_DRA7XX
bool "TI DRA7xx PCIe controller"
depends on PCI
depends on OF && HAS_IOMEM && TI_PIPE3
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW_HOST
help
Enables support for the PCIe controller in the DRA7xx SoC. There
are two instances of PCIe controller in DRA7xx. This controller can
act both as EP and RC. This reuses the Designware core.
config PCIE_DW_PLAT
bool "Platform bus based DesignWare PCIe Controller"
depends on PCI
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW_HOST
---help---
This selects the DesignWare PCIe controller support. Select this if
you have a PCIe controller on Platform bus.
If you have a controller with this interface, say Y or M here.
If unsure, say N.
config PCI_EXYNOS
bool "Samsung Exynos PCIe controller"
depends on PCI
depends on SOC_EXYNOS5440
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
config PCI_IMX6
bool "Freescale i.MX6 PCIe controller"
depends on PCI
depends on SOC_IMX6Q
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
config PCIE_SPEAR13XX
bool "STMicroelectronics SPEAr PCIe controller"
depends on PCI
depends on ARCH_SPEAR13XX
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
help
Say Y here if you want PCIe support on SPEAr13XX SoCs.
config PCI_KEYSTONE
bool "TI Keystone PCIe controller"
depends on PCI
depends on ARCH_KEYSTONE
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
help
Say Y here if you want to enable PCI controller support on Keystone
SoCs. The PCI controller on Keystone is based on Designware hardware
and therefore the driver re-uses the Designware core functions to
implement the driver.
config PCI_LAYERSCAPE
bool "Freescale Layerscape PCIe controller"
depends on PCI
depends on OF && (ARM || ARCH_LAYERSCAPE)
depends on PCI_MSI_IRQ_DOMAIN
select MFD_SYSCON
select PCIE_DW_HOST
help
Say Y here if you want PCIe controller support on Layerscape SoCs.
config PCI_HISI
depends on OF && ARM64
bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers"
depends on PCI
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
help
Say Y here if you want PCIe controller support on HiSilicon
Hip05 and Hip06 SoCs
config PCIE_QCOM
bool "Qualcomm PCIe controller"
depends on PCI
depends on ARCH_QCOM && OF
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
help
Say Y here to enable PCIe controller support on Qualcomm SoCs. The
PCIe controller uses the Designware core plus Qualcomm-specific
hardware wrappers.
config PCIE_ARMADA_8K
bool "Marvell Armada-8K PCIe controller"
depends on PCI
depends on ARCH_MVEBU
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
help
Say Y here if you want to enable PCIe controller support on
Armada-8K SoCs. The PCIe controller on Armada-8K is based on
Designware hardware and therefore the driver re-uses the
Designware core functions to implement the driver.
config PCIE_ARTPEC6
bool "Axis ARTPEC-6 PCIe controller"
depends on PCI
depends on MACH_ARTPEC6
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW_HOST
help
Say Y here to enable PCIe controller support on Axis ARTPEC-6
SoCs. This PCIe controller uses the DesignWare core.
endmenu
obj-$(CONFIG_PCIE_DW) += pcie-designware.o
obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o
obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
# The following drivers are for devices that use the generic ACPI
# pci_root.c driver but don't support standard ECAM config access.
# They contain MCFG quirks to replace the generic ECAM accessors with
# device-specific ones that are shared with the DT driver.
# The ACPI driver is generic and should not require driver-specific
# config options to be enabled, so we always build these drivers on
# ARM64 and use internal ifdefs to only build the pieces we need
# depending on whether ACPI, the DT driver, or both are enabled.
obj-$(CONFIG_ARM64) += pcie-hisi.o
......@@ -26,10 +26,10 @@
#include "pcie-designware.h"
#define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp)
#define to_exynos_pcie(x) dev_get_drvdata((x)->dev)
struct exynos_pcie {
struct pcie_port pp;
struct dw_pcie *pci;
void __iomem *elbi_base; /* DT 0th resource */
void __iomem *phy_base; /* DT 1st resource */
void __iomem *block_base; /* DT 2nd resource */
......@@ -297,8 +297,8 @@ static void exynos_pcie_init_phy(struct exynos_pcie *exynos_pcie)
static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
{
struct pcie_port *pp = &exynos_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = exynos_pcie->pci;
struct device *dev = pci->dev;
if (exynos_pcie->reset_gpio >= 0)
devm_gpio_request_one(dev, exynos_pcie->reset_gpio,
......@@ -307,11 +307,12 @@ static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
{
struct pcie_port *pp = &exynos_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = exynos_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
u32 val;
if (dw_pcie_link_up(pp)) {
if (dw_pcie_link_up(pci)) {
dev_err(dev, "Link already up\n");
return 0;
}
......@@ -336,7 +337,7 @@ static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
PCIE_APP_LTSSM_ENABLE);
/* check if the link is up or not */
if (!dw_pcie_wait_for_link(pp))
if (!dw_pcie_wait_for_link(pci))
return 0;
while (exynos_phy_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED) == 0) {
......@@ -376,14 +377,16 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
{
struct exynos_pcie *exynos_pcie = arg;
struct pcie_port *pp = &exynos_pcie->pp;
struct dw_pcie *pci = exynos_pcie->pci;
struct pcie_port *pp = &pci->pp;
return dw_handle_msi_irq(pp);
}
static void exynos_pcie_msi_init(struct exynos_pcie *exynos_pcie)
{
struct pcie_port *pp = &exynos_pcie->pp;
struct dw_pcie *pci = exynos_pcie->pci;
struct pcie_port *pp = &pci->pp;
u32 val;
dw_pcie_msi_init(pp);
......@@ -402,34 +405,35 @@ static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie)
exynos_pcie_msi_init(exynos_pcie);
}
static u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg)
static u32 exynos_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
u32 val;
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
val = readl(pp->dbi_base + reg);
val = readl(pci->dbi_base + reg);
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
return val;
}
static void exynos_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
static void exynos_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
writel(val, pp->dbi_base + reg);
writel(val, pci->dbi_base + reg);
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
}
static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
u32 *val)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
int ret;
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
ret = dw_pcie_read(pci->dbi_base + where, size, val);
exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
return ret;
}
......@@ -437,18 +441,19 @@ static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
u32 val)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
int ret;
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
ret = dw_pcie_write(pci->dbi_base + where, size, val);
exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
return ret;
}
static int exynos_pcie_link_up(struct pcie_port *pp)
static int exynos_pcie_link_up(struct dw_pcie *pci)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
u32 val;
val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP);
......@@ -460,26 +465,25 @@ static int exynos_pcie_link_up(struct pcie_port *pp)
static void exynos_pcie_host_init(struct pcie_port *pp)
{
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci);
exynos_pcie_establish_link(exynos_pcie);
exynos_pcie_enable_interrupts(exynos_pcie);
}
static struct pcie_host_ops exynos_pcie_host_ops = {
.readl_rc = exynos_pcie_readl_rc,
.writel_rc = exynos_pcie_writel_rc,
static struct dw_pcie_host_ops exynos_pcie_host_ops = {
.rd_own_conf = exynos_pcie_rd_own_conf,
.wr_own_conf = exynos_pcie_wr_own_conf,
.link_up = exynos_pcie_link_up,
.host_init = exynos_pcie_host_init,
};
static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie,
struct platform_device *pdev)
{
struct pcie_port *pp = &exynos_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = exynos_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = &pdev->dev;
int ret;
pp->irq = platform_get_irq(pdev, 1);
......@@ -523,11 +527,17 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie,
return 0;
}
static const struct dw_pcie_ops dw_pcie_ops = {
.readl_dbi = exynos_pcie_readl_dbi,
.writel_dbi = exynos_pcie_writel_dbi,
.link_up = exynos_pcie_link_up,
};
static int __init exynos_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct exynos_pcie *exynos_pcie;
struct pcie_port *pp;
struct device_node *np = dev->of_node;
struct resource *elbi_base;
struct resource *phy_base;
......@@ -538,8 +548,12 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
if (!exynos_pcie)
return -ENOMEM;
pp = &exynos_pcie->pp;
pp->dev = dev;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
pci->ops = &dw_pcie_ops;
exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
......@@ -583,11 +597,12 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)
goto fail_bus_clk;
}
platform_set_drvdata(pdev, exynos_pcie);
ret = exynos_add_pcie_port(exynos_pcie, pdev);
if (ret < 0)
goto fail_bus_clk;
platform_set_drvdata(pdev, exynos_pcie);
return 0;
fail_bus_clk:
......
......@@ -72,7 +72,7 @@
/* Config space registers */
#define DEBUG0 0x728
#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)
static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
u32 *bit_pos)
......@@ -83,7 +83,8 @@ static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
return ks_pcie->app.start + MSI_IRQ;
}
......@@ -100,8 +101,9 @@ static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val)
void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
{
struct pcie_port *pp = &ks_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
u32 pending, vector;
int src, virq;
......@@ -128,10 +130,12 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
struct keystone_pcie *ks_pcie;
struct msi_desc *msi;
struct pcie_port *pp;
struct dw_pcie *pci;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
ks_pcie = to_keystone_pcie(pp);
pci = to_dw_pcie_from_pp(pp);
ks_pcie = to_keystone_pcie(pci);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
......@@ -143,7 +147,8 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
{
u32 reg_offset, bit_pos;
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4),
......@@ -153,7 +158,8 @@ void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
{
u32 reg_offset, bit_pos;
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4),
......@@ -165,11 +171,13 @@ static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
struct keystone_pcie *ks_pcie;
struct msi_desc *msi;
struct pcie_port *pp;
struct dw_pcie *pci;
u32 offset;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
ks_pcie = to_keystone_pcie(pp);
pci = to_dw_pcie_from_pp(pp);
ks_pcie = to_keystone_pcie(pci);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
......@@ -186,11 +194,13 @@ static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
struct keystone_pcie *ks_pcie;
struct msi_desc *msi;
struct pcie_port *pp;
struct dw_pcie *pci;
u32 offset;
msi = irq_data_get_msi_desc(d);
pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
ks_pcie = to_keystone_pcie(pp);
pci = to_dw_pcie_from_pp(pp);
ks_pcie = to_keystone_pcie(pci);
offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
/* Mask the end point if PVM implemented */
......@@ -225,8 +235,9 @@ static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = {
int ks_dw_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct device *dev = pp->dev;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
struct device *dev = pci->dev;
int i;
pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np,
......@@ -254,8 +265,8 @@ void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset)
{
struct pcie_port *pp = &ks_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = ks_pcie->pci;
struct device *dev = pci->dev;
u32 pending;
int virq;
......@@ -285,7 +296,7 @@ irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
return IRQ_NONE;
if (status & ERR_FATAL_IRQ)
dev_err(ks_pcie->pp.dev, "fatal error (status %#010x)\n",
dev_err(ks_pcie->pci->dev, "fatal error (status %#010x)\n",
status);
/* Ack the IRQ; status bits are RW1C */
......@@ -366,15 +377,16 @@ static void ks_dw_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
{
struct pcie_port *pp = &ks_pcie->pp;
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
u32 start = pp->mem->start, end = pp->mem->end;
int i, tr_size;
u32 val;
/* Disable BARs for inbound access */
ks_dw_pcie_set_dbi_mode(ks_pcie);
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 0);
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_1, 0);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0);
ks_dw_pcie_clear_dbi_mode(ks_pcie);
/* Set outbound translation size per window division */
......@@ -415,11 +427,12 @@ static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
unsigned int devfn)
{
u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
struct pcie_port *pp = &ks_pcie->pp;
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
u32 regval;
if (bus == 0)
return pp->dbi_base;
return pci->dbi_base;
regval = (bus << 16) | (device << 8) | function;
......@@ -438,25 +451,27 @@ static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 *val)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
u8 bus_num = bus->number;
void __iomem *addr;
addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
return dw_pcie_cfg_read(addr + where, size, val);
return dw_pcie_read(addr + where, size, val);
}
int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
u8 bus_num = bus->number;
void __iomem *addr;
addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
return dw_pcie_cfg_write(addr + where, size, val);
return dw_pcie_write(addr + where, size, val);
}
/**
......@@ -466,14 +481,15 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
*/
void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
/* Configure and set up BAR0 */
ks_dw_pcie_set_dbi_mode(ks_pcie);
/* Enable BAR0 */
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 1);
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, SZ_4K - 1);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 1);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, SZ_4K - 1);
ks_dw_pcie_clear_dbi_mode(ks_pcie);
......@@ -481,17 +497,17 @@ void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
* For BAR0, just setting bus address for inbound writes (MSI) should
* be sufficient. Use physical address to avoid any conflicts.
*/
dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, ks_pcie->app.start);
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, ks_pcie->app.start);
}
/**
* ks_dw_pcie_link_up() - Check if link up
*/
int ks_dw_pcie_link_up(struct pcie_port *pp)
int ks_dw_pcie_link_up(struct dw_pcie *pci)
{
u32 val;
val = dw_pcie_readl_rc(pp, DEBUG0);
val = dw_pcie_readl_dbi(pci, DEBUG0);
return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
}
......@@ -519,22 +535,23 @@ void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
struct device_node *msi_intc_np)
{
struct pcie_port *pp = &ks_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
struct platform_device *pdev = to_platform_device(dev);
struct resource *res;
/* Index 0 is the config reg. space address */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pp->dbi_base = devm_ioremap_resource(dev, res);
if (IS_ERR(pp->dbi_base))
return PTR_ERR(pp->dbi_base);
pci->dbi_base = devm_ioremap_resource(dev, res);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
/*
* We set these same and is used in pcie rd/wr_other_conf
* functions
*/
pp->va_cfg0_base = pp->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
pp->va_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
pp->va_cfg1_base = pp->va_cfg0_base;
/* Index 1 is the application reg. space address */
......
......@@ -44,7 +44,7 @@
#define PCIE_RC_K2E 0xb009
#define PCIE_RC_K2L 0xb00a
#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
#define to_keystone_pcie(x) dev_get_drvdata((x)->dev)
static void quirk_limit_mrrs(struct pci_dev *dev)
{
......@@ -88,13 +88,14 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);
static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
{
struct pcie_port *pp = &ks_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
unsigned int retries;
dw_pcie_setup_rc(pp);
if (dw_pcie_link_up(pp)) {
if (dw_pcie_link_up(pci)) {
dev_err(dev, "Link already up\n");
return 0;
}
......@@ -102,7 +103,7 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
/* check if the link is up or not */
for (retries = 0; retries < 5; retries++) {
ks_dw_pcie_initiate_link_train(ks_pcie);
if (!dw_pcie_wait_for_link(pp))
if (!dw_pcie_wait_for_link(pci))
return 0;
}
......@@ -115,8 +116,8 @@ static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
unsigned int irq = irq_desc_get_irq(desc);
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
u32 offset = irq - ks_pcie->msi_host_irqs[0];
struct pcie_port *pp = &ks_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = ks_pcie->pci;
struct device *dev = pci->dev;
struct irq_chip *chip = irq_desc_get_chip(desc);
dev_dbg(dev, "%s, irq %d\n", __func__, irq);
......@@ -143,8 +144,8 @@ static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
{
unsigned int irq = irq_desc_get_irq(desc);
struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
struct pcie_port *pp = &ks_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = ks_pcie->pci;
struct device *dev = pci->dev;
u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
struct irq_chip *chip = irq_desc_get_chip(desc);
......@@ -164,7 +165,7 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
char *controller, int *num_irqs)
{
int temp, max_host_irqs, legacy = 1, *host_irqs;
struct device *dev = ks_pcie->pp.dev;
struct device *dev = ks_pcie->pci->dev;
struct device_node *np_pcie = dev->of_node, **np_temp;
if (!strcmp(controller, "msi-interrupt-controller"))
......@@ -262,24 +263,25 @@ static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
static void __init ks_pcie_host_init(struct pcie_port *pp)
{
struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
u32 val;
ks_pcie_establish_link(ks_pcie);
ks_dw_pcie_setup_rc_app_regs(ks_pcie);
ks_pcie_setup_interrupts(ks_pcie);
writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
pp->dbi_base + PCI_IO_BASE);
pci->dbi_base + PCI_IO_BASE);
/* update the Vendor ID */
writew(ks_pcie->device_id, pp->dbi_base + PCI_DEVICE_ID);
writew(ks_pcie->device_id, pci->dbi_base + PCI_DEVICE_ID);
/* update the DEV_STAT_CTRL to publish right mrrs */
val = readl(pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
val = readl(pci->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
val &= ~PCI_EXP_DEVCTL_READRQ;
/* set the mrrs to 256 bytes */
val |= BIT(12);
writel(val, pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
writel(val, pci->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
/*
* PCIe access errors that result into OCP errors are caught by ARM as
......@@ -289,10 +291,9 @@ static void __init ks_pcie_host_init(struct pcie_port *pp)
"Asynchronous external abort");
}
static struct pcie_host_ops keystone_pcie_host_ops = {
static struct dw_pcie_host_ops keystone_pcie_host_ops = {
.rd_other_conf = ks_dw_pcie_rd_other_conf,
.wr_other_conf = ks_dw_pcie_wr_other_conf,
.link_up = ks_dw_pcie_link_up,
.host_init = ks_pcie_host_init,
.msi_set_irq = ks_dw_pcie_msi_set_irq,
.msi_clear_irq = ks_dw_pcie_msi_clear_irq,
......@@ -311,8 +312,9 @@ static irqreturn_t pcie_err_irq_handler(int irq, void *priv)
static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
struct platform_device *pdev)
{
struct pcie_port *pp = &ks_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = ks_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = &pdev->dev;
int ret;
ret = ks_pcie_get_irq_controller_info(ks_pcie,
......@@ -365,6 +367,10 @@ static const struct of_device_id ks_pcie_of_match[] = {
{ },
};
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = ks_dw_pcie_link_up,
};
static int __exit ks_pcie_remove(struct platform_device *pdev)
{
struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
......@@ -377,8 +383,8 @@ static int __exit ks_pcie_remove(struct platform_device *pdev)
static int __init ks_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct keystone_pcie *ks_pcie;
struct pcie_port *pp;
struct resource *res;
void __iomem *reg_p;
struct phy *phy;
......@@ -388,8 +394,12 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
if (!ks_pcie)
return -ENOMEM;
pp = &ks_pcie->pp;
pp->dev = dev;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
pci->ops = &dw_pcie_ops;
/* initialize SerDes Phy if present */
phy = devm_phy_get(dev, "pcie-phy");
......@@ -422,6 +432,8 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
if (ret)
return ret;
platform_set_drvdata(pdev, ks_pcie);
ret = ks_add_pcie_port(ks_pcie, pdev);
if (ret < 0)
goto fail_clk;
......
......@@ -17,7 +17,7 @@
#define MAX_LEGACY_HOST_IRQS 4
struct keystone_pcie {
struct pcie_port pp; /* pp.dbi_base is DT 0th res */
struct dw_pcie *pci;
struct clk *clk;
/* PCI Device ID */
u32 device_id;
......@@ -54,10 +54,10 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 *val);
void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie);
int ks_dw_pcie_link_up(struct pcie_port *pp);
void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie);
void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq);
void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq);
void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp);
int ks_dw_pcie_msi_host_init(struct pcie_port *pp,
struct msi_controller *chip);
int ks_dw_pcie_link_up(struct dw_pcie *pci);
......@@ -39,24 +39,26 @@ struct ls_pcie_drvdata {
u32 lut_offset;
u32 ltssm_shift;
u32 lut_dbg;
struct pcie_host_ops *ops;
struct dw_pcie_host_ops *ops;
const struct dw_pcie_ops *dw_pcie_ops;
};
struct ls_pcie {
struct pcie_port pp; /* pp.dbi_base is DT regs */
struct dw_pcie *pci;
void __iomem *lut;
struct regmap *scfg;
const struct ls_pcie_drvdata *drvdata;
int index;
};
#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
#define to_ls_pcie(x) dev_get_drvdata((x)->dev)
static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
{
struct dw_pcie *pci = pcie->pci;
u32 header_type;
header_type = ioread8(pcie->pp.dbi_base + PCI_HEADER_TYPE);
header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE);
header_type &= 0x7f;
return header_type == PCI_HEADER_TYPE_BRIDGE;
......@@ -65,29 +67,34 @@ static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
/* Clear multi-function bit */
static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
{
iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->pp.dbi_base + PCI_HEADER_TYPE);
struct dw_pcie *pci = pcie->pci;
iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE);
}
/* Fix class value */
static void ls_pcie_fix_class(struct ls_pcie *pcie)
{
iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->pp.dbi_base + PCI_CLASS_DEVICE);
struct dw_pcie *pci = pcie->pci;
iowrite16(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE);
}
/* Drop MSG TLP except for Vendor MSG */
static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
{
u32 val;
struct dw_pcie *pci = pcie->pci;
val = ioread32(pcie->pp.dbi_base + PCIE_STRFMR1);
val = ioread32(pci->dbi_base + PCIE_STRFMR1);
val &= 0xDFFFFFFF;
iowrite32(val, pcie->pp.dbi_base + PCIE_STRFMR1);
iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
}
static int ls1021_pcie_link_up(struct pcie_port *pp)
static int ls1021_pcie_link_up(struct dw_pcie *pci)
{
u32 state;
struct ls_pcie *pcie = to_ls_pcie(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
if (!pcie->scfg)
return 0;
......@@ -103,8 +110,9 @@ static int ls1021_pcie_link_up(struct pcie_port *pp)
static void ls1021_pcie_host_init(struct pcie_port *pp)
{
struct device *dev = pp->dev;
struct ls_pcie *pcie = to_ls_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
struct device *dev = pci->dev;
u32 index[2];
pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
......@@ -127,9 +135,9 @@ static void ls1021_pcie_host_init(struct pcie_port *pp)
ls_pcie_drop_msg_tlp(pcie);
}
static int ls_pcie_link_up(struct pcie_port *pp)
static int ls_pcie_link_up(struct dw_pcie *pci)
{
struct ls_pcie *pcie = to_ls_pcie(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
u32 state;
state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
......@@ -144,19 +152,21 @@ static int ls_pcie_link_up(struct pcie_port *pp)
static void ls_pcie_host_init(struct pcie_port *pp)
{
struct ls_pcie *pcie = to_ls_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct ls_pcie *pcie = to_ls_pcie(pci);
iowrite32(1, pcie->pp.dbi_base + PCIE_DBI_RO_WR_EN);
iowrite32(1, pci->dbi_base + PCIE_DBI_RO_WR_EN);
ls_pcie_fix_class(pcie);
ls_pcie_clear_multifunction(pcie);
ls_pcie_drop_msg_tlp(pcie);
iowrite32(0, pcie->pp.dbi_base + PCIE_DBI_RO_WR_EN);
iowrite32(0, pci->dbi_base + PCIE_DBI_RO_WR_EN);
}
static int ls_pcie_msi_host_init(struct pcie_port *pp,
struct msi_controller *chip)
{
struct device *dev = pp->dev;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct device *dev = pci->dev;
struct device_node *np = dev->of_node;
struct device_node *msi_node;
......@@ -175,20 +185,27 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp,
return 0;
}
static struct pcie_host_ops ls1021_pcie_host_ops = {
.link_up = ls1021_pcie_link_up,
static struct dw_pcie_host_ops ls1021_pcie_host_ops = {
.host_init = ls1021_pcie_host_init,
.msi_host_init = ls_pcie_msi_host_init,
};
static struct pcie_host_ops ls_pcie_host_ops = {
.link_up = ls_pcie_link_up,
static struct dw_pcie_host_ops ls_pcie_host_ops = {
.host_init = ls_pcie_host_init,
.msi_host_init = ls_pcie_msi_host_init,
};
static const struct dw_pcie_ops dw_ls1021_pcie_ops = {
.link_up = ls1021_pcie_link_up,
};
static const struct dw_pcie_ops dw_ls_pcie_ops = {
.link_up = ls_pcie_link_up,
};
static struct ls_pcie_drvdata ls1021_drvdata = {
.ops = &ls1021_pcie_host_ops,
.dw_pcie_ops = &dw_ls1021_pcie_ops,
};
static struct ls_pcie_drvdata ls1043_drvdata = {
......@@ -196,6 +213,7 @@ static struct ls_pcie_drvdata ls1043_drvdata = {
.ltssm_shift = 24,
.lut_dbg = 0x7fc,
.ops = &ls_pcie_host_ops,
.dw_pcie_ops = &dw_ls_pcie_ops,
};
static struct ls_pcie_drvdata ls1046_drvdata = {
......@@ -203,6 +221,7 @@ static struct ls_pcie_drvdata ls1046_drvdata = {
.ltssm_shift = 24,
.lut_dbg = 0x407fc,
.ops = &ls_pcie_host_ops,
.dw_pcie_ops = &dw_ls_pcie_ops,
};
static struct ls_pcie_drvdata ls2080_drvdata = {
......@@ -210,6 +229,7 @@ static struct ls_pcie_drvdata ls2080_drvdata = {
.ltssm_shift = 0,
.lut_dbg = 0x7fc,
.ops = &ls_pcie_host_ops,
.dw_pcie_ops = &dw_ls_pcie_ops,
};
static const struct of_device_id ls_pcie_of_match[] = {
......@@ -223,10 +243,13 @@ static const struct of_device_id ls_pcie_of_match[] = {
static int __init ls_add_pcie_port(struct ls_pcie *pcie)
{
struct pcie_port *pp = &pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
int ret;
pp->ops = pcie->drvdata->ops;
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(dev, "failed to initialize host\n");
......@@ -240,8 +263,8 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *match;
struct dw_pcie *pci;
struct ls_pcie *pcie;
struct pcie_port *pp;
struct resource *dbi_base;
int ret;
......@@ -253,21 +276,27 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
if (!pcie)
return -ENOMEM;
pp = &pcie->pp;
pp->dev = dev;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pcie->drvdata = match->data;
pp->ops = pcie->drvdata->ops;
pci->dev = dev;
pci->ops = pcie->drvdata->dw_pcie_ops;
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
pcie->pp.dbi_base = devm_ioremap_resource(dev, dbi_base);
if (IS_ERR(pcie->pp.dbi_base))
return PTR_ERR(pcie->pp.dbi_base);
pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset;
pcie->lut = pci->dbi_base + pcie->drvdata->lut_offset;
if (!ls_pcie_is_bridge(pcie))
return -ENODEV;
platform_set_drvdata(pdev, pcie);
ret = ls_add_pcie_port(pcie);
if (ret < 0)
return ret;
......
......@@ -29,7 +29,7 @@
#include "pcie-designware.h"
struct armada8k_pcie {
struct pcie_port pp; /* pp.dbi_base is DT ctrl */
struct dw_pcie *pci;
struct clk *clk;
};
......@@ -67,76 +67,77 @@ struct armada8k_pcie {
#define AX_USER_DOMAIN_MASK 0x3
#define AX_USER_DOMAIN_SHIFT 4
#define to_armada8k_pcie(x) container_of(x, struct armada8k_pcie, pp)
#define to_armada8k_pcie(x) dev_get_drvdata((x)->dev)
static int armada8k_pcie_link_up(struct pcie_port *pp)
static int armada8k_pcie_link_up(struct dw_pcie *pci)
{
u32 reg;
u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP;
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_STATUS_REG);
reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_STATUS_REG);
if ((reg & mask) == mask)
return 1;
dev_dbg(pp->dev, "No link detected (Global-Status: 0x%08x).\n", reg);
dev_dbg(pci->dev, "No link detected (Global-Status: 0x%08x).\n", reg);
return 0;
}
static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
{
struct pcie_port *pp = &pcie->pp;
struct dw_pcie *pci = pcie->pci;
u32 reg;
if (!dw_pcie_link_up(pp)) {
if (!dw_pcie_link_up(pci)) {
/* Disable LTSSM state machine to enable configuration */
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
reg &= ~(PCIE_APP_LTSSM_EN);
dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
}
/* Set the device to root complex mode */
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
reg &= ~(PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_SHIFT);
reg |= PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_SHIFT;
dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
/* Set the PCIe master AxCache attributes */
dw_pcie_writel_rc(pp, PCIE_ARCACHE_TRC_REG, ARCACHE_DEFAULT_VALUE);
dw_pcie_writel_rc(pp, PCIE_AWCACHE_TRC_REG, AWCACHE_DEFAULT_VALUE);
dw_pcie_writel_dbi(pci, PCIE_ARCACHE_TRC_REG, ARCACHE_DEFAULT_VALUE);
dw_pcie_writel_dbi(pci, PCIE_AWCACHE_TRC_REG, AWCACHE_DEFAULT_VALUE);
/* Set the PCIe master AxDomain attributes */
reg = dw_pcie_readl_rc(pp, PCIE_ARUSER_REG);
reg = dw_pcie_readl_dbi(pci, PCIE_ARUSER_REG);
reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT);
reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT;
dw_pcie_writel_rc(pp, PCIE_ARUSER_REG, reg);
dw_pcie_writel_dbi(pci, PCIE_ARUSER_REG, reg);
reg = dw_pcie_readl_rc(pp, PCIE_AWUSER_REG);
reg = dw_pcie_readl_dbi(pci, PCIE_AWUSER_REG);
reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT);
reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT;
dw_pcie_writel_rc(pp, PCIE_AWUSER_REG, reg);
dw_pcie_writel_dbi(pci, PCIE_AWUSER_REG, reg);
/* Enable INT A-D interrupts */
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_INT_MASK1_REG);
reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG);
reg |= PCIE_INT_A_ASSERT_MASK | PCIE_INT_B_ASSERT_MASK |
PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK;
dw_pcie_writel_rc(pp, PCIE_GLOBAL_INT_MASK1_REG, reg);
dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG, reg);
if (!dw_pcie_link_up(pp)) {
if (!dw_pcie_link_up(pci)) {
/* Configuration done. Start LTSSM */
reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG);
reg |= PCIE_APP_LTSSM_EN;
dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg);
}
/* Wait until the link becomes active again */
if (dw_pcie_wait_for_link(pp))
dev_err(pp->dev, "Link not up after reconfiguration\n");
if (dw_pcie_wait_for_link(pci))
dev_err(pci->dev, "Link not up after reconfiguration\n");
}
static void armada8k_pcie_host_init(struct pcie_port *pp)
{
struct armada8k_pcie *pcie = to_armada8k_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
dw_pcie_setup_rc(pp);
armada8k_pcie_establish_link(pcie);
......@@ -145,7 +146,7 @@ static void armada8k_pcie_host_init(struct pcie_port *pp)
static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
{
struct armada8k_pcie *pcie = arg;
struct pcie_port *pp = &pcie->pp;
struct dw_pcie *pci = pcie->pci;
u32 val;
/*
......@@ -153,21 +154,21 @@ static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
* PCI device. However, they are also latched into the PCIe
* controller, so we simply discard them.
*/
val = dw_pcie_readl_rc(pp, PCIE_GLOBAL_INT_CAUSE1_REG);
dw_pcie_writel_rc(pp, PCIE_GLOBAL_INT_CAUSE1_REG, val);
val = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG);
dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG, val);
return IRQ_HANDLED;
}
static struct pcie_host_ops armada8k_pcie_host_ops = {
.link_up = armada8k_pcie_link_up,
static struct dw_pcie_host_ops armada8k_pcie_host_ops = {
.host_init = armada8k_pcie_host_init,
};
static int armada8k_add_pcie_port(struct armada8k_pcie *pcie,
struct platform_device *pdev)
{
struct pcie_port *pp = &pcie->pp;
struct dw_pcie *pci = pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = &pdev->dev;
int ret;
......@@ -196,10 +197,14 @@ static int armada8k_add_pcie_port(struct armada8k_pcie *pcie,
return 0;
}
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = armada8k_pcie_link_up,
};
static int armada8k_pcie_probe(struct platform_device *pdev)
{
struct dw_pcie *pci;
struct armada8k_pcie *pcie;
struct pcie_port *pp;
struct device *dev = &pdev->dev;
struct resource *base;
int ret;
......@@ -208,24 +213,30 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
if (!pcie)
return -ENOMEM;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
pci->ops = &dw_pcie_ops;
pcie->clk = devm_clk_get(dev, NULL);
if (IS_ERR(pcie->clk))
return PTR_ERR(pcie->clk);
clk_prepare_enable(pcie->clk);
pp = &pcie->pp;
pp->dev = dev;
/* Get the dw-pcie unit configuration/control registers base. */
base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
pp->dbi_base = devm_ioremap_resource(dev, base);
if (IS_ERR(pp->dbi_base)) {
pci->dbi_base = devm_ioremap_resource(dev, base);
if (IS_ERR(pci->dbi_base)) {
dev_err(dev, "couldn't remap regs base %p\n", base);
ret = PTR_ERR(pp->dbi_base);
ret = PTR_ERR(pci->dbi_base);
goto fail;
}
platform_set_drvdata(pdev, pcie);
ret = armada8k_add_pcie_port(pcie, pdev);
if (ret)
goto fail;
......
......@@ -24,10 +24,10 @@
#include "pcie-designware.h"
#define to_artpec6_pcie(x) container_of(x, struct artpec6_pcie, pp)
#define to_artpec6_pcie(x) dev_get_drvdata((x)->dev)
struct artpec6_pcie {
struct pcie_port pp; /* pp.dbi_base is DT dbi */
struct dw_pcie *pci;
struct regmap *regmap; /* DT axis,syscon-pcie */
void __iomem *phy_base; /* DT phy */
};
......@@ -80,7 +80,8 @@ static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u
static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
{
struct pcie_port *pp = &artpec6_pcie->pp;
struct dw_pcie *pci = artpec6_pcie->pci;
struct pcie_port *pp = &pci->pp;
u32 val;
unsigned int retries;
......@@ -139,7 +140,7 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
* Enable writing to config regs. This is required as the Synopsys
* driver changes the class code. That register needs DBI write enable.
*/
dw_pcie_writel_rc(pp, MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
dw_pcie_writel_dbi(pci, MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
pp->io_base &= ARTPEC6_CPU_TO_BUS_ADDR;
pp->mem_base &= ARTPEC6_CPU_TO_BUS_ADDR;
......@@ -155,19 +156,20 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
/* check if the link is up or not */
if (!dw_pcie_wait_for_link(pp))
if (!dw_pcie_wait_for_link(pci))
return 0;
dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
dev_dbg(pci->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
return -ETIMEDOUT;
}
static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie)
{
struct pcie_port *pp = &artpec6_pcie->pp;
struct dw_pcie *pci = artpec6_pcie->pci;
struct pcie_port *pp = &pci->pp;
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
......@@ -175,20 +177,22 @@ static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie)
static void artpec6_pcie_host_init(struct pcie_port *pp)
{
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci);
artpec6_pcie_establish_link(artpec6_pcie);
artpec6_pcie_enable_interrupts(artpec6_pcie);
}
static struct pcie_host_ops artpec6_pcie_host_ops = {
static struct dw_pcie_host_ops artpec6_pcie_host_ops = {
.host_init = artpec6_pcie_host_init,
};
static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg)
{
struct artpec6_pcie *artpec6_pcie = arg;
struct pcie_port *pp = &artpec6_pcie->pp;
struct dw_pcie *pci = artpec6_pcie->pci;
struct pcie_port *pp = &pci->pp;
return dw_handle_msi_irq(pp);
}
......@@ -196,8 +200,9 @@ static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg)
static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
struct platform_device *pdev)
{
struct pcie_port *pp = &artpec6_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = artpec6_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = pci->dev;
int ret;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
......@@ -232,8 +237,8 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
static int artpec6_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct artpec6_pcie *artpec6_pcie;
struct pcie_port *pp;
struct resource *dbi_base;
struct resource *phy_base;
int ret;
......@@ -242,13 +247,16 @@ static int artpec6_pcie_probe(struct platform_device *pdev)
if (!artpec6_pcie)
return -ENOMEM;
pp = &artpec6_pcie->pp;
pp->dev = dev;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
if (IS_ERR(pp->dbi_base))
return PTR_ERR(pp->dbi_base);
pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
phy_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
artpec6_pcie->phy_base = devm_ioremap_resource(dev, phy_base);
......@@ -261,6 +269,8 @@ static int artpec6_pcie_probe(struct platform_device *pdev)
if (IS_ERR(artpec6_pcie->regmap))
return PTR_ERR(artpec6_pcie->regmap);
platform_set_drvdata(pdev, artpec6_pcie);
ret = artpec6_add_pcie_port(artpec6_pcie, pdev);
if (ret < 0)
return ret;
......
......@@ -25,7 +25,7 @@
#include "pcie-designware.h"
struct dw_plat_pcie {
struct pcie_port pp; /* pp.dbi_base is DT 0th resource */
struct dw_pcie *pci;
};
static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
......@@ -37,21 +37,23 @@ static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
static void dw_plat_pcie_host_init(struct pcie_port *pp)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
dw_pcie_setup_rc(pp);
dw_pcie_wait_for_link(pp);
dw_pcie_wait_for_link(pci);
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
}
static struct pcie_host_ops dw_plat_pcie_host_ops = {
static struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
.host_init = dw_plat_pcie_host_init,
};
static int dw_plat_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev)
{
struct device *dev = pp->dev;
struct device *dev = &pdev->dev;
int ret;
pp->irq = platform_get_irq(pdev, 1);
......@@ -88,7 +90,7 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_plat_pcie *dw_plat_pcie;
struct pcie_port *pp;
struct dw_pcie *pci;
struct resource *res; /* Resource from DT */
int ret;
......@@ -96,15 +98,20 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
if (!dw_plat_pcie)
return -ENOMEM;
pp = &dw_plat_pcie->pp;
pp->dev = dev;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pp->dbi_base = devm_ioremap_resource(dev, res);
if (IS_ERR(pp->dbi_base))
return PTR_ERR(pp->dbi_base);
pci->dbi_base = devm_ioremap_resource(dev, res);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
platform_set_drvdata(pdev, dw_plat_pcie);
ret = dw_plat_add_pcie_port(pp, pdev);
ret = dw_plat_add_pcie_port(&pci->pp, pdev);
if (ret < 0)
return ret;
......
/*
* Synopsys Designware PCIe host controller driver
*
* Copyright (C) 2013 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Author: Jingoo Han <jg1.han@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/types.h>
#include "pcie-designware.h"
/* PCIe Port Logic registers */
#define PLR_OFFSET 0x700
#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4)
#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
int dw_pcie_read(void __iomem *addr, int size, u32 *val)
{
if ((uintptr_t)addr & (size - 1)) {
*val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
}
if (size == 4) {
*val = readl(addr);
} else if (size == 2) {
*val = readw(addr);
} else if (size == 1) {
*val = readb(addr);
} else {
*val = 0;
return PCIBIOS_BAD_REGISTER_NUMBER;
}
return PCIBIOS_SUCCESSFUL;
}
int dw_pcie_write(void __iomem *addr, int size, u32 val)
{
if ((uintptr_t)addr & (size - 1))
return PCIBIOS_BAD_REGISTER_NUMBER;
if (size == 4)
writel(val, addr);
else if (size == 2)
writew(val, addr);
else if (size == 1)
writeb(val, addr);
else
return PCIBIOS_BAD_REGISTER_NUMBER;
return PCIBIOS_SUCCESSFUL;
}
u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
{
if (pci->ops->readl_dbi)
return pci->ops->readl_dbi(pci, reg);
return readl(pci->dbi_base + reg);
}
void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
{
if (pci->ops->writel_dbi)
pci->ops->writel_dbi(pci, reg, val);
else
writel(val, pci->dbi_base + reg);
}
static u32 dw_pcie_readl_unroll(struct dw_pcie *pci, u32 index, u32 reg)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
return dw_pcie_readl_dbi(pci, offset + reg);
}
static void dw_pcie_writel_unroll(struct dw_pcie *pci, u32 index, u32 reg,
u32 val)
{
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
dw_pcie_writel_dbi(pci, offset + reg, val);
}
void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
u64 cpu_addr, u64 pci_addr, u32 size)
{
u32 retries, val;
if (pci->iatu_unroll_enabled) {
dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
lower_32_bits(cpu_addr));
dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
upper_32_bits(cpu_addr));
dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
lower_32_bits(cpu_addr + size - 1));
dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
lower_32_bits(pci_addr));
dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
upper_32_bits(pci_addr));
dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
type);
dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
PCIE_ATU_ENABLE);
} else {
dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
PCIE_ATU_REGION_OUTBOUND | index);
dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE,
lower_32_bits(cpu_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE,
upper_32_bits(cpu_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT,
lower_32_bits(cpu_addr + size - 1));
dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET,
lower_32_bits(pci_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
upper_32_bits(pci_addr));
dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
}
/*
* Make sure ATU enable takes effect before any subsequent config
* and I/O accesses.
*/
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
if (pci->iatu_unroll_enabled)
val = dw_pcie_readl_unroll(pci, index,
PCIE_ATU_UNR_REGION_CTRL2);
else
val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
if (val == PCIE_ATU_ENABLE)
return;
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
}
dev_err(pci->dev, "iATU is not being enabled\n");
}
int dw_pcie_wait_for_link(struct dw_pcie *pci)
{
int retries;
/* check if the link is up or not */
for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
if (dw_pcie_link_up(pci)) {
dev_info(pci->dev, "link up\n");
return 0;
}
usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
}
dev_err(pci->dev, "phy link never came up\n");
return -ETIMEDOUT;
}
int dw_pcie_link_up(struct dw_pcie *pci)
{
u32 val;
if (pci->ops->link_up)
return pci->ops->link_up(pci);
val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1);
return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) &&
(!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)));
}
void dw_pcie_setup(struct dw_pcie *pci)
{
int ret;
u32 val;
u32 lanes;
struct device *dev = pci->dev;
struct device_node *np = dev->of_node;
ret = of_property_read_u32(np, "num-lanes", &lanes);
if (ret)
lanes = 0;
/* set the number of lanes */
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
val &= ~PORT_LINK_MODE_MASK;
switch (lanes) {
case 1:
val |= PORT_LINK_MODE_1_LANES;
break;
case 2:
val |= PORT_LINK_MODE_2_LANES;
break;
case 4:
val |= PORT_LINK_MODE_4_LANES;
break;
case 8:
val |= PORT_LINK_MODE_8_LANES;
break;
default:
dev_err(pci->dev, "num-lanes %u: invalid value\n", lanes);
return;
}
dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
/* set link width speed control register */
val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
switch (lanes) {
case 1:
val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
break;
case 2:
val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
break;
case 4:
val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
break;
case 8:
val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
break;
}
dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
}
......@@ -14,6 +14,81 @@
#ifndef _PCIE_DESIGNWARE_H
#define _PCIE_DESIGNWARE_H
#include <linux/irq.h>
#include <linux/msi.h>
#include <linux/pci.h>
/* Parameters for the waiting for link up routine */
#define LINK_WAIT_MAX_RETRIES 10
#define LINK_WAIT_USLEEP_MIN 90000
#define LINK_WAIT_USLEEP_MAX 100000
/* Parameters for the waiting for iATU enabled routine */
#define LINK_WAIT_MAX_IATU_RETRIES 5
#define LINK_WAIT_IATU_MIN 9000
#define LINK_WAIT_IATU_MAX 10000
/* Synopsys-specific PCIe configuration registers */
#define PCIE_PORT_LINK_CONTROL 0x710
#define PORT_LINK_MODE_MASK (0x3f << 16)
#define PORT_LINK_MODE_1_LANES (0x1 << 16)
#define PORT_LINK_MODE_2_LANES (0x3 << 16)
#define PORT_LINK_MODE_4_LANES (0x7 << 16)
#define PORT_LINK_MODE_8_LANES (0xf << 16)
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8)
#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8)
#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8)
#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8)
#define PORT_LOGIC_LINK_WIDTH_8_LANES (0x8 << 8)
#define PCIE_MSI_ADDR_LO 0x820
#define PCIE_MSI_ADDR_HI 0x824
#define PCIE_MSI_INTR0_ENABLE 0x828
#define PCIE_MSI_INTR0_MASK 0x82C
#define PCIE_MSI_INTR0_STATUS 0x830
#define PCIE_ATU_VIEWPORT 0x900
#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
#define PCIE_ATU_REGION_INDEX2 (0x2 << 0)
#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
#define PCIE_ATU_CR1 0x904
#define PCIE_ATU_TYPE_MEM (0x0 << 0)
#define PCIE_ATU_TYPE_IO (0x2 << 0)
#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
#define PCIE_ATU_CR2 0x908
#define PCIE_ATU_ENABLE (0x1 << 31)
#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
#define PCIE_ATU_LOWER_BASE 0x90C
#define PCIE_ATU_UPPER_BASE 0x910
#define PCIE_ATU_LIMIT 0x914
#define PCIE_ATU_LOWER_TARGET 0x918
#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
/*
* iATU Unroll-specific register definitions
* From 4.80 core version the address translation will be made by unroll
*/
#define PCIE_ATU_UNR_REGION_CTRL1 0x00
#define PCIE_ATU_UNR_REGION_CTRL2 0x04
#define PCIE_ATU_UNR_LOWER_BASE 0x08
#define PCIE_ATU_UNR_UPPER_BASE 0x0C
#define PCIE_ATU_UNR_LIMIT 0x10
#define PCIE_ATU_UNR_LOWER_TARGET 0x14
#define PCIE_ATU_UNR_UPPER_TARGET 0x18
/* Register address builder */
#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \
((0x3 << 20) | ((region) << 9))
/*
* Maximum number of MSI IRQs can be 256 per controller. But keep
* it 32 as of now. Probably we will never need more than 32. If needed,
......@@ -22,10 +97,27 @@
#define MAX_MSI_IRQS 32
#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32)
struct pcie_port;
struct dw_pcie;
struct dw_pcie_host_ops {
int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val);
int (*rd_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 *val);
int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val);
void (*host_init)(struct pcie_port *pp);
void (*msi_set_irq)(struct pcie_port *pp, int irq);
void (*msi_clear_irq)(struct pcie_port *pp, int irq);
phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
u32 (*get_msi_data)(struct pcie_port *pp, int pos);
void (*scan_bus)(struct pcie_port *pp);
int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip);
};
struct pcie_port {
struct device *dev;
u8 root_bus_nr;
void __iomem *dbi_base;
u64 cfg0_base;
void __iomem *va_cfg0_base;
u32 cfg0_size;
......@@ -43,44 +135,64 @@ struct pcie_port {
struct resource *mem;
struct resource *busn;
int irq;
u32 lanes;
u32 num_viewport;
struct pcie_host_ops *ops;
struct dw_pcie_host_ops *ops;
int msi_irq;
struct irq_domain *irq_domain;
unsigned long msi_data;
u8 iatu_unroll_enabled;
DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
};
struct pcie_host_ops {
u32 (*readl_rc)(struct pcie_port *pp, u32 reg);
void (*writel_rc)(struct pcie_port *pp, u32 reg, u32 val);
int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val);
int (*rd_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 *val);
int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
unsigned int devfn, int where, int size, u32 val);
int (*link_up)(struct pcie_port *pp);
void (*host_init)(struct pcie_port *pp);
void (*msi_set_irq)(struct pcie_port *pp, int irq);
void (*msi_clear_irq)(struct pcie_port *pp, int irq);
phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
u32 (*get_msi_data)(struct pcie_port *pp, int pos);
void (*scan_bus)(struct pcie_port *pp);
int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip);
struct dw_pcie_ops {
u32 (*readl_dbi)(struct dw_pcie *pcie, u32 reg);
void (*writel_dbi)(struct dw_pcie *pcie, u32 reg, u32 val);
int (*link_up)(struct dw_pcie *pcie);
};
struct dw_pcie {
struct device *dev;
void __iomem *dbi_base;
u32 num_viewport;
u8 iatu_unroll_enabled;
struct pcie_port pp;
const struct dw_pcie_ops *ops;
};
u32 dw_pcie_readl_rc(struct pcie_port *pp, u32 reg);
void dw_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val);
int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val);
int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val);
#define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
int dw_pcie_read(void __iomem *addr, int size, u32 *val);
int dw_pcie_write(void __iomem *addr, int size, u32 val);
u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg);
void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val);
int dw_pcie_link_up(struct dw_pcie *pci);
int dw_pcie_wait_for_link(struct dw_pcie *pci);
void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
int type, u64 cpu_addr, u64 pci_addr,
u32 size);
void dw_pcie_setup(struct dw_pcie *pci);
#ifdef CONFIG_PCIE_DW_HOST
irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
void dw_pcie_msi_init(struct pcie_port *pp);
int dw_pcie_wait_for_link(struct pcie_port *pp);
int dw_pcie_link_up(struct pcie_port *pp);
void dw_pcie_setup_rc(struct pcie_port *pp);
int dw_pcie_host_init(struct pcie_port *pp);
#else
static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
{
return IRQ_NONE;
}
static inline void dw_pcie_msi_init(struct pcie_port *pp)
{
}
static inline void dw_pcie_setup_rc(struct pcie_port *pp)
{
}
static inline int dw_pcie_host_init(struct pcie_port *pp)
{
return 0;
}
#endif
#endif /* _PCIE_DESIGNWARE_H */
......@@ -127,7 +127,7 @@ struct pci_ecam_ops hisi_pcie_ops = {
#define PCIE_LTSSM_LINKUP_STATE 0x11
#define PCIE_LTSSM_STATE_MASK 0x3F
#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
#define to_hisi_pcie(x) dev_get_drvdata((x)->dev)
struct hisi_pcie;
......@@ -136,7 +136,7 @@ struct pcie_soc_ops {
};
struct hisi_pcie {
struct pcie_port pp; /* pp.dbi_base is DT rc_dbi */
struct dw_pcie *pci;
struct regmap *subctrl;
u32 port_id;
struct pcie_soc_ops *soc_ops;
......@@ -149,10 +149,11 @@ static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
u32 reg;
u32 reg_val;
void *walker = &reg_val;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
walker += (where & 0x3);
reg = where & ~0x3;
reg_val = dw_pcie_readl_rc(pp, reg);
reg_val = dw_pcie_readl_dbi(pci, reg);
if (size == 1)
*val = *(u8 __force *) walker;
......@@ -173,19 +174,20 @@ static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
u32 reg_val;
u32 reg;
void *walker = &reg_val;
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
walker += (where & 0x3);
reg = where & ~0x3;
if (size == 4)
dw_pcie_writel_rc(pp, reg, val);
dw_pcie_writel_dbi(pci, reg, val);
else if (size == 2) {
reg_val = dw_pcie_readl_rc(pp, reg);
reg_val = dw_pcie_readl_dbi(pci, reg);
*(u16 __force *) walker = val;
dw_pcie_writel_rc(pp, reg, reg_val);
dw_pcie_writel_dbi(pci, reg, reg_val);
} else if (size == 1) {
reg_val = dw_pcie_readl_rc(pp, reg);
reg_val = dw_pcie_readl_dbi(pci, reg);
*(u8 __force *) walker = val;
dw_pcie_writel_rc(pp, reg, reg_val);
dw_pcie_writel_dbi(pci, reg, reg_val);
} else
return PCIBIOS_BAD_REGISTER_NUMBER;
......@@ -204,32 +206,32 @@ static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie)
static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie)
{
struct pcie_port *pp = &hisi_pcie->pp;
struct dw_pcie *pci = hisi_pcie->pci;
u32 val;
val = dw_pcie_readl_rc(pp, PCIE_SYS_STATE4);
val = dw_pcie_readl_dbi(pci, PCIE_SYS_STATE4);
return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
}
static int hisi_pcie_link_up(struct pcie_port *pp)
static int hisi_pcie_link_up(struct dw_pcie *pci)
{
struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
struct hisi_pcie *hisi_pcie = to_hisi_pcie(pci);
return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie);
}
static struct pcie_host_ops hisi_pcie_host_ops = {
static struct dw_pcie_host_ops hisi_pcie_host_ops = {
.rd_own_conf = hisi_pcie_cfg_read,
.wr_own_conf = hisi_pcie_cfg_write,
.link_up = hisi_pcie_link_up,
};
static int hisi_add_pcie_port(struct hisi_pcie *hisi_pcie,
struct platform_device *pdev)
{
struct pcie_port *pp = &hisi_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = hisi_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = &pdev->dev;
int ret;
u32 port_id;
......@@ -254,11 +256,15 @@ static int hisi_add_pcie_port(struct hisi_pcie *hisi_pcie,
return 0;
}
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = hisi_pcie_link_up,
};
static int hisi_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct hisi_pcie *hisi_pcie;
struct pcie_port *pp;
const struct of_device_id *match;
struct resource *reg;
struct device_driver *driver;
......@@ -268,8 +274,13 @@ static int hisi_pcie_probe(struct platform_device *pdev)
if (!hisi_pcie)
return -ENOMEM;
pp = &hisi_pcie->pp;
pp->dev = dev;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
pci->ops = &dw_pcie_ops;
driver = dev->driver;
match = of_match_device(driver->of_match_table, dev);
......@@ -283,9 +294,11 @@ static int hisi_pcie_probe(struct platform_device *pdev)
}
reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
pp->dbi_base = devm_ioremap_resource(dev, reg);
if (IS_ERR(pp->dbi_base))
return PTR_ERR(pp->dbi_base);
pci->dbi_base = devm_ioremap_resource(dev, reg);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
platform_set_drvdata(pdev, hisi_pcie);
ret = hisi_add_pcie_port(hisi_pcie, pdev);
if (ret)
......
......@@ -103,7 +103,7 @@ struct qcom_pcie_ops {
};
struct qcom_pcie {
struct pcie_port pp; /* pp.dbi_base is DT dbi */
struct dw_pcie *pci;
void __iomem *parf; /* DT parf */
void __iomem *elbi; /* DT elbi */
union qcom_pcie_resources res;
......@@ -112,7 +112,7 @@ struct qcom_pcie {
struct qcom_pcie_ops *ops;
};
#define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp)
#define to_qcom_pcie(x) dev_get_drvdata((x)->dev)
static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
{
......@@ -155,21 +155,23 @@ static void qcom_pcie_v2_ltssm_enable(struct qcom_pcie *pcie)
static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
{
struct dw_pcie *pci = pcie->pci;
if (dw_pcie_link_up(&pcie->pp))
if (dw_pcie_link_up(pci))
return 0;
/* Enable Link Training state machine */
if (pcie->ops->ltssm_enable)
pcie->ops->ltssm_enable(pcie);
return dw_pcie_wait_for_link(&pcie->pp);
return dw_pcie_wait_for_link(pci);
}
static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
struct device *dev = pcie->pp.dev;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
res->vdda = devm_regulator_get(dev, "vdda");
if (IS_ERR(res->vdda))
......@@ -212,16 +214,14 @@ static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
return PTR_ERR(res->por_reset);
res->phy_reset = devm_reset_control_get(dev, "phy");
if (IS_ERR(res->phy_reset))
return PTR_ERR(res->phy_reset);
return 0;
return PTR_ERR_OR_ZERO(res->phy_reset);
}
static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
struct device *dev = pcie->pp.dev;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
res->vdda = devm_regulator_get(dev, "vdda");
if (IS_ERR(res->vdda))
......@@ -244,10 +244,7 @@ static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
return PTR_ERR(res->slave_bus);
res->core = devm_reset_control_get(dev, "core");
if (IS_ERR(res->core))
return PTR_ERR(res->core);
return 0;
return PTR_ERR_OR_ZERO(res->core);
}
static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie)
......@@ -270,7 +267,8 @@ static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie)
static int qcom_pcie_init_v0(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
struct device *dev = pcie->pp.dev;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
u32 val;
int ret;
......@@ -392,7 +390,8 @@ static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie)
static int qcom_pcie_init_v1(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
struct device *dev = pcie->pp.dev;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
int ret;
ret = reset_control_deassert(res->core);
......@@ -459,7 +458,8 @@ static int qcom_pcie_init_v1(struct qcom_pcie *pcie)
static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
struct device *dev = pcie->pp.dev;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
res->aux_clk = devm_clk_get(dev, "aux");
if (IS_ERR(res->aux_clk))
......@@ -478,16 +478,14 @@ static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie)
return PTR_ERR(res->slave_clk);
res->pipe_clk = devm_clk_get(dev, "pipe");
if (IS_ERR(res->pipe_clk))
return PTR_ERR(res->pipe_clk);
return 0;
return PTR_ERR_OR_ZERO(res->pipe_clk);
}
static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
struct device *dev = pcie->pp.dev;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
u32 val;
int ret;
......@@ -551,7 +549,8 @@ static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
static int qcom_pcie_post_init_v2(struct qcom_pcie *pcie)
{
struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
struct device *dev = pcie->pp.dev;
struct dw_pcie *pci = pcie->pci;
struct device *dev = pci->dev;
int ret;
ret = clk_prepare_enable(res->pipe_clk);
......@@ -563,10 +562,9 @@ static int qcom_pcie_post_init_v2(struct qcom_pcie *pcie)
return 0;
}
static int qcom_pcie_link_up(struct pcie_port *pp)
static int qcom_pcie_link_up(struct dw_pcie *pci)
{
struct qcom_pcie *pcie = to_qcom_pcie(pp);
u16 val = readw(pcie->pp.dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA);
u16 val = readw(pci->dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA);
return !!(val & PCI_EXP_LNKSTA_DLLLA);
}
......@@ -584,7 +582,8 @@ static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
static void qcom_pcie_host_init(struct pcie_port *pp)
{
struct qcom_pcie *pcie = to_qcom_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct qcom_pcie *pcie = to_qcom_pcie(pci);
int ret;
qcom_ep_reset_assert(pcie);
......@@ -622,19 +621,20 @@ static void qcom_pcie_host_init(struct pcie_port *pp)
static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
u32 *val)
{
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
/* the device class is not reported correctly from the register */
if (where == PCI_CLASS_REVISION && size == 4) {
*val = readl(pp->dbi_base + PCI_CLASS_REVISION);
*val = readl(pci->dbi_base + PCI_CLASS_REVISION);
*val &= 0xff; /* keep revision id */
*val |= PCI_CLASS_BRIDGE_PCI << 16;
return PCIBIOS_SUCCESSFUL;
}
return dw_pcie_cfg_read(pp->dbi_base + where, size, val);
return dw_pcie_read(pci->dbi_base + where, size, val);
}
static struct pcie_host_ops qcom_pcie_dw_ops = {
.link_up = qcom_pcie_link_up,
static struct dw_pcie_host_ops qcom_pcie_dw_ops = {
.host_init = qcom_pcie_host_init,
.rd_own_conf = qcom_pcie_rd_own_conf,
};
......@@ -661,19 +661,31 @@ static const struct qcom_pcie_ops ops_v2 = {
.ltssm_enable = qcom_pcie_v2_ltssm_enable,
};
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = qcom_pcie_link_up,
};
static int qcom_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
struct qcom_pcie *pcie;
struct pcie_port *pp;
struct dw_pcie *pci;
struct qcom_pcie *pcie;
int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
return -ENOMEM;
pp = &pcie->pp;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
pci->ops = &dw_pcie_ops;
pp = &pci->pp;
pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev);
pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW);
......@@ -686,9 +698,9 @@ static int qcom_pcie_probe(struct platform_device *pdev)
return PTR_ERR(pcie->parf);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
pp->dbi_base = devm_ioremap_resource(dev, res);
if (IS_ERR(pp->dbi_base))
return PTR_ERR(pp->dbi_base);
pci->dbi_base = devm_ioremap_resource(dev, res);
if (IS_ERR(pci->dbi_base))
return PTR_ERR(pci->dbi_base);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
pcie->elbi = devm_ioremap_resource(dev, res);
......@@ -699,7 +711,6 @@ static int qcom_pcie_probe(struct platform_device *pdev)
if (IS_ERR(pcie->phy))
return PTR_ERR(pcie->phy);
pp->dev = dev;
ret = pcie->ops->get_resources(pcie);
if (ret)
return ret;
......@@ -725,6 +736,8 @@ static int qcom_pcie_probe(struct platform_device *pdev)
if (ret)
return ret;
platform_set_drvdata(pdev, pcie);
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(dev, "cannot initialize host\n");
......
......@@ -25,7 +25,7 @@
#include "pcie-designware.h"
struct spear13xx_pcie {
struct pcie_port pp; /* DT dbi is pp.dbi_base */
struct dw_pcie *pci;
void __iomem *app_base;
struct phy *phy;
struct clk *clk;
......@@ -70,17 +70,18 @@ struct pcie_app_reg {
#define EXP_CAP_ID_OFFSET 0x70
#define to_spear13xx_pcie(x) container_of(x, struct spear13xx_pcie, pp)
#define to_spear13xx_pcie(x) dev_get_drvdata((x)->dev)
static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)
{
struct pcie_port *pp = &spear13xx_pcie->pp;
struct dw_pcie *pci = spear13xx_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
u32 val;
u32 exp_cap_off = EXP_CAP_ID_OFFSET;
if (dw_pcie_link_up(pp)) {
dev_err(pp->dev, "link already up\n");
if (dw_pcie_link_up(pci)) {
dev_err(pci->dev, "link already up\n");
return 0;
}
......@@ -91,34 +92,34 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)
* default value in capability register is 512 bytes. So force
* it to 128 here.
*/
dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, &val);
dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, &val);
val &= ~PCI_EXP_DEVCTL_READRQ;
dw_pcie_cfg_write(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, val);
dw_pcie_write(pci->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, val);
dw_pcie_cfg_write(pp->dbi_base + PCI_VENDOR_ID, 2, 0x104A);
dw_pcie_cfg_write(pp->dbi_base + PCI_DEVICE_ID, 2, 0xCD80);
dw_pcie_write(pci->dbi_base + PCI_VENDOR_ID, 2, 0x104A);
dw_pcie_write(pci->dbi_base + PCI_DEVICE_ID, 2, 0xCD80);
/*
* if is_gen1 is set then handle it, so that some buggy card
* also works
*/
if (spear13xx_pcie->is_gen1) {
dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCAP,
4, &val);
dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCAP,
4, &val);
if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
val &= ~((u32)PCI_EXP_LNKCAP_SLS);
val |= PCI_EXP_LNKCAP_SLS_2_5GB;
dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
PCI_EXP_LNKCAP, 4, val);
dw_pcie_write(pci->dbi_base + exp_cap_off +
PCI_EXP_LNKCAP, 4, val);
}
dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2,
2, &val);
dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2,
2, &val);
if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
val &= ~((u32)PCI_EXP_LNKCAP_SLS);
val |= PCI_EXP_LNKCAP_SLS_2_5GB;
dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
PCI_EXP_LNKCTL2, 2, val);
dw_pcie_write(pci->dbi_base + exp_cap_off +
PCI_EXP_LNKCTL2, 2, val);
}
}
......@@ -128,14 +129,15 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)
| ((u32)1 << REG_TRANSLATION_ENABLE),
&app_reg->app_ctrl_0);
return dw_pcie_wait_for_link(pp);
return dw_pcie_wait_for_link(pci);
}
static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
{
struct spear13xx_pcie *spear13xx_pcie = arg;
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
struct pcie_port *pp = &spear13xx_pcie->pp;
struct dw_pcie *pci = spear13xx_pcie->pci;
struct pcie_port *pp = &pci->pp;
unsigned int status;
status = readl(&app_reg->int_sts);
......@@ -152,7 +154,8 @@ static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie)
{
struct pcie_port *pp = &spear13xx_pcie->pp;
struct dw_pcie *pci = spear13xx_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
/* Enable MSI interrupt */
......@@ -163,9 +166,9 @@ static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pc
}
}
static int spear13xx_pcie_link_up(struct pcie_port *pp)
static int spear13xx_pcie_link_up(struct dw_pcie *pci)
{
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
if (readl(&app_reg->app_status_1) & XMLH_LINK_UP)
......@@ -176,22 +179,23 @@ static int spear13xx_pcie_link_up(struct pcie_port *pp)
static void spear13xx_pcie_host_init(struct pcie_port *pp)
{
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci);
spear13xx_pcie_establish_link(spear13xx_pcie);
spear13xx_pcie_enable_interrupts(spear13xx_pcie);
}
static struct pcie_host_ops spear13xx_pcie_host_ops = {
.link_up = spear13xx_pcie_link_up,
static struct dw_pcie_host_ops spear13xx_pcie_host_ops = {
.host_init = spear13xx_pcie_host_init,
};
static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
struct platform_device *pdev)
{
struct pcie_port *pp = &spear13xx_pcie->pp;
struct device *dev = pp->dev;
struct dw_pcie *pci = spear13xx_pcie->pci;
struct pcie_port *pp = &pci->pp;
struct device *dev = &pdev->dev;
int ret;
pp->irq = platform_get_irq(pdev, 0);
......@@ -219,11 +223,15 @@ static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
return 0;
}
static const struct dw_pcie_ops dw_pcie_ops = {
.link_up = spear13xx_pcie_link_up,
};
static int spear13xx_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dw_pcie *pci;
struct spear13xx_pcie *spear13xx_pcie;
struct pcie_port *pp;
struct device_node *np = dev->of_node;
struct resource *dbi_base;
int ret;
......@@ -232,6 +240,13 @@ static int spear13xx_pcie_probe(struct platform_device *pdev)
if (!spear13xx_pcie)
return -ENOMEM;
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
if (!pci)
return -ENOMEM;
pci->dev = dev;
pci->ops = &dw_pcie_ops;
spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy");
if (IS_ERR(spear13xx_pcie->phy)) {
ret = PTR_ERR(spear13xx_pcie->phy);
......@@ -255,26 +270,24 @@ static int spear13xx_pcie_probe(struct platform_device *pdev)
return ret;
}
pp = &spear13xx_pcie->pp;
pp->dev = dev;
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
if (IS_ERR(pp->dbi_base)) {
pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
if (IS_ERR(pci->dbi_base)) {
dev_err(dev, "couldn't remap dbi base %p\n", dbi_base);
ret = PTR_ERR(pp->dbi_base);
ret = PTR_ERR(pci->dbi_base);
goto fail_clk;
}
spear13xx_pcie->app_base = pp->dbi_base + 0x2000;
spear13xx_pcie->app_base = pci->dbi_base + 0x2000;
if (of_property_read_bool(np, "st,pcie-is-gen1"))
spear13xx_pcie->is_gen1 = true;
platform_set_drvdata(pdev, spear13xx_pcie);
ret = spear13xx_add_pcie_port(spear13xx_pcie, pdev);
if (ret < 0)
goto fail_clk;
platform_set_drvdata(pdev, spear13xx_pcie);
return 0;
fail_clk:
......
menu "PCI host controller drivers"
depends on PCI
config PCI_DRA7XX
bool "TI DRA7xx PCIe controller"
depends on OF && HAS_IOMEM && TI_PIPE3
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
help
Enables support for the PCIe controller in the DRA7xx SoC. There
are two instances of PCIe controller in DRA7xx. This controller can
act both as EP and RC. This reuses the Designware core.
config PCI_MVEBU
bool "Marvell EBU PCIe controller"
depends on ARCH_MVEBU || ARCH_DOVE
......@@ -37,36 +27,6 @@ config PCIE_XILINX_NWL
or End Point. The current option selection will only
support root port enabling.
config PCIE_DW_PLAT
bool "Platform bus based DesignWare PCIe Controller"
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
---help---
This selects the DesignWare PCIe controller support. Select this if
you have a PCIe controller on Platform bus.
If you have a controller with this interface, say Y or M here.
If unsure, say N.
config PCIE_DW
bool
depends on PCI_MSI_IRQ_DOMAIN
config PCI_EXYNOS
bool "Samsung Exynos PCIe controller"
depends on SOC_EXYNOS5440
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW
config PCI_IMX6
bool "Freescale i.MX6 PCIe controller"
depends on SOC_IMX6Q
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW
config PCI_TEGRA
bool "NVIDIA Tegra PCIe controller"
depends on ARCH_TEGRA
......@@ -103,27 +63,6 @@ config PCI_HOST_GENERIC
Say Y here if you want to support a simple generic PCI host
controller, such as the one emulated by kvmtool.
config PCIE_SPEAR13XX
bool "STMicroelectronics SPEAr PCIe controller"
depends on ARCH_SPEAR13XX
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW
help
Say Y here if you want PCIe support on SPEAr13XX SoCs.
config PCI_KEYSTONE
bool "TI Keystone PCIe controller"
depends on ARCH_KEYSTONE
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
select PCIEPORTBUS
help
Say Y here if you want to enable PCI controller support on Keystone
SoCs. The PCI controller on Keystone is based on Designware hardware
and therefore the driver re-uses the Designware core functions to
implement the driver.
config PCIE_XILINX
bool "Xilinx AXI PCIe host bridge support"
depends on ARCH_ZYNQ || MICROBLAZE
......@@ -150,15 +89,6 @@ config PCI_XGENE_MSI
Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC.
This MSI driver supports 5 PCIe ports on the APM X-Gene v1 SoC.
config PCI_LAYERSCAPE
bool "Freescale Layerscape PCIe controller"
depends on OF && (ARM || ARCH_LAYERSCAPE)
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
select MFD_SYSCON
help
Say Y here if you want PCIe controller support on Layerscape SoCs.
config PCI_VERSATILE
bool "ARM Versatile PB PCI controller"
depends on ARCH_VERSATILE
......@@ -217,27 +147,6 @@ config PCIE_ALTERA_MSI
Say Y here if you want PCIe MSI support for the Altera FPGA.
This MSI driver supports Altera MSI to GIC controller IP.
config PCI_HISI
depends on OF && ARM64
bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers"
depends on PCI_MSI_IRQ_DOMAIN
select PCIEPORTBUS
select PCIE_DW
help
Say Y here if you want PCIe controller support on HiSilicon
Hip05 and Hip06 SoCs
config PCIE_QCOM
bool "Qualcomm PCIe controller"
depends on ARCH_QCOM && OF
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
select PCIEPORTBUS
help
Say Y here to enable PCIe controller support on Qualcomm SoCs. The
PCIe controller uses the Designware core plus Qualcomm-specific
hardware wrappers.
config PCI_HOST_THUNDER_PEM
bool "Cavium Thunder PCIe controller to off-chip devices"
depends on ARM64
......@@ -254,28 +163,6 @@ config PCI_HOST_THUNDER_ECAM
help
Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs.
config PCIE_ARMADA_8K
bool "Marvell Armada-8K PCIe controller"
depends on ARCH_MVEBU
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
select PCIEPORTBUS
help
Say Y here if you want to enable PCIe controller support on
Armada-8K SoCs. The PCIe controller on Armada-8K is based on
Designware hardware and therefore the driver re-uses the
Designware core functions to implement the driver.
config PCIE_ARTPEC6
bool "Axis ARTPEC-6 PCIe controller"
depends on MACH_ARTPEC6
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
select PCIEPORTBUS
help
Say Y here to enable PCIe controller support on Axis ARTPEC-6
SoCs. This PCIe controller uses the DesignWare core.
config PCIE_ROCKCHIP
bool "Rockchip PCIe controller"
depends on ARCH_ROCKCHIP || COMPILE_TEST
......
obj-$(CONFIG_PCIE_DW) += pcie-designware.o
obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
......@@ -11,12 +6,9 @@ obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
obj-$(CONFIG_PCIE_RCAR) += pcie-rcar.o
obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o
......@@ -24,9 +16,6 @@ obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
obj-$(CONFIG_VMD) += vmd.o
......@@ -40,7 +29,6 @@ obj-$(CONFIG_VMD) += vmd.o
# ARM64 and use internal ifdefs to only build the pieces we need
# depending on whether ACPI, the DT driver, or both are enabled.
obj-$(CONFIG_ARM64) += pcie-hisi.o
obj-$(CONFIG_ARM64) += pci-thunder-ecam.o
obj-$(CONFIG_ARM64) += pci-thunder-pem.o
obj-$(CONFIG_ARM64) += pci-xgene.o
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment