mirror of https://github.com/torvalds/linux.git
Merge branch 'pci/controller/keystone'
- Fail the probe instead of silently succeeding if ks_pcie_of_data didn't specify Root Complex or Endpoint mode (Siddharth Vadapalli) - Make keystone buildable as a loadable module, except on ARM32 where hook_fault_code() is __init (Siddharth Vadapalli) * pci/controller/keystone: PCI: keystone: Add support to build as a loadable module PCI: dwc: Export dw_pcie_allocate_domains() and dw_pcie_ep_raise_msix_irq() PCI: Export pci_get_host_bridge_device() for use by pci-keystone PCI: keystone: Exit ks_pcie_probe() for invalid mode
This commit is contained in:
commit
5606b7bad0
|
|
@ -482,15 +482,21 @@ config PCI_DRA7XX_EP
|
|||
to enable device-specific features PCI_DRA7XX_EP must be selected.
|
||||
This uses the DesignWare core.
|
||||
|
||||
# ARM32 platforms use hook_fault_code() and cannot support loadable module.
|
||||
config PCI_KEYSTONE
|
||||
bool
|
||||
|
||||
# On non-ARM32 platforms, loadable module can be supported.
|
||||
config PCI_KEYSTONE_TRISTATE
|
||||
tristate
|
||||
|
||||
config PCI_KEYSTONE_HOST
|
||||
bool "TI Keystone PCIe controller (host mode)"
|
||||
tristate "TI Keystone PCIe controller (host mode)"
|
||||
depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
|
||||
depends on PCI_MSI
|
||||
select PCIE_DW_HOST
|
||||
select PCI_KEYSTONE
|
||||
select PCI_KEYSTONE if ARM
|
||||
select PCI_KEYSTONE_TRISTATE if !ARM
|
||||
help
|
||||
Enables support for the PCIe controller in the Keystone SoC to
|
||||
work in host mode. The PCI controller on Keystone is based on
|
||||
|
|
@ -498,11 +504,12 @@ config PCI_KEYSTONE_HOST
|
|||
DesignWare core functions to implement the driver.
|
||||
|
||||
config PCI_KEYSTONE_EP
|
||||
bool "TI Keystone PCIe controller (endpoint mode)"
|
||||
tristate "TI Keystone PCIe controller (endpoint mode)"
|
||||
depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
|
||||
depends on PCI_ENDPOINT
|
||||
select PCIE_DW_EP
|
||||
select PCI_KEYSTONE
|
||||
select PCI_KEYSTONE if ARM
|
||||
select PCI_KEYSTONE_TRISTATE if !ARM
|
||||
help
|
||||
Enables support for the PCIe controller in the Keystone SoC to
|
||||
work in endpoint mode. The PCI controller on Keystone is based
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@ obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
|
|||
obj-$(CONFIG_PCIE_FU740) += pcie-fu740.o
|
||||
obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
|
||||
obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
|
||||
# ARM32 platforms use hook_fault_code() and cannot support loadable module.
|
||||
obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone.o
|
||||
# On non-ARM32 platforms, loadable module can be supported.
|
||||
obj-$(CONFIG_PCI_KEYSTONE_TRISTATE) += pci-keystone.o
|
||||
obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
|
||||
obj-$(CONFIG_PCI_LAYERSCAPE_EP) += pci-layerscape-ep.o
|
||||
obj-$(CONFIG_PCIE_QCOM_COMMON) += pcie-qcom-common.o
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
|
@ -777,29 +778,7 @@ static int ks_pcie_config_intx_irq(struct keystone_pcie *ks_pcie)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
/*
|
||||
* When a PCI device does not exist during config cycles, keystone host
|
||||
* gets a bus error instead of returning 0xffffffff (PCI_ERROR_RESPONSE).
|
||||
* This handler always returns 0 for this kind of fault.
|
||||
*/
|
||||
static int ks_pcie_fault(unsigned long addr, unsigned int fsr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long instr = *(unsigned long *) instruction_pointer(regs);
|
||||
|
||||
if ((instr & 0x0e100090) == 0x00100090) {
|
||||
int reg = (instr >> 12) & 15;
|
||||
|
||||
regs->uregs[reg] = -1;
|
||||
regs->ARM_pc += 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)
|
||||
static int ks_pcie_init_id(struct keystone_pcie *ks_pcie)
|
||||
{
|
||||
int ret;
|
||||
unsigned int id;
|
||||
|
|
@ -831,7 +810,7 @@ static int __init ks_pcie_init_id(struct keystone_pcie *ks_pcie)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init ks_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
static int ks_pcie_host_init(struct dw_pcie_rp *pp)
|
||||
{
|
||||
struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
|
||||
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
|
||||
|
|
@ -861,15 +840,6 @@ static int __init ks_pcie_host_init(struct dw_pcie_rp *pp)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
/*
|
||||
* PCIe access errors that result into OCP errors are caught by ARM as
|
||||
* "External aborts"
|
||||
*/
|
||||
hook_fault_code(17, ks_pcie_fault, SIGBUS, 0,
|
||||
"Asynchronous external abort");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1134,6 +1104,7 @@ static const struct of_device_id ks_pcie_of_match[] = {
|
|||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ks_pcie_of_match);
|
||||
|
||||
static int ks_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
@ -1337,6 +1308,8 @@ static int ks_pcie_probe(struct platform_device *pdev)
|
|||
break;
|
||||
default:
|
||||
dev_err(dev, "INVALID device type %d\n", mode);
|
||||
ret = -EINVAL;
|
||||
goto err_get_sync;
|
||||
}
|
||||
|
||||
ks_pcie_enable_error_irq(ks_pcie);
|
||||
|
|
@ -1379,4 +1352,45 @@ static struct platform_driver ks_pcie_driver = {
|
|||
.of_match_table = ks_pcie_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARM
|
||||
/*
|
||||
* When a PCI device does not exist during config cycles, keystone host
|
||||
* gets a bus error instead of returning 0xffffffff (PCI_ERROR_RESPONSE).
|
||||
* This handler always returns 0 for this kind of fault.
|
||||
*/
|
||||
static int ks_pcie_fault(unsigned long addr, unsigned int fsr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long instr = *(unsigned long *)instruction_pointer(regs);
|
||||
|
||||
if ((instr & 0x0e100090) == 0x00100090) {
|
||||
int reg = (instr >> 12) & 15;
|
||||
|
||||
regs->uregs[reg] = -1;
|
||||
regs->ARM_pc += 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init ks_pcie_init(void)
|
||||
{
|
||||
/*
|
||||
* PCIe access errors that result into OCP errors are caught by ARM as
|
||||
* "External aborts"
|
||||
*/
|
||||
if (of_find_matching_node(NULL, ks_pcie_of_match))
|
||||
hook_fault_code(17, ks_pcie_fault, SIGBUS, 0,
|
||||
"Asynchronous external abort");
|
||||
|
||||
return platform_driver_register(&ks_pcie_driver);
|
||||
}
|
||||
device_initcall(ks_pcie_init);
|
||||
#else
|
||||
builtin_platform_driver(ks_pcie_driver);
|
||||
#endif
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("PCIe controller driver for Texas Instruments Keystone SoCs");
|
||||
MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
|
||||
|
|
|
|||
|
|
@ -797,6 +797,7 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_pcie_ep_raise_msix_irq);
|
||||
|
||||
/**
|
||||
* dw_pcie_ep_cleanup - Cleanup DWC EP resources after fundamental reset
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ int dw_pcie_allocate_domains(struct dw_pcie_rp *pp)
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_pcie_allocate_domains);
|
||||
|
||||
void dw_pcie_free_msi(struct dw_pcie_rp *pp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ struct device *pci_get_host_bridge_device(struct pci_dev *dev)
|
|||
kobject_get(&bridge->kobj);
|
||||
return bridge;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_get_host_bridge_device);
|
||||
|
||||
void pci_put_host_bridge_device(struct device *dev)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -648,6 +648,7 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv);
|
|||
struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
|
||||
size_t priv);
|
||||
void pci_free_host_bridge(struct pci_host_bridge *bridge);
|
||||
struct device *pci_get_host_bridge_device(struct pci_dev *dev);
|
||||
struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
|
||||
|
||||
void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
|
||||
|
|
|
|||
Loading…
Reference in New Issue