2 * This file is part of the coreboot project.
4 * Copyright (C) 2007-2009 coresystems GmbH
5 * Copyright (C) 2013 Vladimir Serbinenko <phcoder@gmail.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
24 #include <console/console.h>
26 #include <arch/ioapic.h>
27 #include <arch/acpi.h>
28 #include <arch/acpigen.h>
29 #include <arch/smp/mpspec.h>
30 #include <device/device.h>
31 #include <device/pci.h>
32 #include <device/pci_ids.h>
33 #include "southbridge/intel/ibexpeak/nvs.h"
35 extern const unsigned char AmlCode
[];
36 #if CONFIG_HAVE_ACPI_SLIC
37 unsigned long acpi_create_slic(unsigned long current
);
40 static void acpi_create_gnvs(global_nvs_t
* gnvs
)
42 memset((void *)gnvs
, 0, sizeof(*gnvs
));
44 gnvs
->mpen
= 1; /* Enable Multi Processing */
45 gnvs
->pcnt
= dev_count_cpu();
49 gnvs
->did
[0] = 0x80000100;
50 gnvs
->did
[1] = 0x80000240;
51 gnvs
->did
[2] = 0x80000410;
52 gnvs
->did
[3] = 0x80000410;
53 gnvs
->did
[4] = 0x00000005;
56 unsigned long acpi_fill_madt(unsigned long current
)
59 current
= acpi_create_madt_lapics(current
);
62 current
+= acpi_create_madt_ioapic((acpi_madt_ioapic_t
*) current
,
66 current
+= acpi_create_madt_irqoverride((acpi_madt_irqoverride_t
*)
68 MP_IRQ_POLARITY_DEFAULT
|
69 MP_IRQ_TRIGGER_DEFAULT
);
70 current
+= acpi_create_madt_irqoverride((acpi_madt_irqoverride_t
*)
72 MP_IRQ_POLARITY_HIGH
|
73 MP_IRQ_TRIGGER_LEVEL
);
76 current
+= acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t
*)
78 MP_IRQ_POLARITY_HIGH
|
79 MP_IRQ_TRIGGER_EDGE
, 0x01);
80 current
+= acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t
*)
81 current
, 1, MP_IRQ_POLARITY_HIGH
|
82 MP_IRQ_TRIGGER_EDGE
, 0x01);
83 current
+= acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t
*)
84 current
, 2, MP_IRQ_POLARITY_HIGH
|
85 MP_IRQ_TRIGGER_EDGE
, 0x01);
86 current
+= acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t
*)
87 current
, 3, MP_IRQ_POLARITY_HIGH
|
88 MP_IRQ_TRIGGER_EDGE
, 0x01);
92 unsigned long acpi_fill_ssdt_generator(unsigned long current
,
93 const char *oem_table_id
)
95 generate_cpu_entries();
96 return (unsigned long)(acpigen_get_current());
99 unsigned long acpi_fill_slit(unsigned long current
)
101 /* Not implemented */
105 unsigned long acpi_fill_srat(unsigned long current
)
107 /* No NUMA, no SRAT */
111 void smm_setup_structures(void *gnvs
, void *tcg
, void *smi1
);
113 #define ALIGN_CURRENT current = (ALIGN(current, 16))
114 unsigned long write_acpi_tables(unsigned long start
)
116 unsigned long current
;
126 #if CONFIG_HAVE_ACPI_SLIC
135 /* Align ACPI tables to 16byte */
138 printk(BIOS_INFO
, "ACPI: Writing ACPI tables at %lx.\n", start
);
140 /* We need at least an RSDP and an RSDT Table */
141 rsdp
= (acpi_rsdp_t
*) current
;
142 current
+= sizeof(acpi_rsdp_t
);
144 rsdt
= (acpi_rsdt_t
*) current
;
145 current
+= sizeof(acpi_rsdt_t
);
147 xsdt
= (acpi_xsdt_t
*) current
;
148 current
+= sizeof(acpi_xsdt_t
);
151 /* clear all table memory */
152 memset((void *)start
, 0, current
- start
);
154 acpi_write_rsdp(rsdp
, rsdt
, xsdt
);
155 acpi_write_rsdt(rsdt
);
156 acpi_write_xsdt(xsdt
);
159 * We explicitly add these tables later on:
161 printk(BIOS_DEBUG
, "ACPI: * HPET\n");
163 hpet
= (acpi_hpet_t
*) current
;
164 current
+= sizeof(acpi_hpet_t
);
166 acpi_create_hpet(hpet
);
167 acpi_add_table(rsdp
, hpet
);
169 /* If we want to use HPET Timers Linux wants an MADT */
170 printk(BIOS_DEBUG
, "ACPI: * MADT\n");
172 madt
= (acpi_madt_t
*) current
;
173 acpi_create_madt(madt
);
174 current
+= madt
->header
.length
;
176 acpi_add_table(rsdp
, madt
);
178 printk(BIOS_DEBUG
, "ACPI: * MCFG\n");
179 mcfg
= (acpi_mcfg_t
*) current
;
180 acpi_create_mcfg(mcfg
);
181 current
+= mcfg
->header
.length
;
183 acpi_add_table(rsdp
, mcfg
);
185 printk(BIOS_DEBUG
, "ACPI: * FACS\n");
186 facs
= (acpi_facs_t
*) current
;
187 current
+= sizeof(acpi_facs_t
);
189 acpi_create_facs(facs
);
191 dsdt
= (acpi_header_t
*) current
;
192 memcpy(dsdt
, &AmlCode
, sizeof(acpi_header_t
));
193 current
+= dsdt
->length
;
194 memcpy(dsdt
, &AmlCode
, dsdt
->length
);
196 /* Fix up global NVS region for SMI handler. The GNVS region lives
197 * in the (high) table area. The low memory map looks like this:
199 * 0x00000000 - 0x000003ff Real Mode IVT
200 * 0x00000400 - 0x000004ff BDA (somewhat unused)
201 * 0x00000500 - 0x0000052f Moved GDT
202 * 0x00000530 - 0x00000b64 coreboot table
203 * 0x0007c000 - 0x0007dfff OS boot sector (unused?)
204 * 0x0007e000 - 0x0007ffff free to use (so no good for acpi+smi)
205 * 0x00080000 - 0x0009fbff usable ram
206 * 0x0009fc00 - 0x0009ffff EBDA (unused?)
207 * 0x000a0000 - 0x000bffff VGA memory
208 * 0x000c0000 - 0x000cffff VGA option rom
209 * 0x000d0000 - 0x000dffff free for other option roms?
210 * 0x000e0000 - 0x000fffff SeaBIOS? (if payload is SeaBIOS it
211 overwrites those tables when
212 loading but uses tables at the RAM
213 end to put the tables again in suitable
215 * 0x000f0000 - 0x000f03ff PIRQ table
216 * 0x000f0400 - 0x000f66?? ACPI tables
217 * 0x000f66?? - 0x000f???? DMI tables
222 /* Pack GNVS into the ACPI table area */
223 for (i
= 0; i
< dsdt
->length
; i
++) {
224 if (*(u32
*) (((u32
) dsdt
) + i
) == 0xC0DEBABE) {
226 "ACPI: Patching up global NVS in DSDT at offset 0x%04x -> 0x%08x\n",
228 *(u32
*) (((u32
) dsdt
) + i
) = current
;
234 acpi_create_gnvs((global_nvs_t
*) current
);
236 /* Keep pointer around */
237 gnvs
= (void *)current
;
242 /* And tell SMI about it */
243 smm_setup_structures(gnvs
, NULL
, NULL
);
245 /* We patched up the DSDT, so we need to recalculate the checksum */
247 dsdt
->checksum
= acpi_checksum((void *)dsdt
, dsdt
->length
);
249 printk(BIOS_DEBUG
, "ACPI: * DSDT @ %p Length %x\n", dsdt
,
252 #if CONFIG_HAVE_ACPI_SLIC
253 printk(BIOS_DEBUG
, "ACPI: * SLIC\n");
254 slic
= (acpi_header_t
*) current
;
255 current
+= acpi_create_slic(current
);
257 acpi_add_table(rsdp
, slic
);
260 printk(BIOS_DEBUG
, "ACPI: * FADT\n");
261 fadt
= (acpi_fadt_t
*) current
;
262 current
+= sizeof(acpi_fadt_t
);
265 acpi_create_fadt(fadt
, facs
, dsdt
);
266 acpi_add_table(rsdp
, fadt
);
268 printk(BIOS_DEBUG
, "ACPI: * SSDT\n");
269 ssdt
= (acpi_header_t
*) current
;
270 acpi_create_ssdt_generator(ssdt
, ACPI_TABLE_CREATOR
);
271 current
+= ssdt
->length
;
272 acpi_add_table(rsdp
, ssdt
);
275 printk(BIOS_DEBUG
, "current = %lx\n", current
);
276 printk(BIOS_INFO
, "ACPI: done.\n");
278 /* Enable Dummy DCC ON# for DVI */
279 printk(BIOS_DEBUG
, "Laptop handling...\n");
280 outb(inb(0x60f) & ~(1 << 5), 0x60f);