mirror of https://gitee.com/openkylin/linux.git
Merge branch 'lorenzo/pci/dwc'
- reduce Keystone "link already up" log level (Fabio Estevam) - move private DT functions to drivers/pci/ (Rob Herring) - factor out dwc CONFIG_PCI Kconfig dependencies (Rob Herring) - add DesignWare support to the endpoint test driver (Gustavo Pimentel) - add DesignWare support for endpoint mode (Gustavo Pimentel) - use devm_ioremap_resource() instead of devm_ioremap() in dra7xx and artpec6 (Gustavo Pimentel) - fix Qualcomm bitwise NOT issue (Dan Carpenter) - add Qualcomm runtime PM support (Srinivas Kandagatla) * lorenzo/pci/dwc: PCI: qcom: add runtime pm support to pcie_port PCI: qcom: Fix a bitwise vs logical NOT typo PCI: dwc: dra7xx: Use devm_ioremap_resource() instead of devm_ioremap() PCI: dwc: artpec6: Use devm_ioremap_resource() instead of devm_ioremap() misc: pci_endpoint_test: Add DesignWare EP entry dt-bindings: PCI: designware: Add support for EP in DesignWare driver PCI: dwc: Add support for EP mode dt-bindings: PCI: designware: Example update PCI: Move private DT related functions into private header PCI: dwc: Move CONFIG_PCI depends to menu PCI: dwc: Replace magic number by defines PCI: dwc: Small computation improvement PCI: dwc: Replace lower into upper case characters PCI: dwc: Define maximum number of vectors PCI: imx6: Remove space before tabs PCI: keystone: Do not treat link up message as error # Conflicts: # include/linux/of_pci.h
This commit is contained in:
commit
f03c7aa459
|
@ -1,7 +1,9 @@
|
|||
* Synopsys DesignWare PCIe interface
|
||||
|
||||
Required properties:
|
||||
- compatible: should contain "snps,dw-pcie" to identify the core.
|
||||
- compatible:
|
||||
"snps,dw-pcie" for RC mode;
|
||||
"snps,dw-pcie-ep" for EP mode;
|
||||
- reg: Should contain the configuration address space.
|
||||
- reg-names: Must be "config" for the PCIe configuration space.
|
||||
(The old way of getting the configuration address space from "ranges"
|
||||
|
@ -41,11 +43,11 @@ EP mode:
|
|||
|
||||
Example configuration:
|
||||
|
||||
pcie: pcie@dffff000 {
|
||||
pcie: pcie@dfc00000 {
|
||||
compatible = "snps,dw-pcie";
|
||||
reg = <0xdffff000 0x1000>, /* Controller registers */
|
||||
<0xd0000000 0x2000>; /* PCI config space */
|
||||
reg-names = "ctrlreg", "config";
|
||||
reg = <0xdfc00000 0x0001000>, /* IP registers */
|
||||
<0xd0000000 0x0002000>; /* Configuration space */
|
||||
reg-names = "dbi", "config";
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
device_type = "pci";
|
||||
|
@ -54,5 +56,15 @@ Example configuration:
|
|||
interrupts = <25>, <24>;
|
||||
#interrupt-cells = <1>;
|
||||
num-lanes = <1>;
|
||||
num-viewport = <3>;
|
||||
};
|
||||
or
|
||||
pcie: pcie@dfc00000 {
|
||||
compatible = "snps,dw-pcie-ep";
|
||||
reg = <0xdfc00000 0x0001000>, /* IP registers 1 */
|
||||
<0xdfc01000 0x0001000>, /* IP registers 2 */
|
||||
<0xd0000000 0x2000000>; /* Configuration space */
|
||||
reg-names = "dbi", "dbi2", "addr_space";
|
||||
num-ib-windows = <6>;
|
||||
num-ob-windows = <2>;
|
||||
num-lanes = <1>;
|
||||
};
|
||||
|
|
|
@ -634,6 +634,7 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev)
|
|||
static const struct pci_device_id pci_endpoint_test_tbl[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, 0xedda) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
menu "DesignWare PCI Core Support"
|
||||
depends on PCI
|
||||
|
||||
config PCIE_DW
|
||||
bool
|
||||
|
||||
config PCIE_DW_HOST
|
||||
bool
|
||||
depends on PCI
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIE_DW
|
||||
|
||||
|
@ -22,7 +22,7 @@ config PCI_DRA7XX
|
|||
config PCI_DRA7XX_HOST
|
||||
bool "TI DRA7xx PCIe controller Host Mode"
|
||||
depends on SOC_DRA7XX || COMPILE_TEST
|
||||
depends on PCI && PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
depends on OF && HAS_IOMEM && TI_PIPE3
|
||||
select PCIE_DW_HOST
|
||||
select PCI_DRA7XX
|
||||
|
@ -51,21 +51,40 @@ config PCI_DRA7XX_EP
|
|||
This uses the DesignWare core.
|
||||
|
||||
config PCIE_DW_PLAT
|
||||
bool "Platform bus based DesignWare PCIe Controller"
|
||||
depends on PCI
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
bool
|
||||
|
||||
config PCIE_DW_PLAT_HOST
|
||||
bool "Platform bus based DesignWare PCIe Controller - Host mode"
|
||||
depends on PCI && 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.
|
||||
select PCIE_DW_PLAT
|
||||
default y
|
||||
help
|
||||
Enables support for the PCIe controller in the Designware IP to
|
||||
work in host mode. There are two instances of PCIe controller in
|
||||
Designware IP.
|
||||
This controller can work either as EP or RC. In order to enable
|
||||
host-specific features PCIE_DW_PLAT_HOST must be selected and in
|
||||
order to enable device-specific features PCI_DW_PLAT_EP must be
|
||||
selected.
|
||||
|
||||
If you have a controller with this interface, say Y or M here.
|
||||
|
||||
If unsure, say N.
|
||||
config PCIE_DW_PLAT_EP
|
||||
bool "Platform bus based DesignWare PCIe Controller - Endpoint mode"
|
||||
depends on PCI && PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI_ENDPOINT
|
||||
select PCIE_DW_EP
|
||||
select PCIE_DW_PLAT
|
||||
help
|
||||
Enables support for the PCIe controller in the Designware IP to
|
||||
work in endpoint mode. There are two instances of PCIe controller
|
||||
in Designware IP.
|
||||
This controller can work either as EP or RC. In order to enable
|
||||
host-specific features PCIE_DW_PLAT_HOST must be selected and in
|
||||
order to enable device-specific features PCI_DW_PLAT_EP must be
|
||||
selected.
|
||||
|
||||
config PCI_EXYNOS
|
||||
bool "Samsung Exynos PCIe controller"
|
||||
depends on PCI
|
||||
depends on SOC_EXYNOS5440
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
|
@ -73,7 +92,6 @@ config PCI_EXYNOS
|
|||
|
||||
config PCI_IMX6
|
||||
bool "Freescale i.MX6 PCIe controller"
|
||||
depends on PCI
|
||||
depends on SOC_IMX6Q
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
|
@ -81,7 +99,6 @@ config PCI_IMX6
|
|||
|
||||
config PCIE_SPEAR13XX
|
||||
bool "STMicroelectronics SPEAr PCIe controller"
|
||||
depends on PCI
|
||||
depends on ARCH_SPEAR13XX
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
|
@ -91,7 +108,6 @@ config PCIE_SPEAR13XX
|
|||
|
||||
config PCI_KEYSTONE
|
||||
bool "TI Keystone PCIe controller"
|
||||
depends on PCI
|
||||
depends on ARCH_KEYSTONE
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
|
@ -104,7 +120,6 @@ config PCI_KEYSTONE
|
|||
|
||||
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
|
||||
|
@ -115,7 +130,6 @@ config PCI_LAYERSCAPE
|
|||
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
|
||||
|
@ -126,7 +140,6 @@ config PCI_HISI
|
|||
|
||||
config PCIE_QCOM
|
||||
bool "Qualcomm PCIe controller"
|
||||
depends on PCI
|
||||
depends on ARCH_QCOM && OF
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
|
@ -138,7 +151,6 @@ config PCIE_QCOM
|
|||
|
||||
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
|
||||
|
@ -155,7 +167,7 @@ config PCIE_ARTPEC6
|
|||
config PCIE_ARTPEC6_HOST
|
||||
bool "Axis ARTPEC-6 PCIe controller Host Mode"
|
||||
depends on MACH_ARTPEC6
|
||||
depends on PCI && PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW_HOST
|
||||
select PCIE_ARTPEC6
|
||||
|
@ -177,7 +189,6 @@ config PCIE_KIRIN
|
|||
depends on OF && ARM64
|
||||
bool "HiSilicon Kirin series SoCs PCIe controllers"
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
depends on PCI
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW_HOST
|
||||
help
|
||||
|
@ -187,7 +198,6 @@ config PCIE_KIRIN
|
|||
config PCIE_HISI_STB
|
||||
bool "HiSilicon STB SoCs PCIe controllers"
|
||||
depends on ARCH_HISI
|
||||
depends on PCI
|
||||
depends on PCI_MSI_IRQ_DOMAIN
|
||||
select PCIEPORTBUS
|
||||
select PCIE_DW_HOST
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "../pci.h"
|
||||
#include "pcie-designware.h"
|
||||
|
||||
/* PCIe controller wrapper DRA7XX configuration registers */
|
||||
|
@ -406,14 +407,14 @@ static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx,
|
|||
ep->ops = &pcie_ep_ops;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ep_dbics");
|
||||
pci->dbi_base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!pci->dbi_base)
|
||||
return -ENOMEM;
|
||||
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, "ep_dbics2");
|
||||
pci->dbi_base2 = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!pci->dbi_base2)
|
||||
return -ENOMEM;
|
||||
pci->dbi_base2 = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pci->dbi_base2))
|
||||
return PTR_ERR(pci->dbi_base2);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
|
||||
if (!res)
|
||||
|
@ -459,9 +460,9 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
|
|||
return ret;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics");
|
||||
pci->dbi_base = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!pci->dbi_base)
|
||||
return -ENOMEM;
|
||||
pci->dbi_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pci->dbi_base))
|
||||
return PTR_ERR(pci->dbi_base);
|
||||
|
||||
pp->ops = &dra7xx_pcie_host_ops;
|
||||
|
||||
|
|
|
@ -338,7 +338,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
|
|||
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
|
||||
IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);
|
||||
break;
|
||||
case IMX6QP: /* FALLTHROUGH */
|
||||
case IMX6QP: /* FALLTHROUGH */
|
||||
case IMX6Q:
|
||||
/* power up core phy and enable ref clock */
|
||||
regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
|
||||
|
|
|
@ -89,7 +89,7 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
|
|||
dw_pcie_setup_rc(pp);
|
||||
|
||||
if (dw_pcie_link_up(pci)) {
|
||||
dev_err(dev, "Link already up\n");
|
||||
dev_info(dev, "Link already up\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -463,9 +463,9 @@ static int artpec6_add_pcie_ep(struct artpec6_pcie *artpec6_pcie,
|
|||
ep->ops = &pcie_ep_ops;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2");
|
||||
pci->dbi_base2 = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!pci->dbi_base2)
|
||||
return -ENOMEM;
|
||||
pci->dbi_base2 = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pci->dbi_base2))
|
||||
return PTR_ERR(pci->dbi_base2);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
|
||||
if (!res)
|
||||
|
|
|
@ -75,7 +75,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
|
|||
|
||||
free_win = find_first_zero_bit(ep->ib_window_map, ep->num_ib_windows);
|
||||
if (free_win >= ep->num_ib_windows) {
|
||||
dev_err(pci->dev, "no free inbound window\n");
|
||||
dev_err(pci->dev, "No free inbound window\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,
|
|||
|
||||
free_win = find_first_zero_bit(ep->ob_window_map, ep->num_ob_windows);
|
||||
if (free_win >= ep->num_ob_windows) {
|
||||
dev_err(pci->dev, "no free outbound window\n");
|
||||
dev_err(pci->dev, "No free outbound window\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,7 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no,
|
|||
|
||||
ret = dw_pcie_ep_outbound_atu(ep, addr, pci_addr, size);
|
||||
if (ret) {
|
||||
dev_err(pci->dev, "failed to enable address\n");
|
||||
dev_err(pci->dev, "Failed to enable address\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -348,21 +348,21 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
|
||||
ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "unable to read *num-ib-windows* property\n");
|
||||
dev_err(dev, "Unable to read *num-ib-windows* property\n");
|
||||
return ret;
|
||||
}
|
||||
if (ep->num_ib_windows > MAX_IATU_IN) {
|
||||
dev_err(dev, "invalid *num-ib-windows*\n");
|
||||
dev_err(dev, "Invalid *num-ib-windows*\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(np, "num-ob-windows", &ep->num_ob_windows);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "unable to read *num-ob-windows* property\n");
|
||||
dev_err(dev, "Unable to read *num-ob-windows* property\n");
|
||||
return ret;
|
||||
}
|
||||
if (ep->num_ob_windows > MAX_IATU_OUT) {
|
||||
dev_err(dev, "invalid *num-ob-windows*\n");
|
||||
dev_err(dev, "Invalid *num-ob-windows*\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
|
||||
epc = devm_pci_epc_create(dev, &epc_ops);
|
||||
if (IS_ERR(epc)) {
|
||||
dev_err(dev, "failed to create epc device\n");
|
||||
dev_err(dev, "Failed to create epc device\n");
|
||||
return PTR_ERR(epc);
|
||||
}
|
||||
|
||||
|
@ -411,6 +411,9 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
epc->features = EPC_FEATURE_NO_LINKUP_NOTIFIER;
|
||||
EPC_FEATURE_SET_BAR(epc->features, BAR_0);
|
||||
|
||||
ep->epc = epc;
|
||||
epc_set_drvdata(epc, ep);
|
||||
dw_pcie_setup(pci);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/pci_regs.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "../pci.h"
|
||||
#include "pcie-designware.h"
|
||||
|
||||
static struct pci_ops dw_pcie_ops;
|
||||
|
@ -83,18 +84,23 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
|
|||
num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
|
||||
|
||||
for (i = 0; i < num_ctrls; i++) {
|
||||
dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
|
||||
&val);
|
||||
dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS +
|
||||
(i * MSI_REG_CTRL_BLOCK_SIZE),
|
||||
4, &val);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
pos = 0;
|
||||
while ((pos = find_next_bit((unsigned long *) &val, 32,
|
||||
pos)) != 32) {
|
||||
irq = irq_find_mapping(pp->irq_domain, i * 32 + pos);
|
||||
while ((pos = find_next_bit((unsigned long *) &val,
|
||||
MAX_MSI_IRQS_PER_CTRL,
|
||||
pos)) != MAX_MSI_IRQS_PER_CTRL) {
|
||||
irq = irq_find_mapping(pp->irq_domain,
|
||||
(i * MAX_MSI_IRQS_PER_CTRL) +
|
||||
pos);
|
||||
generic_handle_irq(irq);
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12,
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS +
|
||||
(i * MSI_REG_CTRL_BLOCK_SIZE),
|
||||
4, 1 << pos);
|
||||
pos++;
|
||||
}
|
||||
|
@ -157,9 +163,9 @@ static void dw_pci_bottom_mask(struct irq_data *data)
|
|||
if (pp->ops->msi_clear_irq) {
|
||||
pp->ops->msi_clear_irq(pp, data->hwirq);
|
||||
} else {
|
||||
ctrl = data->hwirq / 32;
|
||||
res = ctrl * 12;
|
||||
bit = data->hwirq % 32;
|
||||
ctrl = data->hwirq / MAX_MSI_IRQS_PER_CTRL;
|
||||
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
|
||||
bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
||||
|
||||
pp->irq_status[ctrl] &= ~(1 << bit);
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4,
|
||||
|
@ -180,9 +186,9 @@ static void dw_pci_bottom_unmask(struct irq_data *data)
|
|||
if (pp->ops->msi_set_irq) {
|
||||
pp->ops->msi_set_irq(pp, data->hwirq);
|
||||
} else {
|
||||
ctrl = data->hwirq / 32;
|
||||
res = ctrl * 12;
|
||||
bit = data->hwirq % 32;
|
||||
ctrl = data->hwirq / MAX_MSI_IRQS_PER_CTRL;
|
||||
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
|
||||
bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
||||
|
||||
pp->irq_status[ctrl] |= 1 << bit;
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4,
|
||||
|
@ -248,8 +254,10 @@ static void dw_pcie_irq_domain_free(struct irq_domain *domain,
|
|||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&pp->lock, flags);
|
||||
|
||||
bitmap_release_region(pp->msi_irq_in_use, data->hwirq,
|
||||
order_base_2(nr_irqs));
|
||||
|
||||
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -266,7 +274,7 @@ int dw_pcie_allocate_domains(struct pcie_port *pp)
|
|||
pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors,
|
||||
&dw_pcie_msi_domain_ops, pp);
|
||||
if (!pp->irq_domain) {
|
||||
dev_err(pci->dev, "failed to create IRQ domain\n");
|
||||
dev_err(pci->dev, "Failed to create IRQ domain\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -274,7 +282,7 @@ int dw_pcie_allocate_domains(struct pcie_port *pp)
|
|||
&dw_pcie_msi_domain_info,
|
||||
pp->irq_domain);
|
||||
if (!pp->msi_domain) {
|
||||
dev_err(pci->dev, "failed to create MSI domain\n");
|
||||
dev_err(pci->dev, "Failed to create MSI domain\n");
|
||||
irq_domain_remove(pp->irq_domain);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -301,13 +309,13 @@ void dw_pcie_msi_init(struct pcie_port *pp)
|
|||
page = alloc_page(GFP_KERNEL);
|
||||
pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(dev, pp->msi_data)) {
|
||||
dev_err(dev, "failed to map MSI data\n");
|
||||
dev_err(dev, "Failed to map MSI data\n");
|
||||
__free_page(page);
|
||||
return;
|
||||
}
|
||||
msi_target = (u64)pp->msi_data;
|
||||
|
||||
/* program the msi_data */
|
||||
/* Program the msi_data */
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
|
||||
lower_32_bits(msi_target));
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4,
|
||||
|
@ -330,12 +338,12 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
|||
|
||||
cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
|
||||
if (cfg_res) {
|
||||
pp->cfg0_size = resource_size(cfg_res) / 2;
|
||||
pp->cfg1_size = resource_size(cfg_res) / 2;
|
||||
pp->cfg0_size = resource_size(cfg_res) >> 1;
|
||||
pp->cfg1_size = resource_size(cfg_res) >> 1;
|
||||
pp->cfg0_base = cfg_res->start;
|
||||
pp->cfg1_base = cfg_res->start + pp->cfg0_size;
|
||||
} else if (!pp->va_cfg0_base) {
|
||||
dev_err(dev, "missing *config* reg space\n");
|
||||
dev_err(dev, "Missing *config* reg space\n");
|
||||
}
|
||||
|
||||
bridge = pci_alloc_host_bridge(0);
|
||||
|
@ -357,7 +365,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
|||
case IORESOURCE_IO:
|
||||
ret = pci_remap_iospace(win->res, pp->io_base);
|
||||
if (ret) {
|
||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||
dev_warn(dev, "Error %d: failed to map resource %pR\n",
|
||||
ret, win->res);
|
||||
resource_list_destroy_entry(win);
|
||||
} else {
|
||||
|
@ -375,8 +383,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
|||
break;
|
||||
case 0:
|
||||
pp->cfg = win->res;
|
||||
pp->cfg0_size = resource_size(pp->cfg) / 2;
|
||||
pp->cfg1_size = resource_size(pp->cfg) / 2;
|
||||
pp->cfg0_size = resource_size(pp->cfg) >> 1;
|
||||
pp->cfg1_size = resource_size(pp->cfg) >> 1;
|
||||
pp->cfg0_base = pp->cfg->start;
|
||||
pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
|
||||
break;
|
||||
|
@ -391,7 +399,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
|||
pp->cfg->start,
|
||||
resource_size(pp->cfg));
|
||||
if (!pci->dbi_base) {
|
||||
dev_err(dev, "error with ioremap\n");
|
||||
dev_err(dev, "Error with ioremap\n");
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
@ -403,7 +411,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
|||
pp->va_cfg0_base = devm_pci_remap_cfgspace(dev,
|
||||
pp->cfg0_base, pp->cfg0_size);
|
||||
if (!pp->va_cfg0_base) {
|
||||
dev_err(dev, "error with ioremap in function\n");
|
||||
dev_err(dev, "Error with ioremap in function\n");
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
@ -414,7 +422,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
|||
pp->cfg1_base,
|
||||
pp->cfg1_size);
|
||||
if (!pp->va_cfg1_base) {
|
||||
dev_err(dev, "error with ioremap\n");
|
||||
dev_err(dev, "Error with ioremap\n");
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
@ -586,7 +594,7 @@ static int dw_pcie_valid_device(struct pcie_port *pp, struct pci_bus *bus,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* access only one slot on each root port */
|
||||
/* Access only one slot on each root port */
|
||||
if (bus->number == pp->root_bus_nr && dev > 0)
|
||||
return 0;
|
||||
|
||||
|
@ -650,13 +658,15 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
|||
|
||||
/* Initialize IRQ Status array */
|
||||
for (ctrl = 0; ctrl < num_ctrls; ctrl++)
|
||||
dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + (ctrl * 12), 4,
|
||||
&pp->irq_status[ctrl]);
|
||||
/* setup RC BARs */
|
||||
dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE +
|
||||
(ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
||||
4, &pp->irq_status[ctrl]);
|
||||
|
||||
/* Setup RC BARs */
|
||||
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
|
||||
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000);
|
||||
|
||||
/* setup interrupt pins */
|
||||
/* Setup interrupt pins */
|
||||
dw_pcie_dbi_ro_wr_en(pci);
|
||||
val = dw_pcie_readl_dbi(pci, PCI_INTERRUPT_LINE);
|
||||
val &= 0xffff00ff;
|
||||
|
@ -664,13 +674,13 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
|||
dw_pcie_writel_dbi(pci, PCI_INTERRUPT_LINE, val);
|
||||
dw_pcie_dbi_ro_wr_dis(pci);
|
||||
|
||||
/* setup bus numbers */
|
||||
/* Setup bus numbers */
|
||||
val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS);
|
||||
val &= 0xff000000;
|
||||
val |= 0x00ff0100;
|
||||
dw_pcie_writel_dbi(pci, PCI_PRIMARY_BUS, val);
|
||||
|
||||
/* setup command register */
|
||||
/* Setup command register */
|
||||
val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
|
||||
val &= 0xffff0000;
|
||||
val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
|
||||
|
@ -683,7 +693,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
|||
* we should not program the ATU here.
|
||||
*/
|
||||
if (!pp->ops->rd_other_conf) {
|
||||
/* get iATU unroll support */
|
||||
/* Get iATU unroll support */
|
||||
pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci);
|
||||
dev_dbg(pci->dev, "iATU unroll: %s\n",
|
||||
pci->iatu_unroll_enabled ? "enabled" : "disabled");
|
||||
|
@ -701,7 +711,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
|||
|
||||
/* Enable write permission for the DBI read-only register */
|
||||
dw_pcie_dbi_ro_wr_en(pci);
|
||||
/* program correct class for RC */
|
||||
/* Program correct class for RC */
|
||||
dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
|
||||
/* Better disable write permission right after the update */
|
||||
dw_pcie_dbi_ro_wr_dis(pci);
|
||||
|
|
|
@ -12,19 +12,29 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/resource.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "pcie-designware.h"
|
||||
|
||||
struct dw_plat_pcie {
|
||||
struct dw_pcie *pci;
|
||||
struct dw_pcie *pci;
|
||||
struct regmap *regmap;
|
||||
enum dw_pcie_device_mode mode;
|
||||
};
|
||||
|
||||
struct dw_plat_pcie_of_data {
|
||||
enum dw_pcie_device_mode mode;
|
||||
};
|
||||
|
||||
static const struct of_device_id dw_plat_pcie_of_match[];
|
||||
|
||||
static int dw_plat_pcie_host_init(struct pcie_port *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
|
@ -38,13 +48,63 @@ static int dw_plat_pcie_host_init(struct pcie_port *pp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dw_plat_set_num_vectors(struct pcie_port *pp)
|
||||
{
|
||||
pp->num_vectors = MAX_MSI_IRQS;
|
||||
}
|
||||
|
||||
static const struct dw_pcie_host_ops dw_plat_pcie_host_ops = {
|
||||
.host_init = dw_plat_pcie_host_init,
|
||||
.set_num_vectors = dw_plat_set_num_vectors,
|
||||
};
|
||||
|
||||
static int dw_plat_add_pcie_port(struct pcie_port *pp,
|
||||
static int dw_plat_pcie_establish_link(struct dw_pcie *pci)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.start_link = dw_plat_pcie_establish_link,
|
||||
};
|
||||
|
||||
static void dw_plat_pcie_ep_init(struct dw_pcie_ep *ep)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
enum pci_barno bar;
|
||||
|
||||
for (bar = BAR_0; bar <= BAR_5; bar++)
|
||||
dw_pcie_ep_reset_bar(pci, bar);
|
||||
}
|
||||
|
||||
static int dw_plat_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,
|
||||
enum pci_epc_irq_type type,
|
||||
u8 interrupt_num)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
|
||||
|
||||
switch (type) {
|
||||
case PCI_EPC_IRQ_LEGACY:
|
||||
dev_err(pci->dev, "EP cannot trigger legacy IRQs\n");
|
||||
return -EINVAL;
|
||||
case PCI_EPC_IRQ_MSI:
|
||||
return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num);
|
||||
default:
|
||||
dev_err(pci->dev, "UNKNOWN IRQ type\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dw_pcie_ep_ops pcie_ep_ops = {
|
||||
.ep_init = dw_plat_pcie_ep_init,
|
||||
.raise_irq = dw_plat_pcie_ep_raise_irq,
|
||||
};
|
||||
|
||||
static int dw_plat_add_pcie_port(struct dw_plat_pcie *dw_plat_pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct dw_pcie *pci = dw_plat_pcie->pci;
|
||||
struct pcie_port *pp = &pci->pp;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret;
|
||||
|
||||
|
@ -63,15 +123,44 @@ static int dw_plat_add_pcie_port(struct pcie_port *pp,
|
|||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to initialize host\n");
|
||||
dev_err(dev, "Failed to initialize host\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
};
|
||||
static int dw_plat_add_pcie_ep(struct dw_plat_pcie *dw_plat_pcie,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct dw_pcie_ep *ep;
|
||||
struct resource *res;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw_pcie *pci = dw_plat_pcie->pci;
|
||||
|
||||
ep = &pci->ep;
|
||||
ep->ops = &pcie_ep_ops;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2");
|
||||
pci->dbi_base2 = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(pci->dbi_base2))
|
||||
return PTR_ERR(pci->dbi_base2);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
|
||||
if (!res)
|
||||
return -EINVAL;
|
||||
|
||||
ep->phys_base = res->start;
|
||||
ep->addr_size = resource_size(res);
|
||||
|
||||
ret = dw_pcie_ep_init(ep);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize endpoint\n");
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_plat_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -80,6 +169,16 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
|
|||
struct dw_pcie *pci;
|
||||
struct resource *res; /* Resource from DT */
|
||||
int ret;
|
||||
const struct of_device_id *match;
|
||||
const struct dw_plat_pcie_of_data *data;
|
||||
enum dw_pcie_device_mode mode;
|
||||
|
||||
match = of_match_device(dw_plat_pcie_of_match, dev);
|
||||
if (!match)
|
||||
return -EINVAL;
|
||||
|
||||
data = (struct dw_plat_pcie_of_data *)match->data;
|
||||
mode = (enum dw_pcie_device_mode)data->mode;
|
||||
|
||||
dw_plat_pcie = devm_kzalloc(dev, sizeof(*dw_plat_pcie), GFP_KERNEL);
|
||||
if (!dw_plat_pcie)
|
||||
|
@ -93,23 +192,59 @@ static int dw_plat_pcie_probe(struct platform_device *pdev)
|
|||
pci->ops = &dw_pcie_ops;
|
||||
|
||||
dw_plat_pcie->pci = pci;
|
||||
dw_plat_pcie->mode = mode;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
|
||||
if (!res)
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
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(&pci->pp, pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
switch (dw_plat_pcie->mode) {
|
||||
case DW_PCIE_RC_TYPE:
|
||||
if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_HOST))
|
||||
return -ENODEV;
|
||||
|
||||
ret = dw_plat_add_pcie_port(dw_plat_pcie, pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case DW_PCIE_EP_TYPE:
|
||||
if (!IS_ENABLED(CONFIG_PCIE_DW_PLAT_EP))
|
||||
return -ENODEV;
|
||||
|
||||
ret = dw_plat_add_pcie_ep(dw_plat_pcie, pdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "INVALID device type %d\n", dw_plat_pcie->mode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dw_plat_pcie_of_data dw_plat_pcie_rc_of_data = {
|
||||
.mode = DW_PCIE_RC_TYPE,
|
||||
};
|
||||
|
||||
static const struct dw_plat_pcie_of_data dw_plat_pcie_ep_of_data = {
|
||||
.mode = DW_PCIE_EP_TYPE,
|
||||
};
|
||||
|
||||
static const struct of_device_id dw_plat_pcie_of_match[] = {
|
||||
{ .compatible = "snps,dw-pcie", },
|
||||
{
|
||||
.compatible = "snps,dw-pcie",
|
||||
.data = &dw_plat_pcie_rc_of_data,
|
||||
},
|
||||
{
|
||||
.compatible = "snps,dw-pcie-ep",
|
||||
.data = &dw_plat_pcie_ep_of_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ u32 __dw_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
|
|||
|
||||
ret = dw_pcie_read(base + reg, size, &val);
|
||||
if (ret)
|
||||
dev_err(pci->dev, "read DBI address failed\n");
|
||||
dev_err(pci->dev, "Read DBI address failed\n");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
|
|||
|
||||
ret = dw_pcie_write(base + reg, size, val);
|
||||
if (ret)
|
||||
dev_err(pci->dev, "write DBI address failed\n");
|
||||
dev_err(pci->dev, "Write DBI address failed\n");
|
||||
}
|
||||
|
||||
static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
|
||||
|
@ -137,7 +137,7 @@ static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
|
|||
|
||||
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
|
||||
}
|
||||
dev_err(pci->dev, "outbound iATU is not being enabled\n");
|
||||
dev_err(pci->dev, "Outbound iATU is not being enabled\n");
|
||||
}
|
||||
|
||||
void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
|
||||
|
@ -180,7 +180,7 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
|
|||
|
||||
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
|
||||
}
|
||||
dev_err(pci->dev, "outbound iATU is not being enabled\n");
|
||||
dev_err(pci->dev, "Outbound iATU is not being enabled\n");
|
||||
}
|
||||
|
||||
static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
|
||||
|
@ -238,7 +238,7 @@ static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
|
|||
|
||||
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
|
||||
}
|
||||
dev_err(pci->dev, "inbound iATU is not being enabled\n");
|
||||
dev_err(pci->dev, "Inbound iATU is not being enabled\n");
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -284,7 +284,7 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
|
|||
|
||||
usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
|
||||
}
|
||||
dev_err(pci->dev, "inbound iATU is not being enabled\n");
|
||||
dev_err(pci->dev, "Inbound iATU is not being enabled\n");
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
@ -313,16 +313,16 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)
|
|||
{
|
||||
int retries;
|
||||
|
||||
/* check if the link is up or not */
|
||||
/* 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");
|
||||
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");
|
||||
dev_err(pci->dev, "Phy link never came up\n");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ void dw_pcie_setup(struct dw_pcie *pci)
|
|||
if (ret)
|
||||
lanes = 0;
|
||||
|
||||
/* set the number of lanes */
|
||||
/* Set the number of lanes */
|
||||
val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
|
||||
val &= ~PORT_LINK_MODE_MASK;
|
||||
switch (lanes) {
|
||||
|
@ -373,7 +373,7 @@ void dw_pcie_setup(struct dw_pcie *pci)
|
|||
}
|
||||
dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
|
||||
|
||||
/* set link width speed control register */
|
||||
/* 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) {
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
#define MAX_MSI_IRQS 256
|
||||
#define MAX_MSI_IRQS_PER_CTRL 32
|
||||
#define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL)
|
||||
#define MSI_REG_CTRL_BLOCK_SIZE 12
|
||||
#define MSI_DEF_NUM_VECTORS 32
|
||||
|
||||
/* Maximum number of inbound/outbound iATUs */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
@ -869,7 +870,7 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie)
|
|||
|
||||
/* enable PCIe clocks and resets */
|
||||
val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
|
||||
val &= !BIT(0);
|
||||
val &= ~BIT(0);
|
||||
writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
|
||||
|
||||
/* change DBI base address */
|
||||
|
@ -1088,6 +1089,7 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
|
|||
struct qcom_pcie *pcie = to_qcom_pcie(pci);
|
||||
int ret;
|
||||
|
||||
pm_runtime_get_sync(pci->dev);
|
||||
qcom_ep_reset_assert(pcie);
|
||||
|
||||
ret = pcie->ops->init(pcie);
|
||||
|
@ -1124,6 +1126,7 @@ static int qcom_pcie_host_init(struct pcie_port *pp)
|
|||
phy_power_off(pcie->phy);
|
||||
err_deinit:
|
||||
pcie->ops->deinit(pcie);
|
||||
pm_runtime_put(pci->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1212,6 +1215,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
if (!pci)
|
||||
return -ENOMEM;
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pci->dev = dev;
|
||||
pci->ops = &dw_pcie_ops;
|
||||
pp = &pci->pp;
|
||||
|
@ -1257,14 +1261,17 @@ static int qcom_pcie_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
ret = phy_init(pcie->phy);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
ret = dw_pcie_host_init(pp);
|
||||
if (ret) {
|
||||
dev_err(dev, "cannot initialize host\n");
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -435,6 +435,13 @@ static int pci_epf_test_bind(struct pci_epf *epf)
|
|||
if (WARN_ON_ONCE(!epc))
|
||||
return -EINVAL;
|
||||
|
||||
if (epc->features & EPC_FEATURE_NO_LINKUP_NOTIFIER)
|
||||
epf_test->linkup_notifier = false;
|
||||
else
|
||||
epf_test->linkup_notifier = true;
|
||||
|
||||
epf_test->test_reg_bar = EPC_FEATURE_GET_BAR(epc->features);
|
||||
|
||||
ret = pci_epc_write_header(epc, epf->func_no, header);
|
||||
if (ret) {
|
||||
dev_err(dev, "configuration header write failed\n");
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <linux/of_pci.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/* PCIe core registers */
|
||||
#define PCIE_CORE_CMD_STATUS_REG 0x4
|
||||
#define PCIE_CORE_CMD_IO_ACCESS_EN BIT(0)
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/*
|
||||
* Special configuration registers directly in the first few words
|
||||
* in I/O space.
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <linux/of_pci.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/*
|
||||
* PCIe unit register offsets.
|
||||
*/
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <linux/sizes.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/* AHB-PCI Bridge PCI communication registers */
|
||||
#define RCAR_AHBPCI_PCICOM_OFFSET 0x800
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include <soc/tegra/cpuidle.h>
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
#define INT_PCI_MSI_NR (8 * 32)
|
||||
|
||||
/* register definitions */
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
#define V3_PCI_VENDOR 0x00000000
|
||||
#define V3_PCI_DEVICE 0x00000002
|
||||
#define V3_PCI_CMD 0x00000004
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
static void __iomem *versatile_pci_base;
|
||||
static void __iomem *versatile_cfg_base[2];
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
#define PCIECORE_CTLANDSTATUS 0x50
|
||||
#define PIM1_1L 0x80
|
||||
#define IBAR2 0x98
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
#define RP_TX_REG0 0x2000
|
||||
#define RP_TX_REG1 0x2004
|
||||
#define RP_TX_CNTRL 0x2008
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/of_platform.h>
|
||||
#include <linux/phy/phy.h>
|
||||
|
||||
#include "../pci.h"
|
||||
#include "pcie-iproc.h"
|
||||
|
||||
static const struct of_device_id iproc_pcie_of_match_table[] = {
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/* PCIe shared registers */
|
||||
#define PCIE_SYS_CFG 0x00
|
||||
#define PCIE_INT_ENABLE 0x0c
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
#define PCIECAR 0x000010
|
||||
#define PCIECCTLR 0x000018
|
||||
#define CONFIG_SEND_ENABLE (1 << 31)
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include <linux/reset.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/*
|
||||
* The upper 16 bits of PCIE_CLIENT_CONFIG are a write mask for the lower 16
|
||||
* bits. This allows atomic updates of the register without locking.
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/* Bridge core config registers */
|
||||
#define BRCFG_PCIE_RX0 0x00000000
|
||||
#define BRCFG_INTERRUPT 0x00000010
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "../pci.h"
|
||||
|
||||
/* Register definitions */
|
||||
#define XILINX_PCIE_REG_BIR 0x00000130
|
||||
#define XILINX_PCIE_REG_IDR 0x00000138
|
||||
|
|
|
@ -412,4 +412,44 @@ static inline u64 pci_rebar_size_to_bytes(int size)
|
|||
return 1ULL << (size + 20);
|
||||
}
|
||||
|
||||
struct device_node;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
|
||||
int of_get_pci_domain_nr(struct device_node *node);
|
||||
int of_pci_get_max_link_speed(struct device_node *node);
|
||||
|
||||
#else
|
||||
static inline int
|
||||
of_pci_parse_bus_range(struct device_node *node, struct resource *res)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
of_get_pci_domain_nr(struct device_node *node)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
of_pci_get_max_link_speed(struct device_node *node)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
#if defined(CONFIG_OF_ADDRESS)
|
||||
int devm_of_pci_get_host_bridge_resources(struct device *dev,
|
||||
unsigned char busno, unsigned char bus_max,
|
||||
struct list_head *resources, resource_size_t *io_base);
|
||||
#else
|
||||
static inline int devm_of_pci_get_host_bridge_resources(struct device *dev,
|
||||
unsigned char busno, unsigned char bus_max,
|
||||
struct list_head *resources, resource_size_t *io_base)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DRIVERS_PCI_H */
|
||||
|
|
|
@ -13,9 +13,6 @@ struct device_node;
|
|||
struct device_node *of_pci_find_child_device(struct device_node *parent,
|
||||
unsigned int devfn);
|
||||
int of_pci_get_devfn(struct device_node *np);
|
||||
int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
|
||||
int of_get_pci_domain_nr(struct device_node *node);
|
||||
int of_pci_get_max_link_speed(struct device_node *node);
|
||||
void of_pci_check_probe_only(void);
|
||||
int of_pci_map_rid(struct device_node *np, u32 rid,
|
||||
const char *map_name, const char *map_mask_name,
|
||||
|
@ -32,18 +29,6 @@ static inline int of_pci_get_devfn(struct device_node *np)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
of_pci_parse_bus_range(struct device_node *node, struct resource *res)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
of_get_pci_domain_nr(struct device_node *node)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int of_pci_map_rid(struct device_node *np, u32 rid,
|
||||
const char *map_name, const char *map_mask_name,
|
||||
struct device_node **target, u32 *id_out)
|
||||
|
@ -51,12 +36,6 @@ static inline int of_pci_map_rid(struct device_node *np, u32 rid,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
of_pci_get_max_link_speed(struct device_node *node)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void of_pci_check_probe_only(void) { }
|
||||
#endif
|
||||
|
||||
|
@ -70,17 +49,4 @@ of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OF_ADDRESS)
|
||||
int devm_of_pci_get_host_bridge_resources(struct device *dev,
|
||||
unsigned char busno, unsigned char bus_max,
|
||||
struct list_head *resources, resource_size_t *io_base);
|
||||
#else
|
||||
static inline int devm_of_pci_get_host_bridge_resources(struct device *dev,
|
||||
unsigned char busno, unsigned char bus_max,
|
||||
struct list_head *resources, resource_size_t *io_base)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -90,8 +90,16 @@ struct pci_epc {
|
|||
struct config_group *group;
|
||||
/* spinlock to protect against concurrent access of EP controller */
|
||||
spinlock_t lock;
|
||||
unsigned int features;
|
||||
};
|
||||
|
||||
#define EPC_FEATURE_NO_LINKUP_NOTIFIER BIT(0)
|
||||
#define EPC_FEATURE_BAR_MASK (BIT(1) | BIT(2) | BIT(3))
|
||||
#define EPC_FEATURE_SET_BAR(features, bar) \
|
||||
(features |= (EPC_FEATURE_BAR_MASK & (bar << 1)))
|
||||
#define EPC_FEATURE_GET_BAR(features) \
|
||||
((features & EPC_FEATURE_BAR_MASK) >> 1)
|
||||
|
||||
#define to_pci_epc(device) container_of((device), struct pci_epc, dev)
|
||||
|
||||
#define pci_epc_create(dev, ops) \
|
||||
|
|
Loading…
Reference in New Issue