diff options
-rw-r--r-- | drivers/acpi/pci_mcfg.c | 1 | ||||
-rw-r--r-- | drivers/pci/controller/pcie-n1sdp.c | 36 | ||||
-rw-r--r-- | include/linux/pci-ecam.h | 1 |
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) |