blob: 10cf3b709454507e611599b836c3d1825fe92a56 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Saket Sinha331141a2015-08-22 12:20:55 +05302/*
3 * Based on acpi.c from coreboot
4 *
5 * Copyright (C) 2015, Saket Sinha <saket.sinha89@gmail.com>
Bin Meng44256b02016-05-07 07:46:25 -07006 * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com>
Saket Sinha331141a2015-08-22 12:20:55 +05307 */
8
9#include <common.h>
Simon Glass272a7032020-09-22 12:45:32 -060010#include <bloblist.h>
Saket Sinha331141a2015-08-22 12:20:55 +053011#include <cpu.h>
12#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Saket Sinha331141a2015-08-22 12:20:55 +053014#include <dm/uclass-internal.h>
Simon Glass0e113842020-04-26 09:19:47 -060015#include <mapmem.h>
Andy Shevchenko4ca48c92018-11-20 23:52:38 +020016#include <serial.h>
Andy Shevchenko87e95372017-07-21 22:32:02 +030017#include <version.h>
Simon Glassf0a8d682020-07-07 13:12:07 -060018#include <acpi/acpigen.h>
Simon Glass95971892020-09-22 12:45:10 -060019#include <acpi/acpi_device.h>
Simon Glass858fed12020-04-08 16:57:36 -060020#include <acpi/acpi_table.h>
Bin Mengd9050c62016-06-17 02:13:16 -070021#include <asm/acpi/global_nvs.h>
Andy Shevchenko13a5d872017-07-21 22:32:04 +030022#include <asm/ioapic.h>
Saket Sinha331141a2015-08-22 12:20:55 +053023#include <asm/lapic.h>
Andy Shevchenko13a5d872017-07-21 22:32:04 +030024#include <asm/mpspec.h>
Saket Sinha331141a2015-08-22 12:20:55 +053025#include <asm/tables.h>
Bin Mengd9050c62016-06-17 02:13:16 -070026#include <asm/arch/global_nvs.h>
Simon Glass0e113842020-04-26 09:19:47 -060027#include <dm/acpi.h>
Simon Glass9ed41e72020-07-07 21:32:05 -060028#include <linux/err.h>
Saket Sinha331141a2015-08-22 12:20:55 +053029
30/*
Bin Mengb063d5f2016-05-07 07:46:24 -070031 * IASL compiles the dsdt entries and writes the hex values
32 * to a C array AmlCode[] (see dsdt.c).
Saket Sinha331141a2015-08-22 12:20:55 +053033 */
34extern const unsigned char AmlCode[];
35
Andy Shevchenko66d3e632018-01-10 19:40:15 +020036/* ACPI RSDP address to be used in boot parameters */
Bin Menge1029252018-01-30 05:01:16 -080037static ulong acpi_rsdp_addr;
Andy Shevchenko66d3e632018-01-10 19:40:15 +020038
Bin Meng44256b02016-05-07 07:46:25 -070039static void acpi_create_facs(struct acpi_facs *facs)
40{
41 memset((void *)facs, 0, sizeof(struct acpi_facs));
42
43 memcpy(facs->signature, "FACS", 4);
44 facs->length = sizeof(struct acpi_facs);
45 facs->hardware_signature = 0;
46 facs->firmware_waking_vector = 0;
47 facs->global_lock = 0;
48 facs->flags = 0;
49 facs->x_firmware_waking_vector_l = 0;
50 facs->x_firmware_waking_vector_h = 0;
51 facs->version = 1;
52}
53
Saket Sinha331141a2015-08-22 12:20:55 +053054static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
Bin Meng44256b02016-05-07 07:46:25 -070055 u8 cpu, u8 apic)
Saket Sinha331141a2015-08-22 12:20:55 +053056{
Bin Meng44256b02016-05-07 07:46:25 -070057 lapic->type = ACPI_APIC_LAPIC;
Saket Sinha331141a2015-08-22 12:20:55 +053058 lapic->length = sizeof(struct acpi_madt_lapic);
Bin Meng44256b02016-05-07 07:46:25 -070059 lapic->flags = LOCAL_APIC_FLAG_ENABLED;
Saket Sinha331141a2015-08-22 12:20:55 +053060 lapic->processor_id = cpu;
61 lapic->apic_id = apic;
62
63 return lapic->length;
64}
65
Bin Meng3c5234e2016-05-07 07:46:30 -070066int acpi_create_madt_lapics(u32 current)
Saket Sinha331141a2015-08-22 12:20:55 +053067{
68 struct udevice *dev;
George McCollister5a49f872016-06-07 13:40:18 -050069 int total_length = 0;
Simon Glassfcae5472020-09-22 12:45:31 -060070 int cpu_num = 0;
Saket Sinha331141a2015-08-22 12:20:55 +053071
72 for (uclass_find_first_device(UCLASS_CPU, &dev);
73 dev;
74 uclass_find_next_device(&dev)) {
75 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
Simon Glassfcae5472020-09-22 12:45:31 -060076 int length;
77
78 length = acpi_create_madt_lapic(
79 (struct acpi_madt_lapic *)current, cpu_num++,
80 plat->cpu_id);
Bin Meng3c5234e2016-05-07 07:46:30 -070081 current += length;
George McCollister5a49f872016-06-07 13:40:18 -050082 total_length += length;
Bin Meng44256b02016-05-07 07:46:25 -070083 }
84
George McCollister5a49f872016-06-07 13:40:18 -050085 return total_length;
Saket Sinha331141a2015-08-22 12:20:55 +053086}
87
Bin Meng44256b02016-05-07 07:46:25 -070088int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
89 u32 addr, u32 gsi_base)
Saket Sinha331141a2015-08-22 12:20:55 +053090{
Bin Meng6a421582016-05-07 07:46:21 -070091 ioapic->type = ACPI_APIC_IOAPIC;
Saket Sinha331141a2015-08-22 12:20:55 +053092 ioapic->length = sizeof(struct acpi_madt_ioapic);
93 ioapic->reserved = 0x00;
94 ioapic->gsi_base = gsi_base;
95 ioapic->ioapic_id = id;
96 ioapic->ioapic_addr = addr;
97
98 return ioapic->length;
99}
100
101int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
Bin Meng44256b02016-05-07 07:46:25 -0700102 u8 bus, u8 source, u32 gsirq, u16 flags)
Saket Sinha331141a2015-08-22 12:20:55 +0530103{
Bin Meng6a421582016-05-07 07:46:21 -0700104 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
Saket Sinha331141a2015-08-22 12:20:55 +0530105 irqoverride->length = sizeof(struct acpi_madt_irqoverride);
106 irqoverride->bus = bus;
107 irqoverride->source = source;
108 irqoverride->gsirq = gsirq;
109 irqoverride->flags = flags;
110
111 return irqoverride->length;
112}
113
114int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
Bin Meng44256b02016-05-07 07:46:25 -0700115 u8 cpu, u16 flags, u8 lint)
Saket Sinha331141a2015-08-22 12:20:55 +0530116{
Bin Meng6a421582016-05-07 07:46:21 -0700117 lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
Saket Sinha331141a2015-08-22 12:20:55 +0530118 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
119 lapic_nmi->flags = flags;
120 lapic_nmi->processor_id = cpu;
121 lapic_nmi->lint = lint;
122
123 return lapic_nmi->length;
124}
125
Andy Shevchenko13a5d872017-07-21 22:32:04 +0300126static int acpi_create_madt_irq_overrides(u32 current)
127{
128 struct acpi_madt_irqoverride *irqovr;
129 u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
130 int length = 0;
131
132 irqovr = (void *)current;
133 length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
134
135 irqovr = (void *)(current + length);
136 length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
137
138 return length;
139}
140
141__weak u32 acpi_fill_madt(u32 current)
142{
143 current += acpi_create_madt_lapics(current);
144
145 current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
146 io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
147
148 current += acpi_create_madt_irq_overrides(current);
149
150 return current;
151}
152
Saket Sinha331141a2015-08-22 12:20:55 +0530153static void acpi_create_madt(struct acpi_madt *madt)
154{
Bin Meng6a421582016-05-07 07:46:21 -0700155 struct acpi_table_header *header = &(madt->header);
Bin Menga1ec7db2016-05-07 07:46:26 -0700156 u32 current = (u32)madt + sizeof(struct acpi_madt);
Saket Sinha331141a2015-08-22 12:20:55 +0530157
158 memset((void *)madt, 0, sizeof(struct acpi_madt));
159
160 /* Fill out header fields */
Bin Mengb063d5f2016-05-07 07:46:24 -0700161 acpi_fill_header(header, "APIC");
Saket Sinha331141a2015-08-22 12:20:55 +0530162 header->length = sizeof(struct acpi_madt);
Simon Glassf3694aa2020-07-16 21:22:37 -0600163 header->revision = ACPI_MADT_REV_ACPI_3_0;
Saket Sinha331141a2015-08-22 12:20:55 +0530164
165 madt->lapic_addr = LAPIC_DEFAULT_BASE;
Bin Meng6a421582016-05-07 07:46:21 -0700166 madt->flags = ACPI_MADT_PCAT_COMPAT;
Saket Sinha331141a2015-08-22 12:20:55 +0530167
168 current = acpi_fill_madt(current);
169
170 /* (Re)calculate length and checksum */
Bin Menga1ec7db2016-05-07 07:46:26 -0700171 header->length = current - (u32)madt;
Saket Sinha331141a2015-08-22 12:20:55 +0530172
173 header->checksum = table_compute_checksum((void *)madt, header->length);
174}
175
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300176int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
177 u16 seg_nr, u8 start, u8 end)
Saket Sinha331141a2015-08-22 12:20:55 +0530178{
179 memset(mmconfig, 0, sizeof(*mmconfig));
Bin Meng6a421582016-05-07 07:46:21 -0700180 mmconfig->base_address_l = base;
181 mmconfig->base_address_h = 0;
Saket Sinha331141a2015-08-22 12:20:55 +0530182 mmconfig->pci_segment_group_number = seg_nr;
183 mmconfig->start_bus_number = start;
184 mmconfig->end_bus_number = end;
185
186 return sizeof(struct acpi_mcfg_mmconfig);
187}
188
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300189__weak u32 acpi_fill_mcfg(u32 current)
Saket Sinha331141a2015-08-22 12:20:55 +0530190{
191 current += acpi_create_mcfg_mmconfig
192 ((struct acpi_mcfg_mmconfig *)current,
Bin Meng44256b02016-05-07 07:46:25 -0700193 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
Saket Sinha331141a2015-08-22 12:20:55 +0530194
195 return current;
196}
197
198/* MCFG is defined in the PCI Firmware Specification 3.0 */
199static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
200{
Bin Meng6a421582016-05-07 07:46:21 -0700201 struct acpi_table_header *header = &(mcfg->header);
Bin Menga1ec7db2016-05-07 07:46:26 -0700202 u32 current = (u32)mcfg + sizeof(struct acpi_mcfg);
Saket Sinha331141a2015-08-22 12:20:55 +0530203
204 memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
205
206 /* Fill out header fields */
Bin Mengb063d5f2016-05-07 07:46:24 -0700207 acpi_fill_header(header, "MCFG");
Saket Sinha331141a2015-08-22 12:20:55 +0530208 header->length = sizeof(struct acpi_mcfg);
Bin Mengf662fe42016-05-07 07:46:28 -0700209 header->revision = 1;
Saket Sinha331141a2015-08-22 12:20:55 +0530210
211 current = acpi_fill_mcfg(current);
212
213 /* (Re)calculate length and checksum */
Bin Menga1ec7db2016-05-07 07:46:26 -0700214 header->length = current - (u32)mcfg;
Saket Sinha331141a2015-08-22 12:20:55 +0530215 header->checksum = table_compute_checksum((void *)mcfg, header->length);
216}
217
Simon Glass28026282020-09-22 12:45:33 -0600218/**
219 * acpi_create_tcpa() - Create a TCPA table
220 *
221 * @tcpa: Pointer to place to put table
222 *
223 * Trusted Computing Platform Alliance Capabilities Table
224 * TCPA PC Specific Implementation SpecificationTCPA is defined in the PCI
225 * Firmware Specification 3.0
226 */
227static int acpi_create_tcpa(struct acpi_tcpa *tcpa)
228{
229 struct acpi_table_header *header = &tcpa->header;
230 u32 current = (u32)tcpa + sizeof(struct acpi_tcpa);
231 int size = 0x10000; /* Use this as the default size */
232 void *log;
233 int ret;
234
235 if (!CONFIG_IS_ENABLED(BLOBLIST))
236 return -ENXIO;
237 memset(tcpa, '\0', sizeof(struct acpi_tcpa));
238
239 /* Fill out header fields */
240 acpi_fill_header(header, "TCPA");
241 header->length = sizeof(struct acpi_tcpa);
242 header->revision = 1;
243
244 ret = bloblist_ensure_size_ret(BLOBLISTT_TCPA_LOG, &size, &log);
245 if (ret)
246 return log_msg_ret("blob", ret);
247
248 tcpa->platform_class = 0;
249 tcpa->laml = size;
250 tcpa->lasa = (ulong)log;
251
252 /* (Re)calculate length and checksum */
253 header->length = current - (u32)tcpa;
254 header->checksum = table_compute_checksum((void *)tcpa, header->length);
255
256 return 0;
257}
258
Simon Glass272a7032020-09-22 12:45:32 -0600259static int get_tpm2_log(void **ptrp, int *sizep)
260{
261 const int tpm2_default_log_len = 0x10000;
262 int size;
263 int ret;
264
265 *sizep = 0;
266 size = tpm2_default_log_len;
267 ret = bloblist_ensure_size_ret(BLOBLISTT_TPM2_TCG_LOG, &size, ptrp);
268 if (ret)
269 return log_msg_ret("blob", ret);
270 *sizep = size;
271
272 return 0;
273}
274
275static int acpi_create_tpm2(struct acpi_tpm2 *tpm2)
276{
277 struct acpi_table_header *header = &tpm2->header;
278 int tpm2_log_len;
279 void *lasa;
280 int ret;
281
282 memset((void *)tpm2, 0, sizeof(struct acpi_tpm2));
283
284 /*
285 * Some payloads like SeaBIOS depend on log area to use TPM2.
286 * Get the memory size and address of TPM2 log area or initialize it.
287 */
288 ret = get_tpm2_log(&lasa, &tpm2_log_len);
289 if (ret)
290 return ret;
291
292 /* Fill out header fields. */
293 acpi_fill_header(header, "TPM2");
294 memcpy(header->aslc_id, ASLC_ID, 4);
295
296 header->length = sizeof(struct acpi_tpm2);
297 header->revision = acpi_get_table_revision(ACPITAB_TPM2);
298
299 /* Hard to detect for coreboot. Just set it to 0 */
300 tpm2->platform_class = 0;
301
302 /* Must be set to 0 for FIFO-interface support */
303 tpm2->control_area = 0;
304 tpm2->start_method = 6;
305 memset(tpm2->msp, 0, sizeof(tpm2->msp));
306
307 /* Fill the log area size and start address fields. */
308 tpm2->laml = tpm2_log_len;
309 tpm2->lasa = (uintptr_t)lasa;
310
311 /* Calculate checksum. */
312 header->checksum = table_compute_checksum((void *)tpm2, header->length);
313
314 return 0;
315}
316
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300317__weak u32 acpi_fill_csrt(u32 current)
318{
Simon Glass9eb80042020-07-07 21:32:24 -0600319 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300320}
321
Simon Glass9eb80042020-07-07 21:32:24 -0600322static int acpi_create_csrt(struct acpi_csrt *csrt)
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300323{
324 struct acpi_table_header *header = &(csrt->header);
325 u32 current = (u32)csrt + sizeof(struct acpi_csrt);
Simon Glass9eb80042020-07-07 21:32:24 -0600326 uint ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300327
328 memset((void *)csrt, 0, sizeof(struct acpi_csrt));
329
330 /* Fill out header fields */
331 acpi_fill_header(header, "CSRT");
332 header->length = sizeof(struct acpi_csrt);
333 header->revision = 0;
334
Simon Glass9eb80042020-07-07 21:32:24 -0600335 ptr = acpi_fill_csrt(current);
336 if (!ptr)
337 return -ENOENT;
338 current = ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300339
340 /* (Re)calculate length and checksum */
341 header->length = current - (u32)csrt;
342 header->checksum = table_compute_checksum((void *)csrt, header->length);
Simon Glass9eb80042020-07-07 21:32:24 -0600343
344 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300345}
346
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200347static void acpi_create_spcr(struct acpi_spcr *spcr)
348{
349 struct acpi_table_header *header = &(spcr->header);
350 struct serial_device_info serial_info = {0};
351 ulong serial_address, serial_offset;
Simon Glassdaaff932018-12-28 14:23:08 -0700352 struct udevice *dev;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200353 uint serial_config;
354 uint serial_width;
355 int access_size;
356 int space_id;
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200357 int ret = -ENODEV;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200358
Wolfgang Wallner13c23e92020-09-16 16:57:53 +0200359 memset((void *)spcr, 0, sizeof(struct acpi_spcr));
360
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200361 /* Fill out header fields */
362 acpi_fill_header(header, "SPCR");
363 header->length = sizeof(struct acpi_spcr);
364 header->revision = 2;
365
Simon Glass896c1642018-12-28 14:23:10 -0700366 /* Read the device once, here. It is reused below */
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200367 dev = gd->cur_serial_dev;
368 if (dev)
Simon Glass896c1642018-12-28 14:23:10 -0700369 ret = serial_getinfo(dev, &serial_info);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200370 if (ret)
371 serial_info.type = SERIAL_CHIP_UNKNOWN;
372
373 /* Encode chip type */
374 switch (serial_info.type) {
375 case SERIAL_CHIP_16550_COMPATIBLE:
376 spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
377 break;
378 case SERIAL_CHIP_UNKNOWN:
379 default:
380 spcr->interface_type = ACPI_DBG2_UNKNOWN;
381 break;
382 }
383
384 /* Encode address space */
385 switch (serial_info.addr_space) {
386 case SERIAL_ADDRESS_SPACE_MEMORY:
387 space_id = ACPI_ADDRESS_SPACE_MEMORY;
388 break;
389 case SERIAL_ADDRESS_SPACE_IO:
390 default:
391 space_id = ACPI_ADDRESS_SPACE_IO;
392 break;
393 }
394
395 serial_width = serial_info.reg_width * 8;
396 serial_offset = serial_info.reg_offset << serial_info.reg_shift;
397 serial_address = serial_info.addr + serial_offset;
398
399 /* Encode register access size */
400 switch (serial_info.reg_shift) {
401 case 0:
402 access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
403 break;
404 case 1:
405 access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
406 break;
407 case 2:
408 access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
409 break;
410 case 3:
411 access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
412 break;
413 default:
414 access_size = ACPI_ACCESS_SIZE_UNDEFINED;
415 break;
416 }
417
418 debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
419
420 /* Fill GAS */
421 spcr->serial_port.space_id = space_id;
422 spcr->serial_port.bit_width = serial_width;
423 spcr->serial_port.bit_offset = 0;
424 spcr->serial_port.access_size = access_size;
425 spcr->serial_port.addrl = lower_32_bits(serial_address);
426 spcr->serial_port.addrh = upper_32_bits(serial_address);
427
428 /* Encode baud rate */
429 switch (serial_info.baudrate) {
430 case 9600:
431 spcr->baud_rate = 3;
432 break;
433 case 19200:
434 spcr->baud_rate = 4;
435 break;
436 case 57600:
437 spcr->baud_rate = 6;
438 break;
439 case 115200:
440 spcr->baud_rate = 7;
441 break;
442 default:
443 spcr->baud_rate = 0;
444 break;
445 }
446
Simon Glass896c1642018-12-28 14:23:10 -0700447 serial_config = SERIAL_DEFAULT_CONFIG;
448 if (dev)
Simon Glassdaaff932018-12-28 14:23:08 -0700449 ret = serial_getconfig(dev, &serial_config);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200450
451 spcr->parity = SERIAL_GET_PARITY(serial_config);
452 spcr->stop_bits = SERIAL_GET_STOP(serial_config);
453
454 /* No PCI devices for now */
455 spcr->pci_device_id = 0xffff;
456 spcr->pci_vendor_id = 0xffff;
457
Andy Shevchenko225cc8a2020-02-27 17:21:56 +0200458 /*
459 * SPCR has no clue if the UART base clock speed is different
460 * to the default one. However, the SPCR 1.04 defines baud rate
461 * 0 as a preconfigured state of UART and OS is supposed not
462 * to touch the configuration of the serial device.
463 */
464 if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
465 spcr->baud_rate = 0;
466
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200467 /* Fix checksum */
468 header->checksum = table_compute_checksum((void *)spcr, header->length);
469}
470
Simon Glassf0a8d682020-07-07 13:12:07 -0600471void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt,
472 const char *oem_table_id)
473{
474 memset((void *)ssdt, '\0', sizeof(struct acpi_table_header));
475
476 acpi_fill_header(ssdt, "SSDT");
477 ssdt->revision = acpi_get_table_revision(ACPITAB_SSDT);
478 ssdt->aslc_revision = 1;
479 ssdt->length = sizeof(struct acpi_table_header);
480
481 acpi_inc(ctx, sizeof(struct acpi_table_header));
482
483 acpi_fill_ssdt(ctx);
484
485 /* (Re)calculate length and checksum. */
486 ssdt->length = ctx->current - (void *)ssdt;
487 ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
488}
489
Miao Yan3b68c522016-01-20 01:57:06 -0800490/*
Andy Shevchenko4b05bac2018-01-10 19:33:10 +0200491 * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
Miao Yan3b68c522016-01-20 01:57:06 -0800492 */
Simon Glass0e113842020-04-26 09:19:47 -0600493ulong write_acpi_tables(ulong start_addr)
Saket Sinha331141a2015-08-22 12:20:55 +0530494{
Simon Glass0e113842020-04-26 09:19:47 -0600495 struct acpi_ctx sctx, *ctx = &sctx;
Saket Sinha331141a2015-08-22 12:20:55 +0530496 struct acpi_facs *facs;
Bin Meng6a421582016-05-07 07:46:21 -0700497 struct acpi_table_header *dsdt;
Saket Sinha331141a2015-08-22 12:20:55 +0530498 struct acpi_fadt *fadt;
Simon Glassf0a8d682020-07-07 13:12:07 -0600499 struct acpi_table_header *ssdt;
Saket Sinha331141a2015-08-22 12:20:55 +0530500 struct acpi_mcfg *mcfg;
Simon Glass28026282020-09-22 12:45:33 -0600501 struct acpi_tcpa *tcpa;
Saket Sinha331141a2015-08-22 12:20:55 +0530502 struct acpi_madt *madt;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300503 struct acpi_csrt *csrt;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200504 struct acpi_spcr *spcr;
Simon Glass0e113842020-04-26 09:19:47 -0600505 void *start;
506 ulong addr;
Simon Glass28026282020-09-22 12:45:33 -0600507 int ret;
Bin Mengd9050c62016-06-17 02:13:16 -0700508 int i;
Saket Sinha331141a2015-08-22 12:20:55 +0530509
Simon Glass0e113842020-04-26 09:19:47 -0600510 start = map_sysmem(start_addr, 0);
Saket Sinha331141a2015-08-22 12:20:55 +0530511
Simon Glass0e113842020-04-26 09:19:47 -0600512 debug("ACPI: Writing ACPI tables at %lx\n", start_addr);
Saket Sinha331141a2015-08-22 12:20:55 +0530513
Simon Glass9c442a62020-04-26 09:19:51 -0600514 acpi_setup_base_tables(ctx, start);
Saket Sinha331141a2015-08-22 12:20:55 +0530515
516 debug("ACPI: * FACS\n");
Simon Glass0e113842020-04-26 09:19:47 -0600517 facs = ctx->current;
518 acpi_inc_align(ctx, sizeof(struct acpi_facs));
Saket Sinha331141a2015-08-22 12:20:55 +0530519
520 acpi_create_facs(facs);
521
522 debug("ACPI: * DSDT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600523 dsdt = ctx->current;
Simon Glass6ca93152020-07-07 13:12:09 -0600524
525 /* Put the table header first */
Bin Meng6a421582016-05-07 07:46:21 -0700526 memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
Simon Glass0e113842020-04-26 09:19:47 -0600527 acpi_inc(ctx, sizeof(struct acpi_table_header));
Simon Glass6ca93152020-07-07 13:12:09 -0600528
529 /* If the table is not empty, allow devices to inject things */
530 if (dsdt->length >= sizeof(struct acpi_table_header))
531 acpi_inject_dsdt(ctx);
532
533 /* Copy in the AML code itself if any (after the header) */
Simon Glass0e113842020-04-26 09:19:47 -0600534 memcpy(ctx->current,
Bin Mengd90434b2016-05-11 07:45:05 -0700535 (char *)&AmlCode + sizeof(struct acpi_table_header),
536 dsdt->length - sizeof(struct acpi_table_header));
Simon Glass6ca93152020-07-07 13:12:09 -0600537
Wolfgang Wallneraa202822020-09-16 16:57:52 +0200538 acpi_inc(ctx, dsdt->length - sizeof(struct acpi_table_header));
Simon Glass6fe570a2020-09-22 12:44:53 -0600539 dsdt->length = ctx->current - (void *)dsdt;
540 acpi_align(ctx);
Saket Sinha331141a2015-08-22 12:20:55 +0530541
Simon Glass6fe570a2020-09-22 12:44:53 -0600542 if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
543 /* Pack GNVS into the ACPI table area */
544 for (i = 0; i < dsdt->length; i++) {
545 u32 *gnvs = (u32 *)((u32)dsdt + i);
Simon Glass0e113842020-04-26 09:19:47 -0600546
Simon Glass6fe570a2020-09-22 12:44:53 -0600547 if (*gnvs == ACPI_GNVS_ADDR) {
548 *gnvs = map_to_sysmem(ctx->current);
549 debug("Fix up global NVS in DSDT to %#08x\n",
550 *gnvs);
551 break;
552 }
Bin Mengd9050c62016-06-17 02:13:16 -0700553 }
Simon Glass6fe570a2020-09-22 12:44:53 -0600554
555 /*
556 * Fill in platform-specific global NVS variables. If this fails
557 * we cannot return the error but this should only happen while
558 * debugging.
559 */
560 addr = acpi_create_gnvs(ctx->current);
561 if (IS_ERR_VALUE(addr))
562 printf("Error: Gailed to create GNVS\n");
563 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
Bin Mengd9050c62016-06-17 02:13:16 -0700564 }
565
Simon Glass6ca93152020-07-07 13:12:09 -0600566 /*
567 * Recalculate the length and update the DSDT checksum since we patched
568 * the GNVS address. Set the checksum to zero since it is part of the
569 * region being checksummed.
570 */
Bin Mengd9050c62016-06-17 02:13:16 -0700571 dsdt->checksum = 0;
572 dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
573
Simon Glass9ed41e72020-07-07 21:32:05 -0600574 /*
575 * Fill in platform-specific global NVS variables. If this fails we
576 * cannot return the error but this should only happen while debugging.
577 */
578 addr = acpi_create_gnvs(ctx->current);
579 if (IS_ERR_VALUE(addr))
580 printf("Error: Failed to create GNVS\n");
581
Simon Glass0e113842020-04-26 09:19:47 -0600582 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
Bin Mengd9050c62016-06-17 02:13:16 -0700583
Saket Sinha331141a2015-08-22 12:20:55 +0530584 debug("ACPI: * FADT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600585 fadt = ctx->current;
586 acpi_inc_align(ctx, sizeof(struct acpi_fadt));
Saket Sinha331141a2015-08-22 12:20:55 +0530587 acpi_create_fadt(fadt, facs, dsdt);
Simon Glass575a5472020-04-26 09:19:50 -0600588 acpi_add_table(ctx, fadt);
Saket Sinha331141a2015-08-22 12:20:55 +0530589
Simon Glassf0a8d682020-07-07 13:12:07 -0600590 debug("ACPI: * SSDT\n");
591 ssdt = (struct acpi_table_header *)ctx->current;
592 acpi_create_ssdt(ctx, ssdt, OEM_TABLE_ID);
593 if (ssdt->length > sizeof(struct acpi_table_header)) {
594 acpi_inc_align(ctx, ssdt->length);
595 acpi_add_table(ctx, ssdt);
596 }
597
Bin Meng44256b02016-05-07 07:46:25 -0700598 debug("ACPI: * MCFG\n");
Simon Glass0e113842020-04-26 09:19:47 -0600599 mcfg = ctx->current;
Bin Meng44256b02016-05-07 07:46:25 -0700600 acpi_create_mcfg(mcfg);
Simon Glass0e113842020-04-26 09:19:47 -0600601 acpi_inc_align(ctx, mcfg->header.length);
Simon Glass575a5472020-04-26 09:19:50 -0600602 acpi_add_table(ctx, mcfg);
Bin Meng44256b02016-05-07 07:46:25 -0700603
Simon Glass272a7032020-09-22 12:45:32 -0600604 if (IS_ENABLED(CONFIG_TPM_V2)) {
605 struct acpi_tpm2 *tpm2;
Simon Glass272a7032020-09-22 12:45:32 -0600606
607 debug("ACPI: * TPM2\n");
608 tpm2 = (struct acpi_tpm2 *)ctx->current;
609 ret = acpi_create_tpm2(tpm2);
610 if (!ret) {
611 acpi_inc_align(ctx, tpm2->header.length);
612 acpi_add_table(ctx, tpm2);
613 } else {
614 log_warning("TPM2 table creation failed\n");
615 }
616 }
617
Simon Glassc7c46e82020-07-07 13:12:04 -0600618 debug("ACPI: * MADT\n");
619 madt = ctx->current;
620 acpi_create_madt(madt);
621 acpi_inc_align(ctx, madt->header.length);
622 acpi_add_table(ctx, madt);
623
Simon Glass28026282020-09-22 12:45:33 -0600624 debug("ACPI: * TCPA\n");
625 tcpa = (struct acpi_tcpa *)ctx->current;
626 ret = acpi_create_tcpa(tcpa);
627 if (ret) {
628 log_warning("Failed to create TCPA table (err=%d)\n", ret);
629 } else {
630 acpi_inc_align(ctx, tcpa->header.length);
631 acpi_add_table(ctx, tcpa);
632 }
633
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300634 debug("ACPI: * CSRT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600635 csrt = ctx->current;
Simon Glass9eb80042020-07-07 21:32:24 -0600636 if (!acpi_create_csrt(csrt)) {
637 acpi_inc_align(ctx, csrt->header.length);
638 acpi_add_table(ctx, csrt);
639 }
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300640
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200641 debug("ACPI: * SPCR\n");
Simon Glass0e113842020-04-26 09:19:47 -0600642 spcr = ctx->current;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200643 acpi_create_spcr(spcr);
Simon Glass0e113842020-04-26 09:19:47 -0600644 acpi_inc_align(ctx, spcr->header.length);
Simon Glass575a5472020-04-26 09:19:50 -0600645 acpi_add_table(ctx, spcr);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200646
Simon Glass179fb822020-04-26 09:19:48 -0600647 acpi_write_dev_tables(ctx);
648
Simon Glass0e113842020-04-26 09:19:47 -0600649 addr = map_to_sysmem(ctx->current);
650 debug("current = %lx\n", addr);
Saket Sinha331141a2015-08-22 12:20:55 +0530651
Simon Glass575a5472020-04-26 09:19:50 -0600652 acpi_rsdp_addr = (unsigned long)ctx->rsdp;
Bin Mengd2d22182016-05-07 07:46:12 -0700653 debug("ACPI: done\n");
Saket Sinha331141a2015-08-22 12:20:55 +0530654
Simon Glass0e113842020-04-26 09:19:47 -0600655 return addr;
Saket Sinha331141a2015-08-22 12:20:55 +0530656}
Bin Meng34bc74a2017-04-21 07:24:36 -0700657
Bin Menge1029252018-01-30 05:01:16 -0800658ulong acpi_get_rsdp_addr(void)
659{
660 return acpi_rsdp_addr;
661}
Simon Glass4ffe8b02020-09-22 12:45:09 -0600662
663/**
664 * acpi_write_hpet() - Write out a HPET table
665 *
666 * Write out the table for High-Precision Event Timers
667 *
668 * @hpet: Place to put HPET table
669 */
670static int acpi_create_hpet(struct acpi_hpet *hpet)
671{
672 struct acpi_table_header *header = &hpet->header;
673 struct acpi_gen_regaddr *addr = &hpet->addr;
674
675 /*
676 * See IA-PC HPET (High Precision Event Timers) Specification v1.0a
677 * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
678 */
679 memset((void *)hpet, '\0', sizeof(struct acpi_hpet));
680
681 /* Fill out header fields. */
682 acpi_fill_header(header, "HPET");
683
684 header->aslc_revision = ASL_REVISION;
685 header->length = sizeof(struct acpi_hpet);
686 header->revision = acpi_get_table_revision(ACPITAB_HPET);
687
688 /* Fill out HPET address */
689 addr->space_id = 0; /* Memory */
690 addr->bit_width = 64;
691 addr->bit_offset = 0;
692 addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
693 addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
694
695 hpet->id = *(u32 *)CONFIG_HPET_ADDRESS;
696 hpet->number = 0;
697 hpet->min_tick = 0; /* HPET_MIN_TICKS */
698
699 header->checksum = table_compute_checksum(hpet,
700 sizeof(struct acpi_hpet));
701
702 return 0;
703}
704
705int acpi_write_hpet(struct acpi_ctx *ctx)
706{
707 struct acpi_hpet *hpet;
708 int ret;
709
710 log_debug("ACPI: * HPET\n");
711
712 hpet = ctx->current;
713 acpi_inc_align(ctx, sizeof(struct acpi_hpet));
714 acpi_create_hpet(hpet);
715 ret = acpi_add_table(ctx, hpet);
716 if (ret)
717 return log_msg_ret("add", ret);
718
719 return 0;
720}
Simon Glass95971892020-09-22 12:45:10 -0600721
722int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
723 uint access_size)
724{
725 struct acpi_dbg2_header *dbg2 = ctx->current;
726 char path[ACPI_PATH_MAX];
727 struct acpi_gen_regaddr address;
728 phys_addr_t addr;
729 int ret;
730
731 if (!device_active(dev)) {
732 log_info("Device not enabled\n");
733 return -EACCES;
734 }
735 /*
736 * PCI devices don't remember their resource allocation information in
737 * U-Boot at present. We assume that MMIO is used for the UART and that
738 * the address space is 32 bytes: ns16550 uses 8 registers of up to
739 * 32-bits each. This is only for debugging so it is not a big deal.
740 */
741 addr = dm_pci_read_bar32(dev, 0);
742 printf("UART addr %lx\n", (ulong)addr);
743
744 memset(&address, '\0', sizeof(address));
745 address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
746 address.addrl = (uint32_t)addr;
747 address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
748 address.access_size = access_size;
749
750 ret = acpi_device_path(dev, path, sizeof(path));
751 if (ret)
752 return log_msg_ret("path", ret);
753 acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
754 ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
755
756 acpi_inc_align(ctx, dbg2->header.length);
757 acpi_add_table(ctx, dbg2);
758
759 return 0;
760}
Simon Glass87cf8d22020-09-22 12:45:16 -0600761
762void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
763 void *dsdt)
764{
765 struct acpi_table_header *header = &fadt->header;
766
767 memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
768
769 acpi_fill_header(header, "FACP");
770 header->length = sizeof(struct acpi_fadt);
771 header->revision = 4;
772 memcpy(header->oem_id, OEM_ID, 6);
773 memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
774 memcpy(header->aslc_id, ASLC_ID, 4);
775 header->aslc_revision = 1;
776
777 fadt->firmware_ctrl = (unsigned long)facs;
778 fadt->dsdt = (unsigned long)dsdt;
779
780 fadt->x_firmware_ctl_l = (unsigned long)facs;
781 fadt->x_firmware_ctl_h = 0;
782 fadt->x_dsdt_l = (unsigned long)dsdt;
783 fadt->x_dsdt_h = 0;
784
785 fadt->preferred_pm_profile = ACPI_PM_MOBILE;
786
787 /* Use ACPI 3.0 revision */
788 fadt->header.revision = 4;
789}
790
791void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
792 u64 bar)
793{
794 struct dmar_entry *drhd = ctx->current;
795
796 memset(drhd, '\0', sizeof(*drhd));
797 drhd->type = DMAR_DRHD;
798 drhd->length = sizeof(*drhd); /* will be fixed up later */
799 drhd->flags = flags;
800 drhd->segment = segment;
801 drhd->bar = bar;
802 acpi_inc(ctx, drhd->length);
803}
804
805void acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
806 u64 limit)
807{
808 struct dmar_rmrr_entry *rmrr = ctx->current;
809
810 memset(rmrr, '\0', sizeof(*rmrr));
811 rmrr->type = DMAR_RMRR;
812 rmrr->length = sizeof(*rmrr); /* will be fixed up later */
813 rmrr->segment = segment;
814 rmrr->bar = bar;
815 rmrr->limit = limit;
816 acpi_inc(ctx, rmrr->length);
817}
818
819void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base)
820{
821 struct dmar_entry *drhd = base;
822
823 drhd->length = ctx->current - base;
824}
825
826void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base)
827{
828 struct dmar_rmrr_entry *rmrr = base;
829
830 rmrr->length = ctx->current - base;
831}
832
833static int acpi_create_dmar_ds(struct acpi_ctx *ctx, enum dev_scope_type type,
834 uint enumeration_id, pci_dev_t bdf)
835{
836 /* we don't support longer paths yet */
837 const size_t dev_scope_length = sizeof(struct dev_scope) + 2;
838 struct dev_scope *ds = ctx->current;
839
840 memset(ds, '\0', dev_scope_length);
841 ds->type = type;
842 ds->length = dev_scope_length;
843 ds->enumeration = enumeration_id;
844 ds->start_bus = PCI_BUS(bdf);
845 ds->path[0].dev = PCI_DEV(bdf);
846 ds->path[0].fn = PCI_FUNC(bdf);
847
848 return ds->length;
849}
850
851int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf)
852{
853 return acpi_create_dmar_ds(ctx, SCOPE_PCI_SUB, 0, bdf);
854}
855
856int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf)
857{
858 return acpi_create_dmar_ds(ctx, SCOPE_PCI_ENDPOINT, 0, bdf);
859}
860
861int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
862 pci_dev_t bdf)
863{
864 return acpi_create_dmar_ds(ctx, SCOPE_IOAPIC, enumeration_id, bdf);
865}
866
867int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
868 pci_dev_t bdf)
869{
870 return acpi_create_dmar_ds(ctx, SCOPE_MSI_HPET, enumeration_id, bdf);
871}