diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/prom.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/devicetree.c | 110 | ||||
-rw-r--r-- | arch/x86/kernel/irqinit.c | 3 |
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 |
26 | extern int of_ioapic; | ||
27 | extern u64 initial_dtb; | ||
26 | extern void add_dtb(u64 data); | 28 | extern void add_dtb(u64 data); |
29 | void x86_dtb_find_config(void); | ||
30 | void x86_dtb_get_config(unsigned int unused); | ||
27 | void add_interrupt_host(struct irq_domain *ih); | 31 | void add_interrupt_host(struct irq_domain *ih); |
28 | #else | 32 | #else |
29 | static inline void add_dtb(u64 data) { } | 33 | static 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 | ||
32 | extern char cmd_line[COMMAND_LINE_SIZE]; | 39 | extern 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; | ||
15 | char __initdata cmd_line[COMMAND_LINE_SIZE]; | 18 | char __initdata cmd_line[COMMAND_LINE_SIZE]; |
16 | static LIST_HEAD(irq_domains); | 19 | static LIST_HEAD(irq_domains); |
17 | static DEFINE_RAW_SPINLOCK(big_irq_lock); | 20 | static DEFINE_RAW_SPINLOCK(big_irq_lock); |
18 | 21 | ||
22 | int __initdata of_ioapic; | ||
23 | |||
19 | void add_interrupt_host(struct irq_domain *ih) | 24 | void 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 | ||
91 | void __init add_dtb(u64 data) | 96 | void __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 | |||
101 | static 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 | ||
120 | static unsigned int ioapic_id; | ||
121 | |||
122 | static 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 | |||
136 | static 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 | ||
154 | static void __init dtb_ioapic_setup(void) {} | ||
155 | #endif | ||
156 | |||
157 | static void __init dtb_apic_setup(void) | ||
158 | { | ||
159 | dtb_lapic_setup(); | ||
160 | dtb_ioapic_setup(); | ||
161 | } | ||
162 | |||
163 | void __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 | |||
171 | void __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 |