diff options
author | Tomasz Nowicki <tn@semihalf.com> | 2016-12-01 00:07:56 -0600 |
---|---|---|
committer | Bjorn Helgaas <helgaas@kernel.org> | 2016-12-06 13:45:49 -0600 |
commit | 44f22bd91e88f9a1203a6e564a237e593f5f2f74 (patch) | |
tree | c4c5e1e3305986af0fc32be51e804be5e1f24d00 /drivers/pci/host | |
parent | 0d414268fb8d0844030f87027e904f69d96706be (diff) | |
download | blackbird-op-linux-44f22bd91e88f9a1203a6e564a237e593f5f2f74.tar.gz blackbird-op-linux-44f22bd91e88f9a1203a6e564a237e593f5f2f74.zip |
PCI: Add MCFG quirks for Cavium ThunderX pass2.x host controller
ThunderX PCIe controller to off-chip devices (so-called PEM) is not fully
compliant with ECAM standard. It uses non-standard configuration space
accessors (see thunder_pem_ecam_ops) and custom configuration space
granulation (see bus_shift = 24). In order to access configuration space
and probe PEM as ACPI-based PCI host controller we need to add MCFG quirk
infrastructure. This involves:
1. A new thunder_pem_acpi_init() init function to locate PEM-specific
register ranges using ACPI.
2. Export PEM thunder_pem_ecam_ops structure so it is visible to MCFG quirk
code.
3. New quirk entries for each PEM segment. Each contains platform IDs,
mentioned thunder_pem_ecam_ops and CFG resources.
Quirk is considered for ThunderX silicon pass2.x only which is identified
via MCFG revision 1.
ThunderX pass 2.x requires the following accessors:
NUMA Node 0 PCI segments 0- 3: pci_generic_ecam_ops (ECAM-compliant)
NUMA Node 0 PCI segments 4- 9: thunder_pem_ecam_ops (MCFG quirk)
NUMA Node 1 PCI segments 10-13: pci_generic_ecam_ops (ECAM-compliant)
NUMA Node 1 PCI segments 14-19: thunder_pem_ecam_ops (MCFG quirk)
[bhelgaas: adapt to use acpi_get_rc_resources(), update Makefile/ifdefs so
quirk doesn't depend on CONFIG_PCI_HOST_THUNDER_PEM]
Signed-off-by: Tomasz Nowicki <tn@semihalf.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/host')
-rw-r--r-- | drivers/pci/host/Kconfig | 3 | ||||
-rw-r--r-- | drivers/pci/host/Makefile | 2 | ||||
-rw-r--r-- | drivers/pci/host/pci-thunder-pem.c | 44 |
3 files changed, 47 insertions, 2 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index d7e7c0a827c3..1239a8e63368 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -240,7 +240,8 @@ config PCIE_QCOM config PCI_HOST_THUNDER_PEM bool "Cavium Thunder PCIe controller to off-chip devices" - depends on OF && ARM64 + depends on ARM64 + depends on OF || (ACPI && PCI_QUIRKS) select PCI_HOST_COMMON help Say Y here if you want PCIe support for CN88XX Cavium Thunder SoCs. diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 64845f0d6138..97e6bfc55772 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o obj-$(CONFIG_ARM64) += pcie-hisi.o obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o -obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o +obj-$(CONFIG_ARM64) += pci-thunder-pem.o obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c index c3276eede82a..af722eb0ca75 100644 --- a/drivers/pci/host/pci-thunder-pem.c +++ b/drivers/pci/host/pci-thunder-pem.c @@ -18,8 +18,12 @@ #include <linux/init.h> #include <linux/of_address.h> #include <linux/of_pci.h> +#include <linux/pci-acpi.h> #include <linux/pci-ecam.h> #include <linux/platform_device.h> +#include "../pci.h" + +#if defined(CONFIG_PCI_HOST_THUNDER_PEM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)) #define PEM_CFG_WR 0x28 #define PEM_CFG_RD 0x30 @@ -313,6 +317,43 @@ static int thunder_pem_init(struct device *dev, struct pci_config_window *cfg, return 0; } +#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) + +static int thunder_pem_acpi_init(struct pci_config_window *cfg) +{ + struct device *dev = cfg->parent; + struct acpi_device *adev = to_acpi_device(dev); + struct acpi_pci_root *root = acpi_driver_data(adev); + struct resource *res_pem; + int ret; + + res_pem = devm_kzalloc(&adev->dev, sizeof(*res_pem), GFP_KERNEL); + if (!res_pem) + return -ENOMEM; + + ret = acpi_get_rc_resources(dev, "THRX0002", root->segment, res_pem); + if (ret) { + dev_err(dev, "can't get rc base address\n"); + return ret; + } + + return thunder_pem_init(dev, cfg, res_pem); +} + +struct pci_ecam_ops thunder_pem_ecam_ops = { + .bus_shift = 24, + .init = thunder_pem_acpi_init, + .pci_ops = { + .map_bus = pci_ecam_map_bus, + .read = thunder_pem_config_read, + .write = thunder_pem_config_write, + } +}; + +#endif + +#ifdef CONFIG_PCI_HOST_THUNDER_PEM + static int thunder_pem_platform_init(struct pci_config_window *cfg) { struct device *dev = cfg->parent; @@ -364,3 +405,6 @@ static struct platform_driver thunder_pem_driver = { .probe = thunder_pem_probe, }; builtin_platform_driver(thunder_pem_driver); + +#endif +#endif |