aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSayanta Pattanayak <sayanta.pattanayak@arm.com>2021-01-05 18:20:16 +0000
committerKhasim Syed Mohammed <khasim.mohammed@arm.com>2021-02-04 17:30:05 +0530
commit4c6fd624a85c4c80d9444d20f68468d7ddab83f7 (patch)
tree57635f984b22a86f3fbc3bb89a3cf3193a68ca3e
parentb6c1d7ac1eec3b7f8c1ba03d5c0bb3c52f95bec9 (diff)
n1sdp: pcie: add quirk support enabling remote chip PCIeN1SDP-2021.05.26N1SDP-2021.04.26n1sdp
Upstream-Status: Inappropriate [will not be submitted as its an hack required to fix the hardware issue] Base address mapping for remote chip Root PCIe ECAM space. Remote Chip PCIe topology is enumerated in Firmware and current change takes referecne of enumerated PCIe hierarchy of Remote chip into the kernel and include in complete PCIe topology for kernel framework Signed-off-by: Sayanta Pattanayak <sayanta.pattanayak@arm.com> Signed-off-by: Khasim Syed Mohammed <khasim.mohammed@arm.com>
-rw-r--r--drivers/acpi/pci_mcfg.c1
-rw-r--r--drivers/pci/controller/pcie-n1sdp.c36
-rw-r--r--include/linux/pci-ecam.h1
3 files changed, 35 insertions, 3 deletions
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
index f7a7d6e87780..0523f485c930 100644
--- a/drivers/acpi/pci_mcfg.c
+++ b/drivers/acpi/pci_mcfg.c
@@ -149,6 +149,7 @@ static struct mcfg_fixup mcfg_quirks[] = {
/* N1SDP SoC with v1 PCIe controller */
N1SDP_ECAM_MCFG(0x20181101, 0, &pci_n1sdp_pcie_ecam_ops),
N1SDP_ECAM_MCFG(0x20181101, 1, &pci_n1sdp_ccix_ecam_ops),
+ N1SDP_ECAM_MCFG(0x20181101, 2, &pci_n1sdp_remote_pcie_ecam_ops),
#define ALTRA_ECAM_QUIRK(rev, seg) \
{ "Ampere", "Altra ", rev, seg, MCFG_BUS_ANY, &pci_32b_read_ops }
diff --git a/drivers/pci/controller/pcie-n1sdp.c b/drivers/pci/controller/pcie-n1sdp.c
index 45bbe506045a..01f601e36343 100644
--- a/drivers/pci/controller/pcie-n1sdp.c
+++ b/drivers/pci/controller/pcie-n1sdp.c
@@ -28,8 +28,11 @@
/* Platform specific values as hardcoded in the firmware. */
#define AP_NS_SHARED_MEM_BASE 0x06000000
-#define MAX_SEGMENTS 2
+
+/* Two PCIe root complexes in One Chip + One PCIe RC in Remote Chip*/
+#define MAX_SEGMENTS 3
#define BDF_TABLE_SIZE SZ_16K
+#define REMOTE_CHIP_ADDR_OFFSET 0x40000000000
/*
* Shared memory layout as written by the SCP upon boot time:
@@ -100,7 +103,10 @@ static int pci_n1sdp_init(struct pci_config_window *cfg, unsigned int segment)
if (segment >= MAX_SEGMENTS)
return -ENODEV;
- table_base = AP_NS_SHARED_MEM_BASE + segment * BDF_TABLE_SIZE;
+ if (segment > 1)
+ table_base = AP_NS_SHARED_MEM_BASE + REMOTE_CHIP_ADDR_OFFSET;
+ else
+ table_base = AP_NS_SHARED_MEM_BASE + segment * BDF_TABLE_SIZE;
if (!request_mem_region(table_base, BDF_TABLE_SIZE,
"PCIe valid BDFs")) {
@@ -122,9 +128,15 @@ static int pci_n1sdp_init(struct pci_config_window *cfg, unsigned int segment)
memcpy_fromio(pcie_discovery_data[segment], shared_data, bdfs_size);
- rc_remapped_addr[segment] = devm_ioremap(dev,
+ if (segment > 1)
+ rc_remapped_addr[segment] = devm_ioremap(dev,
+ shared_data->rc_base_addr + REMOTE_CHIP_ADDR_OFFSET,
+ PCI_CFG_SPACE_EXP_SIZE);
+ else
+ rc_remapped_addr[segment] = devm_ioremap(dev,
shared_data->rc_base_addr,
PCI_CFG_SPACE_EXP_SIZE);
+
if (!rc_remapped_addr[segment]) {
dev_err(dev, "Cannot remap root port base\n");
return -ENOMEM;
@@ -145,6 +157,11 @@ static int pci_n1sdp_ccix_init(struct pci_config_window *cfg)
return pci_n1sdp_init(cfg, 1);
}
+static int pci_n1sdp_remote_pcie_init(struct pci_config_window *cfg)
+{
+ return pci_n1sdp_init(cfg, 2);
+}
+
const struct pci_ecam_ops pci_n1sdp_pcie_ecam_ops = {
.bus_shift = 20,
.init = pci_n1sdp_pcie_init,
@@ -165,6 +182,16 @@ const struct pci_ecam_ops pci_n1sdp_ccix_ecam_ops = {
}
};
+const struct pci_ecam_ops pci_n1sdp_remote_pcie_ecam_ops = {
+ .bus_shift = 20,
+ .init = pci_n1sdp_remote_pcie_init,
+ .pci_ops = {
+ .map_bus = pci_n1sdp_map_bus,
+ .read = pci_generic_config_read32,
+ .write = pci_generic_config_write32,
+ }
+};
+
struct of_device_id n1sdp_pcie_of_match[] = {
{ .compatible = "arm,n1sdp-pcie" },
{ },
@@ -188,6 +215,9 @@ static int n1sdp_pcie_probe(struct platform_device *pdev)
case 1:
n1sdp_pcie_of_match[0].data = &pci_n1sdp_ccix_ecam_ops;
return pci_host_common_probe(pdev);
+ case 2:
+ n1sdp_pcie_of_match[0].data = &pci_n1sdp_remote_pcie_ecam_ops;
+ return pci_host_common_probe(pdev);
}
dev_err(&pdev->dev, "Invalid segment number, must be smaller than %d\n",
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
index d3959ada44af..08d9684b7dc8 100644
--- a/include/linux/pci-ecam.h
+++ b/include/linux/pci-ecam.h
@@ -60,6 +60,7 @@ extern const struct pci_ecam_ops xgene_v2_pcie_ecam_ops; /* APM X-Gene PCIe v2.x
extern const struct pci_ecam_ops al_pcie_ops; /* Amazon Annapurna Labs PCIe */
extern const struct pci_ecam_ops pci_n1sdp_pcie_ecam_ops; /* Arm N1SDP PCIe */
extern const struct pci_ecam_ops pci_n1sdp_ccix_ecam_ops; /* Arm N1SDP PCIe */
+extern const struct pci_ecam_ops pci_n1sdp_remote_pcie_ecam_ops; /* Arm N1SDP PCIe */
#endif
#if IS_ENABLED(CONFIG_PCI_HOST_COMMON)