@@ -74,6 +74,25 @@ static struct mcfg_fixup mcfg_quirks[] = {
HISI_QUAD_DOM("HIP07 ", 4, &hisi_pcie_ops),
HISI_QUAD_DOM("HIP07 ", 8, &hisi_pcie_ops),
HISI_QUAD_DOM("HIP07 ", 12, &hisi_pcie_ops),
+
+#define THUNDER_PEM_RES(addr, seg) \
+ DEFINE_RES_MEM(addr + (seg << 44), 0x39 * SZ_16M)
+#define THUNDER_PEM_QUIRK(rev, seg) \
+ { "CAVIUM", "THUNDERX", rev, 4 + (10 * seg), MCFG_BUS_ANY, \
+ &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88001f000000UL, seg) }, \
+ { "CAVIUM", "THUNDERX", rev, 5 + (10 * seg), MCFG_BUS_ANY, \
+ &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x884057000000UL, seg) }, \
+ { "CAVIUM", "THUNDERX", rev, 6 + (10 * seg), MCFG_BUS_ANY, \
+ &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88808f000000UL, seg) }, \
+ { "CAVIUM", "THUNDERX", rev, 7 + (10 * seg), MCFG_BUS_ANY, \
+ &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89001f000000UL, seg) }, \
+ { "CAVIUM", "THUNDERX", rev, 8 + (10 * seg), MCFG_BUS_ANY, \
+ &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x894057000000UL, seg) }, \
+ { "CAVIUM", "THUNDERX", rev, 9 + (10 * seg), MCFG_BUS_ANY, \
+ &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89808f000000UL, seg) }
+ /* SoC pass2.x */
+ THUNDER_PEM_QUIRK(1, 0UL),
+ THUNDER_PEM_QUIRK(1, 1UL),
};
static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
@@ -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.
@@ -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
@@ -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
@@ -62,6 +62,7 @@ extern struct pci_ecam_ops pci_generic_ecam_ops;
#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
extern struct pci_ecam_ops pci_32b_ops; /* 32-bit accesses only */
extern struct pci_ecam_ops hisi_pcie_ops; /* HiSilicon */
+extern struct pci_ecam_ops thunder_pem_ecam_ops; /* Cavium ThunderX 2.x */
#endif
#ifdef CONFIG_PCI_HOST_GENERIC