| 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) |