1 /* 2 * Based on acpi.c from coreboot 3 * 4 * Copyright (C) 2015, Saket Sinha <saket.sinha89@gmail.com> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <cpu.h> 11 #include <dm.h> 12 #include <dm/uclass-internal.h> 13 #include <asm/acpi_table.h> 14 #include <asm/lapic.h> 15 #include <asm/tables.h> 16 17 /* 18 * IASL compiles the dsdt entries and writes the hex values 19 * to a C array AmlCode[] (see dsdt.c). 20 */ 21 extern const unsigned char AmlCode[]; 22 23 /** 24 * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length 25 * and checksum. 26 */ 27 static void acpi_add_table(struct acpi_rsdp *rsdp, void *table) 28 { 29 int i, entries_num; 30 struct acpi_rsdt *rsdt; 31 struct acpi_xsdt *xsdt = NULL; 32 33 /* The RSDT is mandatory while the XSDT is not */ 34 rsdt = (struct acpi_rsdt *)rsdp->rsdt_address; 35 36 if (rsdp->xsdt_address) 37 xsdt = (struct acpi_xsdt *)((u32)rsdp->xsdt_address); 38 39 /* This should always be MAX_ACPI_TABLES */ 40 entries_num = ARRAY_SIZE(rsdt->entry); 41 42 for (i = 0; i < entries_num; i++) { 43 if (rsdt->entry[i] == 0) 44 break; 45 } 46 47 if (i >= entries_num) { 48 debug("ACPI: Error: too many tables\n"); 49 return; 50 } 51 52 /* Add table to the RSDT */ 53 rsdt->entry[i] = (u32)table; 54 55 /* Fix RSDT length or the kernel will assume invalid entries */ 56 rsdt->header.length = sizeof(struct acpi_table_header) + 57 (sizeof(u32) * (i + 1)); 58 59 /* Re-calculate checksum */ 60 rsdt->header.checksum = 0; 61 rsdt->header.checksum = table_compute_checksum((u8 *)rsdt, 62 rsdt->header.length); 63 64 /* 65 * And now the same thing for the XSDT. We use the same index as for 66 * now we want the XSDT and RSDT to always be in sync in U-Boot 67 */ 68 if (xsdt) { 69 /* Add table to the XSDT */ 70 xsdt->entry[i] = (u64)(u32)table; 71 72 /* Fix XSDT length */ 73 xsdt->header.length = sizeof(struct acpi_table_header) + 74 (sizeof(u64) * (i + 1)); 75 76 /* Re-calculate checksum */ 77 xsdt->header.checksum = 0; 78 xsdt->header.checksum = table_compute_checksum((u8 *)xsdt, 79 xsdt->header.length); 80 } 81 } 82 83 static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic, 84 u8 cpu, u8 apic) 85 { 86 lapic->type = ACPI_APIC_LAPIC; /* Local APIC structure */ 87 lapic->length = sizeof(struct acpi_madt_lapic); 88 lapic->flags = LOCAL_APIC_FLAG_ENABLED; /* Processor/LAPIC enabled */ 89 lapic->processor_id = cpu; 90 lapic->apic_id = apic; 91 92 return lapic->length; 93 } 94 95 unsigned long acpi_create_madt_lapics(unsigned long current) 96 { 97 struct udevice *dev; 98 99 for (uclass_find_first_device(UCLASS_CPU, &dev); 100 dev; 101 uclass_find_next_device(&dev)) { 102 struct cpu_platdata *plat = dev_get_parent_platdata(dev); 103 104 current += acpi_create_madt_lapic( 105 (struct acpi_madt_lapic *)current, 106 plat->cpu_id, plat->cpu_id); 107 } 108 return current; 109 } 110 111 int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id, u32 addr, 112 u32 gsi_base) 113 { 114 ioapic->type = ACPI_APIC_IOAPIC; 115 ioapic->length = sizeof(struct acpi_madt_ioapic); 116 ioapic->reserved = 0x00; 117 ioapic->gsi_base = gsi_base; 118 ioapic->ioapic_id = id; 119 ioapic->ioapic_addr = addr; 120 121 return ioapic->length; 122 } 123 124 int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride, 125 u8 bus, u8 source, u32 gsirq, u16 flags) 126 { 127 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE; 128 irqoverride->length = sizeof(struct acpi_madt_irqoverride); 129 irqoverride->bus = bus; 130 irqoverride->source = source; 131 irqoverride->gsirq = gsirq; 132 irqoverride->flags = flags; 133 134 return irqoverride->length; 135 } 136 137 int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi, 138 u8 cpu, u16 flags, u8 lint) 139 { 140 lapic_nmi->type = ACPI_APIC_LAPIC_NMI; 141 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi); 142 lapic_nmi->flags = flags; 143 lapic_nmi->processor_id = cpu; 144 lapic_nmi->lint = lint; 145 146 return lapic_nmi->length; 147 } 148 149 void acpi_fill_header(struct acpi_table_header *header, char *signature) 150 { 151 memcpy(header->signature, signature, 4); 152 memcpy(header->oem_id, OEM_ID, 6); 153 memcpy(header->oem_table_id, OEM_TABLE_ID, 8); 154 memcpy(header->aslc_id, ASLC_ID, 4); 155 } 156 157 static void acpi_create_madt(struct acpi_madt *madt) 158 { 159 struct acpi_table_header *header = &(madt->header); 160 unsigned long current = (unsigned long)madt + sizeof(struct acpi_madt); 161 162 memset((void *)madt, 0, sizeof(struct acpi_madt)); 163 164 /* Fill out header fields */ 165 acpi_fill_header(header, "APIC"); 166 header->length = sizeof(struct acpi_madt); 167 168 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */ 169 header->revision = ACPI_REV_ACPI_2_0; 170 171 madt->lapic_addr = LAPIC_DEFAULT_BASE; 172 madt->flags = ACPI_MADT_PCAT_COMPAT; 173 174 current = acpi_fill_madt(current); 175 176 /* (Re)calculate length and checksum */ 177 header->length = current - (unsigned long)madt; 178 179 header->checksum = table_compute_checksum((void *)madt, header->length); 180 } 181 182 static int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, 183 u32 base, u16 seg_nr, u8 start, u8 end) 184 { 185 memset(mmconfig, 0, sizeof(*mmconfig)); 186 mmconfig->base_address_l = base; 187 mmconfig->base_address_h = 0; 188 mmconfig->pci_segment_group_number = seg_nr; 189 mmconfig->start_bus_number = start; 190 mmconfig->end_bus_number = end; 191 192 return sizeof(struct acpi_mcfg_mmconfig); 193 } 194 195 static unsigned long acpi_fill_mcfg(unsigned long current) 196 { 197 current += acpi_create_mcfg_mmconfig 198 ((struct acpi_mcfg_mmconfig *)current, 199 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255); 200 201 return current; 202 } 203 204 /* MCFG is defined in the PCI Firmware Specification 3.0 */ 205 static void acpi_create_mcfg(struct acpi_mcfg *mcfg) 206 { 207 struct acpi_table_header *header = &(mcfg->header); 208 unsigned long current = (unsigned long)mcfg + sizeof(struct acpi_mcfg); 209 210 memset((void *)mcfg, 0, sizeof(struct acpi_mcfg)); 211 212 /* Fill out header fields */ 213 acpi_fill_header(header, "MCFG"); 214 header->length = sizeof(struct acpi_mcfg); 215 216 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */ 217 header->revision = ACPI_REV_ACPI_2_0; 218 219 current = acpi_fill_mcfg(current); 220 221 /* (Re)calculate length and checksum */ 222 header->length = current - (unsigned long)mcfg; 223 header->checksum = table_compute_checksum((void *)mcfg, header->length); 224 } 225 226 static void acpi_create_facs(struct acpi_facs *facs) 227 { 228 memset((void *)facs, 0, sizeof(struct acpi_facs)); 229 230 memcpy(facs->signature, "FACS", 4); 231 facs->length = sizeof(struct acpi_facs); 232 facs->hardware_signature = 0; 233 facs->firmware_waking_vector = 0; 234 facs->global_lock = 0; 235 facs->flags = 0; 236 facs->x_firmware_waking_vector_l = 0; 237 facs->x_firmware_waking_vector_h = 0; 238 facs->version = 1; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */ 239 } 240 241 static void acpi_write_rsdt(struct acpi_rsdt *rsdt) 242 { 243 struct acpi_table_header *header = &(rsdt->header); 244 245 /* Fill out header fields */ 246 acpi_fill_header(header, "RSDT"); 247 header->length = sizeof(struct acpi_rsdt); 248 249 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */ 250 header->revision = ACPI_REV_ACPI_2_0; 251 252 /* Entries are filled in later, we come with an empty set */ 253 254 /* Fix checksum */ 255 header->checksum = table_compute_checksum((void *)rsdt, 256 sizeof(struct acpi_rsdt)); 257 } 258 259 static void acpi_write_xsdt(struct acpi_xsdt *xsdt) 260 { 261 struct acpi_table_header *header = &(xsdt->header); 262 263 /* Fill out header fields */ 264 acpi_fill_header(header, "XSDT"); 265 header->length = sizeof(struct acpi_xsdt); 266 267 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */ 268 header->revision = ACPI_REV_ACPI_2_0; 269 270 /* Entries are filled in later, we come with an empty set */ 271 272 /* Fix checksum */ 273 header->checksum = table_compute_checksum((void *)xsdt, 274 sizeof(struct acpi_xsdt)); 275 } 276 277 static void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, 278 struct acpi_xsdt *xsdt) 279 { 280 memset(rsdp, 0, sizeof(struct acpi_rsdp)); 281 282 memcpy(rsdp->signature, RSDP_SIG, 8); 283 memcpy(rsdp->oem_id, OEM_ID, 6); 284 285 rsdp->length = sizeof(struct acpi_rsdp); 286 rsdp->rsdt_address = (u32)rsdt; 287 288 /* 289 * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2 290 * 291 * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2. 292 * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR 293 * revision 0) 294 */ 295 if (xsdt == NULL) { 296 rsdp->revision = ACPI_RSDP_REV_ACPI_1_0; 297 } else { 298 rsdp->xsdt_address = (u64)(u32)xsdt; 299 rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; 300 } 301 302 /* Calculate checksums */ 303 rsdp->checksum = table_compute_checksum((void *)rsdp, 20); 304 rsdp->ext_checksum = table_compute_checksum((void *)rsdp, 305 sizeof(struct acpi_rsdp)); 306 } 307 308 /* 309 * QEMU's version of write_acpi_tables is defined in 310 * arch/x86/cpu/qemu/fw_cfg.c 311 */ 312 u32 write_acpi_tables(u32 start) 313 { 314 u32 current; 315 struct acpi_rsdp *rsdp; 316 struct acpi_rsdt *rsdt; 317 struct acpi_xsdt *xsdt; 318 struct acpi_facs *facs; 319 struct acpi_table_header *dsdt; 320 struct acpi_fadt *fadt; 321 struct acpi_mcfg *mcfg; 322 struct acpi_madt *madt; 323 324 current = start; 325 326 /* Align ACPI tables to 16byte */ 327 current = ALIGN(current, 16); 328 329 debug("ACPI: Writing ACPI tables at %x\n", start); 330 331 /* We need at least an RSDP and an RSDT Table */ 332 rsdp = (struct acpi_rsdp *)current; 333 current += sizeof(struct acpi_rsdp); 334 current = ALIGN(current, 16); 335 rsdt = (struct acpi_rsdt *)current; 336 current += sizeof(struct acpi_rsdt); 337 current = ALIGN(current, 16); 338 xsdt = (struct acpi_xsdt *)current; 339 current += sizeof(struct acpi_xsdt); 340 current = ALIGN(current, 16); 341 342 /* clear all table memory */ 343 memset((void *)start, 0, current - start); 344 345 acpi_write_rsdp(rsdp, rsdt, xsdt); 346 acpi_write_rsdt(rsdt); 347 acpi_write_xsdt(xsdt); 348 349 debug("ACPI: * FACS\n"); 350 facs = (struct acpi_facs *)current; 351 current += sizeof(struct acpi_facs); 352 current = ALIGN(current, 16); 353 354 acpi_create_facs(facs); 355 356 debug("ACPI: * DSDT\n"); 357 dsdt = (struct acpi_table_header *)current; 358 memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header)); 359 if (dsdt->length >= sizeof(struct acpi_table_header)) { 360 current += sizeof(struct acpi_table_header); 361 memcpy((char *)current, 362 (char *)&AmlCode + sizeof(struct acpi_table_header), 363 dsdt->length - sizeof(struct acpi_table_header)); 364 current += dsdt->length - sizeof(struct acpi_table_header); 365 366 /* (Re)calculate length and checksum */ 367 dsdt->length = current - (unsigned long)dsdt; 368 dsdt->checksum = 0; 369 dsdt->checksum = table_compute_checksum((void *)dsdt, 370 dsdt->length); 371 } 372 current = ALIGN(current, 16); 373 374 debug("ACPI: * FADT\n"); 375 fadt = (struct acpi_fadt *)current; 376 current += sizeof(struct acpi_fadt); 377 current = ALIGN(current, 16); 378 acpi_create_fadt(fadt, facs, dsdt); 379 acpi_add_table(rsdp, fadt); 380 381 debug("ACPI: * MCFG\n"); 382 mcfg = (struct acpi_mcfg *)current; 383 acpi_create_mcfg(mcfg); 384 if (mcfg->header.length > sizeof(struct acpi_mcfg)) { 385 current += mcfg->header.length; 386 current = ALIGN(current, 16); 387 acpi_add_table(rsdp, mcfg); 388 } 389 390 debug("ACPI: * MADT\n"); 391 madt = (struct acpi_madt *)current; 392 acpi_create_madt(madt); 393 if (madt->header.length > sizeof(struct acpi_madt)) { 394 current += madt->header.length; 395 acpi_add_table(rsdp, madt); 396 } 397 current = ALIGN(current, 16); 398 399 debug("current = %x\n", current); 400 401 debug("ACPI: done\n"); 402 403 return current; 404 } 405