1 // SPDX-License-Identifier: GPL-2.0+
3 * Based on acpi.c from coreboot
5 * Copyright (C) 2015, Saket Sinha <saket.sinha89@gmail.com>
6 * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
12 #include <dm/uclass-internal.h>
16 #include <acpi/acpi_table.h>
17 #include <asm/acpi/global_nvs.h>
18 #include <asm/ioapic.h>
19 #include <asm/lapic.h>
20 #include <asm/mpspec.h>
21 #include <asm/tables.h>
22 #include <asm/arch/global_nvs.h>
26 * IASL compiles the dsdt entries and writes the hex values
27 * to a C array AmlCode[] (see dsdt.c).
29 extern const unsigned char AmlCode[];
31 /* ACPI RSDP address to be used in boot parameters */
32 static ulong acpi_rsdp_addr;
34 static void acpi_create_facs(struct acpi_facs *facs)
36 memset((void *)facs, 0, sizeof(struct acpi_facs));
38 memcpy(facs->signature, "FACS", 4);
39 facs->length = sizeof(struct acpi_facs);
40 facs->hardware_signature = 0;
41 facs->firmware_waking_vector = 0;
42 facs->global_lock = 0;
44 facs->x_firmware_waking_vector_l = 0;
45 facs->x_firmware_waking_vector_h = 0;
49 static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
52 lapic->type = ACPI_APIC_LAPIC;
53 lapic->length = sizeof(struct acpi_madt_lapic);
54 lapic->flags = LOCAL_APIC_FLAG_ENABLED;
55 lapic->processor_id = cpu;
56 lapic->apic_id = apic;
61 int acpi_create_madt_lapics(u32 current)
66 for (uclass_find_first_device(UCLASS_CPU, &dev);
68 uclass_find_next_device(&dev)) {
69 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
70 int length = acpi_create_madt_lapic(
71 (struct acpi_madt_lapic *)current,
72 plat->cpu_id, plat->cpu_id);
74 total_length += length;
80 int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
81 u32 addr, u32 gsi_base)
83 ioapic->type = ACPI_APIC_IOAPIC;
84 ioapic->length = sizeof(struct acpi_madt_ioapic);
85 ioapic->reserved = 0x00;
86 ioapic->gsi_base = gsi_base;
87 ioapic->ioapic_id = id;
88 ioapic->ioapic_addr = addr;
90 return ioapic->length;
93 int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
94 u8 bus, u8 source, u32 gsirq, u16 flags)
96 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
97 irqoverride->length = sizeof(struct acpi_madt_irqoverride);
98 irqoverride->bus = bus;
99 irqoverride->source = source;
100 irqoverride->gsirq = gsirq;
101 irqoverride->flags = flags;
103 return irqoverride->length;
106 int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
107 u8 cpu, u16 flags, u8 lint)
109 lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
110 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
111 lapic_nmi->flags = flags;
112 lapic_nmi->processor_id = cpu;
113 lapic_nmi->lint = lint;
115 return lapic_nmi->length;
118 static int acpi_create_madt_irq_overrides(u32 current)
120 struct acpi_madt_irqoverride *irqovr;
121 u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
124 irqovr = (void *)current;
125 length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
127 irqovr = (void *)(current + length);
128 length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
133 __weak u32 acpi_fill_madt(u32 current)
135 current += acpi_create_madt_lapics(current);
137 current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
138 io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
140 current += acpi_create_madt_irq_overrides(current);
145 static void acpi_create_madt(struct acpi_madt *madt)
147 struct acpi_table_header *header = &(madt->header);
148 u32 current = (u32)madt + sizeof(struct acpi_madt);
150 memset((void *)madt, 0, sizeof(struct acpi_madt));
152 /* Fill out header fields */
153 acpi_fill_header(header, "APIC");
154 header->length = sizeof(struct acpi_madt);
155 header->revision = 4;
157 madt->lapic_addr = LAPIC_DEFAULT_BASE;
158 madt->flags = ACPI_MADT_PCAT_COMPAT;
160 current = acpi_fill_madt(current);
162 /* (Re)calculate length and checksum */
163 header->length = current - (u32)madt;
165 header->checksum = table_compute_checksum((void *)madt, header->length);
168 int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
169 u16 seg_nr, u8 start, u8 end)
171 memset(mmconfig, 0, sizeof(*mmconfig));
172 mmconfig->base_address_l = base;
173 mmconfig->base_address_h = 0;
174 mmconfig->pci_segment_group_number = seg_nr;
175 mmconfig->start_bus_number = start;
176 mmconfig->end_bus_number = end;
178 return sizeof(struct acpi_mcfg_mmconfig);
181 __weak u32 acpi_fill_mcfg(u32 current)
183 current += acpi_create_mcfg_mmconfig
184 ((struct acpi_mcfg_mmconfig *)current,
185 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
190 /* MCFG is defined in the PCI Firmware Specification 3.0 */
191 static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
193 struct acpi_table_header *header = &(mcfg->header);
194 u32 current = (u32)mcfg + sizeof(struct acpi_mcfg);
196 memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
198 /* Fill out header fields */
199 acpi_fill_header(header, "MCFG");
200 header->length = sizeof(struct acpi_mcfg);
201 header->revision = 1;
203 current = acpi_fill_mcfg(current);
205 /* (Re)calculate length and checksum */
206 header->length = current - (u32)mcfg;
207 header->checksum = table_compute_checksum((void *)mcfg, header->length);
210 __weak u32 acpi_fill_csrt(u32 current)
215 static void acpi_create_csrt(struct acpi_csrt *csrt)
217 struct acpi_table_header *header = &(csrt->header);
218 u32 current = (u32)csrt + sizeof(struct acpi_csrt);
220 memset((void *)csrt, 0, sizeof(struct acpi_csrt));
222 /* Fill out header fields */
223 acpi_fill_header(header, "CSRT");
224 header->length = sizeof(struct acpi_csrt);
225 header->revision = 0;
227 current = acpi_fill_csrt(current);
229 /* (Re)calculate length and checksum */
230 header->length = current - (u32)csrt;
231 header->checksum = table_compute_checksum((void *)csrt, header->length);
234 static void acpi_create_spcr(struct acpi_spcr *spcr)
236 struct acpi_table_header *header = &(spcr->header);
237 struct serial_device_info serial_info = {0};
238 ulong serial_address, serial_offset;
246 /* Fill out header fields */
247 acpi_fill_header(header, "SPCR");
248 header->length = sizeof(struct acpi_spcr);
249 header->revision = 2;
251 /* Read the device once, here. It is reused below */
252 dev = gd->cur_serial_dev;
254 ret = serial_getinfo(dev, &serial_info);
256 serial_info.type = SERIAL_CHIP_UNKNOWN;
258 /* Encode chip type */
259 switch (serial_info.type) {
260 case SERIAL_CHIP_16550_COMPATIBLE:
261 spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
263 case SERIAL_CHIP_UNKNOWN:
265 spcr->interface_type = ACPI_DBG2_UNKNOWN;
269 /* Encode address space */
270 switch (serial_info.addr_space) {
271 case SERIAL_ADDRESS_SPACE_MEMORY:
272 space_id = ACPI_ADDRESS_SPACE_MEMORY;
274 case SERIAL_ADDRESS_SPACE_IO:
276 space_id = ACPI_ADDRESS_SPACE_IO;
280 serial_width = serial_info.reg_width * 8;
281 serial_offset = serial_info.reg_offset << serial_info.reg_shift;
282 serial_address = serial_info.addr + serial_offset;
284 /* Encode register access size */
285 switch (serial_info.reg_shift) {
287 access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
290 access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
293 access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
296 access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
299 access_size = ACPI_ACCESS_SIZE_UNDEFINED;
303 debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
306 spcr->serial_port.space_id = space_id;
307 spcr->serial_port.bit_width = serial_width;
308 spcr->serial_port.bit_offset = 0;
309 spcr->serial_port.access_size = access_size;
310 spcr->serial_port.addrl = lower_32_bits(serial_address);
311 spcr->serial_port.addrh = upper_32_bits(serial_address);
313 /* Encode baud rate */
314 switch (serial_info.baudrate) {
332 serial_config = SERIAL_DEFAULT_CONFIG;
334 ret = serial_getconfig(dev, &serial_config);
336 spcr->parity = SERIAL_GET_PARITY(serial_config);
337 spcr->stop_bits = SERIAL_GET_STOP(serial_config);
339 /* No PCI devices for now */
340 spcr->pci_device_id = 0xffff;
341 spcr->pci_vendor_id = 0xffff;
344 * SPCR has no clue if the UART base clock speed is different
345 * to the default one. However, the SPCR 1.04 defines baud rate
346 * 0 as a preconfigured state of UART and OS is supposed not
347 * to touch the configuration of the serial device.
349 if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
353 header->checksum = table_compute_checksum((void *)spcr, header->length);
357 * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
359 ulong write_acpi_tables(ulong start_addr)
361 struct acpi_ctx sctx, *ctx = &sctx;
362 struct acpi_facs *facs;
363 struct acpi_table_header *dsdt;
364 struct acpi_fadt *fadt;
365 struct acpi_mcfg *mcfg;
366 struct acpi_madt *madt;
367 struct acpi_csrt *csrt;
368 struct acpi_spcr *spcr;
373 start = map_sysmem(start_addr, 0);
375 debug("ACPI: Writing ACPI tables at %lx\n", start_addr);
377 acpi_setup_base_tables(ctx, start);
379 debug("ACPI: * FACS\n");
381 acpi_inc_align(ctx, sizeof(struct acpi_facs));
383 acpi_create_facs(facs);
385 debug("ACPI: * DSDT\n");
387 memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
388 acpi_inc(ctx, sizeof(struct acpi_table_header));
390 (char *)&AmlCode + sizeof(struct acpi_table_header),
391 dsdt->length - sizeof(struct acpi_table_header));
392 acpi_inc_align(ctx, dsdt->length - sizeof(struct acpi_table_header));
394 /* Pack GNVS into the ACPI table area */
395 for (i = 0; i < dsdt->length; i++) {
396 u32 *gnvs = (u32 *)((u32)dsdt + i);
397 if (*gnvs == ACPI_GNVS_ADDR) {
398 ulong addr = (ulong)map_to_sysmem(ctx->current);
400 debug("Fix up global NVS in DSDT to %#08lx\n", addr);
406 /* Update DSDT checksum since we patched the GNVS address */
408 dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
410 /* Fill in platform-specific global NVS variables */
411 acpi_create_gnvs(ctx->current);
412 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
414 debug("ACPI: * FADT\n");
416 acpi_inc_align(ctx, sizeof(struct acpi_fadt));
417 acpi_create_fadt(fadt, facs, dsdt);
418 acpi_add_table(ctx, fadt);
420 debug("ACPI: * MADT\n");
422 acpi_create_madt(madt);
423 acpi_inc_align(ctx, madt->header.length);
424 acpi_add_table(ctx, madt);
426 debug("ACPI: * MCFG\n");
428 acpi_create_mcfg(mcfg);
429 acpi_inc_align(ctx, mcfg->header.length);
430 acpi_add_table(ctx, mcfg);
432 debug("ACPI: * CSRT\n");
434 acpi_create_csrt(csrt);
435 acpi_inc_align(ctx, csrt->header.length);
436 acpi_add_table(ctx, csrt);
438 debug("ACPI: * SPCR\n");
440 acpi_create_spcr(spcr);
441 acpi_inc_align(ctx, spcr->header.length);
442 acpi_add_table(ctx, spcr);
444 acpi_write_dev_tables(ctx);
446 addr = map_to_sysmem(ctx->current);
447 debug("current = %lx\n", addr);
449 acpi_rsdp_addr = (unsigned long)ctx->rsdp;
450 debug("ACPI: done\n");
455 ulong acpi_get_rsdp_addr(void)
457 return acpi_rsdp_addr;