2 * Based on acpi.c from coreboot
4 * Copyright (C) 2015, Saket Sinha <saket.sinha89@gmail.com>
6 * SPDX-License-Identifier: GPL-2.0+
12 #include <dm/uclass-internal.h>
14 #include <asm/acpi_table.h>
16 #include <asm/ioapic.h>
17 #include <asm/lapic.h>
18 #include <asm/tables.h>
22 * IASL compiles the dsdt entries and
23 * writes the hex values to AmlCode array.
24 * CamelCase cannot be handled here.
26 extern const unsigned char AmlCode[];
29 * Add an ACPI table to the RSDT (and XSDT) structure, recalculate length
32 static void acpi_add_table(struct acpi_rsdp *rsdp, void *table)
35 struct acpi_rsdt *rsdt;
36 struct acpi_xsdt *xsdt = NULL;
38 /* The RSDT is mandatory while the XSDT is not */
39 rsdt = (struct acpi_rsdt *)rsdp->rsdt_address;
41 if (rsdp->xsdt_address)
42 xsdt = (struct acpi_xsdt *)((u32)rsdp->xsdt_address);
44 /* This should always be MAX_ACPI_TABLES */
45 entries_num = ARRAY_SIZE(rsdt->entry);
47 for (i = 0; i < entries_num; i++) {
48 if (rsdt->entry[i] == 0)
52 if (i >= entries_num) {
53 debug("ACPI: Error: too many tables\n");
57 /* Add table to the RSDT */
58 rsdt->entry[i] = (u32)table;
60 /* Fix RSDT length or the kernel will assume invalid entries */
61 rsdt->header.length = sizeof(struct acpi_table_header) +
62 (sizeof(u32) * (i + 1));
64 /* Re-calculate checksum */
65 rsdt->header.checksum = 0;
66 rsdt->header.checksum = table_compute_checksum((u8 *)rsdt,
70 * And now the same thing for the XSDT. We use the same index as for
71 * now we want the XSDT and RSDT to always be in sync in U-Boot
74 /* Add table to the XSDT */
75 xsdt->entry[i] = (u64)(u32)table;
78 xsdt->header.length = sizeof(struct acpi_table_header) +
79 (sizeof(u64) * (i + 1));
81 /* Re-calculate checksum */
82 xsdt->header.checksum = 0;
83 xsdt->header.checksum = table_compute_checksum((u8 *)xsdt,
88 static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
91 lapic->type = ACPI_APIC_LAPIC; /* Local APIC structure */
92 lapic->length = sizeof(struct acpi_madt_lapic);
93 lapic->flags = LOCAL_APIC_FLAG_ENABLED; /* Processor/LAPIC enabled */
94 lapic->processor_id = cpu;
95 lapic->apic_id = apic;
100 unsigned long acpi_create_madt_lapics(unsigned long current)
104 for (uclass_find_first_device(UCLASS_CPU, &dev);
106 uclass_find_next_device(&dev)) {
107 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
109 current += acpi_create_madt_lapic(
110 (struct acpi_madt_lapic *)current,
111 plat->cpu_id, plat->cpu_id);
116 int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id, u32 addr,
119 ioapic->type = ACPI_APIC_IOAPIC;
120 ioapic->length = sizeof(struct acpi_madt_ioapic);
121 ioapic->reserved = 0x00;
122 ioapic->gsi_base = gsi_base;
123 ioapic->ioapic_id = id;
124 ioapic->ioapic_addr = addr;
126 return ioapic->length;
129 int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
130 u8 bus, u8 source, u32 gsirq, u16 flags)
132 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
133 irqoverride->length = sizeof(struct acpi_madt_irqoverride);
134 irqoverride->bus = bus;
135 irqoverride->source = source;
136 irqoverride->gsirq = gsirq;
137 irqoverride->flags = flags;
139 return irqoverride->length;
142 int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
143 u8 cpu, u16 flags, u8 lint)
145 lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
146 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
147 lapic_nmi->flags = flags;
148 lapic_nmi->processor_id = cpu;
149 lapic_nmi->lint = lint;
151 return lapic_nmi->length;
154 static void fill_header(struct acpi_table_header *header, char *signature,
157 memcpy(header->signature, signature, length);
158 memcpy(header->oem_id, OEM_ID, 6);
159 memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
160 memcpy(header->aslc_id, ASLC_ID, 4);
163 static void acpi_create_madt(struct acpi_madt *madt)
165 struct acpi_table_header *header = &(madt->header);
166 unsigned long current = (unsigned long)madt + sizeof(struct acpi_madt);
168 memset((void *)madt, 0, sizeof(struct acpi_madt));
170 /* Fill out header fields */
171 fill_header(header, "APIC", 4);
172 header->length = sizeof(struct acpi_madt);
174 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
175 header->revision = ACPI_REV_ACPI_2_0;
177 madt->lapic_addr = LAPIC_DEFAULT_BASE;
178 madt->flags = ACPI_MADT_PCAT_COMPAT;
180 current = acpi_fill_madt(current);
182 /* (Re)calculate length and checksum */
183 header->length = current - (unsigned long)madt;
185 header->checksum = table_compute_checksum((void *)madt, header->length);
188 static int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig,
189 u32 base, u16 seg_nr, u8 start, u8 end)
191 memset(mmconfig, 0, sizeof(*mmconfig));
192 mmconfig->base_address_l = base;
193 mmconfig->base_address_h = 0;
194 mmconfig->pci_segment_group_number = seg_nr;
195 mmconfig->start_bus_number = start;
196 mmconfig->end_bus_number = end;
198 return sizeof(struct acpi_mcfg_mmconfig);
201 static unsigned long acpi_fill_mcfg(unsigned long current)
203 current += acpi_create_mcfg_mmconfig
204 ((struct acpi_mcfg_mmconfig *)current,
205 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
210 /* MCFG is defined in the PCI Firmware Specification 3.0 */
211 static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
213 struct acpi_table_header *header = &(mcfg->header);
214 unsigned long current = (unsigned long)mcfg + sizeof(struct acpi_mcfg);
216 memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
218 /* Fill out header fields */
219 fill_header(header, "MCFG", 4);
220 header->length = sizeof(struct acpi_mcfg);
222 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
223 header->revision = ACPI_REV_ACPI_2_0;
225 current = acpi_fill_mcfg(current);
227 /* (Re)calculate length and checksum */
228 header->length = current - (unsigned long)mcfg;
229 header->checksum = table_compute_checksum((void *)mcfg, header->length);
232 static void acpi_create_facs(struct acpi_facs *facs)
234 memset((void *)facs, 0, sizeof(struct acpi_facs));
236 memcpy(facs->signature, "FACS", 4);
237 facs->length = sizeof(struct acpi_facs);
238 facs->hardware_signature = 0;
239 facs->firmware_waking_vector = 0;
240 facs->global_lock = 0;
242 facs->x_firmware_waking_vector_l = 0;
243 facs->x_firmware_waking_vector_h = 0;
244 facs->version = 1; /* ACPI 1.0: 0, ACPI 2.0/3.0: 1, ACPI 4.0: 2 */
247 static void acpi_write_rsdt(struct acpi_rsdt *rsdt)
249 struct acpi_table_header *header = &(rsdt->header);
251 /* Fill out header fields */
252 fill_header(header, "RSDT", 4);
253 header->length = sizeof(struct acpi_rsdt);
255 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
256 header->revision = ACPI_REV_ACPI_2_0;
258 /* Entries are filled in later, we come with an empty set */
261 header->checksum = table_compute_checksum((void *)rsdt,
262 sizeof(struct acpi_rsdt));
265 static void acpi_write_xsdt(struct acpi_xsdt *xsdt)
267 struct acpi_table_header *header = &(xsdt->header);
269 /* Fill out header fields */
270 fill_header(header, "XSDT", 4);
271 header->length = sizeof(struct acpi_xsdt);
273 /* ACPI 1.0/2.0: 1, ACPI 3.0: 2, ACPI 4.0: 3 */
274 header->revision = ACPI_REV_ACPI_2_0;
276 /* Entries are filled in later, we come with an empty set */
279 header->checksum = table_compute_checksum((void *)xsdt,
280 sizeof(struct acpi_xsdt));
283 static void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt,
284 struct acpi_xsdt *xsdt)
286 memset(rsdp, 0, sizeof(struct acpi_rsdp));
288 memcpy(rsdp->signature, RSDP_SIG, 8);
289 memcpy(rsdp->oem_id, OEM_ID, 6);
291 rsdp->length = sizeof(struct acpi_rsdp);
292 rsdp->rsdt_address = (u32)rsdt;
295 * Revision: ACPI 1.0: 0, ACPI 2.0/3.0/4.0: 2
297 * Some OSes expect an XSDT to be present for RSD PTR revisions >= 2.
298 * If we don't have an ACPI XSDT, force ACPI 1.0 (and thus RSD PTR
302 rsdp->revision = ACPI_RSDP_REV_ACPI_1_0;
304 rsdp->xsdt_address = (u64)(u32)xsdt;
305 rsdp->revision = ACPI_RSDP_REV_ACPI_2_0;
308 /* Calculate checksums */
309 rsdp->checksum = table_compute_checksum((void *)rsdp, 20);
310 rsdp->ext_checksum = table_compute_checksum((void *)rsdp,
311 sizeof(struct acpi_rsdp));
314 static void acpi_create_ssdt_generator(struct acpi_table_header *ssdt,
315 const char *oem_table_id)
317 unsigned long current = (unsigned long)ssdt +
318 sizeof(struct acpi_table_header);
320 memset((void *)ssdt, 0, sizeof(struct acpi_table_header));
322 memcpy(&ssdt->signature, "SSDT", 4);
323 /* Access size in ACPI 2.0c/3.0/4.0/5.0 */
324 ssdt->revision = ACPI_REV_ACPI_3_0;
325 memcpy(&ssdt->oem_id, OEM_ID, 6);
326 memcpy(&ssdt->oem_table_id, oem_table_id, 8);
327 ssdt->oem_revision = OEM_REVISION;
328 memcpy(&ssdt->aslc_id, ASLC_ID, 4);
329 ssdt->aslc_revision = ASL_COMPILER_REVISION;
330 ssdt->length = sizeof(struct acpi_table_header);
332 /* (Re)calculate length and checksum */
333 ssdt->length = current - (unsigned long)ssdt;
334 ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
338 * QEMU's version of write_acpi_tables is defined in
339 * arch/x86/cpu/qemu/fw_cfg.c
341 u32 write_acpi_tables(u32 start)
344 struct acpi_rsdp *rsdp;
345 struct acpi_rsdt *rsdt;
346 struct acpi_xsdt *xsdt;
347 struct acpi_facs *facs;
348 struct acpi_table_header *dsdt;
349 struct acpi_fadt *fadt;
350 struct acpi_mcfg *mcfg;
351 struct acpi_madt *madt;
352 struct acpi_table_header *ssdt;
356 /* Align ACPI tables to 16byte */
357 current = ALIGN(current, 16);
359 debug("ACPI: Writing ACPI tables at %x\n", start);
361 /* We need at least an RSDP and an RSDT Table */
362 rsdp = (struct acpi_rsdp *)current;
363 current += sizeof(struct acpi_rsdp);
364 current = ALIGN(current, 16);
365 rsdt = (struct acpi_rsdt *)current;
366 current += sizeof(struct acpi_rsdt);
367 current = ALIGN(current, 16);
368 xsdt = (struct acpi_xsdt *)current;
369 current += sizeof(struct acpi_xsdt);
370 current = ALIGN(current, 16);
372 /* clear all table memory */
373 memset((void *)start, 0, current - start);
375 acpi_write_rsdp(rsdp, rsdt, xsdt);
376 acpi_write_rsdt(rsdt);
377 acpi_write_xsdt(xsdt);
379 debug("ACPI: * FACS\n");
380 facs = (struct acpi_facs *)current;
381 current += sizeof(struct acpi_facs);
382 current = ALIGN(current, 16);
384 acpi_create_facs(facs);
386 debug("ACPI: * DSDT\n");
387 dsdt = (struct acpi_table_header *)current;
388 memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
389 if (dsdt->length >= sizeof(struct acpi_table_header)) {
390 current += sizeof(struct acpi_table_header);
391 memcpy((char *)current,
392 (char *)&AmlCode + sizeof(struct acpi_table_header),
393 dsdt->length - sizeof(struct acpi_table_header));
394 current += dsdt->length - sizeof(struct acpi_table_header);
396 /* (Re)calculate length and checksum */
397 dsdt->length = current - (unsigned long)dsdt;
399 dsdt->checksum = table_compute_checksum((void *)dsdt,
402 current = ALIGN(current, 16);
404 debug("ACPI: * FADT\n");
405 fadt = (struct acpi_fadt *)current;
406 current += sizeof(struct acpi_fadt);
407 current = ALIGN(current, 16);
408 acpi_create_fadt(fadt, facs, dsdt);
409 acpi_add_table(rsdp, fadt);
411 debug("ACPI: * MCFG\n");
412 mcfg = (struct acpi_mcfg *)current;
413 acpi_create_mcfg(mcfg);
414 if (mcfg->header.length > sizeof(struct acpi_mcfg)) {
415 current += mcfg->header.length;
416 current = ALIGN(current, 16);
417 acpi_add_table(rsdp, mcfg);
420 debug("ACPI: * MADT\n");
421 madt = (struct acpi_madt *)current;
422 acpi_create_madt(madt);
423 if (madt->header.length > sizeof(struct acpi_madt)) {
424 current += madt->header.length;
425 acpi_add_table(rsdp, madt);
427 current = ALIGN(current, 16);
429 debug("ACPI: * SSDT\n");
430 ssdt = (struct acpi_table_header *)current;
431 acpi_create_ssdt_generator(ssdt, OEM_TABLE_ID);
432 if (ssdt->length > sizeof(struct acpi_table_header)) {
433 current += ssdt->length;
434 acpi_add_table(rsdp, ssdt);
435 current = ALIGN(current, 16);
438 debug("current = %x\n", current);
440 debug("ACPI: done\n");