This fixes a couple of issues with older Linux kernels (that expect an XSDT as
[coreboot.git] / src / arch / i386 / boot / acpi.c
1 /*
2  * coreboot ACPI Table support
3  * written by Stefan Reinauer <stepan@openbios.org>
4  *  Copyright (C) 2004 SUSE LINUX AG
5  *  Copyright (C) 2005-2009 coresystems GmbH
6  *
7  * ACPI FADT, FACS, and DSDT table support added by 
8  * Nick Barker <nick.barker9@btinternet.com>, and those portions
9  *  (C) Copyright 2004 Nick Barker
10  *
11  * Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
12  * 2005.9 yhlu add SRAT table generation
13  */
14
15 /* 
16  * Each system port implementing ACPI has to provide two functions:
17  * 
18  *   write_acpi_tables()
19  *   acpi_dump_apics()
20  *   
21  * See AMD Solo, Island Aruma or Via Epia-M port for more details.
22  */
23
24 #include <console/console.h>
25 #include <string.h>
26 #include <arch/acpi.h>
27 #include <arch/acpigen.h>
28 #include <device/pci.h>
29
30 u8 acpi_checksum(u8 *table, u32 length)
31 {
32         u8 ret=0;
33         while (length--) {
34                 ret += *table;
35                 table++;
36         }
37         return -ret;
38 }
39
40 /*
41  * add an acpi table to rsdt structure, and recalculate checksum
42  */
43
44 void acpi_add_table(acpi_rsdp_t *rsdp, void *table)
45 {
46         int i;
47         acpi_rsdt_t *rsdt;
48         acpi_xsdt_t *xsdt = NULL;
49
50         rsdt = (acpi_rsdt_t *)rsdp->rsdt_address;
51         if (rsdp->xsdt_address) {
52                 xsdt = (acpi_xsdt_t *)((u32)rsdp->xsdt_address);
53         }
54         
55         int entries_num = ARRAY_SIZE(rsdt->entry);
56         
57         for (i=0; i<entries_num; i++) {
58                 if(rsdt->entry[i]==0) {
59                         rsdt->entry[i]=(u32)table;
60                         /* fix length to stop kernel whining about invalid entries */
61                         rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i+1));
62                         /* fix checksum */
63                         /* hope this won't get optimized away */
64                         rsdt->header.checksum=0;
65                         rsdt->header.checksum=acpi_checksum((u8 *)rsdt,
66                                         rsdt->header.length);
67
68                         /* And now the same thing for the XSDT. We use the same
69                          * index as we want the XSDT and RSDT to always be in
70                          * sync in coreboot.
71                          */
72                         if (xsdt) {
73                                 xsdt->entry[i]=(u64)(u32)table;
74                                 xsdt->header.length = sizeof(acpi_header_t) +
75                                         (sizeof(u64) * (i+1));
76                                 xsdt->header.checksum=0;
77                                 xsdt->header.checksum=acpi_checksum((u8 *)xsdt,
78                                                 xsdt->header.length);
79                         }
80                         
81                         printk_debug("ACPI: added table %d/%d Length now %d\n",
82                                         i+1, entries_num, rsdt->header.length);
83                         return;
84                 }
85         }
86
87         printk_err("ACPI: Error: Could not add ACPI table, too many tables.\n");
88 }
89
90 int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end)
91 {
92         mmconfig->base_address = base;
93         mmconfig->base_reserved = 0;
94         mmconfig->pci_segment_group_number = seg_nr;
95         mmconfig->start_bus_number = start;
96         mmconfig->end_bus_number = end;
97         return (sizeof(acpi_mcfg_mmconfig_t));
98 }
99
100 int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic)
101 {
102         lapic->type=0;
103         lapic->length=sizeof(acpi_madt_lapic_t);
104         lapic->flags=1;
105         
106         lapic->processor_id=cpu;
107         lapic->apic_id=apic;
108         
109         return(lapic->length);
110 }
111
112 unsigned long acpi_create_madt_lapics(unsigned long current)
113 {
114         device_t cpu;
115         int cpu_index = 0;
116
117         for(cpu = all_devices; cpu; cpu = cpu->next) {
118                 if ((cpu->path.type != DEVICE_PATH_APIC) ||
119                    (cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER)) {
120                         continue;
121                 }
122                 if (!cpu->enabled) {
123                         continue;
124                 }
125                 current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, cpu_index, cpu->path.apic.apic_id);
126                 cpu_index++;
127         }
128         return current;
129 }
130
131 int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,u32 gsi_base) 
132 {
133         ioapic->type=1;
134         ioapic->length=sizeof(acpi_madt_ioapic_t);
135         ioapic->reserved=0x00;
136         ioapic->gsi_base=gsi_base;
137         
138         ioapic->ioapic_id=id;
139         ioapic->ioapic_addr=addr;
140         
141         return(ioapic->length);
142 }
143
144 int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
145                 u8 bus, u8 source, u32 gsirq, u16 flags)
146 {
147         irqoverride->type=2;
148         irqoverride->length=sizeof(acpi_madt_irqoverride_t);
149         irqoverride->bus=bus;
150         irqoverride->source=source;
151         irqoverride->gsirq=gsirq;
152         irqoverride->flags=flags;
153         
154         return(irqoverride->length);
155 }
156
157 int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
158                 u16 flags, u8 lint)
159 {
160         lapic_nmi->type=4;
161         lapic_nmi->length=sizeof(acpi_madt_lapic_nmi_t);
162         
163         lapic_nmi->flags=flags;
164         lapic_nmi->processor_id=cpu;
165         lapic_nmi->lint=lint;
166         
167         return(lapic_nmi->length);
168 }
169
170 void acpi_create_madt(acpi_madt_t *madt)
171 {
172 #define LOCAL_APIC_ADDR 0xfee00000ULL
173         
174         acpi_header_t *header=&(madt->header);
175         unsigned long current=(unsigned long)madt+sizeof(acpi_madt_t);
176         
177         memset((void *)madt, 0, sizeof(acpi_madt_t));
178         
179         /* fill out header fields */
180         memcpy(header->signature, MADT_NAME, 4);
181         memcpy(header->oem_id, OEM_ID, 6);
182         memcpy(header->oem_table_id, MADT_TABLE, 8);
183         memcpy(header->asl_compiler_id, ASLC, 4);
184         
185         header->length = sizeof(acpi_madt_t);
186         header->revision = 1;
187
188         madt->lapic_addr= LOCAL_APIC_ADDR;
189         madt->flags     = 0x1; /* PCAT_COMPAT */
190
191         current = acpi_fill_madt(current);
192         
193         /* recalculate length */
194         header->length= current - (unsigned long)madt;
195         
196         header->checksum        = acpi_checksum((void *)madt, header->length);
197 }
198
199 void acpi_create_mcfg(acpi_mcfg_t *mcfg)
200 {
201
202         acpi_header_t *header=&(mcfg->header);
203         unsigned long current=(unsigned long)mcfg+sizeof(acpi_mcfg_t);
204         
205         memset((void *)mcfg, 0, sizeof(acpi_mcfg_t));
206         
207         /* fill out header fields */
208         memcpy(header->signature, MCFG_NAME, 4);
209         memcpy(header->oem_id, OEM_ID, 6);
210         memcpy(header->oem_table_id, MCFG_TABLE, 8);
211         memcpy(header->asl_compiler_id, ASLC, 4);
212         
213         header->length = sizeof(acpi_mcfg_t);
214         header->revision = 1;
215
216         current = acpi_fill_mcfg(current);
217         
218         /* recalculate length */
219         header->length= current - (unsigned long)mcfg;
220         
221         header->checksum        = acpi_checksum((void *)mcfg, header->length);
222 }
223
224 /* this can be overriden by platform ACPI setup code,
225    if it calls acpi_create_ssdt_generator */
226 unsigned long __attribute__((weak)) acpi_fill_ssdt_generator(unsigned long current,
227                                                     char *oem_table_id) {
228         return current;
229 }
230
231 void acpi_create_ssdt_generator(acpi_header_t *ssdt, char *oem_table_id)
232 {
233         unsigned long current=(unsigned long)ssdt+sizeof(acpi_header_t);
234         memset((void *)ssdt, 0, sizeof(acpi_header_t));
235         memcpy(&ssdt->signature, SSDT_NAME, 4);
236         ssdt->revision = 2;
237         memcpy(&ssdt->oem_id, OEM_ID, 6);
238         memcpy(&ssdt->oem_table_id, oem_table_id, 8);
239         ssdt->oem_revision = 42;
240         memcpy(&ssdt->asl_compiler_id, "CORE", 4);
241         ssdt->asl_compiler_revision = 42;
242         ssdt->length = sizeof(acpi_header_t);
243
244         acpigen_set_current((char *) current);
245         current = acpi_fill_ssdt_generator(current, oem_table_id);
246
247         /* recalculate length */
248         ssdt->length = current - (unsigned long)ssdt;
249         ssdt->checksum = acpi_checksum((void *)ssdt, ssdt->length);
250 }
251
252 int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
253 {
254         memset((void *)lapic, 0, sizeof(acpi_srat_lapic_t));
255         lapic->type=0;
256         lapic->length=sizeof(acpi_srat_lapic_t);
257         lapic->flags=1;
258
259         lapic->proximity_domain_7_0 = node;
260         lapic->apic_id=apic;
261
262         return(lapic->length);
263 }
264
265 int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek,u32 sizek, u32 flags)
266 {
267         mem->type=1;
268         mem->length=sizeof(acpi_srat_mem_t);
269
270         mem->base_address_low = (basek<<10);
271         mem->base_address_high = (basek>>(32-10));
272
273         mem->length_low = (sizek<<10);
274         mem->length_high = (sizek>>(32-10));
275
276         mem->proximity_domain = node;
277
278         mem->flags = flags; 
279
280         return(mem->length);
281 }
282
283 void acpi_create_srat(acpi_srat_t *srat)
284 {
285
286         acpi_header_t *header=&(srat->header);
287         unsigned long current=(unsigned long)srat+sizeof(acpi_srat_t);
288
289         memset((void *)srat, 0, sizeof(acpi_srat_t));
290
291         /* fill out header fields */
292         memcpy(header->signature, SRAT_NAME, 4);
293         memcpy(header->oem_id, OEM_ID, 6);
294         memcpy(header->oem_table_id, SRAT_TABLE, 8);
295         memcpy(header->asl_compiler_id, ASLC, 4);
296
297         header->length = sizeof(acpi_srat_t);
298         header->revision = 1;
299
300         srat->resv     = 0x1; /* BACK COMP */
301
302         current = acpi_fill_srat(current);
303
304         /* recalculate length */
305         header->length= current - (unsigned long)srat;
306
307         header->checksum        = acpi_checksum((void *)srat, header->length);
308 }
309
310 void acpi_create_slit(acpi_slit_t *slit)
311 {
312
313         acpi_header_t *header=&(slit->header);
314         unsigned long current=(unsigned long)slit+sizeof(acpi_slit_t);
315
316         memset((void *)slit, 0, sizeof(acpi_slit_t));
317
318         /* fill out header fields */
319         memcpy(header->signature, SLIT_NAME, 4);
320         memcpy(header->oem_id, OEM_ID, 6);
321         memcpy(header->oem_table_id, SLIT_TABLE, 8);
322         memcpy(header->asl_compiler_id, ASLC, 4);
323
324         header->length = sizeof(acpi_slit_t);
325         header->revision = 1;
326
327         current = acpi_fill_slit(current);
328
329         /* recalculate length */
330         header->length= current - (unsigned long)slit;
331
332         header->checksum        = acpi_checksum((void *)slit, header->length);
333 }
334
335 void acpi_create_hpet(acpi_hpet_t *hpet)
336 {
337 #define HPET_ADDR  0xfed00000ULL
338         acpi_header_t *header=&(hpet->header);
339         acpi_addr_t *addr=&(hpet->addr);
340         
341         memset((void *)hpet, 0, sizeof(acpi_hpet_t));
342         
343         /* fill out header fields */
344         memcpy(header->signature, HPET_NAME, 4);
345         memcpy(header->oem_id, OEM_ID, 6);
346         memcpy(header->oem_table_id, HPET_TABLE, 8);
347         memcpy(header->asl_compiler_id, ASLC, 4);
348         
349         header->length = sizeof(acpi_hpet_t);
350         header->revision = 1;
351
352         /* fill out HPET address */
353         addr->space_id          = 0; /* Memory */
354         addr->bit_width         = 64;
355         addr->bit_offset        = 0;
356         addr->addrl             = HPET_ADDR & 0xffffffff;
357         addr->addrh             = HPET_ADDR >> 32;
358
359         hpet->id        = 0x102282a0; /* AMD ? */
360         hpet->number    = 0;
361         hpet->min_tick  = 4096;
362         
363         header->checksum        = acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
364 }
365 void acpi_create_facs(acpi_facs_t *facs)
366 {
367         
368         memset( (void *)facs,0, sizeof(acpi_facs_t));
369
370         memcpy(facs->signature, FACS_NAME, 4);
371         facs->length = sizeof(acpi_facs_t);
372         facs->hardware_signature = 0;
373         facs->firmware_waking_vector = 0;
374         facs->global_lock = 0;
375         facs->flags = 0;
376         facs->x_firmware_waking_vector_l = 0;
377         facs->x_firmware_waking_vector_h = 0;
378         facs->version = 1;
379 }
380
381 void acpi_write_rsdt(acpi_rsdt_t *rsdt)
382
383         acpi_header_t *header=&(rsdt->header);
384         
385         /* fill out header fields */
386         memcpy(header->signature, RSDT_NAME, 4);
387         memcpy(header->oem_id, OEM_ID, 6);
388         memcpy(header->oem_table_id, RSDT_TABLE, 8);
389         memcpy(header->asl_compiler_id, ASLC, 4);
390         
391         header->length = sizeof(acpi_rsdt_t);
392         header->revision = 1;
393         
394         /* fill out entries */
395
396         // entries are filled in later, we come with an empty set.
397         
398         /* fix checksum */
399         
400         header->checksum = acpi_checksum((void *)rsdt, sizeof(acpi_rsdt_t));
401 }
402
403 void acpi_write_xsdt(acpi_xsdt_t *xsdt)
404
405         acpi_header_t *header=&(xsdt->header);
406         
407         /* fill out header fields */
408         memcpy(header->signature, XSDT_NAME, 4);
409         memcpy(header->oem_id, OEM_ID, 6);
410         memcpy(header->oem_table_id, RSDT_TABLE, 8);
411         memcpy(header->asl_compiler_id, ASLC, 4);
412         
413         header->length = sizeof(acpi_xsdt_t);
414         header->revision = 1;
415         
416         /* fill out entries */
417
418         // entries are filled in later, we come with an empty set.
419         
420         /* fix checksum */
421         
422         header->checksum = acpi_checksum((void *)xsdt, sizeof(acpi_xsdt_t));
423 }
424
425 void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt, acpi_xsdt_t *xsdt)
426 {
427         memcpy(rsdp->signature, RSDP_SIG, 8);
428         memcpy(rsdp->oem_id, OEM_ID, 6);
429         rsdp->length            = sizeof(acpi_rsdp_t);
430         rsdp->rsdt_address      = (u32)rsdt;
431         /* Some OSes expect an XSDT to be present for RSD PTR 
432          * revisions >= 2. If we don't have an ACPI XSDT, force
433          * ACPI 1.0 (and thus RSD PTR revision 0)
434          */
435         if (xsdt == NULL) {
436                 rsdp->revision          = 0;
437         } else {
438                 rsdp->xsdt_address      = (u64)(u32)xsdt;
439                 rsdp->revision          = 2;
440         }
441         rsdp->checksum          = acpi_checksum((void *)rsdp, 20);
442         rsdp->ext_checksum      = acpi_checksum((void *)rsdp, sizeof(acpi_rsdp_t));
443 }
444
445 #if CONFIG_HAVE_ACPI_RESUME == 1
446 void suspend_resume(void)
447 {
448         void *wake_vec;
449
450 #if 0
451 #if CONFIG_MEM_TRAIN_SEQ != 0
452         #error "So far it works on AMD and CONFIG_MEM_TRAIN_SEQ == 0"
453 #endif
454
455 #if CONFIG_RAMBASE < 0x1F00000
456         #error "For ACPI RESUME you need to have CONFIG_RAMBASE at least 31MB"
457         #error "Chipset support (S3_NVRAM_EARLY and ACPI_IS_WAKEUP_EARLY functions and memory ctrl)"
458         #error "And coreboot memory reserved in mainboard.c"
459 #endif
460 #endif
461         /* if we happen to be resuming find wakeup vector and jump to OS */
462         wake_vec = acpi_find_wakeup_vector();
463         if (wake_vec)
464                 acpi_jump_to_wakeup(wake_vec);
465 }
466
467 /* this is to be filled by SB code - startup value what was found */
468 u8 acpi_slp_type = 0;
469
470 int acpi_is_wakeup(void)
471 {
472         return (acpi_slp_type == 3);
473 }
474
475 static acpi_rsdp_t *valid_rsdp(acpi_rsdp_t *rsdp)
476 {
477         if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0)
478                 return NULL;
479
480         printk_debug("Looking on %p for valid checksum\n", rsdp);
481
482         if (acpi_checksum((void *)rsdp, 20) != 0)
483                 return NULL;
484         printk_debug("Checksum 1 passed\n");
485
486         if ((rsdp->revision > 1) && (acpi_checksum((void *)rsdp,
487                                                 rsdp->length) != 0))
488                 return NULL;
489
490         printk_debug("Checksum 2 passed all OK\n");
491
492         return rsdp;
493 }
494
495 static acpi_rsdp_t *rsdp;
496
497 void *acpi_get_wakeup_rsdp(void)
498 {
499         return rsdp;
500 }
501
502 void *acpi_find_wakeup_vector(void)
503 {
504         char *p, *end;
505
506         acpi_rsdt_t *rsdt;
507         acpi_facs_t *facs;
508         acpi_fadt_t *fadt;
509         void  *wake_vec;
510         int i;
511
512         rsdp = NULL;
513
514         if (!acpi_is_wakeup())
515                 return NULL;
516
517         printk_debug("Trying to find the wakeup vector ...\n");
518
519         /* find RSDP */
520         for (p = (char *) 0xe0000; p <  (char *) 0xfffff; p+=16) {
521                 if ((rsdp = valid_rsdp((acpi_rsdp_t *) p)))
522                         break;
523         }
524
525         if (rsdp == NULL)
526                 return NULL;
527
528         printk_debug("RSDP found at %p\n", rsdp);
529         rsdt = (acpi_rsdt_t *) rsdp->rsdt_address;
530         
531         end = (char *) rsdt + rsdt->header.length;
532         printk_debug("RSDT found at %p ends at %p\n", rsdt, end);
533
534         for (i = 0; ((char *) &rsdt->entry[i]) < end; i++) {
535                 fadt = (acpi_fadt_t *) rsdt->entry[i];
536                 if (strncmp((char *)fadt, FADT_NAME, sizeof(FADT_NAME) - 1) == 0)
537                         break;
538                 fadt = NULL;
539         }
540
541         if (fadt == NULL)
542                 return NULL;
543
544         printk_debug("FADT found at %p\n", fadt);
545         facs = (acpi_facs_t *)fadt->firmware_ctrl;
546
547         if (facs == NULL) {
548                 printk_debug("No FACS found, wake up from S3 not possible.\n");
549                 return NULL;
550         }
551
552         printk_debug("FACS found at %p\n", facs);
553         wake_vec = (void *) facs->firmware_waking_vector;
554         printk_debug("OS waking vector is %p\n", wake_vec);
555         return wake_vec;
556 }
557
558 extern char *lowmem_backup;
559 extern char *lowmem_backup_ptr;
560 extern int lowmem_backup_size;
561
562 void acpi_jump_to_wakeup(void *vector)
563 {
564         /* just restore the SMP trampoline and continue with wakeup on assembly level */
565         memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
566         acpi_jmp_to_realm_wakeup((u32) vector);
567 }
568 #endif