blob: 10fae06b07c39bc2e11c60e093ff77227a5e0367 [file] [log] [blame]
From 74e052b7533827af9f43d093af8f430c99357eac Mon Sep 17 00:00:00 2001
From: Vishnu Banavath <vishnu.banavath@arm.com>
Date: Tue, 23 Aug 2022 15:18:38 +0100
Subject: [PATCH] n1sdp: pcie: add quirk support enabling remote chip PCIe
Base address mapping for remote chip Root PCIe ECAM space.
When two N1SDP boards are coupled via the CCIX connection, the PCI host
complex of the remote board appears as PCIe segment 2 on the primary
board.
The resources of the secondary board, including the host complex, are
mapped at offset 0x40000000000 into the address space of the primary
board, so take that into account when accessing the remote PCIe segment.
Change-Id: I0e8d1eb119aef6444b9df854a39b24441c12195a
Signed-off-by: Sayanta Pattanayak <sayanta.pattanayak@arm.com>
Signed-off-by: Khasim Syed Mohammed <khasim.mohammed@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: sahil <sahil@arm.com>
Upstream-Status: Inappropriate [will not be submitted as its an hack required to fix the hardware issue]
Signed-off-by: Sayanta Pattanayak <sayanta.pattanayak@arm.com>
Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
Signed-off-by: Adam Johnston <adam.johnston@arm.com>
---
drivers/acpi/pci_mcfg.c | 1 +
drivers/pci/controller/pcie-n1sdp.c | 32 +++++++++++++++++++++++++----
include/linux/pci-ecam.h | 1 +
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/pci_mcfg.c b/drivers/acpi/pci_mcfg.c
index 7700d36393ec..806ed8dd0d81 100644
--- a/drivers/acpi/pci_mcfg.c
+++ b/drivers/acpi/pci_mcfg.c
@@ -178,6 +178,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),
#endif /* ARM64 */
};
diff --git a/drivers/pci/controller/pcie-n1sdp.c b/drivers/pci/controller/pcie-n1sdp.c
index 408699b9dcb1..a03665dd056a 100644
--- a/drivers/pci/controller/pcie-n1sdp.c
+++ b/drivers/pci/controller/pcie-n1sdp.c
@@ -30,8 +30,10 @@
/* Platform specific values as hardcoded in the firmware. */
#define AP_NS_SHARED_MEM_BASE 0x06000000
-#define MAX_SEGMENTS 2 /* Two PCIe root complexes. */
+/* 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:
@@ -97,12 +99,17 @@ static int pci_n1sdp_init(struct pci_config_window *cfg, unsigned int segment)
phys_addr_t table_base;
struct device *dev = cfg->parent;
struct pcie_discovery_data *shared_data;
- size_t bdfs_size;
+ size_t bdfs_size, rc_base_addr = 0;
if (segment >= MAX_SEGMENTS)
return -ENODEV;
- table_base = AP_NS_SHARED_MEM_BASE + segment * BDF_TABLE_SIZE;
+ if (segment > 1) {
+ rc_base_addr = REMOTE_CHIP_ADDR_OFFSET;
+ 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")) {
@@ -114,6 +121,7 @@ static int pci_n1sdp_init(struct pci_config_window *cfg, unsigned int segment)
table_base, BDF_TABLE_SIZE);
if (!shared_data)
return -ENOMEM;
+ rc_base_addr += shared_data->rc_base_addr;
/* Copy the valid BDFs structure to allocated normal memory. */
bdfs_size = sizeof(struct pcie_discovery_data) +
@@ -125,7 +133,7 @@ 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,
- shared_data->rc_base_addr,
+ rc_base_addr,
PCI_CFG_SPACE_EXP_SIZE);
if (!rc_remapped_addr[segment]) {
dev_err(dev, "Cannot remap root port base\n");
@@ -161,6 +169,12 @@ static int pci_n1sdp_ccix_init(struct pci_config_window *cfg)
return pci_n1sdp_init(cfg, 1);
}
+/* Called for ACPI segment 2. */
+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,
@@ -181,6 +195,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,
+ }
+};
+
static const struct of_device_id n1sdp_pcie_of_match[] = {
{ .compatible = "arm,n1sdp-pcie", .data = &pci_n1sdp_pcie_ecam_ops },
{ },
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
index e6bbc037cef8..7bd8c1d702ee 100644
--- a/include/linux/pci-ecam.h
+++ b/include/linux/pci-ecam.h
@@ -89,6 +89,7 @@ extern const struct pci_ecam_ops al_pcie_ops; /* Amazon Annapurna Labs PCIe */
extern const struct pci_ecam_ops tegra194_pcie_ops; /* Tegra194 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)