2 * coreboot ACPI Table support
3 * written by Stefan Reinauer <stepan@openbios.org>
4 * (C) 2004 SUSE LINUX AG
5 * (C) 2005 Stefan Reinauer
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
11 * Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
12 * 2005.9 yhlu add SRAT table generation
16 * Each system port implementing ACPI has to provide two functions:
21 * See AMD Solo, Island Aruma or Via Epia-M port for more details.
24 #include <console/console.h>
26 #include <arch/acpi.h>
27 #include <device/pci.h>
29 u8 acpi_checksum(u8 *table, u32 length)
40 * add an acpi table to rsdt structure, and recalculate checksum
43 void acpi_add_table(acpi_rsdt_t *rsdt, void *table)
47 int entries_num = sizeof(rsdt->entry)/sizeof(rsdt->entry[0]);
49 for (i=0; i<entries_num; i++) {
50 if(rsdt->entry[i]==0) {
51 rsdt->entry[i]=(u32)table;
52 /* fix length to stop kernel winging about invalid entries */
53 rsdt->header.length = sizeof(acpi_header_t) + (sizeof(u32) * (i+1));
55 /* hope this won't get optimized away */
56 rsdt->header.checksum=0;
57 rsdt->header.checksum=acpi_checksum((u8 *)rsdt,
60 printk_debug("ACPI: added table %d/%d Length now %d\n",i+1, entries_num, rsdt->header.length);
65 printk_warning("ACPI: could not add ACPI table to RSDT. failed.\n");
68 int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end) {
69 mmconfig->base_address = base;
70 mmconfig->base_reserved = 0;
71 mmconfig->pci_segment_group_number = seg_nr;
72 mmconfig->start_bus_number = start;
73 mmconfig->end_bus_number = end;
74 return (sizeof(acpi_mcfg_mmconfig_t));
78 int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic)
81 lapic->length=sizeof(acpi_madt_lapic_t);
84 lapic->processor_id=cpu;
87 return(lapic->length);
90 int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,u32 gsi_base)
93 ioapic->length=sizeof(acpi_madt_ioapic_t);
94 ioapic->reserved=0x00;
95 ioapic->gsi_base=gsi_base;
98 ioapic->ioapic_addr=addr;
100 return(ioapic->length);
103 int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
104 u8 bus, u8 source, u32 gsirq, u16 flags)
107 irqoverride->length=sizeof(acpi_madt_irqoverride_t);
108 irqoverride->bus=bus;
109 irqoverride->source=source;
110 irqoverride->gsirq=gsirq;
111 irqoverride->flags=flags;
113 return(irqoverride->length);
116 int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
120 lapic_nmi->length=sizeof(acpi_madt_lapic_nmi_t);
122 lapic_nmi->flags=flags;
123 lapic_nmi->processor_id=cpu;
124 lapic_nmi->lint=lint;
126 return(lapic_nmi->length);
129 void acpi_create_madt(acpi_madt_t *madt)
131 #define LOCAL_APIC_ADDR 0xfee00000ULL
133 acpi_header_t *header=&(madt->header);
134 unsigned long current=(unsigned long)madt+sizeof(acpi_madt_t);
136 memset((void *)madt, 0, sizeof(acpi_madt_t));
138 /* fill out header fields */
139 memcpy(header->signature, MADT_NAME, 4);
140 memcpy(header->oem_id, OEM_ID, 6);
141 memcpy(header->oem_table_id, MADT_TABLE, 8);
142 memcpy(header->asl_compiler_id, ASLC, 4);
144 header->length = sizeof(acpi_madt_t);
145 header->revision = 1;
147 madt->lapic_addr= LOCAL_APIC_ADDR;
148 madt->flags = 0x1; /* PCAT_COMPAT */
150 current = acpi_fill_madt(current);
152 /* recalculate length */
153 header->length= current - (unsigned long)madt;
155 header->checksum = acpi_checksum((void *)madt, header->length);
158 void acpi_create_mcfg(acpi_mcfg_t *mcfg)
161 acpi_header_t *header=&(mcfg->header);
162 unsigned long current=(unsigned long)mcfg+sizeof(acpi_mcfg_t);
164 memset((void *)mcfg, 0, sizeof(acpi_mcfg_t));
166 /* fill out header fields */
167 memcpy(header->signature, MCFG_NAME, 4);
168 memcpy(header->oem_id, OEM_ID, 6);
169 memcpy(header->oem_table_id, MCFG_TABLE, 8);
170 memcpy(header->asl_compiler_id, ASLC, 4);
172 header->length = sizeof(acpi_mcfg_t);
173 header->revision = 1;
175 current = acpi_fill_mcfg(current);
177 /* recalculate length */
178 header->length= current - (unsigned long)mcfg;
180 header->checksum = acpi_checksum((void *)mcfg, header->length);
183 int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
186 lapic->length=sizeof(acpi_srat_lapic_t);
189 lapic->proximity_domain_7_0 = node;
192 return(lapic->length);
195 int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek,u32 sizek, u32 flags)
198 mem->length=sizeof(acpi_srat_mem_t);
200 mem->base_address_low = (basek<<10);
201 mem->base_address_high = (basek>>(32-10));
203 mem->length_low = (sizek<<10);
204 mem->length_high = (sizek>>(32-10));
206 mem->proximity_domain = node;
213 void acpi_create_srat(acpi_srat_t *srat)
216 acpi_header_t *header=&(srat->header);
217 unsigned long current=(unsigned long)srat+sizeof(acpi_srat_t);
219 memset((void *)srat, 0, sizeof(acpi_srat_t));
221 /* fill out header fields */
222 memcpy(header->signature, SRAT_NAME, 4);
223 memcpy(header->oem_id, OEM_ID, 6);
224 memcpy(header->oem_table_id, SRAT_TABLE, 8);
225 memcpy(header->asl_compiler_id, ASLC, 4);
227 header->length = sizeof(acpi_srat_t);
228 header->revision = 1;
230 srat->resv = 0x1; /* BACK COMP */
232 current = acpi_fill_srat(current);
234 /* recalculate length */
235 header->length= current - (unsigned long)srat;
237 header->checksum = acpi_checksum((void *)srat, header->length);
240 void acpi_create_slit(acpi_slit_t *slit)
243 acpi_header_t *header=&(slit->header);
244 unsigned long current=(unsigned long)slit+sizeof(acpi_slit_t);
246 memset((void *)slit, 0, sizeof(acpi_slit_t));
248 /* fill out header fields */
249 memcpy(header->signature, SLIT_NAME, 4);
250 memcpy(header->oem_id, OEM_ID, 6);
251 memcpy(header->oem_table_id, SLIT_TABLE, 8);
252 memcpy(header->asl_compiler_id, ASLC, 4);
254 header->length = sizeof(acpi_slit_t);
255 header->revision = 1;
257 // current = acpi_fill_slit(current);
259 /* recalculate length */
260 header->length= current - (unsigned long)slit;
262 header->checksum = acpi_checksum((void *)slit, header->length);
265 void acpi_create_hpet(acpi_hpet_t *hpet)
267 #define HPET_ADDR 0xfed00000ULL
268 acpi_header_t *header=&(hpet->header);
269 acpi_addr_t *addr=&(hpet->addr);
271 memset((void *)hpet, 0, sizeof(acpi_hpet_t));
273 /* fill out header fields */
274 memcpy(header->signature, HPET_NAME, 4);
275 memcpy(header->oem_id, OEM_ID, 6);
276 memcpy(header->oem_table_id, HPET_TABLE, 8);
277 memcpy(header->asl_compiler_id, ASLC, 4);
279 header->length = sizeof(acpi_hpet_t);
280 header->revision = 1;
282 /* fill out HPET address */
283 addr->space_id = 0; /* Memory */
284 addr->bit_width = 64;
285 addr->bit_offset = 0;
286 addr->addrl = HPET_ADDR & 0xffffffff;
287 addr->addrh = HPET_ADDR >> 32;
289 hpet->id = 0x102282a0; /* AMD ? */
291 hpet->min_tick = 4096;
293 header->checksum = acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
296 void acpi_create_facs(acpi_facs_t *facs)
298 memset( (void *)facs,0, sizeof(acpi_facs_t));
300 memcpy(facs->signature,"FACS",4);
301 facs->length = sizeof(acpi_facs_t);
302 facs->hardware_signature = 0;
303 facs->firmware_waking_vector = 0;
304 facs->global_lock = 0;
306 facs->x_firmware_waking_vector_l = 0;
307 facs->x_firmware_waking_vector_h = 0;
311 void acpi_write_rsdt(acpi_rsdt_t *rsdt)
313 acpi_header_t *header=&(rsdt->header);
315 /* fill out header fields */
316 memcpy(header->signature, RSDT_NAME, 4);
317 memcpy(header->oem_id, OEM_ID, 6);
318 memcpy(header->oem_table_id, RSDT_TABLE, 8);
319 memcpy(header->asl_compiler_id, ASLC, 4);
321 header->length = sizeof(acpi_rsdt_t);
322 header->revision = 1;
324 /* fill out entries */
326 // entries are filled in later, we come with an empty set.
330 header->checksum = acpi_checksum((void *)rsdt, sizeof(acpi_rsdt_t));
333 void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt)
335 memcpy(rsdp->signature, RSDP_SIG, 8);
336 memcpy(rsdp->oem_id, OEM_ID, 6);
338 rsdp->length = sizeof(acpi_rsdp_t);
339 rsdp->rsdt_address = (u32)rsdt;
340 rsdp->checksum = acpi_checksum((void *)rsdp, 20);
341 rsdp->ext_checksum = acpi_checksum((void *)rsdp, sizeof(acpi_rsdp_t));