^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2016 Broadcom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Jayachandran C <jchandra@broadcom.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016 Semihalf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Tomasz Nowicki <tn@semihalf.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define pr_fmt(fmt) "ACPI: " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci-acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pci-ecam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Structure to hold entries from the MCFG table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct mcfg_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) phys_addr_t addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) u16 segment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u8 bus_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) u8 bus_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #ifdef CONFIG_PCI_QUIRKS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct mcfg_fixup {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) char oem_id[ACPI_OEM_ID_SIZE + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) u32 oem_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u16 segment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct resource bus_range;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) const struct pci_ecam_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct resource cfgres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define MCFG_BUS_RANGE(start, end) DEFINE_RES_NAMED((start), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) ((end) - (start) + 1), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) NULL, IORESOURCE_BUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define MCFG_BUS_ANY MCFG_BUS_RANGE(0x0, 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static struct mcfg_fixup mcfg_quirks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* { OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define AL_ECAM(table_id, rev, seg, ops) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { "AMAZON", table_id, rev, seg, MCFG_BUS_ANY, ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) AL_ECAM("GRAVITON", 0, 0, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) AL_ECAM("GRAVITON", 0, 1, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) AL_ECAM("GRAVITON", 0, 2, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) AL_ECAM("GRAVITON", 0, 3, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) AL_ECAM("GRAVITON", 0, 4, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) AL_ECAM("GRAVITON", 0, 5, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) AL_ECAM("GRAVITON", 0, 6, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) AL_ECAM("GRAVITON", 0, 7, &al_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define QCOM_ECAM32(seg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { "QCOM ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) QCOM_ECAM32(0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) QCOM_ECAM32(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) QCOM_ECAM32(2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) QCOM_ECAM32(3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) QCOM_ECAM32(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) QCOM_ECAM32(5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) QCOM_ECAM32(6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) QCOM_ECAM32(7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define RKCP_ECAM(seg, table_id, ops) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { "RKCP ", table_id, 0x0000, seg, MCFG_BUS_ANY, ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) RKCP_ECAM(0, "RK3588 ", &rk_pcie_ecam_ops), /* pcie3x4: Name (_SEG, Zero) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define HISI_QUAD_DOM(table_id, seg, ops) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { "HISI ", table_id, 0, (seg) + 0, MCFG_BUS_ANY, ops }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { "HISI ", table_id, 0, (seg) + 1, MCFG_BUS_ANY, ops }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { "HISI ", table_id, 0, (seg) + 2, MCFG_BUS_ANY, ops }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { "HISI ", table_id, 0, (seg) + 3, MCFG_BUS_ANY, ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) HISI_QUAD_DOM("HIP05 ", 0, &hisi_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) HISI_QUAD_DOM("HIP06 ", 0, &hisi_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) HISI_QUAD_DOM("HIP07 ", 0, &hisi_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) HISI_QUAD_DOM("HIP07 ", 4, &hisi_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) HISI_QUAD_DOM("HIP07 ", 8, &hisi_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) HISI_QUAD_DOM("HIP07 ", 12, &hisi_pcie_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define THUNDER_PEM_RES(addr, node) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) DEFINE_RES_MEM((addr) + ((u64) (node) << 44), 0x39 * SZ_16M)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define THUNDER_PEM_QUIRK(rev, node) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) { "CAVIUM", "THUNDERX", rev, 4 + (10 * (node)), MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88001f000000UL, node) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) { "CAVIUM", "THUNDERX", rev, 5 + (10 * (node)), MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x884057000000UL, node) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { "CAVIUM", "THUNDERX", rev, 6 + (10 * (node)), MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88808f000000UL, node) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { "CAVIUM", "THUNDERX", rev, 7 + (10 * (node)), MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89001f000000UL, node) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { "CAVIUM", "THUNDERX", rev, 8 + (10 * (node)), MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x894057000000UL, node) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { "CAVIUM", "THUNDERX", rev, 9 + (10 * (node)), MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89808f000000UL, node) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define THUNDER_ECAM_QUIRK(rev, seg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { "CAVIUM", "THUNDERX", rev, seg, MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) &pci_thunder_ecam_ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* SoC pass2.x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) THUNDER_PEM_QUIRK(1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) THUNDER_PEM_QUIRK(1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) THUNDER_ECAM_QUIRK(1, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* SoC pass1.x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) THUNDER_PEM_QUIRK(2, 0), /* off-chip devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) THUNDER_PEM_QUIRK(2, 1), /* off-chip devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) THUNDER_ECAM_QUIRK(2, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) THUNDER_ECAM_QUIRK(2, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) THUNDER_ECAM_QUIRK(2, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) THUNDER_ECAM_QUIRK(2, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) THUNDER_ECAM_QUIRK(2, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) THUNDER_ECAM_QUIRK(2, 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) THUNDER_ECAM_QUIRK(2, 12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) THUNDER_ECAM_QUIRK(2, 13),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define XGENE_V1_ECAM_MCFG(rev, seg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) &xgene_v1_pcie_ecam_ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define XGENE_V2_ECAM_MCFG(rev, seg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {"APM ", "XGENE ", rev, seg, MCFG_BUS_ANY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) &xgene_v2_pcie_ecam_ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* X-Gene SoC with v1 PCIe controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) XGENE_V1_ECAM_MCFG(1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) XGENE_V1_ECAM_MCFG(1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) XGENE_V1_ECAM_MCFG(1, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) XGENE_V1_ECAM_MCFG(1, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) XGENE_V1_ECAM_MCFG(1, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) XGENE_V1_ECAM_MCFG(2, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) XGENE_V1_ECAM_MCFG(2, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) XGENE_V1_ECAM_MCFG(2, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) XGENE_V1_ECAM_MCFG(2, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) XGENE_V1_ECAM_MCFG(2, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* X-Gene SoC with v2.1 PCIe controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) XGENE_V2_ECAM_MCFG(3, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) XGENE_V2_ECAM_MCFG(3, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* X-Gene SoC with v2.2 PCIe controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) XGENE_V2_ECAM_MCFG(4, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) XGENE_V2_ECAM_MCFG(4, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) XGENE_V2_ECAM_MCFG(4, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #define ALTRA_ECAM_QUIRK(rev, seg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) { "Ampere", "Altra ", rev, seg, MCFG_BUS_ANY, &pci_32b_read_ops }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) ALTRA_ECAM_QUIRK(1, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ALTRA_ECAM_QUIRK(1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ALTRA_ECAM_QUIRK(1, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ALTRA_ECAM_QUIRK(1, 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ALTRA_ECAM_QUIRK(1, 4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ALTRA_ECAM_QUIRK(1, 5),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ALTRA_ECAM_QUIRK(1, 6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ALTRA_ECAM_QUIRK(1, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ALTRA_ECAM_QUIRK(1, 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ALTRA_ECAM_QUIRK(1, 9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ALTRA_ECAM_QUIRK(1, 10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ALTRA_ECAM_QUIRK(1, 11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ALTRA_ECAM_QUIRK(1, 12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ALTRA_ECAM_QUIRK(1, 13),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ALTRA_ECAM_QUIRK(1, 14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ALTRA_ECAM_QUIRK(1, 15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static char mcfg_oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static u32 mcfg_oem_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static int pci_mcfg_quirk_matches(struct mcfg_fixup *f, u16 segment,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct resource *bus_range)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (!memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) !memcmp(f->oem_table_id, mcfg_oem_table_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ACPI_OEM_TABLE_ID_SIZE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) f->oem_revision == mcfg_oem_revision &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) f->segment == segment &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) resource_contains(&f->bus_range, bus_range))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static void pci_mcfg_apply_quirks(struct acpi_pci_root *root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct resource *cfgres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) const struct pci_ecam_ops **ecam_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #ifdef CONFIG_PCI_QUIRKS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u16 segment = root->segment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct resource *bus_range = &root->secondary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct mcfg_fixup *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++, f++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (pci_mcfg_quirk_matches(f, segment, bus_range)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (f->cfgres.start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) *cfgres = f->cfgres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (f->ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *ecam_ops = f->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) dev_info(&root->device->dev, "MCFG quirk: ECAM at %pR for %pR with %ps\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) cfgres, bus_range, *ecam_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* List to save MCFG entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static LIST_HEAD(pci_mcfg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) const struct pci_ecam_ops **ecam_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) const struct pci_ecam_ops *ops = &pci_generic_ecam_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct resource *bus_res = &root->secondary;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) u16 seg = root->segment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct mcfg_entry *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* Use address from _CBA if present, otherwise lookup MCFG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (root->mcfg_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) goto skip_lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * We expect the range in bus_res in the coverage of MCFG bus range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) list_for_each_entry(e, &pci_mcfg_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (e->segment == seg && e->bus_start <= bus_res->start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) e->bus_end >= bus_res->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) root->mcfg_addr = e->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) skip_lookup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) memset(&res, 0, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (root->mcfg_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) res.start = root->mcfg_addr + (bus_res->start << 20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) res.end = res.start + (resource_size(bus_res) << 20) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) res.flags = IORESOURCE_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * Allow quirks to override default ECAM ops and CFG resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * range. This may even fabricate a CFG resource range in case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * MCFG does not have it. Invalid CFG start address means MCFG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * firmware bug or we need another quirk in array.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) pci_mcfg_apply_quirks(root, &res, &ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!res.start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *cfgres = res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *ecam_ops = ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static __init int pci_mcfg_parse(struct acpi_table_header *header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct acpi_table_mcfg *mcfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct acpi_mcfg_allocation *mptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct mcfg_entry *e, *arr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int i, n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (header->length < sizeof(struct acpi_table_mcfg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) n = (header->length - sizeof(struct acpi_table_mcfg)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) sizeof(struct acpi_mcfg_allocation);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) mcfg = (struct acpi_table_mcfg *)header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mptr = (struct acpi_mcfg_allocation *) &mcfg[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) arr = kcalloc(n, sizeof(*arr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!arr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) for (i = 0, e = arr; i < n; i++, mptr++, e++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) e->segment = mptr->pci_segment;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) e->addr = mptr->address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) e->bus_start = mptr->start_bus_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) e->bus_end = mptr->end_bus_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) list_add(&e->list, &pci_mcfg_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) #ifdef CONFIG_PCI_QUIRKS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* Save MCFG IDs and revision for quirks matching */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) memcpy(mcfg_oem_id, header->oem_id, ACPI_OEM_ID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) memcpy(mcfg_oem_table_id, header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) mcfg_oem_revision = header->oem_revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) pr_info("MCFG table detected, %d entries\n", n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* Interface called by ACPI - parse and save MCFG table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) void __init pci_mmcfg_late_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int err = acpi_table_parse(ACPI_SIG_MCFG, pci_mcfg_parse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) pr_debug("Failed to parse MCFG (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }