Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 1 | #include "qemu/osdep.h" |
| 2 | #include "hw/acpi/aml-build.h" |
| 3 | #include "hw/pci-host/gpex.h" |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 4 | #include "hw/arm/virt.h" |
| 5 | #include "hw/pci/pci_bus.h" |
| 6 | #include "hw/pci/pci_bridge.h" |
| 7 | #include "hw/pci/pcie_host.h" |
Jonathan Cameron | fc1e01e | 2022-04-29 15:40:54 +0100 | [diff] [blame] | 8 | #include "hw/acpi/cxl.h" |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 9 | |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 10 | static void acpi_dsdt_add_pci_route_table(Aml *dev, uint32_t irq) |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 11 | { |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 12 | Aml *method, *crs; |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 13 | int i, slot_no; |
| 14 | |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 15 | /* Declare the PCI Routing Table. */ |
| 16 | Aml *rt_pkg = aml_varpackage(PCI_SLOT_MAX * PCI_NUM_PINS); |
| 17 | for (slot_no = 0; slot_no < PCI_SLOT_MAX; slot_no++) { |
| 18 | for (i = 0; i < PCI_NUM_PINS; i++) { |
| 19 | int gsi = (i + slot_no) % PCI_NUM_PINS; |
| 20 | Aml *pkg = aml_package(4); |
| 21 | aml_append(pkg, aml_int((slot_no << 16) | 0xFFFF)); |
| 22 | aml_append(pkg, aml_int(i)); |
| 23 | aml_append(pkg, aml_name("GSI%d", gsi)); |
| 24 | aml_append(pkg, aml_int(0)); |
| 25 | aml_append(rt_pkg, pkg); |
| 26 | } |
| 27 | } |
| 28 | aml_append(dev, aml_name_decl("_PRT", rt_pkg)); |
| 29 | |
| 30 | /* Create GSI link device */ |
| 31 | for (i = 0; i < PCI_NUM_PINS; i++) { |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 32 | uint32_t irqs = irq + i; |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 33 | Aml *dev_gsi = aml_device("GSI%d", i); |
| 34 | aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F"))); |
| 35 | aml_append(dev_gsi, aml_name_decl("_UID", aml_int(i))); |
| 36 | crs = aml_resource_template(); |
| 37 | aml_append(crs, |
| 38 | aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, |
| 39 | AML_EXCLUSIVE, &irqs, 1)); |
| 40 | aml_append(dev_gsi, aml_name_decl("_PRS", crs)); |
| 41 | crs = aml_resource_template(); |
| 42 | aml_append(crs, |
| 43 | aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, |
| 44 | AML_EXCLUSIVE, &irqs, 1)); |
| 45 | aml_append(dev_gsi, aml_name_decl("_CRS", crs)); |
| 46 | method = aml_method("_SRS", 1, AML_NOTSERIALIZED); |
| 47 | aml_append(dev_gsi, method); |
| 48 | aml_append(dev, dev_gsi); |
| 49 | } |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 50 | } |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 51 | |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 52 | static void acpi_dsdt_add_pci_osc(Aml *dev) |
| 53 | { |
| 54 | Aml *method, *UUID, *ifctx, *ifctx1, *elsectx, *buf; |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 55 | |
| 56 | /* Declare an _OSC (OS Control Handoff) method */ |
| 57 | aml_append(dev, aml_name_decl("SUPP", aml_int(0))); |
| 58 | aml_append(dev, aml_name_decl("CTRL", aml_int(0))); |
| 59 | method = aml_method("_OSC", 4, AML_NOTSERIALIZED); |
| 60 | aml_append(method, |
| 61 | aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); |
| 62 | |
| 63 | /* PCI Firmware Specification 3.0 |
| 64 | * 4.5.1. _OSC Interface for PCI Host Bridge Devices |
| 65 | * The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is |
| 66 | * identified by the Universal Unique IDentifier (UUID) |
| 67 | * 33DB4D5B-1FF7-401C-9657-7441C03DD766 |
| 68 | */ |
| 69 | UUID = aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"); |
| 70 | ifctx = aml_if(aml_equal(aml_arg(0), UUID)); |
| 71 | aml_append(ifctx, |
| 72 | aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); |
| 73 | aml_append(ifctx, |
| 74 | aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); |
| 75 | aml_append(ifctx, aml_store(aml_name("CDW2"), aml_name("SUPP"))); |
| 76 | aml_append(ifctx, aml_store(aml_name("CDW3"), aml_name("CTRL"))); |
| 77 | |
| 78 | /* |
| 79 | * Allow OS control for all 5 features: |
| 80 | * PCIeHotplug SHPCHotplug PME AER PCIeCapability. |
| 81 | */ |
| 82 | aml_append(ifctx, aml_and(aml_name("CTRL"), aml_int(0x1F), |
| 83 | aml_name("CTRL"))); |
| 84 | |
| 85 | ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(0x1)))); |
| 86 | aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x08), |
| 87 | aml_name("CDW1"))); |
| 88 | aml_append(ifctx, ifctx1); |
| 89 | |
| 90 | ifctx1 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), aml_name("CTRL")))); |
| 91 | aml_append(ifctx1, aml_or(aml_name("CDW1"), aml_int(0x10), |
| 92 | aml_name("CDW1"))); |
| 93 | aml_append(ifctx, ifctx1); |
| 94 | |
| 95 | aml_append(ifctx, aml_store(aml_name("CTRL"), aml_name("CDW3"))); |
| 96 | aml_append(ifctx, aml_return(aml_arg(3))); |
| 97 | aml_append(method, ifctx); |
| 98 | |
| 99 | elsectx = aml_else(); |
| 100 | aml_append(elsectx, aml_or(aml_name("CDW1"), aml_int(4), |
| 101 | aml_name("CDW1"))); |
| 102 | aml_append(elsectx, aml_return(aml_arg(3))); |
| 103 | aml_append(method, elsectx); |
| 104 | aml_append(dev, method); |
| 105 | |
| 106 | method = aml_method("_DSM", 4, AML_NOTSERIALIZED); |
| 107 | |
| 108 | /* PCI Firmware Specification 3.0 |
| 109 | * 4.6.1. _DSM for PCI Express Slot Information |
| 110 | * The UUID in _DSM in this context is |
| 111 | * {E5C937D0-3553-4D7A-9117-EA4D19C3434D} |
| 112 | */ |
| 113 | UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); |
| 114 | ifctx = aml_if(aml_equal(aml_arg(0), UUID)); |
| 115 | ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0))); |
Michael S. Tsirkin | 40c3472 | 2021-07-27 05:18:47 -0400 | [diff] [blame] | 116 | uint8_t byte_list[1] = {1}; |
| 117 | buf = aml_buffer(1, byte_list); |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 118 | aml_append(ifctx1, aml_return(buf)); |
| 119 | aml_append(ifctx, ifctx1); |
| 120 | aml_append(method, ifctx); |
| 121 | |
| 122 | byte_list[0] = 0; |
| 123 | buf = aml_buffer(1, byte_list); |
| 124 | aml_append(method, aml_return(buf)); |
| 125 | aml_append(dev, method); |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) |
| 129 | { |
| 130 | int nr_pcie_buses = cfg->ecam.size / PCIE_MMCFG_SIZE_MIN; |
| 131 | Aml *method, *crs, *dev, *rbuf; |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 132 | PCIBus *bus = cfg->bus; |
| 133 | CrsRangeSet crs_range_set; |
Jiahui Cen | aee519c | 2021-01-14 18:06:40 +0800 | [diff] [blame] | 134 | CrsRangeEntry *entry; |
| 135 | int i; |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 136 | |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 137 | /* start to construct the tables for pxb */ |
| 138 | crs_range_set_init(&crs_range_set); |
| 139 | if (bus) { |
| 140 | QLIST_FOREACH(bus, &bus->child, sibling) { |
| 141 | uint8_t bus_num = pci_bus_num(bus); |
| 142 | uint8_t numa_node = pci_bus_numa_node(bus); |
Jonathan Cameron | fc1e01e | 2022-04-29 15:40:54 +0100 | [diff] [blame] | 143 | bool is_cxl = pci_bus_is_cxl(bus); |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 144 | |
| 145 | if (!pci_bus_is_root(bus)) { |
| 146 | continue; |
| 147 | } |
| 148 | |
| 149 | /* |
| 150 | * 0 - (nr_pcie_buses - 1) is the bus range for the main |
| 151 | * host-bridge and it equals the MIN of the |
| 152 | * busNr defined for pxb-pcie. |
| 153 | */ |
| 154 | if (bus_num < nr_pcie_buses) { |
| 155 | nr_pcie_buses = bus_num; |
| 156 | } |
| 157 | |
| 158 | dev = aml_device("PC%.02X", bus_num); |
Jonathan Cameron | fc1e01e | 2022-04-29 15:40:54 +0100 | [diff] [blame] | 159 | if (is_cxl) { |
| 160 | struct Aml *pkg = aml_package(2); |
| 161 | aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0016"))); |
| 162 | aml_append(pkg, aml_eisaid("PNP0A08")); |
| 163 | aml_append(pkg, aml_eisaid("PNP0A03")); |
| 164 | aml_append(dev, aml_name_decl("_CID", pkg)); |
| 165 | } else { |
| 166 | aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08"))); |
| 167 | aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03"))); |
| 168 | } |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 169 | aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num))); |
| 170 | aml_append(dev, aml_name_decl("_UID", aml_int(bus_num))); |
| 171 | aml_append(dev, aml_name_decl("_STR", aml_unicode("pxb Device"))); |
Xingang Wang | b48088d | 2021-02-05 01:56:44 +0000 | [diff] [blame] | 172 | aml_append(dev, aml_name_decl("_CCA", aml_int(1))); |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 173 | if (numa_node != NUMA_NODE_UNASSIGNED) { |
| 174 | aml_append(dev, aml_name_decl("_PXM", aml_int(numa_node))); |
| 175 | } |
| 176 | |
| 177 | acpi_dsdt_add_pci_route_table(dev, cfg->irq); |
| 178 | |
| 179 | /* |
Michael Tokarev | f1c0cff | 2023-07-14 14:27:04 +0300 | [diff] [blame] | 180 | * Resources defined for PXBs are composed of the following parts: |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 181 | * 1. The resources the pci-brige/pcie-root-port need. |
| 182 | * 2. The resources the devices behind pxb need. |
| 183 | */ |
Jiahui Cen | e41ee85 | 2021-01-14 18:06:38 +0800 | [diff] [blame] | 184 | crs = build_crs(PCI_HOST_BRIDGE(BUS(bus)->parent), &crs_range_set, |
| 185 | cfg->pio.base, 0, 0, 0); |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 186 | aml_append(dev, aml_name_decl("_CRS", crs)); |
| 187 | |
Jonathan Cameron | fc1e01e | 2022-04-29 15:40:54 +0100 | [diff] [blame] | 188 | if (is_cxl) { |
| 189 | build_cxl_osc_method(dev); |
| 190 | } else { |
| 191 | acpi_dsdt_add_pci_osc(dev); |
| 192 | } |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 193 | |
| 194 | aml_append(scope, dev); |
| 195 | } |
| 196 | } |
Yubo Miao | 6f9765f | 2020-11-19 09:48:37 +0800 | [diff] [blame] | 197 | |
| 198 | /* tables for the main */ |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 199 | dev = aml_device("%s", "PCI0"); |
| 200 | aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A08"))); |
| 201 | aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03"))); |
| 202 | aml_append(dev, aml_name_decl("_SEG", aml_int(0))); |
| 203 | aml_append(dev, aml_name_decl("_BBN", aml_int(0))); |
| 204 | aml_append(dev, aml_name_decl("_UID", aml_int(0))); |
| 205 | aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device"))); |
| 206 | aml_append(dev, aml_name_decl("_CCA", aml_int(1))); |
| 207 | |
| 208 | acpi_dsdt_add_pci_route_table(dev, cfg->irq); |
| 209 | |
| 210 | method = aml_method("_CBA", 0, AML_NOTSERIALIZED); |
| 211 | aml_append(method, aml_return(aml_int(cfg->ecam.base))); |
| 212 | aml_append(dev, method); |
| 213 | |
Jiahui Cen | aee519c | 2021-01-14 18:06:40 +0800 | [diff] [blame] | 214 | /* |
| 215 | * At this point crs_range_set has all the ranges used by pci |
| 216 | * busses *other* than PCI0. These ranges will be excluded from |
| 217 | * the PCI0._CRS. |
| 218 | */ |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 219 | rbuf = aml_resource_template(); |
| 220 | aml_append(rbuf, |
| 221 | aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, |
| 222 | 0x0000, 0x0000, nr_pcie_buses - 1, 0x0000, |
| 223 | nr_pcie_buses)); |
| 224 | if (cfg->mmio32.size) { |
Jiahui Cen | aee519c | 2021-01-14 18:06:40 +0800 | [diff] [blame] | 225 | crs_replace_with_free_ranges(crs_range_set.mem_ranges, |
| 226 | cfg->mmio32.base, |
| 227 | cfg->mmio32.base + cfg->mmio32.size - 1); |
| 228 | for (i = 0; i < crs_range_set.mem_ranges->len; i++) { |
| 229 | entry = g_ptr_array_index(crs_range_set.mem_ranges, i); |
| 230 | aml_append(rbuf, |
| 231 | aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, |
| 232 | AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, |
| 233 | entry->base, entry->limit, |
| 234 | 0x0000, entry->limit - entry->base + 1)); |
| 235 | } |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 236 | } |
| 237 | if (cfg->pio.size) { |
Jiahui Cen | aee519c | 2021-01-14 18:06:40 +0800 | [diff] [blame] | 238 | crs_replace_with_free_ranges(crs_range_set.io_ranges, |
| 239 | 0x0000, |
| 240 | cfg->pio.size - 1); |
| 241 | for (i = 0; i < crs_range_set.io_ranges->len; i++) { |
| 242 | entry = g_ptr_array_index(crs_range_set.io_ranges, i); |
| 243 | aml_append(rbuf, |
| 244 | aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, |
| 245 | AML_ENTIRE_RANGE, 0x0000, entry->base, |
| 246 | entry->limit, cfg->pio.base, |
| 247 | entry->limit - entry->base + 1)); |
| 248 | } |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 249 | } |
| 250 | if (cfg->mmio64.size) { |
Jiahui Cen | aee519c | 2021-01-14 18:06:40 +0800 | [diff] [blame] | 251 | crs_replace_with_free_ranges(crs_range_set.mem_64bit_ranges, |
| 252 | cfg->mmio64.base, |
| 253 | cfg->mmio64.base + cfg->mmio64.size - 1); |
| 254 | for (i = 0; i < crs_range_set.mem_64bit_ranges->len; i++) { |
| 255 | entry = g_ptr_array_index(crs_range_set.mem_64bit_ranges, i); |
| 256 | aml_append(rbuf, |
| 257 | aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, |
| 258 | AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, |
| 259 | entry->base, |
| 260 | entry->limit, 0x0000, |
| 261 | entry->limit - entry->base + 1)); |
| 262 | } |
Yubo Miao | a0e2905 | 2020-11-19 09:48:33 +0800 | [diff] [blame] | 263 | } |
| 264 | aml_append(dev, aml_name_decl("_CRS", rbuf)); |
| 265 | |
| 266 | acpi_dsdt_add_pci_osc(dev); |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 267 | |
| 268 | Aml *dev_res0 = aml_device("%s", "RES0"); |
| 269 | aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02"))); |
| 270 | crs = aml_resource_template(); |
| 271 | aml_append(crs, |
| 272 | aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, |
| 273 | AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, |
| 274 | cfg->ecam.base, |
| 275 | cfg->ecam.base + cfg->ecam.size - 1, |
| 276 | 0x0000, |
| 277 | cfg->ecam.size)); |
| 278 | aml_append(dev_res0, aml_name_decl("_CRS", crs)); |
| 279 | aml_append(dev, dev_res0); |
| 280 | aml_append(scope, dev); |
Jiahui Cen | aee519c | 2021-01-14 18:06:40 +0800 | [diff] [blame] | 281 | |
| 282 | crs_range_set_free(&crs_range_set); |
Gerd Hoffmann | 5b85eab | 2020-09-28 12:42:46 +0200 | [diff] [blame] | 283 | } |
Sunil V L | 8f6a487 | 2023-12-18 20:32:44 +0530 | [diff] [blame] | 284 | |
| 285 | void acpi_dsdt_add_gpex_host(Aml *scope, uint32_t irq) |
| 286 | { |
| 287 | bool ambig; |
| 288 | Object *obj = object_resolve_path_type("", TYPE_GPEX_HOST, &ambig); |
| 289 | |
| 290 | if (!obj || ambig) { |
| 291 | return; |
| 292 | } |
| 293 | |
| 294 | GPEX_HOST(obj)->gpex_cfg.irq = irq; |
| 295 | acpi_dsdt_add_gpex(scope, &GPEX_HOST(obj)->gpex_cfg); |
| 296 | } |