2 * Agami Aruma ACPI support
4 * Copyright 2005 Stefan Reinauer
7 * written by Stefan Reinauer <stepan@openbios.org>
8 * 2005.9 yhlu modify that to more dynamic for AMD Opteron Based MB
11 #include <console/console.h>
13 #include <arch/acpi.h>
14 #include <device/pci.h>
15 #include <device/pci_ids.h>
16 #include <cpu/x86/msr.h>
17 #include <cpu/amd/mtrr.h>
19 #define DUMP_ACPI_TABLES 0
21 #if DUMP_ACPI_TABLES == 1
22 static void dump_mem(unsigned start, unsigned end)
26 print_debug("dump_mem:");
27 for (i = start; i < end; i++) {
29 printk_debug("\n%08x:", i);
32 (unsigned char) *((unsigned char *) i));
38 #define HC_POSSIBLE_NUM 8
39 extern unsigned char AmlCode[];
40 extern unsigned char AmlCode_ssdt[];
42 #if ACPI_SSDTX_NUM >= 1
43 extern unsigned char AmlCode_ssdt2[];
44 extern unsigned char AmlCode_ssdt3[];
45 extern unsigned char AmlCode_ssdt4[];
46 //extern unsigned char AmlCode_ssdt5[];
47 //extern unsigned char AmlCode_ssdt6[];
48 //extern unsigned char AmlCode_ssdt7[];
49 //extern unsigned char AmlCode_ssdt8[];
52 #define IO_APIC_ADDR 0xfec00000UL
54 extern unsigned char bus_isa;
55 extern unsigned char bus_8111_0;
56 extern unsigned char bus_8111_1;
57 extern unsigned char bus_8131[7][3]; // another 6 8131
58 extern unsigned apicid_8111;
59 extern unsigned apicid_8131[7][2];
61 extern unsigned pci1234[];
62 extern unsigned hc_possible_num;
65 extern unsigned hcdn[];
66 extern unsigned sbdnx[7]; // for all 8131
68 unsigned long acpi_fill_mcfg(unsigned long current)
74 unsigned long acpi_fill_madt(unsigned long current)
76 unsigned int gsi_base = 0x18;
78 /* create all subtables for processors */
79 current = acpi_create_madt_lapics(current);
81 /* Write 8111 IOAPIC */
82 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
83 apicid_8111, IO_APIC_ADDR, 0);
85 /* Write all 8131/8132 IOAPICs */
89 dev = dev_find_slot(bus_8131[0][0], PCI_DEVFN(sbdnx[0], 1));
92 res = find_resource(dev, PCI_BASE_ADDRESS_0);
94 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
95 apicid_8131[0][0], res->base, gsi_base);
100 dev = dev_find_slot(bus_8131[0][0], PCI_DEVFN(sbdnx[0] + 1, 1));
102 res = find_resource(dev, PCI_BASE_ADDRESS_0);
104 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
105 apicid_8131[0][1], res->base, gsi_base);
112 for (i = 1; i < hc_possible_num; i++)
116 struct resource *res;
118 if ((pci1234[i] & 1) != 1)
122 dev = dev_find_slot(bus_8131[j][0], PCI_DEVFN(sbdnx[j], 1));
125 res = find_resource(dev, PCI_BASE_ADDRESS_0);
127 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
128 apicid_8131[j][0], res->base, gsi_base);
134 dev_find_slot(bus_8131[j][0],
135 PCI_DEVFN(sbdnx[j] + 1, 1));
138 res = find_resource(dev, PCI_BASE_ADDRESS_0);
140 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
141 apicid_8131[j][1], res->base, gsi_base);
147 dev_find_slot(bus_8131[j + 1][0],
148 PCI_DEVFN(sbdnx[j + 1], 1));
152 res = find_resource(dev, PCI_BASE_ADDRESS_0);
154 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
155 apicid_8131[j + 1][0], res->base, gsi_base);
160 dev = dev_find_slot(bus_8131[j + 1][0], PCI_DEVFN(sbdnx[j + 1] + 1, 1));
163 res = find_resource(dev, PCI_BASE_ADDRESS_0);
165 current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
166 apicid_8131[j + 1][1], res->base, gsi_base);
175 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) current, 0, 0, 2, 5);
176 /* 0: mean bus 0--->ISA */
179 /* 5 mean: 0101 --> Edige-triggered, Active high */
182 /* create all subtables for processors */
183 current = acpi_create_madt_lapic_nmis(current, 5, 1);
184 /* 1: LINT1 connect to NMI */
190 //FIXME: next could be moved to northbridge/amd/amdk8/amdk8_acpi.c or cpu/amd/k8/k8_acpi.c begin
191 static void int_to_stream(uint32_t val, uint8_t * dest)
194 for (i = 0; i < 4; i++) {
195 *(dest + i) = (val >> (8 * i)) & 0xff;
199 extern void get_bus_conf(void);
201 static void update_ssdt(void *ssdt)
216 BUSN = ssdt + 0x3a; //+5 will be next BUSN
217 MMIO = ssdt + 0x57; //+5 will be next MMIO
218 PCIO = ssdt + 0xaf; //+5 will be next PCIO
219 SBLK = ssdt + 0xdc; // one byte
220 TOM1 = ssdt + 0xe3; //
221 HCLK = ssdt + 0xfa; //+5 will be next HCLK
222 SBDN = ssdt + 0xed; //
223 HCDN = ssdt + 0x12a; //+5 will be next HCDN
225 dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
227 for (i = 0; i < 4; i++) {
228 dword = pci_read_config32(dev, 0xe0 + i * 4);
229 int_to_stream(dword, BUSN + i * 5);
232 for (i = 0; i < 0x10; i++) {
233 dword = pci_read_config32(dev, 0x80 + i * 4);
234 int_to_stream(dword, MMIO + i * 5);
237 for (i = 0; i < 0x08; i++) {
238 dword = pci_read_config32(dev, 0xc0 + i * 4);
239 int_to_stream(dword, PCIO + i * 5);
242 *SBLK = (uint8_t) (sblk);
244 msr = rdmsr(TOP_MEM);
245 int_to_stream(msr.lo, TOM1);
247 for (i = 0; i < hc_possible_num; i++) {
248 int_to_stream(pci1234[i], HCLK + i * 5);
249 int_to_stream(hcdn[i], HCDN + i * 5);
251 for (i = hc_possible_num; i < HC_POSSIBLE_NUM; i++) { // in case we set array size to other than 8
252 int_to_stream(0x00000000, HCLK + i * 5);
253 int_to_stream(hcdn[i], HCDN + i * 5);
256 int_to_stream(sbdn, SBDN);
262 unsigned long write_acpi_tables(unsigned long start)
264 unsigned long current;
274 acpi_header_t *ssdtx;
276 unsigned char *AmlCode_ssdtx[HC_POSSIBLE_NUM];
280 /* Align ACPI tables to 16byte */
281 start = (start + 0x0f) & -0x10;
284 printk_info("ACPI: Writing ACPI tables at %lx...\n", start);
286 /* We need at least an RSDP and an RSDT Table */
287 rsdp = (acpi_rsdp_t *) current;
288 current += sizeof(acpi_rsdp_t);
289 rsdt = (acpi_rsdt_t *) current;
290 current += sizeof(acpi_rsdt_t);
292 /* clear all table memory */
293 memset((void *) start, 0, current - start);
295 acpi_write_rsdp(rsdp, rsdt);
296 acpi_write_rsdt(rsdt);
298 get_bus_conf(); // get sblk, pci1234, and sbdn
301 * We explicitly add these tables later on:
303 printk_debug("ACPI: * HPET\n");
304 hpet = (acpi_hpet_t *) current;
305 current += sizeof(acpi_hpet_t);
306 acpi_create_hpet(hpet);
307 acpi_add_table(rsdt, hpet);
309 /* If we want to use HPET Timers Linux wants an MADT */
310 printk_debug("ACPI: * MADT\n");
311 madt = (acpi_madt_t *) current;
312 acpi_create_madt(madt);
313 current += madt->header.length;
314 acpi_add_table(rsdt, madt);
317 printk_debug("ACPI: * SRAT\n");
318 srat = (acpi_srat_t *) current;
319 acpi_create_srat(srat);
320 current += srat->header.length;
321 acpi_add_table(rsdt, srat);
324 printk_debug("ACPI: * SSDT\n");
325 ssdt = (acpi_header_t *) current;
326 current += ((acpi_header_t *) AmlCode_ssdt)->length;
327 memcpy((void *) ssdt, (void *) AmlCode_ssdt,
328 ((acpi_header_t *) AmlCode_ssdt)->length);
329 //Here you need to set value in pci1234, sblk and sbdn in get_bus_conf.c
330 update_ssdt((void *) ssdt);
331 /* recalculate checksum */
334 acpi_checksum((unsigned char *) ssdt, ssdt->length);
335 acpi_add_table(rsdt, ssdt);
337 #if ACPI_SSDTX_NUM >= 1
338 // we need to make ssdt2 match to PCI2 in pci2.asl,... pci1234[1]
339 AmlCode_ssdtx[1] = AmlCode_ssdt2; // if you have different HT IO card for the same ht slot, here need to check vendor id, to set coresponding SSDT
340 AmlCode_ssdtx[2] = AmlCode_ssdt3;
341 AmlCode_ssdtx[3] = AmlCode_ssdt4;
342 // AmlCode_ssdtx[4] = AmlCode_ssdt5;
343 // AmlCode_ssdtx[5] = AmlCode_ssdt6;
344 // AmlCode_ssdtx[6] = AmlCode_ssdt7;
345 // AmlCode_ssdtx[7] = AmlCode_ssdt8;
347 //same htio, but different possition? We may have to copy, change HCIN, and recalculate the checknum and add_table
349 for (i = 1; i < hc_possible_num; i++) { // 0: is hc sblink
350 if ((pci1234[i] & 1) != 1)
352 printk_debug("ACPI: * SSDT for PCI%d\n", i + 1); //pci0 and pci1 are in dsdt
353 ssdtx = (acpi_header_t *) current;
354 current += ((acpi_header_t *) AmlCode_ssdtx[i])->length;
355 memcpy((void *) ssdtx, (void *) AmlCode_ssdtx[i],
356 ((acpi_header_t *) AmlCode_ssdtx[i])->length);
357 acpi_add_table(rsdt, ssdtx);
363 printk_debug("ACPI: * FACS\n");
364 facs = (acpi_facs_t *) current;
365 current += sizeof(acpi_facs_t);
366 acpi_create_facs(facs);
369 printk_debug("ACPI: * DSDT\n");
370 dsdt = (acpi_header_t *) current;
371 current += ((acpi_header_t *) AmlCode)->length;
372 memcpy((void *) dsdt, (void *) AmlCode,
373 ((acpi_header_t *) AmlCode)->length);
374 printk_debug("ACPI: * DSDT @ %08x Length %x\n", dsdt,
378 printk_debug("ACPI: * FADT\n");
379 fadt = (acpi_fadt_t *) current;
380 current += sizeof(acpi_fadt_t);
382 acpi_create_fadt(fadt, facs, dsdt);
383 acpi_add_table(rsdt, fadt);
385 #if DUMP_ACPI_TABLES == 1
386 printk_debug("rsdp\n");
387 dump_mem(rsdp, ((void *) rsdp) + sizeof(acpi_rsdp_t));
389 printk_debug("rsdt\n");
390 dump_mem(rsdt, ((void *) rsdt) + sizeof(acpi_rsdt_t));
392 printk_debug("madt\n");
393 dump_mem(madt, ((void *) madt) + madt->header.length);
395 printk_debug("srat\n");
396 dump_mem(srat, ((void *) srat) + srat->header.length);
398 printk_debug("ssdt\n");
399 dump_mem(ssdt, ((void *) ssdt) + ssdt->length);
401 printk_debug("fadt\n");
402 dump_mem(fadt, ((void *) fadt) + fadt->header.length);
405 printk_info("ACPI: done.\n");