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>
This commit is contained in:
Родитель
9079b35364
Коммит
bcc7c1244f
|
@ -27,6 +27,7 @@
|
|||
extern int of_ioapic;
|
||||
extern u64 initial_dtb;
|
||||
extern void add_dtb(u64 data);
|
||||
extern void x86_add_irq_domains(void);
|
||||
void x86_dtb_find_config(void);
|
||||
void x86_dtb_get_config(unsigned int unused);
|
||||
void add_interrupt_host(struct irq_domain *ih);
|
||||
|
@ -44,6 +45,7 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
|
|||
|
||||
#else
|
||||
static inline void add_dtb(u64 data) { }
|
||||
static inline void x86_add_irq_domains(void) { }
|
||||
static inline void x86_of_pci_init(void) { }
|
||||
#define x86_dtb_find_config x86_init_noop
|
||||
#define x86_dtb_get_config x86_init_uint_noop
|
||||
|
|
|
@ -320,3 +320,107 @@ void __init x86_dtb_get_config(unsigned int unused)
|
|||
dtb_setup_hpet();
|
||||
dtb_apic_setup();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
|
||||
struct of_ioapic_type {
|
||||
u32 out_type;
|
||||
u32 trigger;
|
||||
u32 polarity;
|
||||
};
|
||||
|
||||
static struct of_ioapic_type of_ioapic_type[] =
|
||||
{
|
||||
{
|
||||
.out_type = IRQ_TYPE_EDGE_RISING,
|
||||
.trigger = IOAPIC_EDGE,
|
||||
.polarity = 1,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_LEVEL_LOW,
|
||||
.trigger = IOAPIC_LEVEL,
|
||||
.polarity = 0,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_LEVEL_HIGH,
|
||||
.trigger = IOAPIC_LEVEL,
|
||||
.polarity = 1,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_EDGE_FALLING,
|
||||
.trigger = IOAPIC_EDGE,
|
||||
.polarity = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
|
||||
u32 *out_hwirq, u32 *out_type)
|
||||
{
|
||||
struct io_apic_irq_attr attr;
|
||||
struct of_ioapic_type *it;
|
||||
u32 line, idx, type;
|
||||
|
||||
if (intsize < 2)
|
||||
return -EINVAL;
|
||||
|
||||
line = *intspec;
|
||||
idx = (u32) id->priv;
|
||||
*out_hwirq = line + mp_gsi_routing[idx].gsi_base;
|
||||
|
||||
intspec++;
|
||||
type = *intspec;
|
||||
|
||||
if (type >= ARRAY_SIZE(of_ioapic_type))
|
||||
return -EINVAL;
|
||||
|
||||
it = of_ioapic_type + type;
|
||||
*out_type = it->out_type;
|
||||
|
||||
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
|
||||
|
||||
return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
|
||||
}
|
||||
|
||||
static void __init ioapic_add_ofnode(struct device_node *np)
|
||||
{
|
||||
struct resource r;
|
||||
int i, ret;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &r);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "Failed to obtain address for %s\n",
|
||||
np->full_name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_ioapics; i++) {
|
||||
if (r.start == mp_ioapics[i].apicaddr) {
|
||||
struct irq_domain *id;
|
||||
|
||||
id = kzalloc(sizeof(*id), GFP_KERNEL);
|
||||
BUG_ON(!id);
|
||||
id->controller = np;
|
||||
id->xlate = ioapic_xlate;
|
||||
id->priv = (void *)i;
|
||||
add_interrupt_host(id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
|
||||
}
|
||||
|
||||
void __init x86_add_irq_domains(void)
|
||||
{
|
||||
struct device_node *dp;
|
||||
|
||||
if (!initial_boot_params)
|
||||
return;
|
||||
|
||||
for_each_node_with_property(dp, "interrupt-controller") {
|
||||
if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
|
||||
ioapic_add_ofnode(dp);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void __init x86_add_irq_domains(void) { }
|
||||
#endif
|
||||
|
|
|
@ -118,6 +118,12 @@ void __init init_IRQ(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We probably need a better place for this, but it works for
|
||||
* now ...
|
||||
*/
|
||||
x86_add_irq_domains();
|
||||
|
||||
/*
|
||||
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
|
||||
* If these IRQ's are handled by legacy interrupt-controllers like PIC,
|
||||
|
|
Загрузка…
Ссылка в новой задаче