blob: 5d5b288b6d9fa451d9b821910051e8ce351a9445 [file] [log] [blame]
Jonathan A. Kollaschebbfbd52011-08-05 14:43:08 -05001/*
2 * ACPI support
3 * written by Stefan Reinauer <stepan@openbios.org>
4 * (C) 2005 Stefan Reinauer
5 *
6 *
7 * Copyright 2005 AMD
8 * 2005.9 yhlu modify that to more dynamic for AMD Opteron Based MB
9 */
10
11#include <console/console.h>
12#include <string.h>
13#include <arch/acpi.h>
14#include <arch/io.h>
15#include <arch/smp/mpspec.h>
16#include <device/pci.h>
17#include <device/pci_ids.h>
18#include <cpu/x86/msr.h>
19#include <cpu/amd/mtrr.h>
20#include <cpu/amd/amdk8_sysconf.h>
21#include "../../../northbridge/amd/amdk8/acpi.h"
22//#include <cpu/amd/model_fxx_powernow.h>
23
24extern const unsigned char AmlCode[];
25
26static void acpi_create_hpet_new(acpi_hpet_t *);
27static int acpi_create_hpet_new_fill(acpi_hpet_t *, u32, u16, u8);
28static unsigned long acpi_fill_hpet_new(unsigned long);
29
30void acpi_create_hpet_new(acpi_hpet_t *hpet)
31{
32 acpi_header_t *header=&(hpet->header);
33 unsigned long current=(unsigned long)hpet;
34
35 memset((void *)hpet, 0, sizeof(acpi_hpet_t));
36
37 /* fill out header fields */
38 memcpy(header->signature, "HPET", 4);
39 memcpy(header->oem_id, OEM_ID, 6);
40 memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
41 memcpy(header->asl_compiler_id, ASLC, 4);
42
43 header->length = sizeof(acpi_hpet_t);
44 header->revision = 1;
45
46 current = acpi_fill_hpet_new(current);
47
48 /* recalculate length */
49 header->length = current - (unsigned long)hpet;
50
51 header->checksum = acpi_checksum((void *)hpet, header->length);
52}
53
54
55int acpi_create_hpet_new_fill(acpi_hpet_t *hpet, u32 base, u16 min, u8 attr)
56{
57 static u8 num = 0;
58 acpi_addr_t *addr = &(hpet->addr);
59
60 hpet->id = read32(base + 0x000);
61
62 /* fill out HPET address */
63 addr->space_id = 0; /* Memory */
64 addr->bit_width = 0;
65 addr->bit_offset = 0;
66 addr->addrl = base;
67 addr->addrh = 0;
68
69 hpet->number = num++;
70 hpet->min_tick = min;
71 hpet->attributes = attr;
72
73 return (sizeof(acpi_hpet_t));
74}
75
76static unsigned long acpi_fill_hpet_new(unsigned long current)
77{
78#if 1
79 device_t dev;
80 unsigned long hpet_base;
81
82 dev = dev_find_slot(0x0, PCI_DEVFN(0x1,0));
83 if (!dev)
84 return current;
85
86 hpet_base = pci_read_config32(dev, 0x44) & ~0xf;
87
88 printk(BIOS_INFO, "hpet_base %lx.\n", hpet_base);
89
90 current += acpi_create_hpet_new_fill((acpi_hpet_t *)current, hpet_base, 250, 1);
91#endif
92
93 return current;
94}
95
96unsigned long acpi_fill_mcfg(unsigned long current)
97{
98 device_t dev;
99 unsigned long mcfg_base;
100
101 dev = dev_find_slot(0x0, PCI_DEVFN(0x0,0));
102 if (!dev)
103 return current;
104
105 mcfg_base = pci_read_config16(dev, 0x90);
106 if ((mcfg_base & 0x1000) == 0)
107 return current;
108
109 mcfg_base = (mcfg_base & 0xf) << 28;
110
111 printk(BIOS_INFO, "mcfg_base %lx.\n", mcfg_base);
112
113 current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *)
114 current, mcfg_base, 0x0, 0x0, 0xff);
115 return current;
116}
117
118/* APIC */
119unsigned long acpi_fill_madt(unsigned long current)
120{
121 unsigned long apic_addr;
122 device_t dev;
123
124 /* create all subtables for processors */
125 current = acpi_create_madt_lapics(current);
126
127 /* Write NVIDIA CK804 IOAPIC. */
128 dev = dev_find_slot(0x0, PCI_DEVFN(0x1,0));
129 if (dev) {
130 apic_addr = pci_read_config32(dev, PCI_BASE_ADDRESS_1) & ~0xf;
131 current += acpi_create_madt_ioapic(
132 (acpi_madt_ioapic_t *)current,
133 CONFIG_MAX_CPUS * CONFIG_MAX_PHYSICAL_CPUS,
134 apic_addr, 0);
135 /* Initialize interrupt mapping if mptable.c didn't. */
136#if (!CONFIG_GENERATE_MP_TABLE)
137#error untested config
138 {
139 u32 dword;
140 dword = 0x0120d218;
141 pci_write_config32(dev, 0x7c, dword);
142
143 dword = 0x12008a00;
144 pci_write_config32(dev, 0x80, dword);
145
146 dword = 0x0000007d;
147 pci_write_config32(dev, 0x84, dword);
148 }
149#endif
150 }
151
152 /* IRQ of timer */
153 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
154 current, 0, 0, 2, 0);
155 /* IRQ9 */
156 current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *)
157 current, 0, 9, 9, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW);
158
159 /* create all subtables for processors */
160 /* acpi_create_madt_lapic_nmis returns current, not size. */
161 current = acpi_create_madt_lapic_nmis(current,
162 MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, 1);
163
164 return current;
165}
166
167unsigned long acpi_fill_ssdt_generator(unsigned long current, const char *oem_table_id) {
168 k8acpi_write_vars();
169 //amd_model_fxx_generate_powernow(0, 0, 0);
170 return (unsigned long) (acpigen_get_current());
171}
172
173unsigned long write_acpi_tables(unsigned long start)
174{
175 unsigned long current;
176 acpi_rsdp_t *rsdp;
177 acpi_srat_t *srat;
178 acpi_rsdt_t *rsdt;
179 acpi_hpet_t *hpet;
180 acpi_madt_t *madt;
181 acpi_mcfg_t *mcfg;
182 acpi_fadt_t *fadt;
183 acpi_facs_t *facs;
184 acpi_slit_t *slit;
185 acpi_header_t *ssdt;
186 acpi_header_t *dsdt;
187
188 /* Align ACPI tables to 16 byte. */
189 start = (start + 0x0f) & -0x10;
190 current = start;
191
192 printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx.\n", start);
193
194 /* We need at least an RSDP and an RSDT Table */
195 rsdp = (acpi_rsdp_t *) current;
196 current += sizeof(acpi_rsdp_t);
197
198 current = ALIGN(current, 16);
199 rsdt = (acpi_rsdt_t *) current;
200 current += sizeof(acpi_rsdt_t);
201
202 /* Clear all table memory. */
203 memset((void *) start, 0, current - start);
204
205 acpi_write_rsdp(rsdp, rsdt, NULL);
206 acpi_write_rsdt(rsdt);
207
208 current = ALIGN(current, 64);
209 facs = (acpi_facs_t *) current;
210 printk(BIOS_DEBUG, "ACPI: * FACS %p\n", facs);
211 current += sizeof(acpi_facs_t);
212 acpi_create_facs(facs);
213
214 /* DSDT */
215 current = ALIGN(current, 16);
216 dsdt = (acpi_header_t *) current;
217 printk(BIOS_DEBUG, "ACPI: * DSDT %p\n", dsdt);
218 memcpy(dsdt, &AmlCode, sizeof(acpi_header_t));
219 current += dsdt->length;
220 memcpy(dsdt, &AmlCode, dsdt->length);
221 printk(BIOS_DEBUG, "ACPI: * DSDT @ %p Length %x\n",dsdt,dsdt->length);
222
223 current = ALIGN(current, 16);
224 fadt = (acpi_fadt_t *) current;
225 printk(BIOS_DEBUG, "ACPI: * FACP (FADT) @ %p\n", fadt);
226 current += sizeof(acpi_fadt_t);
227
228 /* Add FADT now that we have facs and dsdt. */
229 acpi_create_fadt(fadt, facs, dsdt);
230 acpi_add_table(rsdp, fadt);
231
232 current = ALIGN(current, 16);
233 mcfg = (acpi_mcfg_t *) current;
234 printk(BIOS_DEBUG, "ACPI: * MCFG @ %p\n", mcfg);
235 acpi_create_mcfg(mcfg);
236 current += mcfg->header.length;
237 acpi_add_table(rsdp, mcfg);
238
239 current = ALIGN(current, 16);
240 hpet = (acpi_hpet_t *) current;
241 printk(BIOS_DEBUG, "ACPI: * HPET @ %p\n", hpet);
242 acpi_create_hpet_new(hpet);
243 acpi_add_table(rsdp, hpet);
244 current += hpet->header.length;
245
246 current = ALIGN(current, 16);
247 madt = (acpi_madt_t *) current;
248 printk(BIOS_DEBUG, "ACPI: * APIC/MADT @ %p\n", madt);
249 acpi_create_madt(madt);
250 current += madt->header.length;
251 acpi_add_table(rsdp, madt);
252
253 current = ALIGN(current, 16);
254 srat = (acpi_srat_t *) current;
255 printk(BIOS_DEBUG, "ACPI: * SRAT @ %p\n", srat);
256 acpi_create_srat(srat);
257 current += srat->header.length;
258 acpi_add_table(rsdp, srat);
259
260 /* SLIT */
261 current = ALIGN(current, 16);
262 slit = (acpi_slit_t *) current;
263 printk(BIOS_DEBUG, "ACPI: * SLIT @ %p\n", slit);
264 acpi_create_slit(slit);
265 current+=slit->header.length;
266 acpi_add_table(rsdp,slit);
267
268 /* SSDT */
269 current = ALIGN(current, 16);
270 ssdt = (acpi_header_t *)current;
271 printk(BIOS_DEBUG, "ACPI: * SSDT @ %p\n", ssdt);
272 acpi_create_ssdt_generator(ssdt, "DYNADATA");
273 current += ssdt->length;
274 acpi_add_table(rsdp, ssdt);
275
276 printk(BIOS_INFO, "ACPI: done %p.\n", (void *)current);
277 return current;
278}