aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-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