1
2
3
4
5
6
7
8
9#include <common.h>
10#include <cpu.h>
11#include <dm.h>
12#include <log.h>
13#include <dm/uclass-internal.h>
14#include <mapmem.h>
15#include <serial.h>
16#include <version.h>
17#include <acpi/acpigen.h>
18#include <acpi/acpi_table.h>
19#include <asm/acpi/global_nvs.h>
20#include <asm/ioapic.h>
21#include <asm/lapic.h>
22#include <asm/mpspec.h>
23#include <asm/tables.h>
24#include <asm/arch/global_nvs.h>
25#include <dm/acpi.h>
26#include <linux/err.h>
27
28
29
30
31
32extern const unsigned char AmlCode[];
33
34
35static ulong acpi_rsdp_addr;
36
37static void acpi_create_facs(struct acpi_facs *facs)
38{
39 memset((void *)facs, 0, sizeof(struct acpi_facs));
40
41 memcpy(facs->signature, "FACS", 4);
42 facs->length = sizeof(struct acpi_facs);
43 facs->hardware_signature = 0;
44 facs->firmware_waking_vector = 0;
45 facs->global_lock = 0;
46 facs->flags = 0;
47 facs->x_firmware_waking_vector_l = 0;
48 facs->x_firmware_waking_vector_h = 0;
49 facs->version = 1;
50}
51
52static int acpi_create_madt_lapic(struct acpi_madt_lapic *lapic,
53 u8 cpu, u8 apic)
54{
55 lapic->type = ACPI_APIC_LAPIC;
56 lapic->length = sizeof(struct acpi_madt_lapic);
57 lapic->flags = LOCAL_APIC_FLAG_ENABLED;
58 lapic->processor_id = cpu;
59 lapic->apic_id = apic;
60
61 return lapic->length;
62}
63
64int acpi_create_madt_lapics(u32 current)
65{
66 struct udevice *dev;
67 int total_length = 0;
68
69 for (uclass_find_first_device(UCLASS_CPU, &dev);
70 dev;
71 uclass_find_next_device(&dev)) {
72 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
73 int length = acpi_create_madt_lapic(
74 (struct acpi_madt_lapic *)current,
75 plat->cpu_id, plat->cpu_id);
76 current += length;
77 total_length += length;
78 }
79
80 return total_length;
81}
82
83int acpi_create_madt_ioapic(struct acpi_madt_ioapic *ioapic, u8 id,
84 u32 addr, u32 gsi_base)
85{
86 ioapic->type = ACPI_APIC_IOAPIC;
87 ioapic->length = sizeof(struct acpi_madt_ioapic);
88 ioapic->reserved = 0x00;
89 ioapic->gsi_base = gsi_base;
90 ioapic->ioapic_id = id;
91 ioapic->ioapic_addr = addr;
92
93 return ioapic->length;
94}
95
96int acpi_create_madt_irqoverride(struct acpi_madt_irqoverride *irqoverride,
97 u8 bus, u8 source, u32 gsirq, u16 flags)
98{
99 irqoverride->type = ACPI_APIC_IRQ_SRC_OVERRIDE;
100 irqoverride->length = sizeof(struct acpi_madt_irqoverride);
101 irqoverride->bus = bus;
102 irqoverride->source = source;
103 irqoverride->gsirq = gsirq;
104 irqoverride->flags = flags;
105
106 return irqoverride->length;
107}
108
109int acpi_create_madt_lapic_nmi(struct acpi_madt_lapic_nmi *lapic_nmi,
110 u8 cpu, u16 flags, u8 lint)
111{
112 lapic_nmi->type = ACPI_APIC_LAPIC_NMI;
113 lapic_nmi->length = sizeof(struct acpi_madt_lapic_nmi);
114 lapic_nmi->flags = flags;
115 lapic_nmi->processor_id = cpu;
116 lapic_nmi->lint = lint;
117
118 return lapic_nmi->length;
119}
120
121static int acpi_create_madt_irq_overrides(u32 current)
122{
123 struct acpi_madt_irqoverride *irqovr;
124 u16 sci_flags = MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH;
125 int length = 0;
126
127 irqovr = (void *)current;
128 length += acpi_create_madt_irqoverride(irqovr, 0, 0, 2, 0);
129
130 irqovr = (void *)(current + length);
131 length += acpi_create_madt_irqoverride(irqovr, 0, 9, 9, sci_flags);
132
133 return length;
134}
135
136__weak u32 acpi_fill_madt(u32 current)
137{
138 current += acpi_create_madt_lapics(current);
139
140 current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
141 io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
142
143 current += acpi_create_madt_irq_overrides(current);
144
145 return current;
146}
147
148static void acpi_create_madt(struct acpi_madt *madt)
149{
150 struct acpi_table_header *header = &(madt->header);
151 u32 current = (u32)madt + sizeof(struct acpi_madt);
152
153 memset((void *)madt, 0, sizeof(struct acpi_madt));
154
155
156 acpi_fill_header(header, "APIC");
157 header->length = sizeof(struct acpi_madt);
158 header->revision = ACPI_MADT_REV_ACPI_3_0;
159
160 madt->lapic_addr = LAPIC_DEFAULT_BASE;
161 madt->flags = ACPI_MADT_PCAT_COMPAT;
162
163 current = acpi_fill_madt(current);
164
165
166 header->length = current - (u32)madt;
167
168 header->checksum = table_compute_checksum((void *)madt, header->length);
169}
170
171int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base,
172 u16 seg_nr, u8 start, u8 end)
173{
174 memset(mmconfig, 0, sizeof(*mmconfig));
175 mmconfig->base_address_l = base;
176 mmconfig->base_address_h = 0;
177 mmconfig->pci_segment_group_number = seg_nr;
178 mmconfig->start_bus_number = start;
179 mmconfig->end_bus_number = end;
180
181 return sizeof(struct acpi_mcfg_mmconfig);
182}
183
184__weak u32 acpi_fill_mcfg(u32 current)
185{
186 current += acpi_create_mcfg_mmconfig
187 ((struct acpi_mcfg_mmconfig *)current,
188 CONFIG_PCIE_ECAM_BASE, 0x0, 0x0, 255);
189
190 return current;
191}
192
193
194static void acpi_create_mcfg(struct acpi_mcfg *mcfg)
195{
196 struct acpi_table_header *header = &(mcfg->header);
197 u32 current = (u32)mcfg + sizeof(struct acpi_mcfg);
198
199 memset((void *)mcfg, 0, sizeof(struct acpi_mcfg));
200
201
202 acpi_fill_header(header, "MCFG");
203 header->length = sizeof(struct acpi_mcfg);
204 header->revision = 1;
205
206 current = acpi_fill_mcfg(current);
207
208
209 header->length = current - (u32)mcfg;
210 header->checksum = table_compute_checksum((void *)mcfg, header->length);
211}
212
213__weak u32 acpi_fill_csrt(u32 current)
214{
215 return 0;
216}
217
218static int acpi_create_csrt(struct acpi_csrt *csrt)
219{
220 struct acpi_table_header *header = &(csrt->header);
221 u32 current = (u32)csrt + sizeof(struct acpi_csrt);
222 uint ptr;
223
224 memset((void *)csrt, 0, sizeof(struct acpi_csrt));
225
226
227 acpi_fill_header(header, "CSRT");
228 header->length = sizeof(struct acpi_csrt);
229 header->revision = 0;
230
231 ptr = acpi_fill_csrt(current);
232 if (!ptr)
233 return -ENOENT;
234 current = ptr;
235
236
237 header->length = current - (u32)csrt;
238 header->checksum = table_compute_checksum((void *)csrt, header->length);
239
240 return 0;
241}
242
243static void acpi_create_spcr(struct acpi_spcr *spcr)
244{
245 struct acpi_table_header *header = &(spcr->header);
246 struct serial_device_info serial_info = {0};
247 ulong serial_address, serial_offset;
248 struct udevice *dev;
249 uint serial_config;
250 uint serial_width;
251 int access_size;
252 int space_id;
253 int ret = -ENODEV;
254
255 memset((void *)spcr, 0, sizeof(struct acpi_spcr));
256
257
258 acpi_fill_header(header, "SPCR");
259 header->length = sizeof(struct acpi_spcr);
260 header->revision = 2;
261
262
263 dev = gd->cur_serial_dev;
264 if (dev)
265 ret = serial_getinfo(dev, &serial_info);
266 if (ret)
267 serial_info.type = SERIAL_CHIP_UNKNOWN;
268
269
270 switch (serial_info.type) {
271 case SERIAL_CHIP_16550_COMPATIBLE:
272 spcr->interface_type = ACPI_DBG2_16550_COMPATIBLE;
273 break;
274 case SERIAL_CHIP_UNKNOWN:
275 default:
276 spcr->interface_type = ACPI_DBG2_UNKNOWN;
277 break;
278 }
279
280
281 switch (serial_info.addr_space) {
282 case SERIAL_ADDRESS_SPACE_MEMORY:
283 space_id = ACPI_ADDRESS_SPACE_MEMORY;
284 break;
285 case SERIAL_ADDRESS_SPACE_IO:
286 default:
287 space_id = ACPI_ADDRESS_SPACE_IO;
288 break;
289 }
290
291 serial_width = serial_info.reg_width * 8;
292 serial_offset = serial_info.reg_offset << serial_info.reg_shift;
293 serial_address = serial_info.addr + serial_offset;
294
295
296 switch (serial_info.reg_shift) {
297 case 0:
298 access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
299 break;
300 case 1:
301 access_size = ACPI_ACCESS_SIZE_WORD_ACCESS;
302 break;
303 case 2:
304 access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
305 break;
306 case 3:
307 access_size = ACPI_ACCESS_SIZE_QWORD_ACCESS;
308 break;
309 default:
310 access_size = ACPI_ACCESS_SIZE_UNDEFINED;
311 break;
312 }
313
314 debug("UART type %u @ %lx\n", spcr->interface_type, serial_address);
315
316
317 spcr->serial_port.space_id = space_id;
318 spcr->serial_port.bit_width = serial_width;
319 spcr->serial_port.bit_offset = 0;
320 spcr->serial_port.access_size = access_size;
321 spcr->serial_port.addrl = lower_32_bits(serial_address);
322 spcr->serial_port.addrh = upper_32_bits(serial_address);
323
324
325 switch (serial_info.baudrate) {
326 case 9600:
327 spcr->baud_rate = 3;
328 break;
329 case 19200:
330 spcr->baud_rate = 4;
331 break;
332 case 57600:
333 spcr->baud_rate = 6;
334 break;
335 case 115200:
336 spcr->baud_rate = 7;
337 break;
338 default:
339 spcr->baud_rate = 0;
340 break;
341 }
342
343 serial_config = SERIAL_DEFAULT_CONFIG;
344 if (dev)
345 ret = serial_getconfig(dev, &serial_config);
346
347 spcr->parity = SERIAL_GET_PARITY(serial_config);
348 spcr->stop_bits = SERIAL_GET_STOP(serial_config);
349
350
351 spcr->pci_device_id = 0xffff;
352 spcr->pci_vendor_id = 0xffff;
353
354
355
356
357
358
359
360 if (serial_info.clock != SERIAL_DEFAULT_CLOCK)
361 spcr->baud_rate = 0;
362
363
364 header->checksum = table_compute_checksum((void *)spcr, header->length);
365}
366
367void acpi_create_ssdt(struct acpi_ctx *ctx, struct acpi_table_header *ssdt,
368 const char *oem_table_id)
369{
370 memset((void *)ssdt, '\0', sizeof(struct acpi_table_header));
371
372 acpi_fill_header(ssdt, "SSDT");
373 ssdt->revision = acpi_get_table_revision(ACPITAB_SSDT);
374 ssdt->aslc_revision = 1;
375 ssdt->length = sizeof(struct acpi_table_header);
376
377 acpi_inc(ctx, sizeof(struct acpi_table_header));
378
379 acpi_fill_ssdt(ctx);
380
381
382 ssdt->length = ctx->current - (void *)ssdt;
383 ssdt->checksum = table_compute_checksum((void *)ssdt, ssdt->length);
384}
385
386
387
388
389ulong write_acpi_tables(ulong start_addr)
390{
391 struct acpi_ctx sctx, *ctx = &sctx;
392 struct acpi_facs *facs;
393 struct acpi_table_header *dsdt;
394 struct acpi_fadt *fadt;
395 struct acpi_table_header *ssdt;
396 struct acpi_mcfg *mcfg;
397 struct acpi_madt *madt;
398 struct acpi_csrt *csrt;
399 struct acpi_spcr *spcr;
400 void *start;
401 ulong addr;
402 int i;
403
404 start = map_sysmem(start_addr, 0);
405
406 debug("ACPI: Writing ACPI tables at %lx\n", start_addr);
407
408 acpi_setup_base_tables(ctx, start);
409
410 debug("ACPI: * FACS\n");
411 facs = ctx->current;
412 acpi_inc_align(ctx, sizeof(struct acpi_facs));
413
414 acpi_create_facs(facs);
415
416 debug("ACPI: * DSDT\n");
417 dsdt = ctx->current;
418
419
420 memcpy(dsdt, &AmlCode, sizeof(struct acpi_table_header));
421 acpi_inc(ctx, sizeof(struct acpi_table_header));
422
423
424 if (dsdt->length >= sizeof(struct acpi_table_header))
425 acpi_inject_dsdt(ctx);
426
427
428 memcpy(ctx->current,
429 (char *)&AmlCode + sizeof(struct acpi_table_header),
430 dsdt->length - sizeof(struct acpi_table_header));
431
432 acpi_inc(ctx, dsdt->length - sizeof(struct acpi_table_header));
433
434
435 for (i = 0; i < dsdt->length; i++) {
436 u32 *gnvs = (u32 *)((u32)dsdt + i);
437 if (*gnvs == ACPI_GNVS_ADDR) {
438 ulong addr = (ulong)map_to_sysmem(ctx->current);
439
440 debug("Fix up global NVS in DSDT to %#08lx\n", addr);
441 *gnvs = addr;
442 break;
443 }
444 }
445
446
447
448
449
450
451 dsdt->length = ctx->current - (void *)dsdt;
452 dsdt->checksum = 0;
453 dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length);
454
455 acpi_align(ctx);
456
457
458
459
460
461 addr = acpi_create_gnvs(ctx->current);
462 if (IS_ERR_VALUE(addr))
463 printf("Error: Failed to create GNVS\n");
464
465 acpi_inc_align(ctx, sizeof(struct acpi_global_nvs));
466
467 debug("ACPI: * FADT\n");
468 fadt = ctx->current;
469 acpi_inc_align(ctx, sizeof(struct acpi_fadt));
470 acpi_create_fadt(fadt, facs, dsdt);
471 acpi_add_table(ctx, fadt);
472
473 debug("ACPI: * SSDT\n");
474 ssdt = (struct acpi_table_header *)ctx->current;
475 acpi_create_ssdt(ctx, ssdt, OEM_TABLE_ID);
476 if (ssdt->length > sizeof(struct acpi_table_header)) {
477 acpi_inc_align(ctx, ssdt->length);
478 acpi_add_table(ctx, ssdt);
479 }
480
481 debug("ACPI: * MCFG\n");
482 mcfg = ctx->current;
483 acpi_create_mcfg(mcfg);
484 acpi_inc_align(ctx, mcfg->header.length);
485 acpi_add_table(ctx, mcfg);
486
487 debug("ACPI: * MADT\n");
488 madt = ctx->current;
489 acpi_create_madt(madt);
490 acpi_inc_align(ctx, madt->header.length);
491 acpi_add_table(ctx, madt);
492
493 debug("ACPI: * CSRT\n");
494 csrt = ctx->current;
495 if (!acpi_create_csrt(csrt)) {
496 acpi_inc_align(ctx, csrt->header.length);
497 acpi_add_table(ctx, csrt);
498 }
499
500 debug("ACPI: * SPCR\n");
501 spcr = ctx->current;
502 acpi_create_spcr(spcr);
503 acpi_inc_align(ctx, spcr->header.length);
504 acpi_add_table(ctx, spcr);
505
506 acpi_write_dev_tables(ctx);
507
508 addr = map_to_sysmem(ctx->current);
509 debug("current = %lx\n", addr);
510
511 acpi_rsdp_addr = (unsigned long)ctx->rsdp;
512 debug("ACPI: done\n");
513
514 return addr;
515}
516
517ulong acpi_get_rsdp_addr(void)
518{
519 return acpi_rsdp_addr;
520}
521