Graeme,
thanks, nice use of the #define with inline assembly to avoid the extra cost of using the frame that the five parameters would mandate with the ARM procedure call standard!
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf
Bye Andrea
Sent from my iPad
On 07/giu/2013, at 16:37, Graeme Gregory graeme.gregory@linaro.org wrote:
From: Graeme Gregory graeme.gregory@linaro.org
Start of initialisation of ACPI ported over from armv7 tree.
Patch will now reach the magical goal of ACPI: Interpreter enabled
Signed-off-by: Graeme Gregory graeme.gregory@linaro.org
arch/arm64/Kconfig | 2 + arch/arm64/include/asm/acpi.h | 153 +++ arch/arm64/include/asm/io.h | 1 + arch/arm64/include/asm/processor.h | 13 + arch/arm64/kernel/Makefile | 3 + arch/arm64/kernel/acpi/Makefile | 6 + arch/arm64/kernel/acpi/acpi_div_64_by_32.S | 105 ++ arch/arm64/kernel/acpi/boot.c | 1582 ++++++++++++++++++++++++++++ arch/arm64/kernel/acpi/cstate.c | 210 ++++ arch/arm64/kernel/acpi/sleep.c | 126 +++ arch/arm64/kernel/acpi/sleep.h | 17 + arch/arm64/kernel/acpi/wakeup_32.S | 100 ++ arch/arm64/kernel/acpi/wakeup_64.S | 124 +++ arch/arm64/kernel/setup.c | 19 + drivers/acpi/Kconfig | 26 +- drivers/acpi/Makefile | 4 +- drivers/acpi/osl.c | 77 ++ drivers/acpi/processor_core.c | 36 +- drivers/acpi/reboot.c | 11 +- drivers/acpi/scan.c | 4 + drivers/of/fdt.c | 54 + drivers/pnp/pnpacpi/rsparser.c | 2 + include/acpi/pdc_arm64.h | 39 + include/linux/acpi.h | 1 + include/linux/of_fdt.h | 4 + 25 files changed, 2703 insertions(+), 16 deletions(-) create mode 100644 arch/arm64/include/asm/acpi.h create mode 100644 arch/arm64/kernel/acpi/Makefile create mode 100644 arch/arm64/kernel/acpi/acpi_div_64_by_32.S create mode 100644 arch/arm64/kernel/acpi/boot.c create mode 100644 arch/arm64/kernel/acpi/cstate.c create mode 100644 arch/arm64/kernel/acpi/sleep.c create mode 100644 arch/arm64/kernel/acpi/sleep.h create mode 100644 arch/arm64/kernel/acpi/wakeup_32.S create mode 100644 arch/arm64/kernel/acpi/wakeup_64.S create mode 100644 include/acpi/pdc_arm64.h
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 43b0e9f..b795dda 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -238,6 +238,8 @@ source "net/Kconfig"
source "drivers/Kconfig"
+source "drivers/acpi/Kconfig"
source "fs/Kconfig"
source "arch/arm64/Kconfig.debug" diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h new file mode 100644 index 0000000..ad578ba --- /dev/null +++ b/arch/arm64/include/asm/acpi.h @@ -0,0 +1,153 @@ +/*
- Copyright (C) 2013, Al Stone ahs3@redhat.com
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+#ifndef _ASM_ARM_ACPI_H +#define _ASM_ARM_ACPI_H
+#ifdef __KERNEL__
+#include <acpi/pdc_arm64.h>
+#include <asm/cacheflush.h>
+#include <linux/init.h>
+#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long
+/*
- Calling conventions:
- ACPI_SYSTEM_XFACE - Interfaces to host OS (handlers, threads)
- ACPI_EXTERNAL_XFACE - External ACPI interfaces
- ACPI_INTERNAL_XFACE - Internal ACPI interfaces
- ACPI_INTERNAL_VAR_XFACE - Internal variable-parameter list interfaces
- */
+#define ACPI_SYSTEM_XFACE +#define ACPI_EXTERNAL_XFACE +#define ACPI_INTERNAL_XFACE +#define ACPI_INTERNAL_VAR_XFACE
+/* Asm macros */ +#define ACPI_ASM_MACROS +#define BREAKPOINT3 +#define ACPI_DISABLE_IRQS() local_irq_disable() +#define ACPI_ENABLE_IRQS() local_irq_enable() +#define ACPI_FLUSH_CPU_CACHE() flush_cache_all()
+#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \
- asm ("mov r0, %2\n" \
"mov r1, %3\n" \
"mov r2, %4\n" \
"bl __arm_acpi_div_64_by_32\n" \
"mov %0, r0\n" \
"mov %1, r1\n" \
: "=r"(q32), "=r"(r32) /* output operands */ \
: "r"(n_hi), "r"(n_lo), "r"(d32) /* input operands */ \
: "r0", "r1", "r2" /* clobbered registers */ \
)
+#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \
- asm ("mov r0, %2\n" \
"mov r1, %3\n" \
"and r2, r0, #1\n" \
"lsr r0, r0, #1\n" \
"lsr r1, r1, #1\n" \
"orr r1, r1, r2, lsl #31\n" \
"mov %0, r0\n" \
"mov %1, r1\n" \
: "=r"(n_hi), "=r"(n_lo) /* output operands */ \
: "0"(n_hi), "1"(n_lo) /* input operands */ \
: "r0", "r1", "r2" /* clobbered registers */ \
)
+/* Blob handling macros */ +#define ACPI_BLOB_HEADER_SIZE 8
+int __acpi_acquire_global_lock(unsigned int *lock); +int __acpi_release_global_lock(unsigned int *lock);
+#define ACPI_ACQUIRE_GLOBAL_LOCK(facs, Acq) \
((Acq) = __acpi_acquire_global_lock(&facs->global_lock))
+#define ACPI_RELEASE_GLOBAL_LOCK(facs, Acq) \
((Acq) = __acpi_release_global_lock(&facs->global_lock))
+/* Basic configuration for ACPI */ +/* BOZO: hardware reduced acpi only? */ +#ifdef CONFIG_ACPI +extern int acpi_disabled; +extern int acpi_noirq; +extern int acpi_pci_disabled; +extern int acpi_strict;
+struct acpi_arm_root {
phys_addr_t phys_address;
unsigned long size;
+}; +extern struct acpi_arm_root acpi_arm_rsdp_info;
+/* Low-level suspend routine. */ +extern int acpi_suspend_lowlevel(void);
+/* Physical address to resume after wakeup */ +/* BOZO: was... +#define acpi_wakeup_address ((unsigned long)(real_mode_header->wakeup_start)) +*/ +#define acpi_wakeup_address (0)
+static inline void disable_acpi(void) +{
- acpi_disabled = 1;
- acpi_pci_disabled = 1;
- acpi_noirq = 1;
+}
+static inline bool arch_has_acpi_pdc(void) +{
- /* BOZO: replace x86 specific-ness here */
- return 0; /* always false for now */
+}
+static inline void arch_acpi_set_pdc_bits(u32 *buf) +{
- /* BOZO: replace x86 specific-ness here */
+}
+static inline void acpi_noirq_set(void) { acpi_noirq = 1; } +static inline void acpi_disable_pci(void) +{
- acpi_pci_disabled = 1;
- acpi_noirq_set();
+}
+#else /* !CONFIG_ACPI */ +#define acpi_disabled 1 /* ACPI sometimes enabled on ARM */ +#define acpi_noirq 1 /* ACPI sometimes enabled on ARM */ +#define acpi_pci_disabled 1 /* ACPI PCI sometimes enabled on ARM */ +#define acpi_strict 1 /* no ACPI spec workarounds on ARM */ +#endif
+#endif /*__KERNEL__*/
+#endif /*_ASM_ARM_ACPI_H*/ diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h index 2e12258..849af4b 100644 --- a/arch/arm64/include/asm/io.h +++ b/arch/arm64/include/asm/io.h @@ -232,6 +232,7 @@ extern void __iounmap(volatile void __iomem *addr); #define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) #define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) #define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC)) +#define ioremap_cache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEFAULT)) #define iounmap __iounmap
#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF) diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index ab239b2..0cbc1f6 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -155,6 +155,19 @@ static inline void spin_lock_prefetch(const void *x) prefetchw(x); }
+/*
- Not all ARM devices have ACPI, but some do
- BOZO: is this correct?
- */
+#ifdef CONFIG_ACPI +enum idle_boot_override { IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
IDLE_POLL, IDLE_FORCE_MWAIT };
+extern unsigned long boot_option_idle_override; +#endif
+/* end BOZO */
#define HAVE_ARCH_PICK_MMAP_LAYOUT
#endif diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 7b4b564..615c672 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -27,3 +27,6 @@ extra-y := $(head-y) vmlinux.lds # vDSO - this must be built first to generate the symbol offsets $(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h $(obj)/vdso/vdso-offsets.h: $(obj)/vdso
+obj-$(CONFIG_ACPI) += acpi/
diff --git a/arch/arm64/kernel/acpi/Makefile b/arch/arm64/kernel/acpi/Makefile new file mode 100644 index 0000000..e28c063 --- /dev/null +++ b/arch/arm64/kernel/acpi/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_ACPI) += boot.o
+# BOZO: need to re-enable this properly +#obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_$(BITS).o +obj-$(CONFIG_ACPI_SLEEP) += sleep.o
diff --git a/arch/arm64/kernel/acpi/acpi_div_64_by_32.S b/arch/arm64/kernel/acpi/acpi_div_64_by_32.S new file mode 100644 index 0000000..99a14a4 --- /dev/null +++ b/arch/arm64/kernel/acpi/acpi_div_64_by_32.S @@ -0,0 +1,105 @@ +/*
- Copyright (c) 2013, Al Stone ahs3@redhat.com
- __acpi_arm_div64_by_32: perform integer division of a 64-bit value
a 32-bit value
- The algorithm is borrowed from the GMP library, but has been redone
- here in order to put this implementation under a GPLv2 license.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+#ifdef __ARM_ARCH_8__
+#include <linux/linkage.h>
+/*
- This needs to be called in the following manner:
n_lo => r0 # these are the low 32 bits of the dividend
n_hi => r1 # the high 32 bits of the dividend
d32 => r2 # the 32-bit divisor
- The result is:
q32 <= r0 # the 32-bit quotient
r32 <= r1 # the 32-bit remainder
- This should be consistent with the normal ARMv7 calling conventions.
- */
+ENTRY(__arm_acpi_div_64_by_32)
mov r12, #32 // loop counter
cmp r2, #0x80000000 // check divisor MSB and clear carry
bcs bigdiv
+loop: adcs r1, r1, r1 // handle each bit
adc r0, r0, r0
cmp r0, r2
subcs r0, r0, r2
sub r12, r12, #1
teq r12, #0
bne loop
mov r3, r0 // stash the remainder for a tic
adc r0, r1, r1 // quotient: add in last carry
mov r1, r3 // remainder (now in right register)
mov pc, lr
+bigdiv: stmfd sp!, { r8, lr } // clear some scratch space
and r8, r1, #1 // save LSB of dividend
mov lr, r0, lsl #31
orrs r1, lr, r1, lsr #1 // r1 = lower part >> 1 bit
mov r0, r0, lsr #1 // r0 = higher part >> 1 bit
and lr, r2, #1 // save LSB of divisor
movs r2, r2, lsr #1 // r2 = floor(divisor / 2)
adc r2, r2, #0 // r2 = ceil(divisor / 2)
+loop2: adcs r1, r1, r1 // handle each bit
adc r0, r0, r0
cmp r0, r2
subcs r0, r0, r2
sub r12, r12, #1
teq r12, #0
bne loop2
adc r1, r1, r1 // shift and add last carry
add r0, r8, r0, lsl #1 // shift in remaining dividend LSB
tst lr, lr
beq evendiv
rsb r2, lr, r2, lsl #1 // restore divisor value
adds r0, r0, r1 // adjust for omitted divisor LSB
addcs r1, r1, #1 // adjust quotient if a carry results
subcs r0, r0, r2 // adjust remainder, if carry
cmp r0, r2
subcs r0, r0, #1 // adjust remainder
addcs r1, r1, #1 // adjust quotient
+evendiv:
mov r3, r0 // stash the remainder for a tic
mov r0, r1 // quotient
mov r1, r3 // remainder
ldmfd sp!, { r8, pc } // restore the registers used
+ENDPROC(__arm_acpi_div_64_by_32)
+#else /* ! __ARM_ARCH_7A__ */ +#error __arm_acpi_div_64_by_32 not defined for this architecture +#endif
diff --git a/arch/arm64/kernel/acpi/boot.c b/arch/arm64/kernel/acpi/boot.c new file mode 100644 index 0000000..754b747 --- /dev/null +++ b/arch/arm64/kernel/acpi/boot.c @@ -0,0 +1,1582 @@ +/*
- boot.c - Architecture-Specific Low-Level ACPI Boot Support
- Copyright (C) 2001, 2002 Paul Diefenbaugh paul.s.diefenbaugh@intel.com
- Copyright (C) 2001 Jun Nakajima jun.nakajima@intel.com
- Copyright (C) 2013, Al Stone ahs3@redhat.com (ARM version)
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+/*
- BOZO: this needs to be done right....
- */
+#include <linux/init.h> +#include <linux/acpi.h> +#include <linux/acpi_pmtmr.h> +#include <linux/efi.h> +#include <linux/cpumask.h> +#include <linux/memblock.h> +#include <linux/module.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/slab.h> +#include <linux/bootmem.h> +#include <linux/ioport.h> +#include <linux/pci.h>
+#include <asm/pgtable.h> +#include <asm/io.h> +#include <asm/smp.h> +#include <asm/acpi.h>
+static int __initdata acpi_force = 0; +u32 acpi_rsdt_forced; +int acpi_disabled = 0; +EXPORT_SYMBOL(acpi_disabled);
+#define BAD_MADT_ENTRY(entry, end) ( \
(!entry) || (unsigned long)entry + sizeof(*entry) > end || \
((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
+#define PREFIX "ACPI: "
+int acpi_noirq; /* skip ACPI IRQ initialization */ +int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */ +EXPORT_SYMBOL(acpi_pci_disabled);
+int acpi_lapic; +int acpi_ioapic; +int acpi_strict;
+u8 acpi_sci_flags __initdata; +int acpi_sci_override_gsi __initdata; +int acpi_skip_timer_override __initdata; +int acpi_use_timer_override __initdata; +int acpi_fix_pin2_polarity __initdata;
+struct acpi_arm_root acpi_arm_rsdp_info; /* info about RSDP from FDT */
+#ifdef CONFIG_X86_LOCAL_APIC +static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; +#endif
+/* --------------------------------------------------------------------------
Boot-time Configuration
- -------------------------------------------------------------------------- */
+/*
- The default interrupt routing model is PIC (8259). This gets
- overridden if IOAPICs are enumerated (below).
- Since we're on ARM, it clearly has to be GIC.
- */
+enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_GIC;
+static unsigned int gsi_to_irq(unsigned int gsi) +{
- int irq = irq_create_mapping(NULL, gsi);
- return irq;
+}
+/*
- BOZO: is it reasonable to just reserve the memory space? Or are there
- other restrictions needed? Or does it need copying to some other place?
- */
+char *__init __acpi_map_table(unsigned long phys, unsigned long size) +{
- if (!phys || !size)
return NULL;
- /* we're already in memory so we cannot io_remap the entry */
return phys_to_virt(phys);
+}
+void __init __acpi_unmap_table(char *map, unsigned long size) +{
- if (!map || !size)
return;
- /* we're already in memory so we cannot io_remap the entry;
* since we're not io_remap'ing, unmap'ing is especially
* pointless
*/
return;
+}
+#ifdef CONFIG_X86_LOCAL_APIC +static int __init acpi_parse_madt(struct acpi_table_header *table) +{
- struct acpi_table_madt *madt = NULL;
- if (!cpu_has_apic)
return -EINVAL;
- madt = (struct acpi_table_madt *)table;
- if (!madt) {
printk(KERN_WARNING PREFIX "Unable to map MADT\n");
return -ENODEV;
- }
- if (madt->address) {
acpi_lapic_addr = (u64) madt->address;
printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
madt->address);
- }
- default_acpi_madt_oem_check(madt->header.oem_id,
madt->header.oem_table_id);
- return 0;
+}
+static void __cpuinit acpi_register_lapic(int id, u8 enabled) +{
- unsigned int ver = 0;
- if (id >= (MAX_LOCAL_APIC-1)) {
printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
return;
- }
- if (!enabled) {
++disabled_cpus;
return;
- }
- if (boot_cpu_physical_apicid != -1U)
ver = apic_version[boot_cpu_physical_apicid];
- generic_processor_info(id, ver);
+}
+static int __init +acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) +{
- struct acpi_madt_local_x2apic *processor = NULL;
- int apic_id;
- u8 enabled;
- processor = (struct acpi_madt_local_x2apic *)header;
- if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- apic_id = processor->local_apic_id;
- enabled = processor->lapic_flags & ACPI_MADT_ENABLED;
+#ifdef CONFIG_X86_X2APIC
- /*
* We need to register disabled CPU as well to permit
* counting disabled CPUs. This allows us to size
* cpus_possible_map more accurately, to permit
* to not preallocating memory for all NR_CPUS
* when we use CPU hotplug.
*/
- if (!apic->apic_id_valid(apic_id) && enabled)
printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
- else
acpi_register_lapic(apic_id, enabled);
+#else
- printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
+#endif
- return 0;
+}
+static int __init +acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) +{
- struct acpi_madt_local_apic *processor = NULL;
- processor = (struct acpi_madt_local_apic *)header;
- if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- /*
* We need to register disabled CPU as well to permit
* counting disabled CPUs. This allows us to size
* cpus_possible_map more accurately, to permit
* to not preallocating memory for all NR_CPUS
* when we use CPU hotplug.
*/
- acpi_register_lapic(processor->id, /* APIC ID */
processor->lapic_flags & ACPI_MADT_ENABLED);
- return 0;
+}
+static int __init +acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end) +{
- struct acpi_madt_local_sapic *processor = NULL;
- processor = (struct acpi_madt_local_sapic *)header;
- if (BAD_MADT_ENTRY(processor, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */
processor->lapic_flags & ACPI_MADT_ENABLED);
- return 0;
+}
+static int __init +acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
const unsigned long end)
+{
- struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;
- lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header;
- if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
return -EINVAL;
- acpi_lapic_addr = lapic_addr_ovr->address;
- return 0;
+}
+static int __init +acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,
const unsigned long end)
+{
- struct acpi_madt_local_x2apic_nmi *x2apic_nmi = NULL;
- x2apic_nmi = (struct acpi_madt_local_x2apic_nmi *)header;
- if (BAD_MADT_ENTRY(x2apic_nmi, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- if (x2apic_nmi->lint != 1)
printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
- return 0;
+}
+static int __init +acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) +{
- struct acpi_madt_local_apic_nmi *lapic_nmi = NULL;
- lapic_nmi = (struct acpi_madt_local_apic_nmi *)header;
- if (BAD_MADT_ENTRY(lapic_nmi, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- if (lapic_nmi->lint != 1)
printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
- return 0;
+}
+#endif /*CONFIG_X86_LOCAL_APIC */
+#ifdef CONFIG_X86_IO_APIC
+static int __init +acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) +{
- struct acpi_madt_io_apic *ioapic = NULL;
- ioapic = (struct acpi_madt_io_apic *)header;
- if (BAD_MADT_ENTRY(ioapic, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- mp_register_ioapic(ioapic->id,
ioapic->address, ioapic->global_irq_base);
- return 0;
+}
+/*
- Parse Interrupt Source Override for the ACPI SCI
- */
+static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi) +{
- if (trigger == 0) /* compatible SCI trigger is level */
trigger = 3;
- if (polarity == 0) /* compatible SCI polarity is low */
polarity = 3;
- /* Command-line over-ride via acpi_sci= */
- if (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)
trigger = (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2;
- if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
- /*
* mp_config_acpi_legacy_irqs() already setup IRQs < 16
* If GSI is < 16, this will update its flags,
* else it will create a new mp_irqs[] entry.
*/
- mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
- /*
* stash over-ride to indicate we've been here
* and for later update of acpi_gbl_FADT
*/
- acpi_sci_override_gsi = gsi;
- return;
+}
+static int __init +acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
const unsigned long end)
+{
- struct acpi_madt_interrupt_override *intsrc = NULL;
- intsrc = (struct acpi_madt_interrupt_override *)header;
- if (BAD_MADT_ENTRY(intsrc, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
acpi_sci_ioapic_setup(intsrc->source_irq,
intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
(intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2,
intsrc->global_irq);
return 0;
- }
- if (intsrc->source_irq == 0) {
if (acpi_skip_timer_override) {
printk(PREFIX "BIOS IRQ0 override ignored.\n");
return 0;
}
if ((intsrc->global_irq == 2) && acpi_fix_pin2_polarity
&& (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
}
- }
- mp_override_legacy_irq(intsrc->source_irq,
intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
(intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2,
intsrc->global_irq);
- return 0;
+}
+static int __init +acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end) +{
- struct acpi_madt_nmi_source *nmi_src = NULL;
- nmi_src = (struct acpi_madt_nmi_source *)header;
- if (BAD_MADT_ENTRY(nmi_src, end))
return -EINVAL;
- acpi_table_print_madt_entry(header);
- /* TBD: Support nimsrc entries? */
- return 0;
+}
+#endif /* CONFIG_X86_IO_APIC */
+/*
- acpi_pic_sci_set_trigger()
- use ELCR to set PIC-mode trigger type for SCI
- If a PIC-mode SCI is not recognized or gives spurious IRQ7's
- it may require Edge Trigger -- use "acpi_sci=edge"
- Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
- for the 8259 PIC. bit[n] = 1 means irq[n] is Level, otherwise Edge.
- ECLR1 is IRQs 0-7 (IRQ 0, 1, 2 must be 0)
- ECLR2 is IRQs 8-15 (IRQ 8, 13 must be 0)
- */
+void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) +{
- unsigned int mask = 1 << irq;
- unsigned int old, new;
- /* Real old ELCR mask */
- old = inb(0x4d0) | (inb(0x4d1) << 8);
- /*
* If we use ACPI to set PCI IRQs, then we should clear ELCR
* since we will set it correctly as we enable the PCI irq
* routing.
*/
- new = acpi_noirq ? old : 0;
- /*
* Update SCI information in the ELCR, it isn't in the PCI
* routing tables..
*/
- switch (trigger) {
- case 1: /* Edge - clear */
new &= ~mask;
break;
- case 3: /* Level - set */
new |= mask;
break;
- }
- if (old == new)
return;
- printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old);
- outb(new, 0x4d0);
- outb(new >> 8, 0x4d1);
+}
+int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) +{
- *irq = gsi_to_irq(gsi);
- return 0;
+} +EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
+static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
int trigger, int polarity)
+{ +#ifdef CONFIG_PCI
- /*
* Make sure all (legacy) PCI IRQs are set as level-triggered.
*/
- if (trigger == ACPI_LEVEL_SENSITIVE)
eisa_set_level_irq(gsi);
+#endif
- return gsi;
+}
+static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
int trigger, int polarity)
+{ +#ifdef CONFIG_X86_IO_APIC
- gsi = mp_register_gsi(dev, gsi, trigger, polarity);
+#endif
- return gsi;
+}
+int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
int trigger, int polarity) = acpi_register_gsi_pic;
+/*
- success: return IRQ number (>=0)
- failure: return < 0
- */
+int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) +{
- unsigned int irq;
- unsigned int plat_gsi = gsi;
- plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
- irq = gsi_to_irq(plat_gsi);
- return irq;
+} +EXPORT_SYMBOL_GPL(acpi_register_gsi);
+void acpi_unregister_gsi(u32 gsi) +{ +} +EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
+void __init acpi_set_irq_model_pic(void) +{
- acpi_irq_model = ACPI_IRQ_MODEL_PIC;
- __acpi_register_gsi = acpi_register_gsi_pic;
- acpi_ioapic = 0;
+}
+void __init acpi_set_irq_model_ioapic(void) +{
- acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
- __acpi_register_gsi = acpi_register_gsi_ioapic;
- acpi_ioapic = 1;
+}
+/*
- ACPI based hotplug support for CPU
- */
+#ifdef CONFIG_ACPI_HOTPLUG_CPU +#include <acpi/processor.h>
+static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) +{ +#ifdef CONFIG_ACPI_NUMA
- int nid;
- nid = acpi_get_node(handle);
- if (nid == -1 || !node_online(nid))
return;
- set_apicid_to_node(physid, nid);
- numa_set_node(cpu, nid);
+#endif +}
+static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) +{
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- union acpi_object *obj;
- struct acpi_madt_local_apic *lapic;
- cpumask_var_t tmp_map, new_map;
- u8 physid;
- int cpu;
- int retval = -ENOMEM;
- if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
return -EINVAL;
- if (!buffer.length || !buffer.pointer)
return -EINVAL;
- obj = buffer.pointer;
- if (obj->type != ACPI_TYPE_BUFFER ||
obj->buffer.length < sizeof(*lapic)) {
kfree(buffer.pointer);
return -EINVAL;
- }
- lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer;
- if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC ||
!(lapic->lapic_flags & ACPI_MADT_ENABLED)) {
kfree(buffer.pointer);
return -EINVAL;
- }
- physid = lapic->id;
- kfree(buffer.pointer);
- buffer.length = ACPI_ALLOCATE_BUFFER;
- buffer.pointer = NULL;
- lapic = NULL;
- if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
goto out;
- if (!alloc_cpumask_var(&new_map, GFP_KERNEL))
goto free_tmp_map;
- cpumask_copy(tmp_map, cpu_present_mask);
+#ifdef CONFIG_X86
/* BOZO: ?? */
- acpi_register_lapic(physid, ACPI_MADT_ENABLED);
+#endif
- /*
* If acpi_register_lapic successfully generates a new logical cpu
* number, then the following will get us exactly what was mapped
*/
- cpumask_andnot(new_map, cpu_present_mask, tmp_map);
- if (cpumask_empty(new_map)) {
printk ("Unable to map lapic to logical cpu number\n");
retval = -EINVAL;
goto free_new_map;
- }
- acpi_processor_set_pdc(handle);
- cpu = cpumask_first(new_map);
- acpi_map_cpu2node(handle, cpu, physid);
- *pcpu = cpu;
- retval = 0;
+free_new_map:
- free_cpumask_var(new_map);
+free_tmp_map:
- free_cpumask_var(tmp_map);
+out:
- return retval;
+}
+/* wrapper to silence section mismatch warning */ +int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu) +{
- return _acpi_map_lsapic(handle, pcpu);
+} +EXPORT_SYMBOL(acpi_map_lsapic);
+int acpi_unmap_lsapic(int cpu) +{ +#ifdef CONFIG_X86
/* BOZO: ??? */
- per_cpu(x86_cpu_to_apicid, cpu) = -1;
- set_cpu_present(cpu, false);
- num_processors--;
+#endif
- return (0);
+}
+EXPORT_SYMBOL(acpi_unmap_lsapic); +#endif /* CONFIG_ACPI_HOTPLUG_CPU */
+int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) +{
- /* TBD */
- return -EINVAL;
+}
+EXPORT_SYMBOL(acpi_register_ioapic);
+int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base) +{
- /* TBD */
- return -EINVAL;
+}
+EXPORT_SYMBOL(acpi_unregister_ioapic);
+static int __init acpi_parse_sbf(struct acpi_table_header *table) +{
- struct acpi_table_boot *sb;
- sb = (struct acpi_table_boot *)table;
- if (!sb) {
printk(KERN_WARNING PREFIX "Unable to map SBF\n");
return -ENODEV;
- }
+#ifdef CONFIG_X86
/* BOZO: can this be ignored? do we need SBF? */
- sbf_port = sb->cmos_index; /* Save CMOS port */
+#endif
- return 0;
+}
+#ifdef CONFIG_HPET_TIMER +#include <asm/hpet.h>
+static struct __initdata resource *hpet_res;
+static int __init acpi_parse_hpet(struct acpi_table_header *table) +{
- struct acpi_table_hpet *hpet_tbl;
- hpet_tbl = (struct acpi_table_hpet *)table;
- if (!hpet_tbl) {
printk(KERN_WARNING PREFIX "Unable to map HPET\n");
return -ENODEV;
- }
- if (hpet_tbl->address.space_id != ACPI_SPACE_MEM) {
printk(KERN_WARNING PREFIX "HPET timers must be located in "
"memory.\n");
return -1;
- }
- hpet_address = hpet_tbl->address.address;
- hpet_blockid = hpet_tbl->sequence;
- /*
* Some broken BIOSes advertise HPET at 0x0. We really do not
* want to allocate a resource there.
*/
- if (!hpet_address) {
printk(KERN_WARNING PREFIX
"HPET id: %#x base: %#lx is invalid\n",
hpet_tbl->id, hpet_address);
return 0;
- }
+#ifdef CONFIG_X86_64
- /*
* Some even more broken BIOSes advertise HPET at
* 0xfed0000000000000 instead of 0xfed00000. Fix it up and add
* some noise:
*/
- if (hpet_address == 0xfed0000000000000UL) {
if (!hpet_force_user) {
printk(KERN_WARNING PREFIX "HPET id: %#x "
"base: 0xfed0000000000000 is bogus\n "
"try hpet=force on the kernel command line to "
"fix it up to 0xfed00000.\n", hpet_tbl->id);
hpet_address = 0;
return 0;
}
printk(KERN_WARNING PREFIX
"HPET id: %#x base: 0xfed0000000000000 fixed up "
"to 0xfed00000.\n", hpet_tbl->id);
hpet_address >>= 32;
- }
+#endif
- printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
hpet_tbl->id, hpet_address);
- /*
* Allocate and initialize the HPET firmware resource for adding into
* the resource tree during the lateinit timeframe.
*/
+#define HPET_RESOURCE_NAME_SIZE 9
- hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
- hpet_res->name = (void *)&hpet_res[1];
- hpet_res->flags = IORESOURCE_MEM;
- snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, "HPET %u",
hpet_tbl->sequence);
- hpet_res->start = hpet_address;
- hpet_res->end = hpet_address + (1 * 1024) - 1;
- return 0;
+}
+/*
- hpet_insert_resource inserts the HPET resources used into the resource
- tree.
- */
+static __init int hpet_insert_resource(void) +{
- if (!hpet_res)
return 1;
- return insert_resource(&iomem_resource, hpet_res);
+}
+late_initcall(hpet_insert_resource);
+#else +#define acpi_parse_hpet NULL +#endif
+static int __init acpi_parse_fadt(struct acpi_table_header *table) +{
+#ifdef CONFIG_X86_PM_TIMER
- /* detect the location of the ACPI PM Timer */
- if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) {
/* FADT rev. 2 */
if (acpi_gbl_FADT.xpm_timer_block.space_id !=
ACPI_ADR_SPACE_SYSTEM_IO)
return 0;
pmtmr_ioport = acpi_gbl_FADT.xpm_timer_block.address;
/*
* "X" fields are optional extensions to the original V1.0
* fields, so we must selectively expand V1.0 fields if the
* corresponding X field is zero.
*/
if (!pmtmr_ioport)
pmtmr_ioport = acpi_gbl_FADT.pm_timer_block;
- } else {
/* FADT rev. 1 */
pmtmr_ioport = acpi_gbl_FADT.pm_timer_block;
- }
- if (pmtmr_ioport)
printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
pmtmr_ioport);
+#endif
- return 0;
+}
+#ifdef CONFIG_X86_LOCAL_APIC +/*
- Parse LAPIC entries in MADT
- returns 0 on success, < 0 on error
- */
+static int __init early_acpi_parse_madt_lapic_addr_ovr(void) +{
- int count;
- if (!cpu_has_apic)
return -ENODEV;
- /*
* Note that the LAPIC address is obtained from the MADT (32-bit value)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count =
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
acpi_parse_lapic_addr_ovr, 0);
- if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
return count;
- }
- register_lapic_address(acpi_lapic_addr);
- return count;
+}
+static int __init acpi_parse_madt_lapic_entries(void) +{
- int count;
- int x2count = 0;
- if (!cpu_has_apic)
return -ENODEV;
- /*
* Note that the LAPIC address is obtained from the MADT (32-bit value)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
*/
- count =
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
acpi_parse_lapic_addr_ovr, 0);
- if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing LAPIC address override entry\n");
return count;
- }
- register_lapic_address(acpi_lapic_addr);
- count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
acpi_parse_sapic, MAX_LOCAL_APIC);
- if (!count) {
x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
acpi_parse_x2apic, MAX_LOCAL_APIC);
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
acpi_parse_lapic, MAX_LOCAL_APIC);
- }
- if (!count && !x2count) {
printk(KERN_ERR PREFIX "No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */
return -ENODEV;
- } else if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
- }
- x2count =
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
acpi_parse_x2apic_nmi, 0);
- count =
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
- if (count < 0 || x2count < 0) {
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
- }
- return 0;
+} +#endif /* CONFIG_X86_LOCAL_APIC */
+#ifdef CONFIG_X86_IO_APIC +#define MP_ISA_BUS 0
+#ifdef CONFIG_X86_ES7000 +extern int es7000_plat; +#endif
+void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) +{
- int ioapic;
- int pin;
- struct mpc_intsrc mp_irq;
- /*
* Convert 'gsi' to 'ioapic.pin'.
*/
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0)
return;
- pin = mp_find_ioapic_pin(ioapic, gsi);
- /*
* TBD: This check is for faulty timer entries, where the override
* erroneously sets the trigger to level, resulting in a HUGE
* increase of timer interrupts!
*/
- if ((bus_irq == 0) && (trigger == 3))
trigger = 1;
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger << 2) | polarity;
- mp_irq.srcbus = MP_ISA_BUS;
- mp_irq.srcbusirq = bus_irq; /* IRQ */
- mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
- mp_irq.dstirq = pin; /* INTIN# */
- mp_save_irq(&mp_irq);
- isa_irq_to_gsi[bus_irq] = gsi;
+}
+void __init mp_config_acpi_legacy_irqs(void) +{
- int i;
- struct mpc_intsrc mp_irq;
+#ifdef CONFIG_EISA
- /*
* Fabricate the legacy ISA bus (bus #31).
*/
- mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
+#endif
- set_bit(MP_ISA_BUS, mp_bus_not_pci);
- pr_debug("Bus #%d is ISA\n", MP_ISA_BUS);
+#ifdef CONFIG_X86_ES7000
- /*
* Older generations of ES7000 have no legacy identity mappings
*/
- if (es7000_plat == 1)
return;
+#endif
- /*
* Use the default configuration for the IRQs 0-15. Unless
* overridden by (MADT) interrupt source override entries.
*/
- for (i = 0; i < 16; i++) {
int ioapic, pin;
unsigned int dstapic;
int idx;
u32 gsi;
/* Locate the gsi that irq i maps to. */
if (acpi_isa_irq_to_gsi(i, &gsi))
continue;
/*
* Locate the IOAPIC that manages the ISA IRQ.
*/
ioapic = mp_find_ioapic(gsi);
if (ioapic < 0)
continue;
pin = mp_find_ioapic_pin(ioapic, gsi);
dstapic = mpc_ioapic_id(ioapic);
for (idx = 0; idx < mp_irq_entries; idx++) {
struct mpc_intsrc *irq = mp_irqs + idx;
/* Do we already have a mapping for this ISA IRQ? */
if (irq->srcbus == MP_ISA_BUS && irq->srcbusirq == i)
break;
/* Do we already have a mapping for this IOAPIC pin */
if (irq->dstapic == dstapic && irq->dstirq == pin)
break;
}
if (idx != mp_irq_entries) {
printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
continue; /* IRQ already used */
}
mp_irq.type = MP_INTSRC;
mp_irq.irqflag = 0; /* Conforming */
mp_irq.srcbus = MP_ISA_BUS;
mp_irq.dstapic = dstapic;
mp_irq.irqtype = mp_INT;
mp_irq.srcbusirq = i; /* Identity mapped */
mp_irq.dstirq = pin;
mp_save_irq(&mp_irq);
- }
+}
+static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
+{ +#ifdef CONFIG_X86_MPPARSE
- struct mpc_intsrc mp_irq;
- struct pci_dev *pdev;
- unsigned char number;
- unsigned int devfn;
- int ioapic;
- u8 pin;
- if (!acpi_ioapic)
return 0;
- if (!dev)
return 0;
- if (dev->bus != &pci_bus_type)
return 0;
- pdev = to_pci_dev(dev);
- number = pdev->bus->number;
- devfn = pdev->devfn;
- pin = pdev->pin;
- /* print the entry should happen on mptable identically */
- mp_irq.type = MP_INTSRC;
- mp_irq.irqtype = mp_INT;
- mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
- mp_irq.srcbus = number;
- mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
- ioapic = mp_find_ioapic(gsi);
- mp_irq.dstapic = mpc_ioapic_id(ioapic);
- mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
- mp_save_irq(&mp_irq);
+#endif
- return 0;
+}
+int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) +{
- int ioapic;
- int ioapic_pin;
- struct io_apic_irq_attr irq_attr;
- if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
- /* Don't set up the ACPI SCI because it's already set up */
- if (acpi_gbl_FADT.sci_interrupt == gsi)
return gsi;
- ioapic = mp_find_ioapic(gsi);
- if (ioapic < 0) {
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
return gsi;
- }
- ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
- if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
printk(KERN_ERR "Invalid reference to IOAPIC pin "
"%d-%d\n", mpc_ioapic_id(ioapic),
ioapic_pin);
return gsi;
- }
- if (enable_update_mptable)
mp_config_acpi_gsi(dev, gsi, trigger, polarity);
- set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
- io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
- return gsi;
+}
+/*
- Parse IOAPIC related entries in MADT
- returns 0 on success, < 0 on error
- */
+static int __init acpi_parse_madt_ioapic_entries(void) +{
- int count;
- /*
* ACPI interpreter is required to complete interrupt setup,
* so if it is off, don't enumerate the io-apics with ACPI.
* If MPS is present, it will handle them,
* otherwise the system will stay in PIC mode
*/
- if (acpi_disabled || acpi_noirq)
return -ENODEV;
- if (!cpu_has_apic)
return -ENODEV;
- /*
* if "noapic" boot option, don't look for IO-APICs
*/
- if (skip_ioapic_setup) {
printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
"due to 'noapic' option.\n");
return -ENODEV;
- }
- count =
acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
MAX_IO_APICS);
- if (!count) {
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
return -ENODEV;
- } else if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
return count;
- }
- count =
acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
nr_irqs);
- if (count < 0) {
printk(KERN_ERR PREFIX
"Error parsing interrupt source overrides entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
- }
- /*
* If BIOS did not supply an INT_SRC_OVR for the SCI
* pretend we got one so we can set the SCI flags.
*/
- if (!acpi_sci_override_gsi)
acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0,
acpi_gbl_FADT.sci_interrupt);
- /* Fill in identity legacy mappings where no override */
- mp_config_acpi_legacy_irqs();
- count =
acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
nr_irqs);
- if (count < 0) {
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
- }
- return 0;
+} +#else +static inline int acpi_parse_madt_ioapic_entries(void) +{
- return -1;
+} +#endif /* !CONFIG_X86_IO_APIC */
+static void __init early_acpi_process_madt(void) +{ +#ifdef CONFIG_X86_LOCAL_APIC
- int error;
- if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
/*
* Parse MADT LAPIC entries
*/
error = early_acpi_parse_madt_lapic_addr_ovr();
if (!error) {
acpi_lapic = 1;
smp_found_config = 1;
}
if (error == -EINVAL) {
/*
* Dell Precision Workstation 410, 610 come here.
*/
printk(KERN_ERR PREFIX
"Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
- }
+#endif +}
+static void __init acpi_process_madt(void) +{ +#ifdef CONFIG_X86_LOCAL_APIC
- int error;
- if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) {
/*
* Parse MADT LAPIC entries
*/
error = acpi_parse_madt_lapic_entries();
if (!error) {
acpi_lapic = 1;
/*
* Parse MADT IO-APIC entries
*/
error = acpi_parse_madt_ioapic_entries();
if (!error) {
acpi_set_irq_model_ioapic();
smp_found_config = 1;
}
}
if (error == -EINVAL) {
/*
* Dell Precision Workstation 410, 610 come here.
*/
printk(KERN_ERR PREFIX
"Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
- } else {
/*
* ACPI found no MADT, and so ACPI wants UP PIC mode.
* In the event an MPS table was found, forget it.
* Boot with "acpi=off" to use MPS on such a system.
*/
if (smp_found_config) {
printk(KERN_WARNING PREFIX
"No APIC-table, disabling MPS\n");
smp_found_config = 0;
}
- }
- /*
* ACPI supports both logical (e.g. Hyper-Threading) and physical
* processors, where MPS only supports physical.
*/
- if (acpi_lapic && acpi_ioapic)
printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
"information\n");
- else if (acpi_lapic)
printk(KERN_INFO "Using ACPI for processor (LAPIC) "
"configuration information\n");
+#endif
- return;
+}
+void set_checksum(u8 *start, int len, u8 *cksum) +{
- u8 newsum, oldsum;
- u8 *p;
- newsum = 0;
- for (p = (u8 *)start; p < (u8 *)(start + len); p++)
newsum += *p;
- oldsum = *cksum;
- newsum = (u8)(newsum - oldsum);
- *cksum = (u8)(0 - newsum);
+}
+void __init acpi_arm_blob_relocate(void) +{
- /*
* Fortunately, there are only a few tables that need to
* have their offsets converted to actual addresses.
*
* NB: all values in the blob are little-endian.
*/
- struct acpi_table_rsdp *rp;
- struct acpi_table_xsdt *xp;
- struct acpi_table_fadt *fp;
- phys_addr_t paddress;
- void *vaddress;
- u32 entries;
- u32 ii;
- u64 *tmp;
- if (!acpi_arm_rsdp_info.phys_address && !acpi_arm_rsdp_info.size) {
printk(KERN_ERR "(E) ACPI: failed to find rsdp info\n");
return;
- }
- paddress = acpi_arm_rsdp_info.phys_address;
- paddress += ACPI_BLOB_HEADER_SIZE;
- vaddress = phys_to_virt(paddress);
- /* fixups for the rsdp */
- rp = (struct acpi_table_rsdp *)vaddress;
- if (rp->rsdt_physical_address)
rp->rsdt_physical_address += paddress;
- if (rp->xsdt_physical_address)
rp->xsdt_physical_address += paddress;
- set_checksum((u8 *)rp, rp->length, &(rp->checksum));
- /* fixups for the xsdt */
- vaddress = phys_to_virt(rp->xsdt_physical_address);
- xp = (struct acpi_table_xsdt *)vaddress;
- entries = xp->header.length - sizeof (struct acpi_table_header);
- entries /= 8; /* length is in bytes */
- tmp = (u64 *)(&(xp->table_offset_entry[0]));
- for (ii = 0; ii < entries; ii++)
*tmp++ += paddress;
- set_checksum((u8 *)xp, xp->header.length, &(xp->header.checksum));
- /* fixups for the fadt */
- vaddress = phys_to_virt(xp->table_offset_entry[0]);
- fp = (struct acpi_table_fadt *)vaddress;
- if (fp->facs)
fp->facs += paddress;
- if (fp->dsdt)
fp->dsdt += paddress;
- if (fp->Xfacs)
fp->Xfacs += paddress;
- if (fp->Xdsdt)
fp->Xdsdt += paddress;
- /* Always fix up the checksums since we've changed bits. */
- set_checksum((u8 *)fp, fp->header.length, &(fp->header.checksum));
+}
+/*
- ========== OLD COMMENTS FROM x86 =================================
- acpi_boot_table_init() and acpi_boot_init()
- called from setup_arch(), always.
- checksums all tables
- enumerates lapics
- enumerates io-apics
- acpi_table_init() is separate to allow reading SRAT without
- other side effects.
- side effects of acpi_boot_init:
- acpi_lapic = 1 if LAPIC found
- acpi_ioapic = 1 if IOAPIC found
- if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
- if acpi_blacklisted() acpi_disabled = 1;
- acpi_irq_model=...
- ...
- ==================================================================
- We have to approach this a little different on ARMv7. We are
- passed in an ACPI blob and we really have no idea where in RAM
- it will be located. So, what should have been the physical
- addresses of other tables cannot really be hardcoded into the
- tables. What we will do is put an offset in the blob that is
- the offset from the beginning of the RSDP structure. However,
- what that means is that we have to unpack the blob and do a
- bit of fixup work on the offsets to turn them into kernel
- virtual addresses so we can pass them on for later use.
- */
+void __init acpi_boot_table_init(void) +{
- /*
* If acpi_disabled, bail out
*/
- if (acpi_disabled)
return;
printk(KERN_DEBUG "acpi: enter acpi_boot_table_init\n");
- /*
* Fix up the addresses in the ACPI we've loaded
* in. The blob has them as offsets and we need
* actual addresses.
*/
- acpi_arm_blob_relocate();
- /*
* Initialize the ACPI boot-time table parser.
*/
- if (acpi_table_init()) {
disable_acpi();
return;
- }
printk(KERN_INFO "(I) acpi_table_init call completed\n");
- acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
- /*
* blacklist may disable ACPI entirely
*/
- if (acpi_blacklisted()) {
if (acpi_force) {
printk(KERN_WARNING PREFIX "acpi=force override\n");
} else {
printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
disable_acpi();
return;
}
- }
printk(KERN_INFO "(I) exit acpi_boot_table_init\n");
+}
+int __init early_acpi_boot_init(void) +{
- /*
* If acpi_disabled, bail out
*/
- if (acpi_disabled)
return 1;
printk(KERN_INFO "enter early_acpi_boot_init\n");
- /*
* Process the Multiple APIC Description Table (MADT), if present
*/
- early_acpi_process_madt();
- return 0;
+}
+int __init acpi_boot_init(void) +{
- /*
* If acpi_disabled, bail out
*/
- if (acpi_disabled)
return 1;
printk(KERN_INFO "enter acpi_boot_init\n");
- acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
- /*
* set sci_int and PM timer address
*/
- acpi_table_parse(ACPI_SIG_FADT, acpi_parse_fadt);
- /*
* Process the Multiple APIC Description Table (MADT), if present
*/
- acpi_process_madt();
- acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet);
+#ifdef CONFIG_X86
- if (!acpi_noirq)
x86_init.pci.init = pci_acpi_init;
+#endif
- return 0;
+}
+static int __init parse_acpi(char *arg) +{
- if (!arg)
return -EINVAL;
- /* "acpi=off" disables both ACPI table parsing and interpreter */
- if (strcmp(arg, "off") == 0) {
disable_acpi();
- }
- /* acpi=force to over-ride black-list */
- else if (strcmp(arg, "force") == 0) {
acpi_force = 1;
acpi_disabled = 0;
- }
- /* acpi=strict disables out-of-spec workarounds */
- else if (strcmp(arg, "strict") == 0) {
acpi_strict = 1;
- }
- /* acpi=rsdt use RSDT instead of XSDT */
- else if (strcmp(arg, "rsdt") == 0) {
acpi_rsdt_forced = 1;
- }
- /* "acpi=noirq" disables ACPI interrupt routing */
- else if (strcmp(arg, "noirq") == 0) {
acpi_noirq_set();
- }
- /* "acpi=copy_dsdt" copys DSDT */
- else if (strcmp(arg, "copy_dsdt") == 0) {
acpi_gbl_copy_dsdt_locally = 1;
- } else {
/* Core will printk when we return error. */
return -EINVAL;
- }
- return 0;
+} +early_param("acpi", parse_acpi);
+/* FIXME: Using pci= for an ACPI parameter is a travesty. */ +static int __init parse_pci(char *arg) +{
- if (arg && strcmp(arg, "noacpi") == 0)
acpi_disable_pci();
- return 0;
+} +early_param("pci", parse_pci);
+int __init acpi_mps_check(void) +{ +#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE) +/* mptable code is not built-in*/
- if (acpi_disabled || acpi_noirq) {
printk(KERN_WARNING "MPS support code is not built-in.\n"
"Using acpi=off or acpi=noirq or pci=noacpi "
"may have problem\n");
return 1;
- }
+#endif
- return 0;
+}
+#ifdef CONFIG_X86_IO_APIC +static int __init parse_acpi_skip_timer_override(char *arg) +{
- acpi_skip_timer_override = 1;
- return 0;
+} +early_param("acpi_skip_timer_override", parse_acpi_skip_timer_override);
+static int __init parse_acpi_use_timer_override(char *arg) +{
- acpi_use_timer_override = 1;
- return 0;
+} +early_param("acpi_use_timer_override", parse_acpi_use_timer_override); +#endif /* CONFIG_X86_IO_APIC */
+static int __init setup_acpi_sci(char *s) +{
- if (!s)
return -EINVAL;
- if (!strcmp(s, "edge"))
acpi_sci_flags = ACPI_MADT_TRIGGER_EDGE |
(acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK);
- else if (!strcmp(s, "level"))
acpi_sci_flags = ACPI_MADT_TRIGGER_LEVEL |
(acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK);
- else if (!strcmp(s, "high"))
acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_HIGH |
(acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK);
- else if (!strcmp(s, "low"))
acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_LOW |
(acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK);
- else
return -EINVAL;
- return 0;
+} +early_param("acpi_sci", setup_acpi_sci);
+int __acpi_acquire_global_lock(unsigned int *lock) +{
- unsigned int old, new, val;
- do {
old = *lock;
new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
val = cmpxchg(lock, old, new);
- } while (unlikely (val != old));
- return (new < 3) ? -1 : 0;
+}
+int __acpi_release_global_lock(unsigned int *lock) +{
- unsigned int old, new, val;
- do {
old = *lock;
new = old & ~0x3;
val = cmpxchg(lock, old, new);
- } while (unlikely (val != old));
- return old & 0x1;
+}
diff --git a/arch/arm64/kernel/acpi/cstate.c b/arch/arm64/kernel/acpi/cstate.c new file mode 100644 index 0000000..80d4b3d --- /dev/null +++ b/arch/arm64/kernel/acpi/cstate.c @@ -0,0 +1,210 @@ +/*
- Copyright (C) 2005 Intel Corporation
- Venkatesh Pallipadi venkatesh.pallipadi@intel.com
- Added _PDC for SMP C-states on Intel CPUs
- */
+/* BOZO: i think we just want to ignore C-states for now */
+#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/acpi.h> +#include <linux/cpu.h> +#include <linux/sched.h>
+#include <acpi/processor.h> +#include <asm/acpi.h> +#ifdef CONFIG_X86 +#include <asm/mwait.h> +#include <asm/special_insns.h> +#endif
+/*
- Initialize bm_flags based on the CPU cache properties
- On SMP it depends on cache configuration
- When cache is not shared among all CPUs, we flush cache
- before entering C3.
- When cache is shared among all CPUs, we use bm_check
- mechanism as in UP case
- This routine is called only after all the CPUs are online
- */
+void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
unsigned int cpu)
+{ +#ifdef CONFIG_X86
- struct cpuinfo_x86 *c = &cpu_data(cpu);
- flags->bm_check = 0;
- if (num_online_cpus() == 1)
flags->bm_check = 1;
- else if (c->x86_vendor == X86_VENDOR_INTEL) {
/*
* Today all MP CPUs that support C3 share cache.
* And caches should not be flushed by software while
* entering C3 type state.
*/
flags->bm_check = 1;
- }
- /*
* On all recent Intel platforms, ARB_DISABLE is a nop.
* So, set bm_control to zero to indicate that ARB_DISABLE
* is not required while entering C3 type state on
* P4, Core and beyond CPUs
*/
- if (c->x86_vendor == X86_VENDOR_INTEL &&
(c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f)))
flags->bm_control = 0;
+#endif +} +EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
+/* The code below handles cstate entry with monitor-mwait pair on Intel*/
+struct cstate_entry {
- struct {
unsigned int eax;
unsigned int ecx;
- } states[ACPI_PROCESSOR_MAX_POWER];
+}; +static struct cstate_entry __percpu *cpu_cstate_entry; /* per CPU ptr */
+static short mwait_supported[ACPI_PROCESSOR_MAX_POWER];
+#define NATIVE_CSTATE_BEYOND_HALT (2)
+static long acpi_processor_ffh_cstate_probe_cpu(void *_cx) +{
- struct acpi_processor_cx *cx = _cx;
- long retval;
- unsigned int eax, ebx, ecx, edx;
- unsigned int edx_part;
- unsigned int cstate_type; /* C-state type and not ACPI C-state type */
- unsigned int num_cstate_subtype;
- cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx);
- /* Check whether this particular cx_type (in CST) is supported or not */
- cstate_type = ((cx->address >> MWAIT_SUBSTATE_SIZE) &
MWAIT_CSTATE_MASK) + 1;
- edx_part = edx >> (cstate_type * MWAIT_SUBSTATE_SIZE);
- num_cstate_subtype = edx_part & MWAIT_SUBSTATE_MASK;
- retval = 0;
- if (num_cstate_subtype < (cx->address & MWAIT_SUBSTATE_MASK)) {
retval = -1;
goto out;
- }
- /* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */
- if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
!(ecx & CPUID5_ECX_INTERRUPT_BREAK)) {
retval = -1;
goto out;
- }
- if (!mwait_supported[cstate_type]) {
mwait_supported[cstate_type] = 1;
printk(KERN_DEBUG
"Monitor-Mwait will be used to enter C-%d "
"state\n", cx->type);
- }
- snprintf(cx->desc,
ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
cx->address);
+out:
- return retval;
+}
+int acpi_processor_ffh_cstate_probe(unsigned int cpu,
struct acpi_processor_cx *cx, struct acpi_power_register *reg)
+{
- struct cstate_entry *percpu_entry;
- struct cpuinfo_x86 *c = &cpu_data(cpu);
- long retval;
- if (!cpu_cstate_entry || c->cpuid_level < CPUID_MWAIT_LEAF)
return -1;
- if (reg->bit_offset != NATIVE_CSTATE_BEYOND_HALT)
return -1;
- percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
- percpu_entry->states[cx->index].eax = 0;
- percpu_entry->states[cx->index].ecx = 0;
- /* Make sure we are running on right CPU */
- retval = work_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx);
- if (retval == 0) {
/* Use the hint in CST */
percpu_entry->states[cx->index].eax = cx->address;
percpu_entry->states[cx->index].ecx = MWAIT_ECX_INTERRUPT_BREAK;
- }
- /*
* For _CST FFH on Intel, if GAS.access_size bit 1 is cleared,
* then we should skip checking BM_STS for this C-state.
* ref: "Intel Processor Vendor-Specific ACPI Interface Specification"
*/
- if ((c->x86_vendor == X86_VENDOR_INTEL) && !(reg->access_size & 0x2))
cx->bm_sts_skip = 1;
- return retval;
+} +EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe);
+/*
- This uses new MONITOR/MWAIT instructions on P4 processors with PNI,
- which can obviate IPI to trigger checking of need_resched.
- We execute MONITOR against need_resched and enter optimized wait state
- through MWAIT. Whenever someone changes need_resched, we would be woken
- up from MWAIT (without an IPI).
- New with Core Duo processors, MWAIT can take some hints based on CPU
- capability.
- */
+void mwait_idle_with_hints(unsigned long ax, unsigned long cx) +{
- if (!need_resched()) {
if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)¤t_thread_info()->flags);
__monitor((void *)¤t_thread_info()->flags, 0, 0);
smp_mb();
if (!need_resched())
__mwait(ax, cx);
- }
+}
+void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) +{
- unsigned int cpu = smp_processor_id();
- struct cstate_entry *percpu_entry;
- percpu_entry = per_cpu_ptr(cpu_cstate_entry, cpu);
- mwait_idle_with_hints(percpu_entry->states[cx->index].eax,
percpu_entry->states[cx->index].ecx);
+} +EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_enter);
+static int __init ffh_cstate_init(void) +{
- struct cpuinfo_x86 *c = &boot_cpu_data;
- if (c->x86_vendor != X86_VENDOR_INTEL)
return -1;
- cpu_cstate_entry = alloc_percpu(struct cstate_entry);
- return 0;
+}
+static void __exit ffh_cstate_exit(void) +{
- free_percpu(cpu_cstate_entry);
- cpu_cstate_entry = NULL;
+}
+arch_initcall(ffh_cstate_init); +__exitcall(ffh_cstate_exit); diff --git a/arch/arm64/kernel/acpi/sleep.c b/arch/arm64/kernel/acpi/sleep.c new file mode 100644 index 0000000..d9d4209 --- /dev/null +++ b/arch/arm64/kernel/acpi/sleep.c @@ -0,0 +1,126 @@ +/*
- sleep.c - x86-specific ACPI sleep support.
- Copyright (C) 2001-2003 Patrick Mochel
- Copyright (C) 2001-2003 Pavel Machek pavel@ucw.cz
- */
+int acpi_suspend_lowlevel(void) +{
/* BOZO: dummy routine; see below for actual */
return 0;
+}
+#ifdef CONFIG_X86 +/* BOZO: disable everything for now... */
+#include <linux/acpi.h> +#include <linux/bootmem.h> +#include <linux/memblock.h> +#include <linux/dmi.h> +#include <linux/cpumask.h> +#include <asm/segment.h> +#include <asm/desc.h> +#include <asm/pgtable.h> +#include <asm/cacheflush.h> +#include <asm/realmode.h>
+#include "../../realmode/rm/wakeup.h" +#include "sleep.h"
+unsigned long acpi_realmode_flags;
+#if defined(CONFIG_SMP) && defined(CONFIG_64BIT) +static char temp_stack[4096]; +#endif
+/**
- acpi_suspend_lowlevel - save kernel state
- Create an identity mapped page table and copy the wakeup routine to
- low memory.
- */
+int acpi_suspend_lowlevel(void) +{
- struct wakeup_header *header =
(struct wakeup_header *) __va(real_mode_header->wakeup_header);
- if (header->signature != WAKEUP_HEADER_SIGNATURE) {
printk(KERN_ERR "wakeup header does not match\n");
return -EINVAL;
- }
- header->video_mode = saved_video_mode;
- header->pmode_behavior = 0;
+#ifndef CONFIG_64BIT
- store_gdt((struct desc_ptr *)&header->pmode_gdt);
- if (!rdmsr_safe(MSR_EFER,
&header->pmode_efer_low,
&header->pmode_efer_high))
header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_EFER);
+#endif /* !CONFIG_64BIT */
- header->pmode_cr0 = read_cr0();
- if (__this_cpu_read(cpu_info.cpuid_level) >= 0) {
header->pmode_cr4 = read_cr4();
header->pmode_behavior |= (1 << WAKEUP_BEHAVIOR_RESTORE_CR4);
- }
- if (!rdmsr_safe(MSR_IA32_MISC_ENABLE,
&header->pmode_misc_en_low,
&header->pmode_misc_en_high))
header->pmode_behavior |=
(1 << WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE);
- header->realmode_flags = acpi_realmode_flags;
- header->real_magic = 0x12345678;
+#ifndef CONFIG_64BIT
- header->pmode_entry = (u32)&wakeup_pmode_return;
- header->pmode_cr3 = (u32)__pa(&initial_page_table);
- saved_magic = 0x12345678;
+#else /* CONFIG_64BIT */ +#ifdef CONFIG_SMP
- stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
- early_gdt_descr.address =
(unsigned long)get_cpu_gdt_table(smp_processor_id());
- initial_gs = per_cpu_offset(smp_processor_id());
+#endif
- initial_code = (unsigned long)wakeup_long64;
saved_magic = 0x123456789abcdef0L;
+#endif /* CONFIG_64BIT */
- do_suspend_lowlevel();
- return 0;
+}
+static int __init acpi_sleep_setup(char *str) +{
- while ((str != NULL) && (*str != '\0')) {
if (strncmp(str, "s3_bios", 7) == 0)
acpi_realmode_flags |= 1;
if (strncmp(str, "s3_mode", 7) == 0)
acpi_realmode_flags |= 2;
if (strncmp(str, "s3_beep", 7) == 0)
acpi_realmode_flags |= 4;
+#ifdef CONFIG_HIBERNATION
if (strncmp(str, "s4_nohwsig", 10) == 0)
acpi_no_s4_hw_signature();
+#endif
if (strncmp(str, "nonvs", 5) == 0)
acpi_nvs_nosave();
if (strncmp(str, "nonvs_s3", 8) == 0)
acpi_nvs_nosave_s3();
if (strncmp(str, "old_ordering", 12) == 0)
acpi_old_suspend_ordering();
str = strchr(str, ',');
if (str != NULL)
str += strspn(str, ", \t");
- }
- return 1;
+}
+__setup("acpi_sleep=", acpi_sleep_setup);
+#endif diff --git a/arch/arm64/kernel/acpi/sleep.h b/arch/arm64/kernel/acpi/sleep.h new file mode 100644 index 0000000..67f59f8c --- /dev/null +++ b/arch/arm64/kernel/acpi/sleep.h @@ -0,0 +1,17 @@ +/*
- Variables and functions used by the code in sleep.c
- */
+#include <asm/realmode.h>
+extern unsigned long saved_video_mode; +extern long saved_magic;
+extern int wakeup_pmode_return;
+extern u8 wake_sleep_flags;
+extern unsigned long acpi_copy_wakeup_routine(unsigned long); +extern void wakeup_long64(void);
+extern void do_suspend_lowlevel(void); diff --git a/arch/arm64/kernel/acpi/wakeup_32.S b/arch/arm64/kernel/acpi/wakeup_32.S new file mode 100644 index 0000000..13ab720 --- /dev/null +++ b/arch/arm64/kernel/acpi/wakeup_32.S @@ -0,0 +1,100 @@
- .section .text..page_aligned
+#include <linux/linkage.h> +#include <asm/segment.h> +#include <asm/page_types.h>
+# Copyright 2003, 2008 Pavel Machek pavel@suse.cz, distribute under GPLv2
- .code32
- ALIGN
+ENTRY(wakeup_pmode_return) +wakeup_pmode_return:
- movw $__KERNEL_DS, %ax
- movw %ax, %ss
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
- # reload the gdt, as we need the full 32 bit address
- lgdt saved_gdt
- lidt saved_idt
- lldt saved_ldt
- ljmp $(__KERNEL_CS), $1f
+1:
- movl %cr3, %eax
- movl %eax, %cr3
- wbinvd
- # and restore the stack ... but you need gdt for this to work
- movl saved_context_esp, %esp
- movl %cs:saved_magic, %eax
- cmpl $0x12345678, %eax
- jne bogus_magic
- # jump to place where we left off
- movl saved_eip, %eax
- jmp *%eax
+bogus_magic:
- jmp bogus_magic
+save_registers:
- sgdt saved_gdt
- sidt saved_idt
- sldt saved_ldt
- str saved_tss
- leal 4(%esp), %eax
- movl %eax, saved_context_esp
- movl %ebx, saved_context_ebx
- movl %ebp, saved_context_ebp
- movl %esi, saved_context_esi
- movl %edi, saved_context_edi
- pushfl
- popl saved_context_eflags
- movl $ret_point, saved_eip
- ret
+restore_registers:
- movl saved_context_ebp, %ebp
- movl saved_context_ebx, %ebx
- movl saved_context_esi, %esi
- movl saved_context_edi, %edi
- pushl saved_context_eflags
- popfl
- ret
+ENTRY(do_suspend_lowlevel)
- call save_processor_state
- call save_registers
- pushl $3
- call acpi_enter_sleep_state
- addl $4, %esp
+# In case of S3 failure, we'll emerge here. Jump +# to ret_point to recover
- jmp ret_point
- .p2align 4,,7
+ret_point:
- call restore_registers
- call restore_processor_state
- ret
+.data +ALIGN +ENTRY(saved_magic) .long 0 +ENTRY(saved_eip) .long 0
+# saved registers +saved_gdt: .long 0,0 +saved_idt: .long 0,0 +saved_ldt: .long 0 +saved_tss: .long 0
diff --git a/arch/arm64/kernel/acpi/wakeup_64.S b/arch/arm64/kernel/acpi/wakeup_64.S new file mode 100644 index 0000000..8ea5164 --- /dev/null +++ b/arch/arm64/kernel/acpi/wakeup_64.S @@ -0,0 +1,124 @@ +.text +#include <linux/linkage.h> +#include <asm/segment.h> +#include <asm/pgtable_types.h> +#include <asm/page_types.h> +#include <asm/msr.h> +#include <asm/asm-offsets.h>
+# Copyright 2003 Pavel Machek pavel@suse.cz, distribute under GPLv2
+.code64
- /*
* Hooray, we are in Long 64-bit mode (but still running in low memory)
*/
+ENTRY(wakeup_long64)
- movq saved_magic, %rax
- movq $0x123456789abcdef0, %rdx
- cmpq %rdx, %rax
- jne bogus_64_magic
- movw $__KERNEL_DS, %ax
- movw %ax, %ss
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %fs
- movw %ax, %gs
- movq saved_rsp, %rsp
- movq saved_rbx, %rbx
- movq saved_rdi, %rdi
- movq saved_rsi, %rsi
- movq saved_rbp, %rbp
- movq saved_rip, %rax
- jmp *%rax
+ENDPROC(wakeup_long64)
+bogus_64_magic:
- jmp bogus_64_magic
+ENTRY(do_suspend_lowlevel)
- subq $8, %rsp
- xorl %eax, %eax
- call save_processor_state
- movq $saved_context, %rax
- movq %rsp, pt_regs_sp(%rax)
- movq %rbp, pt_regs_bp(%rax)
- movq %rsi, pt_regs_si(%rax)
- movq %rdi, pt_regs_di(%rax)
- movq %rbx, pt_regs_bx(%rax)
- movq %rcx, pt_regs_cx(%rax)
- movq %rdx, pt_regs_dx(%rax)
- movq %r8, pt_regs_r8(%rax)
- movq %r9, pt_regs_r9(%rax)
- movq %r10, pt_regs_r10(%rax)
- movq %r11, pt_regs_r11(%rax)
- movq %r12, pt_regs_r12(%rax)
- movq %r13, pt_regs_r13(%rax)
- movq %r14, pt_regs_r14(%rax)
- movq %r15, pt_regs_r15(%rax)
- pushfq
- popq pt_regs_flags(%rax)
- movq $resume_point, saved_rip(%rip)
- movq %rsp, saved_rsp
- movq %rbp, saved_rbp
- movq %rbx, saved_rbx
- movq %rdi, saved_rdi
- movq %rsi, saved_rsi
- addq $8, %rsp
- movl $3, %edi
- xorl %eax, %eax
- call acpi_enter_sleep_state
- /* in case something went wrong, restore the machine status and go on */
- jmp resume_point
- .align 4
+resume_point:
- /* We don't restore %rax, it must be 0 anyway */
- movq $saved_context, %rax
- movq saved_context_cr4(%rax), %rbx
- movq %rbx, %cr4
- movq saved_context_cr3(%rax), %rbx
- movq %rbx, %cr3
- movq saved_context_cr2(%rax), %rbx
- movq %rbx, %cr2
- movq saved_context_cr0(%rax), %rbx
- movq %rbx, %cr0
- pushq pt_regs_flags(%rax)
- popfq
- movq pt_regs_sp(%rax), %rsp
- movq pt_regs_bp(%rax), %rbp
- movq pt_regs_si(%rax), %rsi
- movq pt_regs_di(%rax), %rdi
- movq pt_regs_bx(%rax), %rbx
- movq pt_regs_cx(%rax), %rcx
- movq pt_regs_dx(%rax), %rdx
- movq pt_regs_r8(%rax), %r8
- movq pt_regs_r9(%rax), %r9
- movq pt_regs_r10(%rax), %r10
- movq pt_regs_r11(%rax), %r11
- movq pt_regs_r12(%rax), %r12
- movq pt_regs_r13(%rax), %r13
- movq pt_regs_r14(%rax), %r14
- movq pt_regs_r15(%rax), %r15
- xorl %eax, %eax
- addq $8, %rsp
- jmp restore_processor_state
+ENDPROC(do_suspend_lowlevel)
+.data +ENTRY(saved_rbp) .quad 0 +ENTRY(saved_rsi) .quad 0 +ENTRY(saved_rdi) .quad 0 +ENTRY(saved_rbx) .quad 0
+ENTRY(saved_rip) .quad 0 +ENTRY(saved_rsp) .quad 0
+ENTRY(saved_magic) .quad 0 diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 6a9a532..250c840 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -41,6 +41,9 @@ #include <linux/memblock.h> #include <linux/of_fdt.h> #include <linux/of_platform.h> +#ifdef CONFIG_ACPI +#include <linux/acpi.h> +#endif
#include <asm/cputype.h> #include <asm/elf.h> @@ -54,6 +57,10 @@ #include <asm/memblock.h> #include <asm/psci.h>
+#ifdef CONFIG_ACPI +#include <asm/acpi.h> +#endif
unsigned int processor_id; EXPORT_SYMBOL(processor_id);
@@ -166,6 +173,10 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
/* Retrieve various information from the /chosen node */ of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); +#ifdef CONFIG_ACPI
- /* Retrieve ACPI pointers from /chosen node */
of_scan_flat_dt(early_init_dt_scan_acpi, &acpi_arm_rsdp_info);
+#endif /* Initialize {size,address}-cells info */ of_scan_flat_dt(early_init_dt_scan_root, NULL); /* Setup memory, calling early_init_dt_add_memory_arch */ @@ -264,6 +275,14 @@ void __init setup_arch(char **cmdline_p) paging_init(); request_standard_resources();
+#ifdef CONFIG_ACPI
- /*
* Parse the ACPI tables for possible boot-time configuration
*/
- acpi_boot_table_init();
- early_acpi_boot_init();
+#endif
unflatten_device_tree();
psci_init();
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 4bf68c8..ef39891 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -5,10 +5,9 @@ menuconfig ACPI bool "ACPI (Advanced Configuration and Power Interface) Support" depends on !IA64_HP_SIM
- depends on IA64 || X86
- depends on PCI
- depends on ((IA64 || X86) && PCI) || (ARM || ARM64) select PNP
- default y
- default y if !(ARM || ARM64) help Advanced Configuration and Power Interface (ACPI) support for Linux requires an ACPI-compliant platform (hardware/firmware),
@@ -46,6 +45,7 @@ config ACPI_SLEEP config ACPI_PROCFS bool "Deprecated /proc/acpi files" depends on PROC_FS
help For backwards compatibility, this option allows deprecated /proc/acpi/ files to exist, even whendepends on IA64 || X86
@@ -59,6 +59,7 @@ config ACPI_PROCFS config ACPI_PROCFS_POWER bool "Deprecated power /proc/acpi directories" depends on PROC_FS
help For backwards compatibility, this option allows deprecated power /proc/acpi/ directories to exist, even whendepends on IA64 || X86
@@ -94,6 +95,7 @@ config ACPI_EC_DEBUGFS config ACPI_PROC_EVENT bool "Deprecated /proc/acpi/event support" depends on PROC_FS
default y help A user-space daemon, acpid, typically reads /proc/acpi/eventdepends on IA64 || X86
@@ -111,9 +113,9 @@ config ACPI_PROC_EVENT
config ACPI_AC tristate "AC Adapter"
- depends on X86
- depends on X86 || (ARM || ARM64) select POWER_SUPPLY
- default y
- default y if !(ARM || ARM64) help This driver supports the AC Adapter object, which indicates whether a system is on AC or not. If you have a system that can
@@ -124,9 +126,9 @@ config ACPI_AC
config ACPI_BATTERY tristate "Battery"
- depends on X86
- depends on X86 || (ARM || ARM64) select POWER_SUPPLY
- default y
- default y if !(ARM || ARM64) help This driver adds support for battery information through /proc/acpi/battery. If you have a mobile system with a battery,
@@ -150,7 +152,8 @@ config ACPI_BUTTON
config ACPI_VIDEO tristate "Video"
- depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL
- depends on (X86 || (ARM || ARM64)) && \
depends on INPUT select THERMAL helpBACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL
@@ -220,7 +223,7 @@ config ACPI_HOTPLUG_CPU config ACPI_PROCESSOR_AGGREGATOR tristate "Processor Aggregator" depends on ACPI_PROCESSOR
- depends on X86
- depends on X86 || (ARM || ARM64) help ACPI 4.0 defines processor Aggregator, which enables OS to perform specific processor configuration and control that applies to all
@@ -245,7 +248,7 @@ config ACPI_THERMAL config ACPI_NUMA bool "NUMA support" depends on NUMA
- depends on (X86 || IA64)
- depends on (X86 || IA64 || ARM64) default y if IA64_GENERIC || IA64_SGI_SN2
config ACPI_CUSTOM_DSDT_FILE @@ -309,6 +312,7 @@ config ACPI_DEBUG_FUNC_TRACE config ACPI_PCI_SLOT bool "PCI slot detection driver" depends on SYSFS
- depends on PCI default n help This driver creates entries in /sys/bus/pci/slots/ for all PCI
@@ -363,7 +367,7 @@ config ACPI_HOTPLUG_MEMORY
config ACPI_SBS tristate "Smart Battery System"
- depends on X86
- depends on X86 || (ARM || ARM64) select POWER_SUPPLY help This driver supports the Smart Battery System, another
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 474fcfe..3dc16fb 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -9,7 +9,7 @@ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT # ACPI Boot-Time Table Parsing # obj-y += tables.o -obj-$(CONFIG_X86) += blacklist.o +obj-$(CONFIG_ACPI) += blacklist.o
# # ACPI Core Subsystem (Interpreter) @@ -37,7 +37,7 @@ acpi-y += resource.o acpi-y += processor_core.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o -acpi-y += pci_root.o pci_link.o pci_irq.o +acpi-$(CONFIG_PCI) += pci_root.o pci_link.o pci_irq.o acpi-y += csrt.o acpi-y += acpi_platform.o acpi-y += power.o diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 586e7e9..351edf0 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -242,6 +242,67 @@ static int __init setup_acpi_rsdp(char *arg) early_param("acpi_rsdp", setup_acpi_rsdp); #endif
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +#include <asm/byteorder.h> +#include <asm/acpi.h> +#include <acpi/actbl.h>
+void acpi_find_arm_root_pointer(acpi_physical_address *pa) +{
/* BOZO: temporarily clunky.
* What we do is, while using u-boot still, is use the values
* that have already been retrieved from the FDT node
* (/chosen/linux,acpi-start and /chosen/linux,acpi-len) which
* contain the address of the first byte of the RSDP after it
* has been loaded into RAM during u-boot (e.g., using something
* like fatload mmc 0:2 42008000 my.blob), and the size of the
* data in the complete ACPI blob. We only do this since we have
* to collaborate with FDT so we have to load FDT and the ACPI
* tables in but only have one address we can use via bootm.
* With UEFI, we should just be able to use the efi_enabled
* branch below in acpi_os_get_root_pointer().
*/
void *address;
struct acpi_table_rsdp *rp;
if (!acpi_arm_rsdp_info.phys_address && !acpi_arm_rsdp_info.size) {
printk(KERN_ERR "(E) ACPI: failed to find rsdp info\n");
*pa = (acpi_physical_address)NULL;
return;
}
address = phys_to_virt(acpi_arm_rsdp_info.phys_address);
- address += ACPI_BLOB_HEADER_SIZE;
*pa = (acpi_physical_address)address;
rp = (struct acpi_table_rsdp *)address;
printk(KERN_DEBUG "(I) ACPI rsdp rp: 0x%08lx\n", (long unsigned int)rp);
if (rp) {
printk(KERN_DEBUG "(I) ACPI rsdp content:\n");
printk(KERN_DEBUG "(I) signature: %.8s\n", rp->signature);
printk(KERN_DEBUG "(I) checksum: 0x%02x\n", rp->checksum);
printk(KERN_DEBUG "(I) oem_id: %.6s\n", rp->oem_id);
printk(KERN_DEBUG "(I) revision: %d\n", rp->revision);
printk(KERN_DEBUG "(I) rsdt: 0x%08lX\n",
(long unsigned int)rp->rsdt_physical_address);
printk(KERN_DEBUG "(I) length: %d\n", rp->length);
printk(KERN_DEBUG "(I) xsdt: 0x%016llX\n",
(u64)rp->xsdt_physical_address);
printk(KERN_DEBUG "(I) x_checksum: 0x%02x\n",
rp->extended_checksum);
*pa = (acpi_physical_address)(virt_to_phys(rp));
}
else {
printk(KERN_ERR "(E) ACPI missing rsdp info\n");
*pa = (acpi_physical_address)NULL;
}
return;
+} +#endif
acpi_physical_address __init acpi_os_get_root_pointer(void) { #ifdef CONFIG_KEXEC @@ -262,7 +323,11 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) } else { acpi_physical_address pa = 0;
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
acpi_find_arm_root_pointer(&pa);
+#else acpi_find_root_pointer(&pa); +#endif return pa; } } @@ -1030,9 +1095,16 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, return AE_ERROR; }
+#ifdef CONFIG_X86
/* BOZO: probably should not call this function at all
result = raw_pci_read(pci_id->segment, pci_id->bus, PCI_DEVFN(pci_id->device, pci_id->function), reg, size, &value32);* if there is no PCI... */
+#else
result = 0;
value32 = 0;
+#endif *value = value32;
return (result ? AE_ERROR : AE_OK); @@ -1058,9 +1130,14 @@ acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, return AE_ERROR; }
+#ifdef CONFIG_X86
result = raw_pci_write(pci_id->segment, pci_id->bus, PCI_DEVFN(pci_id->device, pci_id->function), reg, size, value);/* BOZO: how do we handle not having PCI? */
+#else
result = 0;
+#endif
return (result ? AE_ERROR : AE_OK); } diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 164d495..1d9033d 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -90,6 +90,22 @@ static int map_lsapic_id(struct acpi_subtable_header *entry, return 1; }
+static int map_gic_id(struct acpi_subtable_header *entry,
u32 acpi_id, int *apic_id)
+{
- struct acpi_madt_generic_interrupt *gic =
(struct acpi_madt_generic_interrupt *)entry;
- if (!(gic->flags & ACPI_MADT_ENABLED))
return 0;
- if (gic->uid != acpi_id)
return 0;
- *apic_id = gic->gic_id;
- return 1;
+}
static int map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; @@ -125,7 +141,10 @@ static int map_madt_entry(int type, u32 acpi_id) } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { if (map_lsapic_id(header, type, acpi_id, &apic_id)) break;
}
} else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
if (map_gic_id(header, acpi_id, &apic_id))
break;
} return apic_id;} entry += header->length;
@@ -155,6 +174,8 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) map_lapic_id(header, acpi_id, &apic_id); } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { map_lsapic_id(header, type, acpi_id, &apic_id);
- } else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) {
}map_gic_id(header, acpi_id, &apic_id);
exit: @@ -199,6 +220,16 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) return apic_id; }
+#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
- return apic_id;
- /*
* BOZO: need to abstract this out to have it make sense --
* it's not that ARM has no equivalent, it's that apic_id is
* arch-specific
*/
+#else
#ifdef CONFIG_SMP for_each_possible_cpu(i) { if (cpu_physical_id(i) == apic_id) @@ -209,6 +240,9 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) if (apic_id == 0) return apic_id; #endif
+#endif
- return -1;
} EXPORT_SYMBOL_GPL(acpi_get_cpuid); diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index a6c77e8b..410d0be 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c @@ -6,9 +6,7 @@ void acpi_reboot(void) { struct acpi_generic_address *rr;
struct pci_bus *bus0; u8 reset_value;
unsigned int devfn;
if (acpi_disabled) return;
@@ -31,7 +29,15 @@ void acpi_reboot(void) /* The reset register can only exist in I/O, Memory or PCI config space * on a device on bus 0. */ switch (rr->space_id) { +/*
- There are some rare cases in the ARM world with PCI is not one
- of the buses available to us, even though we use ACPI.
- */
+#ifdef CONFIG_PCI case ACPI_ADR_SPACE_PCI_CONFIG:
struct pci_bus *bus0;
unsigned int devfn;
/* The reset register can only live on bus 0. */ bus0 = pci_find_bus(0, 0); if (!bus0)
@@ -44,6 +50,7 @@ void acpi_reboot(void) pci_bus_write_config_byte(bus0, devfn, (rr->address & 0xffff), reset_value); break; +#endif
case ACPI_ADR_SPACE_SYSTEM_MEMORY: case ACPI_ADR_SPACE_SYSTEM_IO: diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5e7e991..97b9227 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1785,8 +1785,10 @@ int __init acpi_scan_init(void) printk(KERN_ERR PREFIX "Could not register bus type\n"); }
+#if defined(CONFIG_PCI) acpi_pci_root_init(); acpi_pci_link_init(); +#endif acpi_platform_init(); acpi_csrt_init(); acpi_container_init(); @@ -1812,7 +1814,9 @@ int __init acpi_scan_init(void)
acpi_update_all_gpes();
+#if defined(CONFIG_PCI) acpi_pci_root_hp_init(); +#endif
out: mutex_unlock(&acpi_scan_lock); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 808be06..61a032c 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -25,6 +25,10 @@
#include <asm/page.h>
+#ifdef CONFIG_ACPI +#include <asm/io.h> +#endif
char *of_fdt_get_string(struct boot_param_header *blob, u32 offset) { return ((char *)blob) + @@ -696,6 +700,56 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, return 1; }
+#if (defined(CONFIG_ARM64) || defined (CONFIG_ARM)) && defined(CONFIG_ACPI) +#include <linux/memblock.h> +#include <linux/acpi.h> +#include <asm/acpi.h> +#include <acpi/actbl.h>
+int __init early_init_dt_scan_acpi(unsigned long node, const char *uname,
int depth, void *data)
+{
- unsigned long l;
unsigned int *p;
struct acpi_arm_root *pinfo;
unsigned char *sig;
- pr_debug("search "chosen" for acpi info, depth: %d, uname: %s\n",
depth, uname);
- if (depth != 1 || !data ||
(strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
return 0;
- /* Retrieve acpi,address line */
pinfo = (struct acpi_arm_root *)data;
- p = of_get_flat_dt_prop(node, "linux,acpi-start", &l);
- if (p != NULL && l > 0)
pinfo->phys_address = be32_to_cpu(*p);
- /* Retrieve acpi,size line */
- p = of_get_flat_dt_prop(node, "linux,acpi-len", &l);
- if (p != NULL && l > 0)
pinfo->size = be32_to_cpu(*p);
- printk("acpi: start info is 0x%016llX, %lu bytes\n",
pinfo->phys_address, pinfo->size);
- memblock_reserve(pinfo->phys_address, pinfo->size);
sig = phys_to_virt(pinfo->phys_address);
printk("acpi: sig is \"%c%c%c%c\"\n",
sig[0], sig[1], sig[2], sig[3]);
printk("acpi: info is %02x %02x %02x %02x\n",
sig[4], sig[5], sig[6], sig[7]);
printk("acpi: first table is \"%c%c%c%c\"\n",
sig[8], sig[9], sig[10], sig[11]);
- return 1;
+} +#endif
/**
- unflatten_device_tree - create tree of device_nodes from flat blob
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index b8f4ea7..464f8c9 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -113,8 +113,10 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r) { +#ifdef CONFIG_PCI if (!(r->flags & IORESOURCE_DISABLED)) pcibios_penalize_isa_irq(r->start, 1); +#endif
pnp_add_resource(dev, r); } diff --git a/include/acpi/pdc_arm64.h b/include/acpi/pdc_arm64.h new file mode 100644 index 0000000..ac8f197 --- /dev/null +++ b/include/acpi/pdc_arm64.h @@ -0,0 +1,39 @@
+/* _PDC bit definition for ARMv7 processors */
+#ifndef __PDC_ARM_H__ +#define __PDC_ARM_H__
+/* BOZO: is this even necessary? */
+/* _PDC bit definition for ARM processors */
+#define ACPI_PDC_P_FFH (0x0001) +#define ACPI_PDC_C_C1_HALT (0x0002) +#define ACPI_PDC_T_FFH (0x0004) +#define ACPI_PDC_SMP_C1PT (0x0008) +#define ACPI_PDC_SMP_C2C3 (0x0010) +#define ACPI_PDC_SMP_P_SWCOORD (0x0020) +#define ACPI_PDC_SMP_C_SWCOORD (0x0040) +#define ACPI_PDC_SMP_T_SWCOORD (0x0080) +#define ACPI_PDC_C_C1_FFH (0x0100) +#define ACPI_PDC_C_C2C3_FFH (0x0200) +#define ACPI_PDC_SMP_P_HWCOORD (0x0800)
+#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI_PDC_P_FFH)
+#define ACPI_PDC_EST_CAPABILITY_SWSMP (ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI_PDC_SMP_P_SWCOORD | \
ACPI_PDC_SMP_P_HWCOORD | \
ACPI_PDC_P_FFH)
+#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \
ACPI_PDC_SMP_C1PT | \
ACPI_PDC_C_C1_HALT | \
ACPI_PDC_C_C1_FFH | \
ACPI_PDC_C_C2C3_FFH)
+#endif /* __PDC_ARM_H__ */ diff --git a/include/linux/acpi.h b/include/linux/acpi.h index bcbdd74..893670e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -49,6 +49,7 @@ enum acpi_irq_model_id { ACPI_IRQ_MODEL_IOAPIC, ACPI_IRQ_MODEL_IOSAPIC, ACPI_IRQ_MODEL_PLATFORM,
- ACPI_IRQ_MODEL_GIC, ACPI_IRQ_MODEL_COUNT
};
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index ed136ad..98c1029 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -93,6 +93,10 @@ extern unsigned long of_get_flat_dt_root(void);
extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data); +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) +extern int early_init_dt_scan_acpi(unsigned long node, const char *uname,
int depth, void *data);
+#endif extern void early_init_dt_check_for_initrd(unsigned long node); extern int early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data); -- 1.7.10.4
Linaro-acpi mailing list Linaro-acpi@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-acpi