Fix Fam14 AGESA ACPI table generation
[coreboot.git] / src / mainboard / amd / inagua / acpi_tables.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2011 Advanced Micro Devices, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #include <console/console.h>
21 #include <string.h>
22 #include <arch/acpi.h>
23 #include <arch/ioapic.h>
24 #include <device/pci.h>
25 #include <device/pci_ids.h>
26 #include <cpu/x86/msr.h>
27 #include "agesawrapper.h"
28 #include <cpu/amd/mtrr.h>
29 #include <cpu/amd/amdfam14.h>
30
31 #define DUMP_ACPI_TABLES 0
32
33 #if DUMP_ACPI_TABLES == 1
34
35 static void dump_mem(u32 start, u32 end)
36 {
37
38         u32 i;
39         print_debug("dump_mem:");
40         for (i = start; i < end; i++) {
41                 if ((i & 0xf) == 0) {
42                         printk(BIOS_DEBUG, "\n%08x:", i);
43                 }
44                 printk(BIOS_DEBUG, " %02x", (u8)*((u8 *)i));
45         }
46         print_debug("\n");
47 }
48 #endif
49
50 extern const unsigned char AmlCode[];
51
52 unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id)
53 {
54         int lens;
55         msr_t msr;
56         char pscope[] = "\\_SB.PCI0";
57
58         lens = acpigen_write_scope(pscope);
59         msr = rdmsr(TOP_MEM);
60         lens += acpigen_write_name_dword("TOM1", msr.lo);
61         msr = rdmsr(TOP_MEM2);
62         /*
63          * Since XP only implements parts of ACPI 2.0, we can't use a qword
64          * here.
65          * See http://www.acpi.info/presentations/S01USMOBS169_OS%2520new.ppt
66          * slide 22ff.
67          * Shift value right by 20 bit to make it fit into 32bit,
68          * giving us 1MB granularity and a limit of almost 4Exabyte of memory.
69          */
70         lens += acpigen_write_name_dword("TOM2", (msr.hi << 12) | msr.lo >> 20);
71         acpigen_patch_len(lens - 1);
72         return (unsigned long) (acpigen_get_current());
73 }
74
75 unsigned long acpi_fill_mcfg(unsigned long current)
76 {
77         /* Just a dummy */
78         return current;
79 }
80
81 unsigned long acpi_fill_madt(unsigned long current)
82 {
83         /* create all subtables for processors */
84         current = acpi_create_madt_lapics(current);
85
86         /* Write SB800 IOAPIC, only one */
87         current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current,
88                                 CONFIG_MAX_CPUS, IO_APIC_ADDR, 0);
89
90         current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
91                         current, 0, 0, 2, 0);
92         current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
93                         current, 0, 9, 9, 0xF);
94
95         /* 0: mean bus 0--->ISA */
96         /* 0: PIC 0 */
97         /* 2: APIC 2 */
98         /* 5 mean: 0101 --> Edige-triggered, Active high */
99
100         /* create all subtables for processors */
101         /* current = acpi_create_madt_lapic_nmis(current, 5, 1); */
102         /* 1: LINT1 connect to NMI */
103
104         return current;
105 }
106
107 unsigned long acpi_fill_slit(unsigned long current)
108 {
109         // Not implemented
110         return current;
111 }
112
113 unsigned long acpi_fill_srat(unsigned long current)
114 {
115         /* No NUMA, no SRAT */
116         return current;
117 }
118
119 unsigned long write_acpi_tables(unsigned long start)
120 {
121         unsigned long current;
122         acpi_rsdp_t *rsdp;
123         acpi_rsdt_t *rsdt;
124         acpi_hpet_t *hpet;
125         acpi_madt_t *madt;
126         acpi_srat_t *srat;
127         acpi_slit_t *slit;
128         acpi_fadt_t *fadt;
129         acpi_facs_t *facs;
130         acpi_header_t *dsdt;
131         acpi_header_t *ssdt;
132         acpi_header_t *ssdt2;
133         acpi_header_t *alib;
134
135         get_bus_conf(); /* it will get sblk, pci1234, hcdn, and sbdn */
136
137         /* Align ACPI tables to 16 bytes */
138         start = (start + 0x0f) & -0x10;
139         current = start;
140
141         printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx...\n", start);
142
143         /* We need at least an RSDP and an RSDT Table */
144         rsdp = (acpi_rsdp_t *) current;
145         current += sizeof(acpi_rsdp_t);
146         rsdt = (acpi_rsdt_t *) current;
147         current += sizeof(acpi_rsdt_t);
148
149         /* clear all table memory */
150         memset((void *)start, 0, current - start);
151
152         acpi_write_rsdp(rsdp, rsdt, NULL);
153         acpi_write_rsdt(rsdt);
154
155         /* DSDT */
156         current  = ( current + 0x07) & -0x08;
157         printk(BIOS_DEBUG, "ACPI:  * DSDT at %lx\n", current);
158         dsdt = (acpi_header_t *)current;
159         memcpy(dsdt, &AmlCode, sizeof(acpi_header_t));
160         current += dsdt->length;
161         memcpy(dsdt, &AmlCode, dsdt->length);
162         printk(BIOS_DEBUG, "ACPI:  * DSDT @ %p Length %x\n",dsdt,dsdt->length);
163
164         /* FACS */ // it needs 64 bit alignment
165         current  = ( current + 0x07) & -0x08;
166         printk(BIOS_DEBUG, "ACPI:  * FACS at %lx\n", current);
167         facs = (acpi_facs_t *) current;
168         current += sizeof(acpi_facs_t);
169         acpi_create_facs(facs);
170
171         /* FADT */
172         current  = ( current + 0x07) & -0x08;
173         printk(BIOS_DEBUG, "ACPI:  * FADT at %lx\n", current);
174         fadt = (acpi_fadt_t *) current;
175         current += sizeof(acpi_fadt_t);
176
177         acpi_create_fadt(fadt, facs, dsdt);
178         acpi_add_table(rsdp, fadt);
179
180         /*
181          * We explicitly add these tables later on:
182          */
183         current  = ( current + 0x07) & -0x08;
184         printk(BIOS_DEBUG, "ACPI:  * HPET at %lx\n", current);
185         hpet = (acpi_hpet_t *) current;
186         current += sizeof(acpi_hpet_t);
187         acpi_create_hpet(hpet);
188         acpi_add_table(rsdp, hpet);
189
190         /* If we want to use HPET Timers Linux wants an MADT */
191         current  = ( current + 0x07) & -0x08;
192         printk(BIOS_DEBUG, "ACPI:  * MADT at %lx\n",current);
193         madt = (acpi_madt_t *) current;
194         acpi_create_madt(madt);
195         current += madt->header.length;
196         acpi_add_table(rsdp, madt);
197
198         /* SRAT */
199         current  = ( current + 0x07) & -0x08;
200         printk(BIOS_DEBUG, "ACPI:  * SRAT at %lx\n", current);
201         srat = (acpi_srat_t *) agesawrapper_getlateinitptr (PICK_SRAT);
202         if (srat != NULL) {
203                 memcpy((void *)current, srat, srat->header.length);
204                 srat = (acpi_srat_t *) current;
205                 current += srat->header.length;
206                 acpi_add_table(rsdp, srat);
207         }
208         else {
209                 printk(BIOS_DEBUG, "  AGESA SRAT table NULL. Skipping.\n");
210         }
211
212         /* SLIT */
213         current  = ( current + 0x07) & -0x08;
214         printk(BIOS_DEBUG, "ACPI:  * SLIT at %lx\n", current);
215         slit = (acpi_slit_t *) agesawrapper_getlateinitptr (PICK_SLIT);
216         if (slit != NULL) {
217                 memcpy((void *)current, slit, slit->header.length);
218                 slit = (acpi_slit_t *) current;
219                 current += slit->header.length;
220                 acpi_add_table(rsdp, slit);
221         }
222         else {
223                 printk(BIOS_DEBUG, "  AGESA SLIT table NULL. Skipping.\n");
224         }
225
226         /* SSDT */
227         current  = ( current + 0x0f) & -0x10;
228         printk(BIOS_DEBUG, "ACPI:  * AGESA ALIB SSDT at %lx\n", current);
229         alib = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_ALIB);
230         if (alib != NULL) {
231                 memcpy((void *)current, alib, alib->length);
232                 ssdt = (acpi_header_t *) current;
233                 current += alib->length;
234                 acpi_add_table(rsdp,alib);
235         }
236         else {
237                 printk(BIOS_DEBUG, "    AGESA ALIB SSDT table NULL. Skipping.\n");
238         }
239
240 #if 0 // The DSDT needs additional work for the AGESA SSDT Pstate table
241         current  = ( current + 0x0f) & -0x10;
242         printk(BIOS_DEBUG, "ACPI:  * AGESA SSDT Pstate at %lx\n", current);
243         ssdt = (acpi_header_t *)agesawrapper_getlateinitptr (PICK_PSTATE);
244         if (ssdt != NULL) {
245                 memcpy((void *)current, ssdt, ssdt->length);
246                 ssdt = (acpi_header_t *) current;
247                 current += ssdt->length;
248         }
249         else {
250                 printk(BIOS_DEBUG, "  AGESA SSDT table NULL. Skipping.\n");
251         }
252         acpi_add_table(rsdp,ssdt);
253 #endif
254
255         current  = ( current + 0x0f) & -0x10;
256         printk(BIOS_DEBUG, "ACPI:  * coreboot TOM SSDT2 at %lx\n", current);
257         ssdt2 = (acpi_header_t *) current;
258         acpi_create_ssdt_generator(ssdt2, ACPI_TABLE_CREATOR);
259         current += ssdt2->length;
260         acpi_add_table(rsdp,ssdt2);
261
262 #if DUMP_ACPI_TABLES == 1
263         printk(BIOS_DEBUG, "rsdp\n");
264         dump_mem(rsdp, ((void *)rsdp) + sizeof(acpi_rsdp_t));
265
266         printk(BIOS_DEBUG, "rsdt\n");
267         dump_mem(rsdt, ((void *)rsdt) + sizeof(acpi_rsdt_t));
268
269         printk(BIOS_DEBUG, "madt\n");
270         dump_mem(madt, ((void *)madt) + madt->header.length);
271
272         printk(BIOS_DEBUG, "srat\n");
273         dump_mem(srat, ((void *)srat) + srat->header.length);
274
275         printk(BIOS_DEBUG, "slit\n");
276         dump_mem(slit, ((void *)slit) + slit->header.length);
277
278         printk(BIOS_DEBUG, "ssdt\n");
279         dump_mem(ssdt, ((void *)ssdt) + ssdt->length);
280
281         printk(BIOS_DEBUG, "ssdt2\n");
282         dump_mem(ssdt2, ((void *)ssdt2) + ssdt2->length);
283
284         printk(BIOS_DEBUG, "fadt\n");
285         dump_mem(fadt, ((void *)fadt) + fadt->header.length);
286 #endif
287
288         printk(BIOS_INFO, "ACPI: done.\n");
289         return current;
290 }