blob: e257c7898383b1606d48e7521ddbdd088b595107 [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>
10#include <cpu.h>
11#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Saket Sinha331141a2015-08-22 12:20:55 +053013#include <dm/uclass-internal.h>
Simon Glass0e113842020-04-26 09:19:47 -060014#include <mapmem.h>
Andy Shevchenko4ca48c92018-11-20 23:52:38 +020015#include <serial.h>
Andy Shevchenko87e95372017-07-21 22:32:02 +030016#include <version.h>
Simon Glassf0a8d682020-07-07 13:12:07 -060017#include <acpi/acpigen.h>
Simon Glass95971892020-09-22 12:45:10 -060018#include <acpi/acpi_device.h>
Simon Glass858fed12020-04-08 16:57:36 -060019#include <acpi/acpi_table.h>
Bin Mengd9050c62016-06-17 02:13:16 -070020#include <asm/acpi/global_nvs.h>
Andy Shevchenko13a5d872017-07-21 22:32:04 +030021#include <asm/ioapic.h>
Saket Sinha331141a2015-08-22 12:20:55 +053022#include <asm/lapic.h>
Andy Shevchenko13a5d872017-07-21 22:32:04 +030023#include <asm/mpspec.h>
Saket Sinha331141a2015-08-22 12:20:55 +053024#include <asm/tables.h>
Bin Mengd9050c62016-06-17 02:13:16 -070025#include <asm/arch/global_nvs.h>
Simon Glass0e113842020-04-26 09:19:47 -060026#include <dm/acpi.h>
Simon Glass9ed41e72020-07-07 21:32:05 -060027#include <linux/err.h>
Saket Sinha331141a2015-08-22 12:20:55 +053028
29/*
Bin Mengb063d5f2016-05-07 07:46:24 -070030 * IASL compiles the dsdt entries and writes the hex values
31 * to a C array AmlCode[] (see dsdt.c).
Saket Sinha331141a2015-08-22 12:20:55 +053032 */
33extern const unsigned char AmlCode[];
34
Andy Shevchenko66d3e632018-01-10 19:40:15 +020035/* ACPI RSDP address to be used in boot parameters */
Bin Menge1029252018-01-30 05:01:16 -080036static ulong acpi_rsdp_addr;
Andy Shevchenko66d3e632018-01-10 19:40:15 +020037
Bin Meng44256b02016-05-07 07:46:25 -070038static void acpi_create_facs(struct acpi_facs *facs)
39{
40 memset((void *)facs, 0, sizeof(struct acpi_facs));
41
42 memcpy(facs->signature, "FACS", 4);
43 facs->length = sizeof(struct acpi_facs);
44 facs->hardware_signature = 0;
45 facs->firmware_waking_vector = 0;
46 facs->global_lock = 0;
47 facs->flags = 0;
48 facs->x_firmware_waking_vector_l = 0;
49 facs->x_firmware_waking_vector_h = 0;
50 facs->version = 1;
51}
52
Saket Sinha331141a2015-08-22 12:20:55 +053053static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
Bin Meng44256b02016-05-07 07:46:25 -070054 u8 cpu, u8 apic)
Saket Sinha331141a2015-08-22 12:20:55 +053055{
Bin Meng44256b02016-05-07 07:46:25 -070056 lapic->type = ACPI_APIC_LAPIC;
Saket Sinha331141a2015-08-22 12:20:55 +053057 lapic->length = sizeof(struct acpi_madt_lapic);
Bin Meng44256b02016-05-07 07:46:25 -070058 lapic->flags = LOCAL_APIC_FLAG_ENABLED;
Saket Sinha331141a2015-08-22 12:20:55 +053059 lapic->processor_id = cpu;
60 lapic->apic_id = apic;
61
62 return lapic->length;
63}
64
Bin Meng3c5234e2016-05-07 07:46:30 -070065int acpi_create_madt_lapics(u32 current)
Saket Sinha331141a2015-08-22 12:20:55 +053066{
67 struct udevice *dev;
George McCollister5a49f872016-06-07 13:40:18 -050068 int total_length = 0;
Saket Sinha331141a2015-08-22 12:20:55 +053069
70 for (uclass_find_first_device(UCLASS_CPU, &dev);
71 dev;
72 uclass_find_next_device(&dev)) {
73 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
George McCollister5a49f872016-06-07 13:40:18 -050074 int length = acpi_create_madt_lapic(
75 (struct acpi_madt_lapic *)current,
76 plat->cpu_id, plat->cpu_id);
Bin Meng3c5234e2016-05-07 07:46:30 -070077 current += length;
George McCollister5a49f872016-06-07 13:40:18 -050078 total_length += length;
Bin Meng44256b02016-05-07 07:46:25 -070079 }
80
George McCollister5a49f872016-06-07 13:40:18 -050081 return total_length;
Saket Sinha331141a2015-08-22 12:20:55 +053082}
83
Bin Meng44256b02016-05-07 07:46:25 -070084int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
85 u32 addr, u32 gsi_base)
Saket Sinha331141a2015-08-22 12:20:55 +053086{
Bin Meng6a421582016-05-07 07:46:21 -070087 ioapic->type = ACPI_APIC_IOAPIC;
Saket Sinha331141a2015-08-22 12:20:55 +053088 ioapic->length = sizeof(struct acpi_madt_ioapic);
89 ioapic->reserved = 0x00;
90 ioapic->gsi_base = gsi_base;
91 ioapic->ioapic_id = id;
92 ioapic->ioapic_addr = addr;
93
94 return ioapic->length;
95}
96
97int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
Bin Meng44256b02016-05-07 07:46:25 -070098 u8 bus, u8 source, u32 gsirq, u16 flags)
Saket Sinha331141a2015-08-22 12:20:55 +053099{
Bin Meng6a421582016-05-07 07:46:21 -0700100 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
Saket Sinha331141a2015-08-22 12:20:55 +0530101 irqoverride->length = sizeof(struct acpi_madt_irqoverride);
102 irqoverride->bus = bus;
103 irqoverride->source = source;
104 irqoverride->gsirq = gsirq;
105 irqoverride->flags = flags;
106
107 return irqoverride->length;
108}
109
110int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
Bin Meng44256b02016-05-07 07:46:25 -0700111 u8 cpu, u16 flags, u8 lint)
Saket Sinha331141a2015-08-22 12:20:55 +0530112{
Bin Meng6a421582016-05-07 07:46:21 -0700113 lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
Saket Sinha331141a2015-08-22 12:20:55 +0530114 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
115 lapic_nmi->flags = flags;
116 lapic_nmi->processor_id = cpu;
117 lapic_nmi->lint = lint;
118
119 return lapic_nmi->length;
120}
121
Andy Shevchenko13a5d872017-07-21 22:32:04 +0300122static int acpi_create_madt_irq_overrides(u32 current)
123{
124 struct acpi_madt_irqoverride *irqovr;
125 u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
126 int length = 0;
127
128 irqovr = (void *)current;
129 length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
130
131 irqovr = (void *)(current + length);
132 length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
133
134 return length;
135}
136
137__weak u32 acpi_fill_madt(u32 current)
138{
139 current += acpi_create_madt_lapics(current);
140
141 current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
142 io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
143
144 current += acpi_create_madt_irq_overrides(current);
145
146 return current;
147}
148
Saket Sinha331141a2015-08-22 12:20:55 +0530149static void acpi_create_madt(struct acpi_madt *madt)
150{
Bin Meng6a421582016-05-07 07:46:21 -0700151 struct acpi_table_header *header = &(madt->header);
Bin Menga1ec7db2016-05-07 07:46:26 -0700152 u32 current = (u32)madt + sizeof(struct acpi_madt);
Saket Sinha331141a2015-08-22 12:20:55 +0530153
154 memset((void *)madt, 0, sizeof(struct acpi_madt));
155
156 /* Fill out header fields */
Bin Mengb063d5f2016-05-07 07:46:24 -0700157 acpi_fill_header(header, "APIC");
Saket Sinha331141a2015-08-22 12:20:55 +0530158 header->length = sizeof(struct acpi_madt);
Simon Glassf3694aa2020-07-16 21:22:37 -0600159 header->revision = ACPI_MADT_REV_ACPI_3_0;
Saket Sinha331141a2015-08-22 12:20:55 +0530160
161 madt->lapic_addr = LAPIC_DEFAULT_BASE;
Bin Meng6a421582016-05-07 07:46:21 -0700162 madt->flags = ACPI_MADT_PCAT_COMPAT;
Saket Sinha331141a2015-08-22 12:20:55 +0530163
164 current = acpi_fill_madt(current);
165
166 /* (Re)calculate length and checksum */
Bin Menga1ec7db2016-05-07 07:46:26 -0700167 header->length = current - (u32)madt;
Saket Sinha331141a2015-08-22 12:20:55 +0530168
169 header->checksum = table_compute_checksum((void *)madt, header->length);
170}
171
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300172int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
173 u16 seg_nr, u8 start, u8 end)
Saket Sinha331141a2015-08-22 12:20:55 +0530174{
175 memset(mmconfig, 0, sizeof(*mmconfig));
Bin Meng6a421582016-05-07 07:46:21 -0700176 mmconfig->base_address_l = base;
177 mmconfig->base_address_h = 0;
Saket Sinha331141a2015-08-22 12:20:55 +0530178 mmconfig->pci_segment_group_number = seg_nr;
179 mmconfig->start_bus_number = start;
180 mmconfig->end_bus_number = end;
181
182 return sizeof(struct acpi_mcfg_mmconfig);
183}
184
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300185__weak u32 acpi_fill_mcfg(u32 current)
Saket Sinha331141a2015-08-22 12:20:55 +0530186{
187 current += acpi_create_mcfg_mmconfig
188 ((struct acpi_mcfg_mmconfig *)current,
Bin Meng44256b02016-05-07 07:46:25 -0700189 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
Saket Sinha331141a2015-08-22 12:20:55 +0530190
191 return current;
192}
193
194/* MCFG is defined in the PCI Firmware Specification 3.0 */
195static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
196{
Bin Meng6a421582016-05-07 07:46:21 -0700197 struct acpi_table_header *header = &(mcfg->header);
Bin Menga1ec7db2016-05-07 07:46:26 -0700198 u32 current = (u32)mcfg + sizeof(struct acpi_mcfg);
Saket Sinha331141a2015-08-22 12:20:55 +0530199
200 memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
201
202 /* Fill out header fields */
Bin Mengb063d5f2016-05-07 07:46:24 -0700203 acpi_fill_header(header, "MCFG");
Saket Sinha331141a2015-08-22 12:20:55 +0530204 header->length = sizeof(struct acpi_mcfg);
Bin Mengf662fe42016-05-07 07:46:28 -0700205 header->revision = 1;
Saket Sinha331141a2015-08-22 12:20:55 +0530206
207 current = acpi_fill_mcfg(current);
208
209 /* (Re)calculate length and checksum */
Bin Menga1ec7db2016-05-07 07:46:26 -0700210 header->length = current - (u32)mcfg;
Saket Sinha331141a2015-08-22 12:20:55 +0530211 header->checksum = table_compute_checksum((void *)mcfg, header->length);
212}
213
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300214__weak u32 acpi_fill_csrt(u32 current)
215{
Simon Glass9eb80042020-07-07 21:32:24 -0600216 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300217}
218
Simon Glass9eb80042020-07-07 21:32:24 -0600219static int acpi_create_csrt(struct acpi_csrt *csrt)
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300220{
221 struct acpi_table_header *header = &(csrt->header);
222 u32 current = (u32)csrt + sizeof(struct acpi_csrt);
Simon Glass9eb80042020-07-07 21:32:24 -0600223 uint ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300224
225 memset((void *)csrt, 0, sizeof(struct acpi_csrt));
226
227 /* Fill out header fields */
228 acpi_fill_header(header, "CSRT");
229 header->length = sizeof(struct acpi_csrt);
230 header->revision = 0;
231
Simon Glass9eb80042020-07-07 21:32:24 -0600232 ptr = acpi_fill_csrt(current);
233 if (!ptr)
234 return -ENOENT;
235 current = ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300236
237 /* (Re)calculate length and checksum */
238 header->length = current - (u32)csrt;
239 header->checksum = table_compute_checksum((void *)csrt, header->length);
Simon Glass9eb80042020-07-07 21:32:24 -0600240
241 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300242}
243
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200244static void acpi_create_spcr(struct acpi_spcr *spcr)
245{
246 struct acpi_table_header *header = &(spcr->header);
247 struct serial_device_info serial_info = {0};
248 ulong serial_address, serial_offset;
Simon Glassdaaff932018-12-28 14:23:08 -0700249 struct udevice *dev;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200250 uint serial_config;
251 uint serial_width;
252 int access_size;
253 int space_id;
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200254 int ret = -ENODEV;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200255
Wolfgang Wallner13c23e92020-09-16 16:57:53 +0200256 memset((void *)spcr, 0, sizeof(struct acpi_spcr));
257
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200258 /* Fill out header fields */
259 acpi_fill_header(header, "SPCR");
260 header->length = sizeof(struct acpi_spcr);
261 header->revision = 2;
262
Simon Glass896c1642018-12-28 14:23:10 -0700263 /* Read the device once, here. It is reused below */
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200264 dev = gd->cur_serial_dev;
265 if (dev)
Simon Glass896c1642018-12-28 14:23:10 -0700266 ret = serial_getinfo(dev, &serial_info);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200267 if (ret)
268 serial_info.type = SERIAL_CHIP_UNKNOWN;
269
270 /* Encode chip type */
271 switch (serial_info.type) {
272 case SERIAL_CHIP_16550_COMPATIBLE:
273 spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
274 break;
275 case SERIAL_CHIP_UNKNOWN:
276 default:
277 spcr->interface_type = ACPI_DBG2_UNKNOWN;
278 break;
279 }
280
281 /* Encode address space */
282 switch (serial_info.addr_space) {
283 case SERIAL_ADDRESS_SPACE_MEMORY:
284 space_id = ACPI_ADDRESS_SPACE_MEMORY;
285 break;
286 case SERIAL_ADDRESS_SPACE_IO:
287 default:
288 space_id = ACPI_ADDRESS_SPACE_IO;
289 break;
290 }
291
292 serial_width = serial_info.reg_width * 8;
293 serial_offset = serial_info.reg_offset << serial_info.reg_shift;
294 serial_address = serial_info.addr + serial_offset;
295
296 /* Encode register access size */
297 switch (serial_info.reg_shift) {
298 case 0:
299 access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
300 break;
301 case 1:
302 access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
303 break;
304 case 2:
305 access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
306 break;
307 case 3:
308 access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
309 break;
310 default:
311 access_size = ACPI_ACCESS_SIZE_UNDEFINED;
312 break;
313 }
314
315 debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
316
317 /* Fill GAS */
318 spcr->serial_port.space_id = space_id;
319 spcr->serial_port.bit_width = serial_width;
320 spcr->serial_port.bit_offset = 0;
321 spcr->serial_port.access_size = access_size;
322 spcr->serial_port.addrl = lower_32_bits(serial_address);
323 spcr->serial_port.addrh = upper_32_bits(serial_address);
324
325 /* Encode baud rate */
326 switch (serial_info.baudrate) {
327 case 9600:
328 spcr->baud_rate = 3;
329 break;
330 case 19200:
331 spcr->baud_rate = 4;
332 break;
333 case 57600:
334 spcr->baud_rate = 6;
335 break;
336 case 115200:
337 spcr->baud_rate = 7;
338 break;
339 default:
340 spcr->baud_rate = 0;
341 break;
342 }
343
Simon Glass896c1642018-12-28 14:23:10 -0700344 serial_config = SERIAL_DEFAULT_CONFIG;
345 if (dev)
Simon Glassdaaff932018-12-28 14:23:08 -0700346 ret = serial_getconfig(dev, &serial_config);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200347
348 spcr->parity = SERIAL_GET_PARITY(serial_config);
349 spcr->stop_bits = SERIAL_GET_STOP(serial_config);
350
351 /* No PCI devices for now */
352 spcr->pci_device_id = 0xffff;
353 spcr->pci_vendor_id = 0xffff;
354
Andy Shevchenko225cc8a2020-02-27 17:21:56 +0200355 /*
356 * SPCR has no clue if the UART base clock speed is different
357 * to the default one. However, the SPCR 1.04 defines baud rate
358 * 0 as a preconfigured state of UART and OS is supposed not
359 * to touch the configuration of the serial device.
360 */
361 if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
362 spcr->baud_rate = 0;
363
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200364 /* Fix checksum */
365 header->checksum = table_compute_checksum((void *)spcr, header->length);
366}
367
Simon Glassf0a8d682020-07-07 13:12:07 -0600368void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt,
369 const char *oem_table_id)
370{
371 memset((void *)ssdt, '\0', sizeof(struct acpi_table_header));
372
373 acpi_fill_header(ssdt, "SSDT");
374 ssdt->revision = acpi_get_table_revision(ACPITAB_SSDT);
375 ssdt->aslc_revision = 1;
376 ssdt->length = sizeof(struct acpi_table_header);
377
378 acpi_inc(ctx, sizeof(struct acpi_table_header));
379
380 acpi_fill_ssdt(ctx);
381
382 /* (Re)calculate length and checksum. */
383 ssdt->length = ctx->current - (void *)ssdt;
384 ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
385}
386
Miao Yan3b68c522016-01-20 01:57:06 -0800387/*
Andy Shevchenko4b05bac2018-01-10 19:33:10 +0200388 * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
Miao Yan3b68c522016-01-20 01:57:06 -0800389 */
Simon Glass0e113842020-04-26 09:19:47 -0600390ulong write_acpi_tables(ulong start_addr)
Saket Sinha331141a2015-08-22 12:20:55 +0530391{
Simon Glass0e113842020-04-26 09:19:47 -0600392 struct acpi_ctx sctx, *ctx = &sctx;
Saket Sinha331141a2015-08-22 12:20:55 +0530393 struct acpi_facs *facs;
Bin Meng6a421582016-05-07 07:46:21 -0700394 struct acpi_table_header *dsdt;
Saket Sinha331141a2015-08-22 12:20:55 +0530395 struct acpi_fadt *fadt;
Simon Glassf0a8d682020-07-07 13:12:07 -0600396 struct acpi_table_header *ssdt;
Saket Sinha331141a2015-08-22 12:20:55 +0530397 struct acpi_mcfg *mcfg;
398 struct acpi_madt *madt;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300399 struct acpi_csrt *csrt;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200400 struct acpi_spcr *spcr;
Simon Glass0e113842020-04-26 09:19:47 -0600401 void *start;
402 ulong addr;
Bin Mengd9050c62016-06-17 02:13:16 -0700403 int i;
Saket Sinha331141a2015-08-22 12:20:55 +0530404
Simon Glass0e113842020-04-26 09:19:47 -0600405 start = map_sysmem(start_addr, 0);
Saket Sinha331141a2015-08-22 12:20:55 +0530406
Simon Glass0e113842020-04-26 09:19:47 -0600407 debug("ACPI: Writing ACPI tables at %lx\n", start_addr);
Saket Sinha331141a2015-08-22 12:20:55 +0530408
Simon Glass9c442a62020-04-26 09:19:51 -0600409 acpi_setup_base_tables(ctx, start);
Saket Sinha331141a2015-08-22 12:20:55 +0530410
411 debug("ACPI: * FACS\n");
Simon Glass0e113842020-04-26 09:19:47 -0600412 facs = ctx->current;
413 acpi_inc_align(ctx, sizeof(struct acpi_facs));
Saket Sinha331141a2015-08-22 12:20:55 +0530414
415 acpi_create_facs(facs);
416
417 debug("ACPI: * DSDT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600418 dsdt = ctx->current;
Simon Glass6ca93152020-07-07 13:12:09 -0600419
420 /* Put the table header first */
Bin Meng6a421582016-05-07 07:46:21 -0700421 memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
Simon Glass0e113842020-04-26 09:19:47 -0600422 acpi_inc(ctx, sizeof(struct acpi_table_header));
Simon Glass6ca93152020-07-07 13:12:09 -0600423
424 /* If the table is not empty, allow devices to inject things */
425 if (dsdt->length >= sizeof(struct acpi_table_header))
426 acpi_inject_dsdt(ctx);
427
428 /* Copy in the AML code itself if any (after the header) */
Simon Glass0e113842020-04-26 09:19:47 -0600429 memcpy(ctx->current,
Bin Mengd90434b2016-05-11 07:45:05 -0700430 (char *)&AmlCode + sizeof(struct acpi_table_header),
431 dsdt->length - sizeof(struct acpi_table_header));
Simon Glass6ca93152020-07-07 13:12:09 -0600432
Wolfgang Wallneraa202822020-09-16 16:57:52 +0200433 acpi_inc(ctx, dsdt->length - sizeof(struct acpi_table_header));
Simon Glass6fe570a2020-09-22 12:44:53 -0600434 dsdt->length = ctx->current - (void *)dsdt;
435 acpi_align(ctx);
Saket Sinha331141a2015-08-22 12:20:55 +0530436
Simon Glass6fe570a2020-09-22 12:44:53 -0600437 if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
438 /* Pack GNVS into the ACPI table area */
439 for (i = 0; i < dsdt->length; i++) {
440 u32 *gnvs = (u32 *)((u32)dsdt + i);
Simon Glass0e113842020-04-26 09:19:47 -0600441
Simon Glass6fe570a2020-09-22 12:44:53 -0600442 if (*gnvs == ACPI_GNVS_ADDR) {
443 *gnvs = map_to_sysmem(ctx->current);
444 debug("Fix up global NVS in DSDT to %#08x\n",
445 *gnvs);
446 break;
447 }
Bin Mengd9050c62016-06-17 02:13:16 -0700448 }
Simon Glass6fe570a2020-09-22 12:44:53 -0600449
450 /*
451 * Fill in platform-specific global NVS variables. If this fails
452 * we cannot return the error but this should only happen while
453 * debugging.
454 */
455 addr = acpi_create_gnvs(ctx->current);
456 if (IS_ERR_VALUE(addr))
457 printf("Error: Gailed to create GNVS\n");
458 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
Bin Mengd9050c62016-06-17 02:13:16 -0700459 }
460
Simon Glass6ca93152020-07-07 13:12:09 -0600461 /*
462 * Recalculate the length and update the DSDT checksum since we patched
463 * the GNVS address. Set the checksum to zero since it is part of the
464 * region being checksummed.
465 */
Bin Mengd9050c62016-06-17 02:13:16 -0700466 dsdt->checksum = 0;
467 dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
468
Simon Glass9ed41e72020-07-07 21:32:05 -0600469 /*
470 * Fill in platform-specific global NVS variables. If this fails we
471 * cannot return the error but this should only happen while debugging.
472 */
473 addr = acpi_create_gnvs(ctx->current);
474 if (IS_ERR_VALUE(addr))
475 printf("Error: Failed to create GNVS\n");
476
Simon Glass0e113842020-04-26 09:19:47 -0600477 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
Bin Mengd9050c62016-06-17 02:13:16 -0700478
Saket Sinha331141a2015-08-22 12:20:55 +0530479 debug("ACPI: * FADT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600480 fadt = ctx->current;
481 acpi_inc_align(ctx, sizeof(struct acpi_fadt));
Saket Sinha331141a2015-08-22 12:20:55 +0530482 acpi_create_fadt(fadt, facs, dsdt);
Simon Glass575a5472020-04-26 09:19:50 -0600483 acpi_add_table(ctx, fadt);
Saket Sinha331141a2015-08-22 12:20:55 +0530484
Simon Glassf0a8d682020-07-07 13:12:07 -0600485 debug("ACPI: * SSDT\n");
486 ssdt = (struct acpi_table_header *)ctx->current;
487 acpi_create_ssdt(ctx, ssdt, OEM_TABLE_ID);
488 if (ssdt->length > sizeof(struct acpi_table_header)) {
489 acpi_inc_align(ctx, ssdt->length);
490 acpi_add_table(ctx, ssdt);
491 }
492
Bin Meng44256b02016-05-07 07:46:25 -0700493 debug("ACPI: * MCFG\n");
Simon Glass0e113842020-04-26 09:19:47 -0600494 mcfg = ctx->current;
Bin Meng44256b02016-05-07 07:46:25 -0700495 acpi_create_mcfg(mcfg);
Simon Glass0e113842020-04-26 09:19:47 -0600496 acpi_inc_align(ctx, mcfg->header.length);
Simon Glass575a5472020-04-26 09:19:50 -0600497 acpi_add_table(ctx, mcfg);
Bin Meng44256b02016-05-07 07:46:25 -0700498
Simon Glassc7c46e82020-07-07 13:12:04 -0600499 debug("ACPI: * MADT\n");
500 madt = ctx->current;
501 acpi_create_madt(madt);
502 acpi_inc_align(ctx, madt->header.length);
503 acpi_add_table(ctx, madt);
504
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300505 debug("ACPI: * CSRT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600506 csrt = ctx->current;
Simon Glass9eb80042020-07-07 21:32:24 -0600507 if (!acpi_create_csrt(csrt)) {
508 acpi_inc_align(ctx, csrt->header.length);
509 acpi_add_table(ctx, csrt);
510 }
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300511
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200512 debug("ACPI: * SPCR\n");
Simon Glass0e113842020-04-26 09:19:47 -0600513 spcr = ctx->current;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200514 acpi_create_spcr(spcr);
Simon Glass0e113842020-04-26 09:19:47 -0600515 acpi_inc_align(ctx, spcr->header.length);
Simon Glass575a5472020-04-26 09:19:50 -0600516 acpi_add_table(ctx, spcr);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200517
Simon Glass179fb822020-04-26 09:19:48 -0600518 acpi_write_dev_tables(ctx);
519
Simon Glass0e113842020-04-26 09:19:47 -0600520 addr = map_to_sysmem(ctx->current);
521 debug("current = %lx\n", addr);
Saket Sinha331141a2015-08-22 12:20:55 +0530522
Simon Glass575a5472020-04-26 09:19:50 -0600523 acpi_rsdp_addr = (unsigned long)ctx->rsdp;
Bin Mengd2d22182016-05-07 07:46:12 -0700524 debug("ACPI: done\n");
Saket Sinha331141a2015-08-22 12:20:55 +0530525
Simon Glass0e113842020-04-26 09:19:47 -0600526 return addr;
Saket Sinha331141a2015-08-22 12:20:55 +0530527}
Bin Meng34bc74a2017-04-21 07:24:36 -0700528
Bin Menge1029252018-01-30 05:01:16 -0800529ulong acpi_get_rsdp_addr(void)
530{
531 return acpi_rsdp_addr;
532}
Simon Glass4ffe8b02020-09-22 12:45:09 -0600533
534/**
535 * acpi_write_hpet() - Write out a HPET table
536 *
537 * Write out the table for High-Precision Event Timers
538 *
539 * @hpet: Place to put HPET table
540 */
541static int acpi_create_hpet(struct acpi_hpet *hpet)
542{
543 struct acpi_table_header *header = &hpet->header;
544 struct acpi_gen_regaddr *addr = &hpet->addr;
545
546 /*
547 * See IA-PC HPET (High Precision Event Timers) Specification v1.0a
548 * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
549 */
550 memset((void *)hpet, '\0', sizeof(struct acpi_hpet));
551
552 /* Fill out header fields. */
553 acpi_fill_header(header, "HPET");
554
555 header->aslc_revision = ASL_REVISION;
556 header->length = sizeof(struct acpi_hpet);
557 header->revision = acpi_get_table_revision(ACPITAB_HPET);
558
559 /* Fill out HPET address */
560 addr->space_id = 0; /* Memory */
561 addr->bit_width = 64;
562 addr->bit_offset = 0;
563 addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
564 addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
565
566 hpet->id = *(u32 *)CONFIG_HPET_ADDRESS;
567 hpet->number = 0;
568 hpet->min_tick = 0; /* HPET_MIN_TICKS */
569
570 header->checksum = table_compute_checksum(hpet,
571 sizeof(struct acpi_hpet));
572
573 return 0;
574}
575
576int acpi_write_hpet(struct acpi_ctx *ctx)
577{
578 struct acpi_hpet *hpet;
579 int ret;
580
581 log_debug("ACPI: * HPET\n");
582
583 hpet = ctx->current;
584 acpi_inc_align(ctx, sizeof(struct acpi_hpet));
585 acpi_create_hpet(hpet);
586 ret = acpi_add_table(ctx, hpet);
587 if (ret)
588 return log_msg_ret("add", ret);
589
590 return 0;
591}
Simon Glass95971892020-09-22 12:45:10 -0600592
593int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
594 uint access_size)
595{
596 struct acpi_dbg2_header *dbg2 = ctx->current;
597 char path[ACPI_PATH_MAX];
598 struct acpi_gen_regaddr address;
599 phys_addr_t addr;
600 int ret;
601
602 if (!device_active(dev)) {
603 log_info("Device not enabled\n");
604 return -EACCES;
605 }
606 /*
607 * PCI devices don't remember their resource allocation information in
608 * U-Boot at present. We assume that MMIO is used for the UART and that
609 * the address space is 32 bytes: ns16550 uses 8 registers of up to
610 * 32-bits each. This is only for debugging so it is not a big deal.
611 */
612 addr = dm_pci_read_bar32(dev, 0);
613 printf("UART addr %lx\n", (ulong)addr);
614
615 memset(&address, '\0', sizeof(address));
616 address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
617 address.addrl = (uint32_t)addr;
618 address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
619 address.access_size = access_size;
620
621 ret = acpi_device_path(dev, path, sizeof(path));
622 if (ret)
623 return log_msg_ret("path", ret);
624 acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
625 ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
626
627 acpi_inc_align(ctx, dbg2->header.length);
628 acpi_add_table(ctx, dbg2);
629
630 return 0;
631}