blob: 5876355afe26000f4cd42ab74a62efd83434e184 [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;
Simon Glassfcae5472020-09-22 12:45:31 -060069 int cpu_num = 0;
Saket Sinha331141a2015-08-22 12:20:55 +053070
71 for (uclass_find_first_device(UCLASS_CPU, &dev);
72 dev;
73 uclass_find_next_device(&dev)) {
74 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
Simon Glassfcae5472020-09-22 12:45:31 -060075 int length;
76
77 length = acpi_create_madt_lapic(
78 (struct acpi_madt_lapic *)current, cpu_num++,
79 plat->cpu_id);
Bin Meng3c5234e2016-05-07 07:46:30 -070080 current += length;
George McCollister5a49f872016-06-07 13:40:18 -050081 total_length += length;
Bin Meng44256b02016-05-07 07:46:25 -070082 }
83
George McCollister5a49f872016-06-07 13:40:18 -050084 return total_length;
Saket Sinha331141a2015-08-22 12:20:55 +053085}
86
Bin Meng44256b02016-05-07 07:46:25 -070087int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
88 u32 addr, u32 gsi_base)
Saket Sinha331141a2015-08-22 12:20:55 +053089{
Bin Meng6a421582016-05-07 07:46:21 -070090 ioapic->type = ACPI_APIC_IOAPIC;
Saket Sinha331141a2015-08-22 12:20:55 +053091 ioapic->length = sizeof(struct acpi_madt_ioapic);
92 ioapic->reserved = 0x00;
93 ioapic->gsi_base = gsi_base;
94 ioapic->ioapic_id = id;
95 ioapic->ioapic_addr = addr;
96
97 return ioapic->length;
98}
99
100int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
Bin Meng44256b02016-05-07 07:46:25 -0700101 u8 bus, u8 source, u32 gsirq, u16 flags)
Saket Sinha331141a2015-08-22 12:20:55 +0530102{
Bin Meng6a421582016-05-07 07:46:21 -0700103 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
Saket Sinha331141a2015-08-22 12:20:55 +0530104 irqoverride->length = sizeof(struct acpi_madt_irqoverride);
105 irqoverride->bus = bus;
106 irqoverride->source = source;
107 irqoverride->gsirq = gsirq;
108 irqoverride->flags = flags;
109
110 return irqoverride->length;
111}
112
113int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
Bin Meng44256b02016-05-07 07:46:25 -0700114 u8 cpu, u16 flags, u8 lint)
Saket Sinha331141a2015-08-22 12:20:55 +0530115{
Bin Meng6a421582016-05-07 07:46:21 -0700116 lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
Saket Sinha331141a2015-08-22 12:20:55 +0530117 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
118 lapic_nmi->flags = flags;
119 lapic_nmi->processor_id = cpu;
120 lapic_nmi->lint = lint;
121
122 return lapic_nmi->length;
123}
124
Andy Shevchenko13a5d872017-07-21 22:32:04 +0300125static int acpi_create_madt_irq_overrides(u32 current)
126{
127 struct acpi_madt_irqoverride *irqovr;
128 u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
129 int length = 0;
130
131 irqovr = (void *)current;
132 length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
133
134 irqovr = (void *)(current + length);
135 length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
136
137 return length;
138}
139
140__weak u32 acpi_fill_madt(u32 current)
141{
142 current += acpi_create_madt_lapics(current);
143
144 current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
145 io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
146
147 current += acpi_create_madt_irq_overrides(current);
148
149 return current;
150}
151
Saket Sinha331141a2015-08-22 12:20:55 +0530152static void acpi_create_madt(struct acpi_madt *madt)
153{
Bin Meng6a421582016-05-07 07:46:21 -0700154 struct acpi_table_header *header = &(madt->header);
Bin Menga1ec7db2016-05-07 07:46:26 -0700155 u32 current = (u32)madt + sizeof(struct acpi_madt);
Saket Sinha331141a2015-08-22 12:20:55 +0530156
157 memset((void *)madt, 0, sizeof(struct acpi_madt));
158
159 /* Fill out header fields */
Bin Mengb063d5f2016-05-07 07:46:24 -0700160 acpi_fill_header(header, "APIC");
Saket Sinha331141a2015-08-22 12:20:55 +0530161 header->length = sizeof(struct acpi_madt);
Simon Glassf3694aa2020-07-16 21:22:37 -0600162 header->revision = ACPI_MADT_REV_ACPI_3_0;
Saket Sinha331141a2015-08-22 12:20:55 +0530163
164 madt->lapic_addr = LAPIC_DEFAULT_BASE;
Bin Meng6a421582016-05-07 07:46:21 -0700165 madt->flags = ACPI_MADT_PCAT_COMPAT;
Saket Sinha331141a2015-08-22 12:20:55 +0530166
167 current = acpi_fill_madt(current);
168
169 /* (Re)calculate length and checksum */
Bin Menga1ec7db2016-05-07 07:46:26 -0700170 header->length = current - (u32)madt;
Saket Sinha331141a2015-08-22 12:20:55 +0530171
172 header->checksum = table_compute_checksum((void *)madt, header->length);
173}
174
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300175int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
176 u16 seg_nr, u8 start, u8 end)
Saket Sinha331141a2015-08-22 12:20:55 +0530177{
178 memset(mmconfig, 0, sizeof(*mmconfig));
Bin Meng6a421582016-05-07 07:46:21 -0700179 mmconfig->base_address_l = base;
180 mmconfig->base_address_h = 0;
Saket Sinha331141a2015-08-22 12:20:55 +0530181 mmconfig->pci_segment_group_number = seg_nr;
182 mmconfig->start_bus_number = start;
183 mmconfig->end_bus_number = end;
184
185 return sizeof(struct acpi_mcfg_mmconfig);
186}
187
Andy Shevchenkoc1ae9802017-07-21 22:32:05 +0300188__weak u32 acpi_fill_mcfg(u32 current)
Saket Sinha331141a2015-08-22 12:20:55 +0530189{
190 current += acpi_create_mcfg_mmconfig
191 ((struct acpi_mcfg_mmconfig *)current,
Bin Meng44256b02016-05-07 07:46:25 -0700192 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
Saket Sinha331141a2015-08-22 12:20:55 +0530193
194 return current;
195}
196
197/* MCFG is defined in the PCI Firmware Specification 3.0 */
198static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
199{
Bin Meng6a421582016-05-07 07:46:21 -0700200 struct acpi_table_header *header = &(mcfg->header);
Bin Menga1ec7db2016-05-07 07:46:26 -0700201 u32 current = (u32)mcfg + sizeof(struct acpi_mcfg);
Saket Sinha331141a2015-08-22 12:20:55 +0530202
203 memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
204
205 /* Fill out header fields */
Bin Mengb063d5f2016-05-07 07:46:24 -0700206 acpi_fill_header(header, "MCFG");
Saket Sinha331141a2015-08-22 12:20:55 +0530207 header->length = sizeof(struct acpi_mcfg);
Bin Mengf662fe42016-05-07 07:46:28 -0700208 header->revision = 1;
Saket Sinha331141a2015-08-22 12:20:55 +0530209
210 current = acpi_fill_mcfg(current);
211
212 /* (Re)calculate length and checksum */
Bin Menga1ec7db2016-05-07 07:46:26 -0700213 header->length = current - (u32)mcfg;
Saket Sinha331141a2015-08-22 12:20:55 +0530214 header->checksum = table_compute_checksum((void *)mcfg, header->length);
215}
216
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300217__weak u32 acpi_fill_csrt(u32 current)
218{
Simon Glass9eb80042020-07-07 21:32:24 -0600219 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300220}
221
Simon Glass9eb80042020-07-07 21:32:24 -0600222static int acpi_create_csrt(struct acpi_csrt *csrt)
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300223{
224 struct acpi_table_header *header = &(csrt->header);
225 u32 current = (u32)csrt + sizeof(struct acpi_csrt);
Simon Glass9eb80042020-07-07 21:32:24 -0600226 uint ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300227
228 memset((void *)csrt, 0, sizeof(struct acpi_csrt));
229
230 /* Fill out header fields */
231 acpi_fill_header(header, "CSRT");
232 header->length = sizeof(struct acpi_csrt);
233 header->revision = 0;
234
Simon Glass9eb80042020-07-07 21:32:24 -0600235 ptr = acpi_fill_csrt(current);
236 if (!ptr)
237 return -ENOENT;
238 current = ptr;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300239
240 /* (Re)calculate length and checksum */
241 header->length = current - (u32)csrt;
242 header->checksum = table_compute_checksum((void *)csrt, header->length);
Simon Glass9eb80042020-07-07 21:32:24 -0600243
244 return 0;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300245}
246
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200247static void acpi_create_spcr(struct acpi_spcr *spcr)
248{
249 struct acpi_table_header *header = &(spcr->header);
250 struct serial_device_info serial_info = {0};
251 ulong serial_address, serial_offset;
Simon Glassdaaff932018-12-28 14:23:08 -0700252 struct udevice *dev;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200253 uint serial_config;
254 uint serial_width;
255 int access_size;
256 int space_id;
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200257 int ret = -ENODEV;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200258
Wolfgang Wallner13c23e92020-09-16 16:57:53 +0200259 memset((void *)spcr, 0, sizeof(struct acpi_spcr));
260
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200261 /* Fill out header fields */
262 acpi_fill_header(header, "SPCR");
263 header->length = sizeof(struct acpi_spcr);
264 header->revision = 2;
265
Simon Glass896c1642018-12-28 14:23:10 -0700266 /* Read the device once, here. It is reused below */
Andy Shevchenkobf9c8e32019-02-28 17:19:54 +0200267 dev = gd->cur_serial_dev;
268 if (dev)
Simon Glass896c1642018-12-28 14:23:10 -0700269 ret = serial_getinfo(dev, &serial_info);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200270 if (ret)
271 serial_info.type = SERIAL_CHIP_UNKNOWN;
272
273 /* Encode chip type */
274 switch (serial_info.type) {
275 case SERIAL_CHIP_16550_COMPATIBLE:
276 spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
277 break;
278 case SERIAL_CHIP_UNKNOWN:
279 default:
280 spcr->interface_type = ACPI_DBG2_UNKNOWN;
281 break;
282 }
283
284 /* Encode address space */
285 switch (serial_info.addr_space) {
286 case SERIAL_ADDRESS_SPACE_MEMORY:
287 space_id = ACPI_ADDRESS_SPACE_MEMORY;
288 break;
289 case SERIAL_ADDRESS_SPACE_IO:
290 default:
291 space_id = ACPI_ADDRESS_SPACE_IO;
292 break;
293 }
294
295 serial_width = serial_info.reg_width * 8;
296 serial_offset = serial_info.reg_offset << serial_info.reg_shift;
297 serial_address = serial_info.addr + serial_offset;
298
299 /* Encode register access size */
300 switch (serial_info.reg_shift) {
301 case 0:
302 access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
303 break;
304 case 1:
305 access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
306 break;
307 case 2:
308 access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
309 break;
310 case 3:
311 access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
312 break;
313 default:
314 access_size = ACPI_ACCESS_SIZE_UNDEFINED;
315 break;
316 }
317
318 debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
319
320 /* Fill GAS */
321 spcr->serial_port.space_id = space_id;
322 spcr->serial_port.bit_width = serial_width;
323 spcr->serial_port.bit_offset = 0;
324 spcr->serial_port.access_size = access_size;
325 spcr->serial_port.addrl = lower_32_bits(serial_address);
326 spcr->serial_port.addrh = upper_32_bits(serial_address);
327
328 /* Encode baud rate */
329 switch (serial_info.baudrate) {
330 case 9600:
331 spcr->baud_rate = 3;
332 break;
333 case 19200:
334 spcr->baud_rate = 4;
335 break;
336 case 57600:
337 spcr->baud_rate = 6;
338 break;
339 case 115200:
340 spcr->baud_rate = 7;
341 break;
342 default:
343 spcr->baud_rate = 0;
344 break;
345 }
346
Simon Glass896c1642018-12-28 14:23:10 -0700347 serial_config = SERIAL_DEFAULT_CONFIG;
348 if (dev)
Simon Glassdaaff932018-12-28 14:23:08 -0700349 ret = serial_getconfig(dev, &serial_config);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200350
351 spcr->parity = SERIAL_GET_PARITY(serial_config);
352 spcr->stop_bits = SERIAL_GET_STOP(serial_config);
353
354 /* No PCI devices for now */
355 spcr->pci_device_id = 0xffff;
356 spcr->pci_vendor_id = 0xffff;
357
Andy Shevchenko225cc8a2020-02-27 17:21:56 +0200358 /*
359 * SPCR has no clue if the UART base clock speed is different
360 * to the default one. However, the SPCR 1.04 defines baud rate
361 * 0 as a preconfigured state of UART and OS is supposed not
362 * to touch the configuration of the serial device.
363 */
364 if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
365 spcr->baud_rate = 0;
366
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200367 /* Fix checksum */
368 header->checksum = table_compute_checksum((void *)spcr, header->length);
369}
370
Simon Glassf0a8d682020-07-07 13:12:07 -0600371void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt,
372 const char *oem_table_id)
373{
374 memset((void *)ssdt, '\0', sizeof(struct acpi_table_header));
375
376 acpi_fill_header(ssdt, "SSDT");
377 ssdt->revision = acpi_get_table_revision(ACPITAB_SSDT);
378 ssdt->aslc_revision = 1;
379 ssdt->length = sizeof(struct acpi_table_header);
380
381 acpi_inc(ctx, sizeof(struct acpi_table_header));
382
383 acpi_fill_ssdt(ctx);
384
385 /* (Re)calculate length and checksum. */
386 ssdt->length = ctx->current - (void *)ssdt;
387 ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
388}
389
Miao Yan3b68c522016-01-20 01:57:06 -0800390/*
Andy Shevchenko4b05bac2018-01-10 19:33:10 +0200391 * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c
Miao Yan3b68c522016-01-20 01:57:06 -0800392 */
Simon Glass0e113842020-04-26 09:19:47 -0600393ulong write_acpi_tables(ulong start_addr)
Saket Sinha331141a2015-08-22 12:20:55 +0530394{
Simon Glass0e113842020-04-26 09:19:47 -0600395 struct acpi_ctx sctx, *ctx = &sctx;
Saket Sinha331141a2015-08-22 12:20:55 +0530396 struct acpi_facs *facs;
Bin Meng6a421582016-05-07 07:46:21 -0700397 struct acpi_table_header *dsdt;
Saket Sinha331141a2015-08-22 12:20:55 +0530398 struct acpi_fadt *fadt;
Simon Glassf0a8d682020-07-07 13:12:07 -0600399 struct acpi_table_header *ssdt;
Saket Sinha331141a2015-08-22 12:20:55 +0530400 struct acpi_mcfg *mcfg;
401 struct acpi_madt *madt;
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300402 struct acpi_csrt *csrt;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200403 struct acpi_spcr *spcr;
Simon Glass0e113842020-04-26 09:19:47 -0600404 void *start;
405 ulong addr;
Bin Mengd9050c62016-06-17 02:13:16 -0700406 int i;
Saket Sinha331141a2015-08-22 12:20:55 +0530407
Simon Glass0e113842020-04-26 09:19:47 -0600408 start = map_sysmem(start_addr, 0);
Saket Sinha331141a2015-08-22 12:20:55 +0530409
Simon Glass0e113842020-04-26 09:19:47 -0600410 debug("ACPI: Writing ACPI tables at %lx\n", start_addr);
Saket Sinha331141a2015-08-22 12:20:55 +0530411
Simon Glass9c442a62020-04-26 09:19:51 -0600412 acpi_setup_base_tables(ctx, start);
Saket Sinha331141a2015-08-22 12:20:55 +0530413
414 debug("ACPI: * FACS\n");
Simon Glass0e113842020-04-26 09:19:47 -0600415 facs = ctx->current;
416 acpi_inc_align(ctx, sizeof(struct acpi_facs));
Saket Sinha331141a2015-08-22 12:20:55 +0530417
418 acpi_create_facs(facs);
419
420 debug("ACPI: * DSDT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600421 dsdt = ctx->current;
Simon Glass6ca93152020-07-07 13:12:09 -0600422
423 /* Put the table header first */
Bin Meng6a421582016-05-07 07:46:21 -0700424 memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
Simon Glass0e113842020-04-26 09:19:47 -0600425 acpi_inc(ctx, sizeof(struct acpi_table_header));
Simon Glass6ca93152020-07-07 13:12:09 -0600426
427 /* If the table is not empty, allow devices to inject things */
428 if (dsdt->length >= sizeof(struct acpi_table_header))
429 acpi_inject_dsdt(ctx);
430
431 /* Copy in the AML code itself if any (after the header) */
Simon Glass0e113842020-04-26 09:19:47 -0600432 memcpy(ctx->current,
Bin Mengd90434b2016-05-11 07:45:05 -0700433 (char *)&AmlCode + sizeof(struct acpi_table_header),
434 dsdt->length - sizeof(struct acpi_table_header));
Simon Glass6ca93152020-07-07 13:12:09 -0600435
Wolfgang Wallneraa202822020-09-16 16:57:52 +0200436 acpi_inc(ctx, dsdt->length - sizeof(struct acpi_table_header));
Simon Glass6fe570a2020-09-22 12:44:53 -0600437 dsdt->length = ctx->current - (void *)dsdt;
438 acpi_align(ctx);
Saket Sinha331141a2015-08-22 12:20:55 +0530439
Simon Glass6fe570a2020-09-22 12:44:53 -0600440 if (!IS_ENABLED(CONFIG_ACPI_GNVS_EXTERNAL)) {
441 /* Pack GNVS into the ACPI table area */
442 for (i = 0; i < dsdt->length; i++) {
443 u32 *gnvs = (u32 *)((u32)dsdt + i);
Simon Glass0e113842020-04-26 09:19:47 -0600444
Simon Glass6fe570a2020-09-22 12:44:53 -0600445 if (*gnvs == ACPI_GNVS_ADDR) {
446 *gnvs = map_to_sysmem(ctx->current);
447 debug("Fix up global NVS in DSDT to %#08x\n",
448 *gnvs);
449 break;
450 }
Bin Mengd9050c62016-06-17 02:13:16 -0700451 }
Simon Glass6fe570a2020-09-22 12:44:53 -0600452
453 /*
454 * Fill in platform-specific global NVS variables. If this fails
455 * we cannot return the error but this should only happen while
456 * debugging.
457 */
458 addr = acpi_create_gnvs(ctx->current);
459 if (IS_ERR_VALUE(addr))
460 printf("Error: Gailed to create GNVS\n");
461 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
Bin Mengd9050c62016-06-17 02:13:16 -0700462 }
463
Simon Glass6ca93152020-07-07 13:12:09 -0600464 /*
465 * Recalculate the length and update the DSDT checksum since we patched
466 * the GNVS address. Set the checksum to zero since it is part of the
467 * region being checksummed.
468 */
Bin Mengd9050c62016-06-17 02:13:16 -0700469 dsdt->checksum = 0;
470 dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
471
Simon Glass9ed41e72020-07-07 21:32:05 -0600472 /*
473 * Fill in platform-specific global NVS variables. If this fails we
474 * cannot return the error but this should only happen while debugging.
475 */
476 addr = acpi_create_gnvs(ctx->current);
477 if (IS_ERR_VALUE(addr))
478 printf("Error: Failed to create GNVS\n");
479
Simon Glass0e113842020-04-26 09:19:47 -0600480 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
Bin Mengd9050c62016-06-17 02:13:16 -0700481
Saket Sinha331141a2015-08-22 12:20:55 +0530482 debug("ACPI: * FADT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600483 fadt = ctx->current;
484 acpi_inc_align(ctx, sizeof(struct acpi_fadt));
Saket Sinha331141a2015-08-22 12:20:55 +0530485 acpi_create_fadt(fadt, facs, dsdt);
Simon Glass575a5472020-04-26 09:19:50 -0600486 acpi_add_table(ctx, fadt);
Saket Sinha331141a2015-08-22 12:20:55 +0530487
Simon Glassf0a8d682020-07-07 13:12:07 -0600488 debug("ACPI: * SSDT\n");
489 ssdt = (struct acpi_table_header *)ctx->current;
490 acpi_create_ssdt(ctx, ssdt, OEM_TABLE_ID);
491 if (ssdt->length > sizeof(struct acpi_table_header)) {
492 acpi_inc_align(ctx, ssdt->length);
493 acpi_add_table(ctx, ssdt);
494 }
495
Bin Meng44256b02016-05-07 07:46:25 -0700496 debug("ACPI: * MCFG\n");
Simon Glass0e113842020-04-26 09:19:47 -0600497 mcfg = ctx->current;
Bin Meng44256b02016-05-07 07:46:25 -0700498 acpi_create_mcfg(mcfg);
Simon Glass0e113842020-04-26 09:19:47 -0600499 acpi_inc_align(ctx, mcfg->header.length);
Simon Glass575a5472020-04-26 09:19:50 -0600500 acpi_add_table(ctx, mcfg);
Bin Meng44256b02016-05-07 07:46:25 -0700501
Simon Glassc7c46e82020-07-07 13:12:04 -0600502 debug("ACPI: * MADT\n");
503 madt = ctx->current;
504 acpi_create_madt(madt);
505 acpi_inc_align(ctx, madt->header.length);
506 acpi_add_table(ctx, madt);
507
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300508 debug("ACPI: * CSRT\n");
Simon Glass0e113842020-04-26 09:19:47 -0600509 csrt = ctx->current;
Simon Glass9eb80042020-07-07 21:32:24 -0600510 if (!acpi_create_csrt(csrt)) {
511 acpi_inc_align(ctx, csrt->header.length);
512 acpi_add_table(ctx, csrt);
513 }
Andy Shevchenko607dbd12019-07-14 19:23:57 +0300514
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200515 debug("ACPI: * SPCR\n");
Simon Glass0e113842020-04-26 09:19:47 -0600516 spcr = ctx->current;
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200517 acpi_create_spcr(spcr);
Simon Glass0e113842020-04-26 09:19:47 -0600518 acpi_inc_align(ctx, spcr->header.length);
Simon Glass575a5472020-04-26 09:19:50 -0600519 acpi_add_table(ctx, spcr);
Andy Shevchenko4ca48c92018-11-20 23:52:38 +0200520
Simon Glass179fb822020-04-26 09:19:48 -0600521 acpi_write_dev_tables(ctx);
522
Simon Glass0e113842020-04-26 09:19:47 -0600523 addr = map_to_sysmem(ctx->current);
524 debug("current = %lx\n", addr);
Saket Sinha331141a2015-08-22 12:20:55 +0530525
Simon Glass575a5472020-04-26 09:19:50 -0600526 acpi_rsdp_addr = (unsigned long)ctx->rsdp;
Bin Mengd2d22182016-05-07 07:46:12 -0700527 debug("ACPI: done\n");
Saket Sinha331141a2015-08-22 12:20:55 +0530528
Simon Glass0e113842020-04-26 09:19:47 -0600529 return addr;
Saket Sinha331141a2015-08-22 12:20:55 +0530530}
Bin Meng34bc74a2017-04-21 07:24:36 -0700531
Bin Menge1029252018-01-30 05:01:16 -0800532ulong acpi_get_rsdp_addr(void)
533{
534 return acpi_rsdp_addr;
535}
Simon Glass4ffe8b02020-09-22 12:45:09 -0600536
537/**
538 * acpi_write_hpet() - Write out a HPET table
539 *
540 * Write out the table for High-Precision Event Timers
541 *
542 * @hpet: Place to put HPET table
543 */
544static int acpi_create_hpet(struct acpi_hpet *hpet)
545{
546 struct acpi_table_header *header = &hpet->header;
547 struct acpi_gen_regaddr *addr = &hpet->addr;
548
549 /*
550 * See IA-PC HPET (High Precision Event Timers) Specification v1.0a
551 * https://www.intel.com/content/dam/www/public/us/en/documents/technical-specifications/software-developers-hpet-spec-1-0a.pdf
552 */
553 memset((void *)hpet, '\0', sizeof(struct acpi_hpet));
554
555 /* Fill out header fields. */
556 acpi_fill_header(header, "HPET");
557
558 header->aslc_revision = ASL_REVISION;
559 header->length = sizeof(struct acpi_hpet);
560 header->revision = acpi_get_table_revision(ACPITAB_HPET);
561
562 /* Fill out HPET address */
563 addr->space_id = 0; /* Memory */
564 addr->bit_width = 64;
565 addr->bit_offset = 0;
566 addr->addrl = CONFIG_HPET_ADDRESS & 0xffffffff;
567 addr->addrh = ((unsigned long long)CONFIG_HPET_ADDRESS) >> 32;
568
569 hpet->id = *(u32 *)CONFIG_HPET_ADDRESS;
570 hpet->number = 0;
571 hpet->min_tick = 0; /* HPET_MIN_TICKS */
572
573 header->checksum = table_compute_checksum(hpet,
574 sizeof(struct acpi_hpet));
575
576 return 0;
577}
578
579int acpi_write_hpet(struct acpi_ctx *ctx)
580{
581 struct acpi_hpet *hpet;
582 int ret;
583
584 log_debug("ACPI: * HPET\n");
585
586 hpet = ctx->current;
587 acpi_inc_align(ctx, sizeof(struct acpi_hpet));
588 acpi_create_hpet(hpet);
589 ret = acpi_add_table(ctx, hpet);
590 if (ret)
591 return log_msg_ret("add", ret);
592
593 return 0;
594}
Simon Glass95971892020-09-22 12:45:10 -0600595
596int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev,
597 uint access_size)
598{
599 struct acpi_dbg2_header *dbg2 = ctx->current;
600 char path[ACPI_PATH_MAX];
601 struct acpi_gen_regaddr address;
602 phys_addr_t addr;
603 int ret;
604
605 if (!device_active(dev)) {
606 log_info("Device not enabled\n");
607 return -EACCES;
608 }
609 /*
610 * PCI devices don't remember their resource allocation information in
611 * U-Boot at present. We assume that MMIO is used for the UART and that
612 * the address space is 32 bytes: ns16550 uses 8 registers of up to
613 * 32-bits each. This is only for debugging so it is not a big deal.
614 */
615 addr = dm_pci_read_bar32(dev, 0);
616 printf("UART addr %lx\n", (ulong)addr);
617
618 memset(&address, '\0', sizeof(address));
619 address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
620 address.addrl = (uint32_t)addr;
621 address.addrh = (uint32_t)((addr >> 32) & 0xffffffff);
622 address.access_size = access_size;
623
624 ret = acpi_device_path(dev, path, sizeof(path));
625 if (ret)
626 return log_msg_ret("path", ret);
627 acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT,
628 ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path);
629
630 acpi_inc_align(ctx, dbg2->header.length);
631 acpi_add_table(ctx, dbg2);
632
633 return 0;
634}
Simon Glass87cf8d22020-09-22 12:45:16 -0600635
636void acpi_fadt_common(struct acpi_fadt *fadt, struct acpi_facs *facs,
637 void *dsdt)
638{
639 struct acpi_table_header *header = &fadt->header;
640
641 memset((void *)fadt, '\0', sizeof(struct acpi_fadt));
642
643 acpi_fill_header(header, "FACP");
644 header->length = sizeof(struct acpi_fadt);
645 header->revision = 4;
646 memcpy(header->oem_id, OEM_ID, 6);
647 memcpy(header->oem_table_id, OEM_TABLE_ID, 8);
648 memcpy(header->aslc_id, ASLC_ID, 4);
649 header->aslc_revision = 1;
650
651 fadt->firmware_ctrl = (unsigned long)facs;
652 fadt->dsdt = (unsigned long)dsdt;
653
654 fadt->x_firmware_ctl_l = (unsigned long)facs;
655 fadt->x_firmware_ctl_h = 0;
656 fadt->x_dsdt_l = (unsigned long)dsdt;
657 fadt->x_dsdt_h = 0;
658
659 fadt->preferred_pm_profile = ACPI_PM_MOBILE;
660
661 /* Use ACPI 3.0 revision */
662 fadt->header.revision = 4;
663}
664
665void acpi_create_dmar_drhd(struct acpi_ctx *ctx, uint flags, uint segment,
666 u64 bar)
667{
668 struct dmar_entry *drhd = ctx->current;
669
670 memset(drhd, '\0', sizeof(*drhd));
671 drhd->type = DMAR_DRHD;
672 drhd->length = sizeof(*drhd); /* will be fixed up later */
673 drhd->flags = flags;
674 drhd->segment = segment;
675 drhd->bar = bar;
676 acpi_inc(ctx, drhd->length);
677}
678
679void acpi_create_dmar_rmrr(struct acpi_ctx *ctx, uint segment, u64 bar,
680 u64 limit)
681{
682 struct dmar_rmrr_entry *rmrr = ctx->current;
683
684 memset(rmrr, '\0', sizeof(*rmrr));
685 rmrr->type = DMAR_RMRR;
686 rmrr->length = sizeof(*rmrr); /* will be fixed up later */
687 rmrr->segment = segment;
688 rmrr->bar = bar;
689 rmrr->limit = limit;
690 acpi_inc(ctx, rmrr->length);
691}
692
693void acpi_dmar_drhd_fixup(struct acpi_ctx *ctx, void *base)
694{
695 struct dmar_entry *drhd = base;
696
697 drhd->length = ctx->current - base;
698}
699
700void acpi_dmar_rmrr_fixup(struct acpi_ctx *ctx, void *base)
701{
702 struct dmar_rmrr_entry *rmrr = base;
703
704 rmrr->length = ctx->current - base;
705}
706
707static int acpi_create_dmar_ds(struct acpi_ctx *ctx, enum dev_scope_type type,
708 uint enumeration_id, pci_dev_t bdf)
709{
710 /* we don't support longer paths yet */
711 const size_t dev_scope_length = sizeof(struct dev_scope) + 2;
712 struct dev_scope *ds = ctx->current;
713
714 memset(ds, '\0', dev_scope_length);
715 ds->type = type;
716 ds->length = dev_scope_length;
717 ds->enumeration = enumeration_id;
718 ds->start_bus = PCI_BUS(bdf);
719 ds->path[0].dev = PCI_DEV(bdf);
720 ds->path[0].fn = PCI_FUNC(bdf);
721
722 return ds->length;
723}
724
725int acpi_create_dmar_ds_pci_br(struct acpi_ctx *ctx, pci_dev_t bdf)
726{
727 return acpi_create_dmar_ds(ctx, SCOPE_PCI_SUB, 0, bdf);
728}
729
730int acpi_create_dmar_ds_pci(struct acpi_ctx *ctx, pci_dev_t bdf)
731{
732 return acpi_create_dmar_ds(ctx, SCOPE_PCI_ENDPOINT, 0, bdf);
733}
734
735int acpi_create_dmar_ds_ioapic(struct acpi_ctx *ctx, uint enumeration_id,
736 pci_dev_t bdf)
737{
738 return acpi_create_dmar_ds(ctx, SCOPE_IOAPIC, enumeration_id, bdf);
739}
740
741int acpi_create_dmar_ds_msi_hpet(struct acpi_ctx *ctx, uint enumeration_id,
742 pci_dev_t bdf)
743{
744 return acpi_create_dmar_ds(ctx, SCOPE_MSI_HPET, enumeration_id, bdf);
745}