Merge with Linux 2.5.74.
[linux-2.6/linux-mips.git] / arch / x86_64 / kernel / acpi / boot.c
blob2da4df05dee05049a61225a93ee3f2b21b1308ed
1 /*
2 * acpi.c - Architecture-Specific Low-Level ACPI Support
4 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5 * Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
6 * Copyright (C) 2001 Patrick Mochel <mochel@osdl.org>
7 * Copyright (C) 2002 Andi Kleen, SuSE Labs (x86-64 port)
9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 #include <linux/config.h>
29 #include <linux/kernel.h>
30 #include <linux/init.h>
31 #include <linux/types.h>
32 #include <linux/stddef.h>
33 #include <linux/slab.h>
34 #include <linux/pci.h>
35 #include <linux/bootmem.h>
36 #include <linux/irq.h>
37 #include <linux/acpi.h>
38 #include <asm/mpspec.h>
39 #include <asm/io.h>
40 #include <asm/apic.h>
41 #include <asm/apicdef.h>
42 #include <asm/page.h>
43 #include <asm/pgtable.h>
44 #include <asm/pgalloc.h>
45 #include <asm/io_apic.h>
46 #include <asm/proto.h>
47 #include <asm/tlbflush.h>
49 extern int acpi_disabled;
51 #define PREFIX "ACPI: "
54 /* --------------------------------------------------------------------------
55 Boot-time Configuration
56 -------------------------------------------------------------------------- */
58 #ifdef CONFIG_ACPI_BOOT
60 enum acpi_irq_model_id acpi_irq_model;
62 /* rely on all ACPI tables being in the direct mapping */
63 char *
64 __acpi_map_table (
65 unsigned long phys_addr,
66 unsigned long size)
68 if (!phys_addr || !size)
69 return NULL;
71 if (phys_addr < (end_pfn_map << PAGE_SHIFT))
72 return __va(phys_addr);
74 return NULL;
77 #ifdef CONFIG_X86_LOCAL_APIC
79 int acpi_lapic;
81 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
84 static int __init
85 acpi_parse_madt (
86 unsigned long phys_addr,
87 unsigned long size)
89 struct acpi_table_madt *madt = NULL;
91 if (!phys_addr || !size)
92 return -EINVAL;
94 madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
95 if (!madt) {
96 printk(KERN_WARNING PREFIX "Unable to map MADT\n");
97 return -ENODEV;
100 if (madt->lapic_address)
101 acpi_lapic_addr = (u64) madt->lapic_address;
103 printk(KERN_INFO PREFIX "Local APIC address 0x%016x\n",
104 madt->lapic_address);
106 return 0;
110 static int __init
111 acpi_parse_lapic (
112 acpi_table_entry_header *header)
114 struct acpi_table_lapic *processor = NULL;
116 processor = (struct acpi_table_lapic*) header;
117 if (!processor)
118 return -EINVAL;
120 acpi_table_print_madt_entry(header);
122 mp_register_lapic (
123 processor->id, /* APIC ID */
124 processor->flags.enabled); /* Enabled? */
126 return 0;
130 static int __init
131 acpi_parse_lapic_addr_ovr (
132 acpi_table_entry_header *header)
134 struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;
136 lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
137 if (!lapic_addr_ovr)
138 return -EINVAL;
140 acpi_lapic_addr = lapic_addr_ovr->address;
142 return 0;
146 static int __init
147 acpi_parse_lapic_nmi (
148 acpi_table_entry_header *header)
150 struct acpi_table_lapic_nmi *lapic_nmi = NULL;
152 lapic_nmi = (struct acpi_table_lapic_nmi*) header;
153 if (!lapic_nmi)
154 return -EINVAL;
156 acpi_table_print_madt_entry(header);
158 if (lapic_nmi->lint != 1)
159 printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
161 return 0;
164 #endif /*CONFIG_X86_LOCAL_APIC*/
166 #ifdef CONFIG_X86_IO_APIC
168 int acpi_ioapic;
170 static int __init
171 acpi_parse_ioapic (
172 acpi_table_entry_header *header)
174 struct acpi_table_ioapic *ioapic = NULL;
176 ioapic = (struct acpi_table_ioapic*) header;
177 if (!ioapic)
178 return -EINVAL;
180 acpi_table_print_madt_entry(header);
182 mp_register_ioapic (
183 ioapic->id,
184 ioapic->address,
185 ioapic->global_irq_base);
187 return 0;
191 static int __init
192 acpi_parse_int_src_ovr (
193 acpi_table_entry_header *header)
195 struct acpi_table_int_src_ovr *intsrc = NULL;
197 intsrc = (struct acpi_table_int_src_ovr*) header;
198 if (!intsrc)
199 return -EINVAL;
201 acpi_table_print_madt_entry(header);
203 mp_override_legacy_irq (
204 intsrc->bus_irq,
205 intsrc->flags.polarity,
206 intsrc->flags.trigger,
207 intsrc->global_irq);
209 return 0;
213 static int __init
214 acpi_parse_nmi_src (
215 acpi_table_entry_header *header)
217 struct acpi_table_nmi_src *nmi_src = NULL;
219 nmi_src = (struct acpi_table_nmi_src*) header;
220 if (!nmi_src)
221 return -EINVAL;
223 acpi_table_print_madt_entry(header);
225 /* TBD: Support nimsrc entries? */
227 return 0;
230 #endif /*CONFIG_X86_IO_APIC*/
232 #ifdef CONFIG_HPET_TIMER
233 static int __init
234 acpi_parse_hpet (
235 unsigned long phys_addr,
236 unsigned long size)
238 struct acpi_table_hpet *hpet_tbl;
240 hpet_tbl = __va(phys_addr);
242 if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) {
243 printk(KERN_WARNING "acpi: HPET timers must be located in memory.\n");
244 return -1;
247 vxtime.hpet_address = hpet_tbl->addr.addrl |
248 ((long) hpet_tbl->addr.addrh << 32);
250 printk(KERN_INFO "acpi: HPET id: %#x base: %#lx\n",
251 hpet_tbl->id, vxtime.hpet_address);
253 return 0;
255 #endif
257 static unsigned long __init
258 acpi_scan_rsdp (
259 unsigned long start,
260 unsigned long length)
262 unsigned long offset = 0;
263 unsigned long sig_len = sizeof("RSD PTR ") - 1;
266 * Scan all 16-byte boundaries of the physical memory region for the
267 * RSDP signature.
269 for (offset = 0; offset < length; offset += 16) {
270 if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
271 continue;
272 return (start + offset);
275 return 0;
279 unsigned long __init
280 acpi_find_rsdp (void)
282 unsigned long rsdp_phys = 0;
285 * Scan memory looking for the RSDP signature. First search EBDA (low
286 * memory) paragraphs and then search upper memory (E0000-FFFFF).
288 rsdp_phys = acpi_scan_rsdp (0, 0x400);
289 if (!rsdp_phys)
290 rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF);
292 return rsdp_phys;
296 int __init
297 acpi_boot_init (void)
299 int result = 0;
302 * The default interrupt routing model is PIC (8259). This gets
303 * overriden if IOAPICs are enumerated (below).
305 acpi_irq_model = ACPI_IRQ_MODEL_PIC;
308 * Initialize the ACPI boot-time table parser.
310 result = acpi_table_init();
311 if (result)
312 return result;
314 result = acpi_blacklisted();
315 if (result) {
316 acpi_disabled = 1;
317 return result;
318 } else
319 printk(KERN_NOTICE PREFIX "BIOS passes blacklist\n");
322 extern int disable_apic;
323 if (disable_apic)
324 return 0;
326 #ifdef CONFIG_X86_LOCAL_APIC
329 * MADT
330 * ----
331 * Parse the Multiple APIC Description Table (MADT), if exists.
332 * Note that this table provides platform SMP configuration
333 * information -- the successor to MPS tables.
336 result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
337 if (!result) {
338 printk(KERN_WARNING PREFIX "MADT not present\n");
339 return 0;
341 else if (result < 0) {
342 printk(KERN_ERR PREFIX "Error parsing MADT\n");
343 return result;
345 else if (result > 1)
346 printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n");
349 * Local APIC
350 * ----------
351 * Note that the LAPIC address is obtained from the MADT (32-bit value)
352 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
355 result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr);
356 if (result < 0) {
357 printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
358 return result;
361 mp_register_lapic_address(acpi_lapic_addr);
363 result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic);
364 if (!result) {
365 printk(KERN_ERR PREFIX "No LAPIC entries present\n");
366 /* TBD: Cleanup to allow fallback to MPS */
367 return -ENODEV;
369 else if (result < 0) {
370 printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
371 /* TBD: Cleanup to allow fallback to MPS */
372 return result;
375 result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi);
376 if (result < 0) {
377 printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
378 /* TBD: Cleanup to allow fallback to MPS */
379 return result;
382 acpi_lapic = 1;
384 #endif /*CONFIG_X86_LOCAL_APIC*/
386 #ifdef CONFIG_X86_IO_APIC
389 * I/O APIC
390 * --------
393 result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic);
394 if (!result) {
395 printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
396 return -ENODEV;
398 else if (result < 0) {
399 printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
400 return result;
403 /* Build a default routing table for legacy (ISA) interrupts. */
404 mp_config_acpi_legacy_irqs();
406 result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
407 if (result < 0) {
408 printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
409 /* TBD: Cleanup to allow fallback to MPS */
410 return result;
413 result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
414 if (result < 0) {
415 printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
416 /* TBD: Cleanup to allow fallback to MPS */
417 return result;
420 acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
422 acpi_ioapic = 1;
424 #endif /*CONFIG_X86_IO_APIC*/
426 #ifdef CONFIG_X86_LOCAL_APIC
427 if (acpi_lapic && acpi_ioapic)
428 smp_found_config = 1;
429 #endif
431 #ifdef CONFIG_HPET_TIMER
432 result = acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
433 if (result < 0)
434 printk("ACPI: no HPET table found (%d).\n", result);
435 #endif
437 return 0;
440 #endif /*CONFIG_ACPI_BOOT*/