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>
41 #include <asm/apicdef.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 */
65 unsigned long phys_addr
,
68 if (!phys_addr
|| !size
)
71 if (phys_addr
< (end_pfn_map
<< PAGE_SHIFT
))
72 return __va(phys_addr
);
77 #ifdef CONFIG_X86_LOCAL_APIC
81 static u64 acpi_lapic_addr __initdata
= APIC_DEFAULT_PHYS_BASE
;
86 unsigned long phys_addr
,
89 struct acpi_table_madt
*madt
= NULL
;
91 if (!phys_addr
|| !size
)
94 madt
= (struct acpi_table_madt
*) __acpi_map_table(phys_addr
, size
);
96 printk(KERN_WARNING PREFIX
"Unable to map MADT\n");
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
);
112 acpi_table_entry_header
*header
)
114 struct acpi_table_lapic
*processor
= NULL
;
116 processor
= (struct acpi_table_lapic
*) header
;
120 acpi_table_print_madt_entry(header
);
123 processor
->id
, /* APIC ID */
124 processor
->flags
.enabled
); /* Enabled? */
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
;
140 acpi_lapic_addr
= lapic_addr_ovr
->address
;
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
;
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");
164 #endif /*CONFIG_X86_LOCAL_APIC*/
166 #ifdef CONFIG_X86_IO_APIC
172 acpi_table_entry_header
*header
)
174 struct acpi_table_ioapic
*ioapic
= NULL
;
176 ioapic
= (struct acpi_table_ioapic
*) header
;
180 acpi_table_print_madt_entry(header
);
185 ioapic
->global_irq_base
);
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
;
201 acpi_table_print_madt_entry(header
);
203 mp_override_legacy_irq (
205 intsrc
->flags
.polarity
,
206 intsrc
->flags
.trigger
,
215 acpi_table_entry_header
*header
)
217 struct acpi_table_nmi_src
*nmi_src
= NULL
;
219 nmi_src
= (struct acpi_table_nmi_src
*) header
;
223 acpi_table_print_madt_entry(header
);
225 /* TBD: Support nimsrc entries? */
230 #endif /*CONFIG_X86_IO_APIC*/
232 #ifdef CONFIG_HPET_TIMER
235 unsigned long phys_addr
,
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");
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
);
257 static unsigned long __init
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
269 for (offset
= 0; offset
< length
; offset
+= 16) {
270 if (strncmp((char *) (start
+ offset
), "RSD PTR ", sig_len
))
272 return (start
+ offset
);
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);
290 rsdp_phys
= acpi_scan_rsdp (0xE0000, 0xFFFFF);
297 acpi_boot_init (void)
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();
314 result
= acpi_blacklisted();
319 printk(KERN_NOTICE PREFIX
"BIOS passes blacklist\n");
322 extern int disable_apic
;
326 #ifdef CONFIG_X86_LOCAL_APIC
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
);
338 printk(KERN_WARNING PREFIX
"MADT not present\n");
341 else if (result
< 0) {
342 printk(KERN_ERR PREFIX
"Error parsing MADT\n");
346 printk(KERN_WARNING PREFIX
"Multiple MADT tables exist\n");
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
);
357 printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
361 mp_register_lapic_address(acpi_lapic_addr
);
363 result
= acpi_table_parse_madt(ACPI_MADT_LAPIC
, acpi_parse_lapic
);
365 printk(KERN_ERR PREFIX
"No LAPIC entries present\n");
366 /* TBD: Cleanup to allow fallback to MPS */
369 else if (result
< 0) {
370 printk(KERN_ERR PREFIX
"Error parsing LAPIC entry\n");
371 /* TBD: Cleanup to allow fallback to MPS */
375 result
= acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI
, acpi_parse_lapic_nmi
);
377 printk(KERN_ERR PREFIX
"Error parsing LAPIC NMI entry\n");
378 /* TBD: Cleanup to allow fallback to MPS */
384 #endif /*CONFIG_X86_LOCAL_APIC*/
386 #ifdef CONFIG_X86_IO_APIC
393 result
= acpi_table_parse_madt(ACPI_MADT_IOAPIC
, acpi_parse_ioapic
);
395 printk(KERN_ERR PREFIX
"No IOAPIC entries present\n");
398 else if (result
< 0) {
399 printk(KERN_ERR PREFIX
"Error parsing IOAPIC entry\n");
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
);
408 printk(KERN_ERR PREFIX
"Error parsing interrupt source overrides entry\n");
409 /* TBD: Cleanup to allow fallback to MPS */
413 result
= acpi_table_parse_madt(ACPI_MADT_NMI_SRC
, acpi_parse_nmi_src
);
415 printk(KERN_ERR PREFIX
"Error parsing NMI SRC entry\n");
416 /* TBD: Cleanup to allow fallback to MPS */
420 acpi_irq_model
= ACPI_IRQ_MODEL_IOAPIC
;
424 #endif /*CONFIG_X86_IO_APIC*/
426 #ifdef CONFIG_X86_LOCAL_APIC
427 if (acpi_lapic
&& acpi_ioapic
)
428 smp_found_config
= 1;
431 #ifdef CONFIG_HPET_TIMER
432 result
= acpi_table_parse(ACPI_HPET
, acpi_parse_hpet
);
434 printk("ACPI: no HPET table found (%d).\n", result
);
440 #endif /*CONFIG_ACPI_BOOT*/