blob: 18b284789d79778772b85a212b0ca04d39d1da1c [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
Simon Glass2326a8b2020-09-22 12:45:34 -06009#define LOG_CATEGORY LOGC_ACPI
10
Saket Sinha331141a2015-08-22 12:20:55 +053011#include <common.h>
Simon Glass272a7032020-09-22 12:45:32 -060012#include <bloblist.h>
Saket Sinha331141a2015-08-22 12:20:55 +053013#include <cpu.h>
14#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
Saket Sinha331141a2015-08-22 12:20:55 +053016#include <dm/uclass-internal.h>
Simon Glass0e113842020-04-26 09:19:47 -060017#include <mapmem.h>
Andy Shevchenko4ca48c92018-11-20 23:52:38 +020018#include <serial.h>
Simon Glassf0a8d682020-07-07 13:12:07 -060019#include <acpi/acpigen.h>
Simon Glass95971892020-09-22 12:45:10 -060020#include <acpi/acpi_device.h>
Simon Glass858fed12020-04-08 16:57:36 -060021#include <acpi/acpi_table.h>
Bin Mengd9050c62016-06-17 02:13:16 -070022#include <asm/acpi/global_nvs.h>
Andy Shevchenko13a5d872017-07-21 22:32:04 +030023#include <asm/ioapic.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060024#include <asm/global_data.h>
Saket Sinha331141a2015-08-22 12:20:55 +053025#include <asm/lapic.h>
Andy Shevchenko13a5d872017-07-21 22:32:04 +030026#include <asm/mpspec.h>
Saket Sinha331141a2015-08-22 12:20:55 +053027#include <asm/tables.h>
Bin Mengd9050c62016-06-17 02:13:16 -070028#include <asm/arch/global_nvs.h>
Simon Glass0e113842020-04-26 09:19:47 -060029#include <dm/acpi.h>
Simon Glass9ed41e72020-07-07 21:32:05 -060030#include <linux/err.h>
Saket Sinha331141a2015-08-22 12:20:55 +053031
Andy Shevchenko66d3e632018-01-10 19:40:15 +020032/* ACPI RSDP address to be used in boot parameters */
Bin Menge1029252018-01-30 05:01:16 -080033static ulong acpi_rsdp_addr;
Andy Shevchenko66d3e632018-01-10 19:40:15 +020034
Saket Sinha331141a2015-08-22 12:20:55 +053035static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
Bin Meng44256b02016-05-07 07:46:25 -070036 u8 cpu, u8 apic)
Saket Sinha331141a2015-08-22 12:20:55 +053037{
Bin Meng44256b02016-05-07 07:46:25 -070038 lapic->type = ACPI_APIC_LAPIC;
Saket Sinha331141a2015-08-22 12:20:55 +053039 lapic->length = sizeof(struct acpi_madt_lapic);
Bin Meng44256b02016-05-07 07:46:25 -070040 lapic->flags = LOCAL_APIC_FLAG_ENABLED;
Saket Sinha331141a2015-08-22 12:20:55 +053041 lapic->processor_id = cpu;
42 lapic->apic_id = apic;
43
44 return lapic->length;
45}
46
Bin Meng3c5234e2016-05-07 07:46:30 -070047int acpi_create_madt_lapics(u32 current)
Saket Sinha331141a2015-08-22 12:20:55 +053048{
49 struct udevice *dev;
George McCollister5a49f872016-06-07 13:40:18 -050050 int total_length = 0;
Simon Glassfcae5472020-09-22 12:45:31 -060051 int cpu_num = 0;
Saket Sinha331141a2015-08-22 12:20:55 +053052
53 for (uclass_find_first_device(UCLASS_CPU, &dev);
54 dev;
55 uclass_find_next_device(&dev)) {
Simon Glassb75b15b2020-12-03 16:55:23 -070056 struct cpu_plat *plat = dev_get_parent_plat(dev);
Simon Glassfcae5472020-09-22 12:45:31 -060057 int length;
58
59 length = acpi_create_madt_lapic(
60 (struct acpi_madt_lapic *)current, cpu_num++,
61 plat->cpu_id);
Bin Meng3c5234e2016-05-07 07:46:30 -070062 current += length;
George McCollister5a49f872016-06-07 13:40:18 -050063 total_length += length;
Bin Meng44256b02016-05-07 07:46:25 -070064 }
65
George McCollister5a49f872016-06-07 13:40:18 -050066 return total_length;
Saket Sinha331141a2015-08-22 12:20:55 +053067}
68
Bin Meng44256b02016-05-07 07:46:25 -070069int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
70 u32 addr, u32 gsi_base)
Saket Sinha331141a2015-08-22 12:20:55 +053071{
Bin Meng6a421582016-05-07 07:46:21 -070072 ioapic->type = ACPI_APIC_IOAPIC;
Saket Sinha331141a2015-08-22 12:20:55 +053073 ioapic->length = sizeof(struct acpi_madt_ioapic);
74 ioapic->reserved = 0x00;
75 ioapic->gsi_base = gsi_base;
76 ioapic->ioapic_id = id;
77 ioapic->ioapic_addr = addr;
78
79 return ioapic->length;
80}
81
82int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
Bin Meng44256b02016-05-07 07:46:25 -070083 u8 bus, u8 source, u32 gsirq, u16 flags)
Saket Sinha331141a2015-08-22 12:20:55 +053084{
Bin Meng6a421582016-05-07 07:46:21 -070085 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
Saket Sinha331141a2015-08-22 12:20:55 +053086 irqoverride->length = sizeof(struct acpi_madt_irqoverride);
87 irqoverride->bus = bus;
88 irqoverride->source = source;
89 irqoverride->gsirq = gsirq;
90 irqoverride->flags = flags;
91
92 return irqoverride->length;
93}
94
95int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
Bin Meng44256b02016-05-07 07:46:25 -070096 u8 cpu, u16 flags, u8 lint)
Saket Sinha331141a2015-08-22 12:20:55 +053097{
Bin Meng6a421582016-05-07 07:46:21 -070098 lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
Saket Sinha331141a2015-08-22 12:20:55 +053099 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
100 lapic_nmi->flags = flags;
101 lapic_nmi->processor_id = cpu;
102 lapic_nmi->lint = lint;
103
104 return lapic_nmi->length;
105}
106
Andy Shevchenko13a5d872017-07-21 22:32:04 +0300107static int acpi_create_madt_irq_overrides(u32 current)
108{
109 struct acpi_madt_irqoverride *irqovr;
110 u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
111 int length = 0;
112
113 irqovr = (void *)current;
114 length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
115
116 irqovr = (void *)(current + length);
117 length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
118
119 return length;
120}
121
122__weak u32 acpi_fill_madt(u32 current)
123{
124 current += acpi_create_madt_lapics(current);
125
126 current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
127 io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
128
129 current += acpi_create_madt_irq_overrides(current);
130
131 return current;
132}
133
Saket Sinha331141a2015-08-22 12:20:55 +0530134static void acpi_create_madt(struct acpi_madt *madt)
135{
Bin Meng6a421582016-05-07 07:46:21 -0700136 struct acpi_table_header *header = &(madt->header);
Bin Menga1ec7db2016-05-07 07:46:26 -0700137 u32 current = (u32)madt + sizeof(struct acpi_madt);
Saket Sinha331141a2015-08-22 12:20:55 +0530138
139 memset((void *)madt, 0, sizeof(struct acpi_madt));
140
141 /* Fill out header fields */
Bin Mengb063d5f2016-05-07 07:46:24 -0700142 acpi_fill_header(header, "APIC");
Saket Sinha331141a2015-08-22 12:20:55 +0530143 header->length = sizeof(struct acpi_madt);
Simon Glassf3694aa2020-07-16 21:22:37 -0600144 header->revision = ACPI_MADT_REV_ACPI_3_0;
Saket Sinha331141a2015-08-22 12:20:55 +0530145
146 madt->lapic_addr = LAPIC_DEFAULT_BASE;
Bin Meng6a421582016-05-07 07:46:21 -0700147 madt->flags = ACPI_MADT_PCAT_COMPAT;
Saket Sinha331141a2015-08-22 12:20:55 +0530148
149 current = acpi_fill_madt(current);
150
151 /* (Re)calculate length and checksum */
Bin Menga1ec7db2016-05-07 07:46:26 -0700152 header->length = current - (u32)madt;
Saket Sinha331141a2015-08-22 12:20:55 +0530153
154 header->checksum = table_compute_checksum((void *)madt, header->length);
155}
156
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300157int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
158 u16 seg_nr, u8 start, u8 end)
Saket Sinha331141a2015-08-22 12:20:55 +0530159{
160 memset(mmconfig, 0, sizeof(*mmconfig));
Bin Meng6a421582016-05-07 07:46:21 -0700161 mmconfig->base_address_l = base;
162 mmconfig->base_address_h = 0;
Saket Sinha331141a2015-08-22 12:20:55 +0530163 mmconfig->pci_segment_group_number = seg_nr;
164 mmconfig->start_bus_number = start;
165 mmconfig->end_bus_number = end;
166
167 return sizeof(struct acpi_mcfg_mmconfig);
168}
169
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300170__weak u32 acpi_fill_mcfg(u32 current)
Saket Sinha331141a2015-08-22 12:20:55 +0530171{
172 current += acpi_create_mcfg_mmconfig
173 ((struct acpi_mcfg_mmconfig *)current,
Bin Meng44256b02016-05-07 07:46:25 -0700174 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
Saket Sinha331141a2015-08-22 12:20:55 +0530175
176 return current;
177}
178
Simon Glass28026282020-09-22 12:45:33 -0600179/**
180 * acpi_create_tcpa() - Create a TCPA table
181 *
182 * @tcpa: Pointer to place to put table
183 *
184 * Trusted Computing Platform Alliance Capabilities Table
185 * TCPA PC Specific Implementation SpecificationTCPA is defined in the PCI
186 * Firmware Specification 3.0
187 */
188static int acpi_create_tcpa(struct acpi_tcpa *tcpa)
189{
190 struct acpi_table_header *header = &tcpa->header;
191 u32 current = (u32)tcpa + sizeof(struct acpi_tcpa);
192 int size = 0x10000; /* Use this as the default size */
193 void *log;
194 int ret;
195
196 if (!CONFIG_IS_ENABLED(BLOBLIST))
197 return -ENXIO;
198 memset(tcpa, '\0', sizeof(struct acpi_tcpa));
199
200 /* Fill out header fields */
201 acpi_fill_header(header, "TCPA");
202 header->length = sizeof(struct acpi_tcpa);
203 header->revision = 1;
204
205 ret = bloblist_ensure_size_ret(BLOBLISTT_TCPA_LOG, &size, &log);
206 if (ret)
207 return log_msg_ret("blob", ret);
208
209 tcpa->platform_class = 0;
210 tcpa->laml = size;
211 tcpa->lasa = (ulong)log;
212
213 /* (Re)calculate length and checksum */
214 header->length = current - (u32)tcpa;
215 header->checksum = table_compute_checksum((void *)tcpa, header->length);
216
217 return 0;
218}
219
Simon Glass272a7032020-09-22 12:45:32 -0600220static int get_tpm2_log(void **ptrp, int *sizep)
221{
222 const int tpm2_default_log_len = 0x10000;
223 int size;
224 int ret;
225
226 *sizep = 0;
227 size = tpm2_default_log_len;
228 ret = bloblist_ensure_size_ret(BLOBLISTT_TPM2_TCG_LOG, &size, ptrp);
229 if (ret)
230 return log_msg_ret("blob", ret);
231 *sizep = size;
232
233 return 0;
234}
235
236static int acpi_create_tpm2(struct acpi_tpm2 *tpm2)
237{
238 struct acpi_table_header *header = &tpm2->header;
239 int tpm2_log_len;
240 void *lasa;
241 int ret;
242
243 memset((void *)tpm2, 0, sizeof(struct acpi_tpm2));
244
245 /*
246 * Some payloads like SeaBIOS depend on log area to use TPM2.
247 * Get the memory size and address of TPM2 log area or initialize it.
248 */
249 ret = get_tpm2_log(&lasa, &tpm2_log_len);
250 if (ret)
251 return ret;
252
253 /* Fill out header fields. */
254 acpi_fill_header(header, "TPM2");
255 memcpy(header->aslc_id, ASLC_ID, 4);
256
257 header->length = sizeof(struct acpi_tpm2);
258 header->revision = acpi_get_table_revision(ACPITAB_TPM2);
259
260 /* Hard to detect for coreboot. Just set it to 0 */
261 tpm2->platform_class = 0;
262
263 /* Must be set to 0 for FIFO-interface support */
264 tpm2->control_area = 0;
265 tpm2->start_method = 6;
266 memset(tpm2->msp, 0, sizeof(tpm2->msp));
267
268 /* Fill the log area size and start address fields. */
269 tpm2->laml = tpm2_log_len;
270 tpm2->lasa = (uintptr_t)lasa;
271
272 /* Calculate checksum. */
273 header->checksum = table_compute_checksum((void *)tpm2, header->length);
274
275 return 0;
276}
277
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300278__weak u32 acpi_fill_csrt(u32 current)
279{
Simon Glass9eb80042020-07-07 21:32:24 -0600280 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300281}
282
Simon Glass9eb80042020-07-07 21:32:24 -0600283static int acpi_create_csrt(struct acpi_csrt *csrt)
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300284{
285 struct acpi_table_header *header = &(csrt->header);
286 u32 current = (u32)csrt + sizeof(struct acpi_csrt);
Simon Glass9eb80042020-07-07 21:32:24 -0600287 uint ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300288
289 memset((void *)csrt, 0, sizeof(struct acpi_csrt));
290
291 /* Fill out header fields */
292 acpi_fill_header(header, "CSRT");
293 header->length = sizeof(struct acpi_csrt);
294 header->revision = 0;
295
Simon Glass9eb80042020-07-07 21:32:24 -0600296 ptr = acpi_fill_csrt(current);
297 if (!ptr)
298 return -ENOENT;
299 current = ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300300
301 /* (Re)calculate length and checksum */
302 header->length = current - (u32)csrt;
303 header->checksum = table_compute_checksum((void *)csrt, header->length);
Simon Glass9eb80042020-07-07 21:32:24 -0600304
305 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300306}
307
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200308static void acpi_create_spcr(struct acpi_spcr *spcr)
309{
310 struct acpi_table_header *header = &(spcr->header);
311 struct serial_device_info serial_info = {0};
312 ulong serial_address, serial_offset;
Simon Glassdaaff932018-12-28 14:23:08 -0700313 struct udevice *dev;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200314 uint serial_config;
315 uint serial_width;
316 int access_size;
317 int space_id;
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200318 int ret = -ENODEV;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200319
Wolfgang Wallner13c23e92020-09-16 16:57:53 +0200320 memset((void *)spcr, 0, sizeof(struct acpi_spcr));
321
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200322 /* Fill out header fields */
323 acpi_fill_header(header, "SPCR");
324 header->length = sizeof(struct acpi_spcr);
325 header->revision = 2;
326
Simon Glass896c1642018-12-28 14:23:10 -0700327 /* Read the device once, here. It is reused below */
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200328 dev = gd->cur_serial_dev;
329 if (dev)
Simon Glass896c1642018-12-28 14:23:10 -0700330 ret = serial_getinfo(dev, &serial_info);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200331 if (ret)
332 serial_info.type = SERIAL_CHIP_UNKNOWN;
333
334 /* Encode chip type */
335 switch (serial_info.type) {
336 case SERIAL_CHIP_16550_COMPATIBLE:
337 spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
338 break;
339 case SERIAL_CHIP_UNKNOWN:
340 default:
341 spcr->interface_type = ACPI_DBG2_UNKNOWN;
342 break;
343 }
344
345 /* Encode address space */
346 switch (serial_info.addr_space) {
347 case SERIAL_ADDRESS_SPACE_MEMORY:
348 space_id = ACPI_ADDRESS_SPACE_MEMORY;
349 break;
350 case SERIAL_ADDRESS_SPACE_IO:
351 default:
352 space_id = ACPI_ADDRESS_SPACE_IO;
353 break;
354 }
355
356 serial_width = serial_info.reg_width * 8;
357 serial_offset = serial_info.reg_offset << serial_info.reg_shift;
358 serial_address = serial_info.addr + serial_offset;
359
360 /* Encode register access size */
361 switch (serial_info.reg_shift) {
362 case 0:
363 access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
364 break;
365 case 1:
366 access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
367 break;
368 case 2:
369 access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
370 break;
371 case 3:
372 access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
373 break;
374 default:
375 access_size = ACPI_ACCESS_SIZE_UNDEFINED;
376 break;
377 }
378
379 debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
380
381 /* Fill GAS */
382 spcr->serial_port.space_id = space_id;
383 spcr->serial_port.bit_width = serial_width;
384 spcr->serial_port.bit_offset = 0;
385 spcr->serial_port.access_size = access_size;
386 spcr->serial_port.addrl = lower_32_bits(serial_address);
387 spcr->serial_port.addrh = upper_32_bits(serial_address);
388
389 /* Encode baud rate */
390 switch (serial_info.baudrate) {
391 case 9600:
392 spcr->baud_rate = 3;
393 break;
394 case 19200:
395 spcr->baud_rate = 4;
396 break;
397 case 57600:
398 spcr->baud_rate = 6;
399 break;
400 case 115200:
401 spcr->baud_rate = 7;
402 break;
403 default:
404 spcr->baud_rate = 0;
405 break;
406 }
407
Simon Glass896c1642018-12-28 14:23:10 -0700408 serial_config = SERIAL_DEFAULT_CONFIG;
409 if (dev)
Simon Glassdaaff932018-12-28 14:23:08 -0700410 ret = serial_getconfig(dev, &serial_config);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200411
412 spcr->parity = SERIAL_GET_PARITY(serial_config);
413 spcr->stop_bits = SERIAL_GET_STOP(serial_config);
414
415 /* No PCI devices for now */
416 spcr->pci_device_id = 0xffff;
417 spcr->pci_vendor_id = 0xffff;
418
Andy Shevchenko225cc8a2020-02-27 17:21:56 +0200419 /*
420 * SPCR has no clue if the UART base clock speed is different
421 * to the default one. However, the SPCR 1.04 defines baud rate
422 * 0 as a preconfigured state of UART and OS is supposed not
423 * to touch the configuration of the serial device.
424 */
425 if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
426 spcr->baud_rate = 0;
427
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200428 /* Fix checksum */
429 header->checksum = table_compute_checksum((void *)spcr, header->length);
430}
431
Simon Glassd2a98eb2021-12-01 09:02:53 -0700432int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry)
Saket Sinha331141a2015-08-22 12:20:55 +0530433{
Simon Glass0e113842020-04-26 09:19:47 -0600434 ulong addr;
Saket Sinha331141a2015-08-22 12:20:55 +0530435
Simon Glass6fe570a2020-09-22 12:44:53 -0600436 if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
Simon Glassd2a98eb2021-12-01 09:02:53 -0700437 int i;
438
439 /* We need the DSDT to be done */
440 if (!ctx->dsdt)
441 return log_msg_ret("dsdt", -EAGAIN);
442
Simon Glass6fe570a2020-09-22 12:44:53 -0600443 /* Pack GNVS into the ACPI table area */
Simon Glass83c3cb52021-12-01 09:02:52 -0700444 for (i = 0; i < ctx->dsdt->length; i++) {
445 u32 *gnvs = (u32 *)((u32)ctx->dsdt + i);
Simon Glass0e113842020-04-26 09:19:47 -0600446
Simon Glass6fe570a2020-09-22 12:44:53 -0600447 if (*gnvs == ACPI_GNVS_ADDR) {
448 *gnvs = map_to_sysmem(ctx->current);
Simon Glassd2a98eb2021-12-01 09:02:53 -0700449 log_debug("Fix up global NVS in DSDT to %#08x\n",
450 *gnvs);
Simon Glass6fe570a2020-09-22 12:44:53 -0600451 break;
452 }
Bin Mengd9050c62016-06-17 02:13:16 -0700453 }
Simon Glass6fe570a2020-09-22 12:44:53 -0600454
455 /*
Simon Glassd2a98eb2021-12-01 09:02:53 -0700456 * Recalculate the length and update the DSDT checksum since we
457 * patched the GNVS address. Set the checksum to zero since it
458 * is part of the region being checksummed.
Simon Glass6fe570a2020-09-22 12:44:53 -0600459 */
Simon Glassd2a98eb2021-12-01 09:02:53 -0700460 ctx->dsdt->checksum = 0;
461 ctx->dsdt->checksum = table_compute_checksum((void *)ctx->dsdt,
462 ctx->dsdt->length);
Bin Mengd9050c62016-06-17 02:13:16 -0700463 }
464
Simon Glassd2a98eb2021-12-01 09:02:53 -0700465 /* Fill in platform-specific global NVS variables */
Simon Glass9ed41e72020-07-07 21:32:05 -0600466 addr = acpi_create_gnvs(ctx->current);
467 if (IS_ERR_VALUE(addr))
Simon Glassd2a98eb2021-12-01 09:02:53 -0700468 return log_msg_ret("gnvs", (int)addr);
Simon Glass9ed41e72020-07-07 21:32:05 -0600469
Simon Glass0e113842020-04-26 09:19:47 -0600470 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
Bin Mengd9050c62016-06-17 02:13:16 -0700471
Simon Glassd2a98eb2021-12-01 09:02:53 -0700472 return 0;
473}
474ACPI_WRITER(4gnvs, "GNVS", acpi_write_gnvs, 0);
475
Simon Glass68000952021-12-01 09:02:56 -0700476/* MCFG is defined in the PCI Firmware Specification 3.0 */
477int acpi_write_mcfg(struct acpi_ctx *ctx, const struct acpi_writer *entry)
478{
479 struct acpi_table_header *header;
480 struct acpi_mcfg *mcfg;
481 u32 current;
482
483 mcfg = ctx->current;
484 header = &mcfg->header;
485
486 current = (u32)mcfg + sizeof(struct acpi_mcfg);
487
488 memset(mcfg, '\0', sizeof(struct acpi_mcfg));
489
490 /* Fill out header fields */
491 acpi_fill_header(header, "MCFG");
492 header->length = sizeof(struct acpi_mcfg);
493 header->revision = 1;
494
495 /* (Re)calculate length and checksum */
496 header->length = current - (u32)mcfg;
497 header->checksum = table_compute_checksum(mcfg, header->length);
498
499 acpi_inc(ctx, mcfg->header.length);
500 acpi_add_table(ctx, mcfg);
501
502 return 0;
503}
504ACPI_WRITER(5mcfg, "MCFG", acpi_write_mcfg, 0);
505
Simon Glassd2a98eb2021-12-01 09:02:53 -0700506/*
507 * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
508 */
509int write_acpi_tables_x86(struct acpi_ctx *ctx,
510 const struct acpi_writer *entry)
511{
Simon Glassd2a98eb2021-12-01 09:02:53 -0700512 struct acpi_tcpa *tcpa;
513 struct acpi_madt *madt;
514 struct acpi_csrt *csrt;
515 struct acpi_spcr *spcr;
516 int ret;
517
Simon Glass272a7032020-09-22 12:45:32 -0600518 if (IS_ENABLED(CONFIG_TPM_V2)) {
519 struct acpi_tpm2 *tpm2;
Simon Glass272a7032020-09-22 12:45:32 -0600520
521 debug("ACPI: * TPM2\n");
522 tpm2 = (struct acpi_tpm2 *)ctx->current;
523 ret = acpi_create_tpm2(tpm2);
524 if (!ret) {
525 acpi_inc_align(ctx, tpm2->header.length);
526 acpi_add_table(ctx, tpm2);
527 } else {
528 log_warning("TPM2 table creation failed\n");
529 }
530 }
531
Simon Glassc7c46e82020-07-07 13:12:04 -0600532 debug("ACPI: * MADT\n");
533 madt = ctx->current;
534 acpi_create_madt(madt);
535 acpi_inc_align(ctx, madt->header.length);
536 acpi_add_table(ctx, madt);
537
Simon Glass14ca07c2020-11-04 09:57:40 -0700538 if (IS_ENABLED(CONFIG_TPM_V1)) {
539 debug("ACPI: * TCPA\n");
540 tcpa = (struct acpi_tcpa *)ctx->current;
541 ret = acpi_create_tcpa(tcpa);
542 if (ret) {
543 log_warning("Failed to create TCPA table (err=%d)\n",
544 ret);
545 } else {
546 acpi_inc_align(ctx, tcpa->header.length);
547 acpi_add_table(ctx, tcpa);
548 }
Simon Glass28026282020-09-22 12:45:33 -0600549 }
550
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300551 debug("ACPI: * CSRT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600552 csrt = ctx->current;
Simon Glass9eb80042020-07-07 21:32:24 -0600553 if (!acpi_create_csrt(csrt)) {
554 acpi_inc_align(ctx, csrt->header.length);
555 acpi_add_table(ctx, csrt);
556 }
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300557
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200558 debug("ACPI: * SPCR\n");
Simon Glass0e113842020-04-26 09:19:47 -0600559 spcr = ctx->current;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200560 acpi_create_spcr(spcr);
Simon Glass0e113842020-04-26 09:19:47 -0600561 acpi_inc_align(ctx, spcr->header.length);
Simon Glass575a5472020-04-26 09:19:50 -0600562 acpi_add_table(ctx, spcr);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200563
Simon Glass179fb822020-04-26 09:19:48 -0600564 acpi_write_dev_tables(ctx);
565
Simon Glass575a5472020-04-26 09:19:50 -0600566 acpi_rsdp_addr = (unsigned long)ctx->rsdp;
Bin Mengd2d22182016-05-07 07:46:12 -0700567 debug("ACPI: done\n");
Saket Sinha331141a2015-08-22 12:20:55 +0530568
Simon Glass16170882021-12-01 09:02:49 -0700569 return 0;
Saket Sinha331141a2015-08-22 12:20:55 +0530570}
Simon Glass83c3cb52021-12-01 09:02:52 -0700571ACPI_WRITER(9x86, NULL, write_acpi_tables_x86, 0);
Bin Meng34bc74a2017-04-21 07:24:36 -0700572
Bin Menge1029252018-01-30 05:01:16 -0800573ulong acpi_get_rsdp_addr(void)
574{
575 return acpi_rsdp_addr;
576}
Simon Glass4ffe8b02020-09-22 12:45:09 -0600577
578/**
579 * acpi_write_hpet() - Write out a HPET table
580 *
581 * Write out the table for High-Precision Event Timers
582 *
583 * @hpet: Place to put HPET table
584 */
585static int acpi_create_hpet(struct acpi_hpet *hpet)
586{
587 struct acpi_table_header *header = &hpet->header;
588 struct acpi_gen_regaddr *addr = &hpet->addr;
589
590 /*
591 * See IA-PC HPET (High Precision Event Timers) Specification v1.0a
592 * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
593 */
594 memset((void *)hpet, '\0', sizeof(struct acpi_hpet));
595
596 /* Fill out header fields. */
597 acpi_fill_header(header, "HPET");
598
599 header->aslc_revision = ASL_REVISION;
600 header->length = sizeof(struct acpi_hpet);
601 header->revision = acpi_get_table_revision(ACPITAB_HPET);
602
603 /* Fill out HPET address */
604 addr->space_id = 0; /* Memory */
605 addr->bit_width = 64;
606 addr->bit_offset = 0;
607 addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
608 addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
609
610 hpet->id = *(u32 *)CONFIG_HPET_ADDRESS;
611 hpet->number = 0;
612 hpet->min_tick = 0; /* HPET_MIN_TICKS */
613
614 header->checksum = table_compute_checksum(hpet,
615 sizeof(struct acpi_hpet));
616
617 return 0;
618}
619
620int acpi_write_hpet(struct acpi_ctx *ctx)
621{
622 struct acpi_hpet *hpet;
623 int ret;
624
625 log_debug("ACPI: * HPET\n");
626
627 hpet = ctx->current;
628 acpi_inc_align(ctx, sizeof(struct acpi_hpet));
629 acpi_create_hpet(hpet);
630 ret = acpi_add_table(ctx, hpet);
631 if (ret)
632 return log_msg_ret("add", ret);
633
634 return 0;
635}
Simon Glass95971892020-09-22 12:45:10 -0600636
637int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
638 uint access_size)
639{
640 struct acpi_dbg2_header *dbg2 = ctx->current;
641 char path[ACPI_PATH_MAX];
642 struct acpi_gen_regaddr address;
643 phys_addr_t addr;
644 int ret;
645
646 if (!device_active(dev)) {
647 log_info("Device not enabled\n");
648 return -EACCES;
649 }
650 /*
651 * PCI devices don't remember their resource allocation information in
652 * U-Boot at present. We assume that MMIO is used for the UART and that
653 * the address space is 32 bytes: ns16550 uses 8 registers of up to
654 * 32-bits each. This is only for debugging so it is not a big deal.
655 */
656 addr = dm_pci_read_bar32(dev, 0);
Simon Glass75081202020-11-04 09:57:41 -0700657 log_debug("UART addr %lx\n", (ulong)addr);
Simon Glass95971892020-09-22 12:45:10 -0600658
659 memset(&address, '\0', sizeof(address));
660 address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
661 address.addrl = (uint32_t)addr;
662 address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
663 address.access_size = access_size;
664
665 ret = acpi_device_path(dev, path, sizeof(path));
666 if (ret)
667 return log_msg_ret("path", ret);
668 acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
669 ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
670
671 acpi_inc_align(ctx, dbg2->header.length);
672 acpi_add_table(ctx, dbg2);
673
674 return 0;
675}
Simon Glass87cf8d22020-09-22 12:45:16 -0600676
677void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
678 void *dsdt)
679{
680 struct acpi_table_header *header = &fadt->header;
681
682 memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
683
684 acpi_fill_header(header, "FACP");
685 header->length = sizeof(struct acpi_fadt);
686 header->revision = 4;
687 memcpy(header->oem_id, OEM_ID, 6);
688 memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
689 memcpy(header->aslc_id, ASLC_ID, 4);
690 header->aslc_revision = 1;
691
692 fadt->firmware_ctrl = (unsigned long)facs;
693 fadt->dsdt = (unsigned long)dsdt;
694
695 fadt->x_firmware_ctl_l = (unsigned long)facs;
696 fadt->x_firmware_ctl_h = 0;
697 fadt->x_dsdt_l = (unsigned long)dsdt;
698 fadt->x_dsdt_h = 0;
699
700 fadt->preferred_pm_profile = ACPI_PM_MOBILE;
701
702 /* Use ACPI 3.0 revision */
703 fadt->header.revision = 4;
704}
705
706void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
707 u64 bar)
708{
709 struct dmar_entry *drhd = ctx->current;
710
711 memset(drhd, '\0', sizeof(*drhd));
712 drhd->type = DMAR_DRHD;
713 drhd->length = sizeof(*drhd); /* will be fixed up later */
714 drhd->flags = flags;
715 drhd->segment = segment;
716 drhd->bar = bar;
717 acpi_inc(ctx, drhd->length);
718}
719
720void acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
721 u64 limit)
722{
723 struct dmar_rmrr_entry *rmrr = ctx->current;
724
725 memset(rmrr, '\0', sizeof(*rmrr));
726 rmrr->type = DMAR_RMRR;
727 rmrr->length = sizeof(*rmrr); /* will be fixed up later */
728 rmrr->segment = segment;
729 rmrr->bar = bar;
730 rmrr->limit = limit;
731 acpi_inc(ctx, rmrr->length);
732}
733
734void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base)
735{
736 struct dmar_entry *drhd = base;
737
738 drhd->length = ctx->current - base;
739}
740
741void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base)
742{
743 struct dmar_rmrr_entry *rmrr = base;
744
745 rmrr->length = ctx->current - base;
746}
747
748static int acpi_create_dmar_ds(struct acpi_ctx *ctx, enum dev_scope_type type,
749 uint enumeration_id, pci_dev_t bdf)
750{
751 /* we don't support longer paths yet */
752 const size_t dev_scope_length = sizeof(struct dev_scope) + 2;
753 struct dev_scope *ds = ctx->current;
754
755 memset(ds, '\0', dev_scope_length);
756 ds->type = type;
757 ds->length = dev_scope_length;
758 ds->enumeration = enumeration_id;
759 ds->start_bus = PCI_BUS(bdf);
760 ds->path[0].dev = PCI_DEV(bdf);
761 ds->path[0].fn = PCI_FUNC(bdf);
762
763 return ds->length;
764}
765
766int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf)
767{
768 return acpi_create_dmar_ds(ctx, SCOPE_PCI_SUB, 0, bdf);
769}
770
771int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf)
772{
773 return acpi_create_dmar_ds(ctx, SCOPE_PCI_ENDPOINT, 0, bdf);
774}
775
776int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
777 pci_dev_t bdf)
778{
779 return acpi_create_dmar_ds(ctx, SCOPE_IOAPIC, enumeration_id, bdf);
780}
781
782int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
783 pci_dev_t bdf)
784{
785 return acpi_create_dmar_ds(ctx, SCOPE_MSI_HPET, enumeration_id, bdf);
786}