aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2011-02-22 15:07:44 -0500
committerThomas Gleixner <tglx@linutronix.de>2011-02-23 16:27:54 -0500
commitbcc7c1244fcfd852b9f4590935491057e1cab9dd (patch)
tree4b68fc51466e8b42f343d6f26db0f1200d595c50 /arch/x86/kernel
parent9079b35364e75ce6b968a179f861d2f819f33e61 (diff)
x86: ioapic: Add OF bindings for IO_APIC
ioapic_xlate provides a translation from the information in device tree to ioapic related informations. This includes - obtaining hw irq which is the vector number "=> pin number + gsi" - obtaining type (level/edge/..) - programming this information into ioapic ioapic_add_ofnode adds an irq_domain based on informations from the device tree. This information (irq_domain) is required in order to map a device to its proper interrupt controller. [ tglx: Adapted to the io_apic changes, which let us move that whole code to devicetree.c ] Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Cc: sodaville@linutronix.de Cc: devicetree-discuss@lists.ozlabs.org LKML-Reference: <1298405266-1624-10-git-send-email-bigeasy@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/devicetree.c104
-rw-r--r--arch/x86/kernel/irqinit.c6
2 files changed, 110 insertions, 0 deletions
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 0bc83bfa4ead..2d65897a39d0 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -320,3 +320,107 @@ void __init x86_dtb_get_config(unsigned int unused)
320 dtb_setup_hpet(); 320 dtb_setup_hpet();
321 dtb_apic_setup(); 321 dtb_apic_setup();
322} 322}
323
324#ifdef CONFIG_X86_IO_APIC
325
326struct of_ioapic_type {
327 u32 out_type;
328 u32 trigger;
329 u32 polarity;
330};
331
332static struct of_ioapic_type of_ioapic_type[] =
333{
334 {
335 .out_type = IRQ_TYPE_EDGE_RISING,
336 .trigger = IOAPIC_EDGE,
337 .polarity = 1,
338 },
339 {
340 .out_type = IRQ_TYPE_LEVEL_LOW,
341 .trigger = IOAPIC_LEVEL,
342 .polarity = 0,
343 },
344 {
345 .out_type = IRQ_TYPE_LEVEL_HIGH,
346 .trigger = IOAPIC_LEVEL,
347 .polarity = 1,
348 },
349 {
350 .out_type = IRQ_TYPE_EDGE_FALLING,
351 .trigger = IOAPIC_EDGE,
352 .polarity = 0,
353 },
354};
355
356static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
357 u32 *out_hwirq, u32 *out_type)
358{
359 struct io_apic_irq_attr attr;
360 struct of_ioapic_type *it;
361 u32 line, idx, type;
362
363 if (intsize < 2)
364 return -EINVAL;
365
366 line = *intspec;
367 idx = (u32) id->priv;
368 *out_hwirq = line + mp_gsi_routing[idx].gsi_base;
369
370 intspec++;
371 type = *intspec;
372
373 if (type >= ARRAY_SIZE(of_ioapic_type))
374 return -EINVAL;
375
376 it = of_ioapic_type + type;
377 *out_type = it->out_type;
378
379 set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
380
381 return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
382}
383
384static void __init ioapic_add_ofnode(struct device_node *np)
385{
386 struct resource r;
387 int i, ret;
388
389 ret = of_address_to_resource(np, 0, &r);
390 if (ret) {
391 printk(KERN_ERR "Failed to obtain address for %s\n",
392 np->full_name);
393 return;
394 }
395
396 for (i = 0; i < nr_ioapics; i++) {
397 if (r.start == mp_ioapics[i].apicaddr) {
398 struct irq_domain *id;
399
400 id = kzalloc(sizeof(*id), GFP_KERNEL);
401 BUG_ON(!id);
402 id->controller = np;
403 id->xlate = ioapic_xlate;
404 id->priv = (void *)i;
405 add_interrupt_host(id);
406 return;
407 }
408 }
409 printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
410}
411
412void __init x86_add_irq_domains(void)
413{
414 struct device_node *dp;
415
416 if (!initial_boot_params)
417 return;
418
419 for_each_node_with_property(dp, "interrupt-controller") {
420 if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
421 ioapic_add_ofnode(dp);
422 }
423}
424#else
425void __init x86_add_irq_domains(void) { }
426#endif
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 4cadf8688dbd..9f76f89f43a4 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -119,6 +119,12 @@ void __init init_IRQ(void)
119 int i; 119 int i;
120 120
121 /* 121 /*
122 * We probably need a better place for this, but it works for
123 * now ...
124 */
125 x86_add_irq_domains();
126
127 /*
122 * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15. 128 * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
123 * If these IRQ's are handled by legacy interrupt-controllers like PIC, 129 * If these IRQ's are handled by legacy interrupt-controllers like PIC,
124 * then this configuration will likely be static after the boot. If 130 * then this configuration will likely be static after the boot. If