aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2011-02-22 15:07:40 -0500
committerThomas Gleixner <tglx@linutronix.de>2011-02-23 16:27:53 -0500
commit3879a6f32948330782889cebc4d74c4f2316c676 (patch)
treea3e8b6904eea8593e72ff9b52e2ce4c5697f60da /arch/x86
parent19c4f5f7f7e9c5db89a91627af2a426cfb5568de (diff)
x86: dtb: Add early parsing of IO_APIC
APIC and IO_APIC have to be added to the system early because native_init_IRQ() requires it. In order to obtain the address of the ioapic the device tree has to be unflattened so of_address_to_resource() works. The device tree is relocated to ensure it is always covered by the kernel mapping. That way the boot loader does not have to make any assumptions about kernel's memory layout. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Grant Likely <grant.likely@secretlab.ca> Cc: sodaville@linutronix.de Cc: devicetree-discuss@lists.ozlabs.org Cc: Dirk Brandewie <dirk.brandewie@gmail.com> LKML-Reference: <1298405266-1624-6-git-send-email-bigeasy@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/prom.h7
-rw-r--r--arch/x86/kernel/devicetree.c110
-rw-r--r--arch/x86/kernel/irqinit.c3
3 files changed, 117 insertions, 3 deletions
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index 83833ac33dd1..35ec32b47500 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -23,10 +23,17 @@
23#include <asm/irq_controller.h> 23#include <asm/irq_controller.h>
24 24
25#ifdef CONFIG_OF 25#ifdef CONFIG_OF
26extern int of_ioapic;
27extern u64 initial_dtb;
26extern void add_dtb(u64 data); 28extern void add_dtb(u64 data);
29void x86_dtb_find_config(void);
30void x86_dtb_get_config(unsigned int unused);
27void add_interrupt_host(struct irq_domain *ih); 31void add_interrupt_host(struct irq_domain *ih);
28#else 32#else
29static inline void add_dtb(u64 data) { } 33static inline void add_dtb(u64 data) { }
34#define x86_dtb_find_config x86_init_noop
35#define x86_dtb_get_config x86_init_uint_noop
36#define of_ioapic 0
30#endif 37#endif
31 38
32extern char cmd_line[COMMAND_LINE_SIZE]; 39extern char cmd_line[COMMAND_LINE_SIZE];
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index ef98e4edada1..2739d5613a38 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -7,15 +7,20 @@
7#include <linux/list.h> 7#include <linux/list.h>
8#include <linux/of.h> 8#include <linux/of.h>
9#include <linux/of_fdt.h> 9#include <linux/of_fdt.h>
10#include <linux/of_address.h>
10#include <linux/of_platform.h> 11#include <linux/of_platform.h>
11#include <linux/slab.h> 12#include <linux/slab.h>
12 13
13#include <asm/irq_controller.h> 14#include <asm/irq_controller.h>
15#include <asm/apic.h>
14 16
17__initdata u64 initial_dtb;
15char __initdata cmd_line[COMMAND_LINE_SIZE]; 18char __initdata cmd_line[COMMAND_LINE_SIZE];
16static LIST_HEAD(irq_domains); 19static LIST_HEAD(irq_domains);
17static DEFINE_RAW_SPINLOCK(big_irq_lock); 20static DEFINE_RAW_SPINLOCK(big_irq_lock);
18 21
22int __initdata of_ioapic;
23
19void add_interrupt_host(struct irq_domain *ih) 24void add_interrupt_host(struct irq_domain *ih)
20{ 25{
21 unsigned long flags; 26 unsigned long flags;
@@ -90,6 +95,107 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
90 95
91void __init add_dtb(u64 data) 96void __init add_dtb(u64 data)
92{ 97{
93 initial_boot_params = phys_to_virt((u64) (u32) data + 98 initial_dtb = data + offsetof(struct setup_data, data);
94 offsetof(struct setup_data, data)); 99}
100
101static void __init dtb_lapic_setup(void)
102{
103#ifdef CONFIG_X86_LOCAL_APIC
104 if (apic_force_enable())
105 return;
106
107 smp_found_config = 1;
108 pic_mode = 1;
109 /* Required for ioapic registration */
110 set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
111 if (boot_cpu_physical_apicid == -1U)
112 boot_cpu_physical_apicid = read_apic_id();
113
114 generic_processor_info(boot_cpu_physical_apicid,
115 GET_APIC_VERSION(apic_read(APIC_LVR)));
116#endif
117}
118
119#ifdef CONFIG_X86_IO_APIC
120static unsigned int ioapic_id;
121
122static void __init dtb_add_ioapic(struct device_node *dn)
123{
124 struct resource r;
125 int ret;
126
127 ret = of_address_to_resource(dn, 0, &r);
128 if (ret) {
129 printk(KERN_ERR "Can't obtain address from node %s.\n",
130 dn->full_name);
131 return;
132 }
133 mp_register_ioapic(++ioapic_id, r.start, gsi_top);
134}
135
136static void __init dtb_ioapic_setup(void)
137{
138 struct device_node *dn;
139
140 if (!smp_found_config)
141 return;
142
143 for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
144 dtb_add_ioapic(dn);
145
146 if (nr_ioapics) {
147 of_ioapic = 1;
148 return;
149 }
150 printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
151 smp_found_config = 0;
152}
153#else
154static void __init dtb_ioapic_setup(void) {}
155#endif
156
157static void __init dtb_apic_setup(void)
158{
159 dtb_lapic_setup();
160 dtb_ioapic_setup();
161}
162
163void __init x86_dtb_find_config(void)
164{
165 if (initial_dtb)
166 smp_found_config = 1;
167 else
168 printk(KERN_ERR "Missing device tree!.\n");
169}
170
171void __init x86_dtb_get_config(unsigned int unused)
172{
173 u32 size, map_len;
174 void *new_dtb;
175
176 if (!initial_dtb)
177 return;
178
179 map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
180 (u64)sizeof(struct boot_param_header));
181
182 initial_boot_params = early_memremap(initial_dtb, map_len);
183 size = be32_to_cpu(initial_boot_params->totalsize);
184 if (map_len < size) {
185 early_iounmap(initial_boot_params, map_len);
186 initial_boot_params = early_memremap(initial_dtb, size);
187 map_len = size;
188 }
189
190 new_dtb = alloc_bootmem(size);
191 memcpy(new_dtb, initial_boot_params, size);
192 early_iounmap(initial_boot_params, map_len);
193
194 initial_boot_params = new_dtb;
195
196 /* root level address cells */
197 of_scan_flat_dt(early_init_dt_scan_root, NULL);
198
199 unflatten_device_tree();
200 dtb_apic_setup();
95} 201}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index c752e973958d..4cadf8688dbd 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -25,6 +25,7 @@
25#include <asm/setup.h> 25#include <asm/setup.h>
26#include <asm/i8259.h> 26#include <asm/i8259.h>
27#include <asm/traps.h> 27#include <asm/traps.h>
28#include <asm/prom.h>
28 29
29/* 30/*
30 * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts: 31 * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
@@ -243,7 +244,7 @@ void __init native_init_IRQ(void)
243 set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]); 244 set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
244 } 245 }
245 246
246 if (!acpi_ioapic) 247 if (!acpi_ioapic && !of_ioapic)
247 setup_irq(2, &irq2); 248 setup_irq(2, &irq2);
248 249
249#ifdef CONFIG_X86_32 250#ifdef CONFIG_X86_32