137 lines
5.4 KiB
Diff
137 lines
5.4 KiB
Diff
From b59e0d6c6035db80fc9044df0333f96ede53ad7a Mon Sep 17 00:00:00 2001
|
|
From: Sayanta Pattanayak <sayanta.pattanayak@arm.com>
|
|
Date: Wed, 9 Feb 2022 20:37:43 +0530
|
|
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 2d4c1c699ffe..27f1e9a45c17 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 */
|
|
|
|
#ifdef CONFIG_LOONGARCH
|
|
diff --git a/drivers/pci/controller/pcie-n1sdp.c b/drivers/pci/controller/pcie-n1sdp.c
|
|
index 408699b9dcb1..b3b02417fd7d 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 b3cf3adeab28..d4316795c00d 100644
|
|
--- a/include/linux/pci-ecam.h
|
|
+++ b/include/linux/pci-ecam.h
|
|
@@ -90,6 +90,7 @@ extern const struct pci_ecam_ops tegra194_pcie_ops; /* Tegra194 PCIe */
|
|
extern const struct pci_ecam_ops loongson_pci_ecam_ops; /* Loongson 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)
|