x86, devicetree, irq: Use common mechanism to support irqdomain
Now the ioapic driver provides a common interface to create irqdomain, so replace the private implementation. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Joerg Roedel <joro@8bytes.org> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Grant Likely <grant.likely@linaro.org> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Rob Herring <rob.herring@calxeda.com> Cc: Michal Simek <monstr@monstr.eu> Cc: Tony Lindgren <tony@atomide.com> Link: http://lkml.kernel.org/r/1402302011-23642-29-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
1b5d3e00d4
commit
facd8fdb25
|
@ -26,12 +26,10 @@
|
|||
extern int of_ioapic;
|
||||
extern u64 initial_dtb;
|
||||
extern void add_dtb(u64 data);
|
||||
extern void x86_add_irq_domains(void);
|
||||
void x86_of_pci_init(void);
|
||||
void x86_dtb_init(void);
|
||||
#else
|
||||
static inline void add_dtb(u64 data) { }
|
||||
static inline void x86_add_irq_domains(void) { }
|
||||
static inline void x86_of_pci_init(void) { }
|
||||
static inline void x86_dtb_init(void) { }
|
||||
#define of_ioapic 0
|
||||
|
|
|
@ -166,10 +166,82 @@ static void __init dtb_lapic_setup(void)
|
|||
#ifdef CONFIG_X86_IO_APIC
|
||||
static unsigned int ioapic_id;
|
||||
|
||||
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 *domain,
|
||||
struct device_node *controller,
|
||||
const u32 *intspec, u32 intsize,
|
||||
irq_hw_number_t *out_hwirq, u32 *out_type)
|
||||
{
|
||||
struct io_apic_irq_attr attr;
|
||||
struct of_ioapic_type *it;
|
||||
u32 line, idx;
|
||||
int rc;
|
||||
|
||||
if (WARN_ON(intsize < 2))
|
||||
return -EINVAL;
|
||||
|
||||
line = intspec[0];
|
||||
|
||||
if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
|
||||
return -EINVAL;
|
||||
|
||||
it = &of_ioapic_type[intspec[1]];
|
||||
|
||||
idx = (u32)(long)domain->host_data;
|
||||
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
|
||||
|
||||
rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
|
||||
cpu_to_node(0), &attr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
*out_hwirq = line;
|
||||
*out_type = it->out_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct irq_domain_ops ioapic_irq_domain_ops = {
|
||||
.xlate = ioapic_xlate,
|
||||
};
|
||||
|
||||
static void __init dtb_add_ioapic(struct device_node *dn)
|
||||
{
|
||||
struct resource r;
|
||||
int ret;
|
||||
struct ioapic_domain_cfg cfg = {
|
||||
.type = IOAPIC_DOMAIN_DYNAMIC,
|
||||
.ops = &ioapic_irq_domain_ops,
|
||||
.dev = dn,
|
||||
};
|
||||
|
||||
ret = of_address_to_resource(dn, 0, &r);
|
||||
if (ret) {
|
||||
|
@ -177,7 +249,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
|
|||
dn->full_name);
|
||||
return;
|
||||
}
|
||||
mp_register_ioapic(++ioapic_id, r.start, gsi_top, NULL);
|
||||
mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
|
||||
}
|
||||
|
||||
static void __init dtb_ioapic_setup(void)
|
||||
|
@ -239,148 +311,3 @@ void __init x86_dtb_init(void)
|
|||
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 *domain,
|
||||
struct device_node *controller,
|
||||
const u32 *intspec, u32 intsize,
|
||||
irq_hw_number_t *out_hwirq, u32 *out_type)
|
||||
{
|
||||
struct io_apic_irq_attr attr;
|
||||
struct of_ioapic_type *it;
|
||||
u32 line, idx;
|
||||
int rc;
|
||||
|
||||
if (WARN_ON(intsize < 2))
|
||||
return -EINVAL;
|
||||
|
||||
line = intspec[0];
|
||||
|
||||
if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
|
||||
return -EINVAL;
|
||||
|
||||
it = &of_ioapic_type[intspec[1]];
|
||||
|
||||
idx = (u32) domain->host_data;
|
||||
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
|
||||
|
||||
rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
|
||||
cpu_to_node(0), &attr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
*out_hwirq = line;
|
||||
*out_type = it->out_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct irq_domain_ops ioapic_irq_domain_ops = {
|
||||
.xlate = ioapic_xlate,
|
||||
};
|
||||
|
||||
static void dt_add_ioapic_domain(unsigned int ioapic_num,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct irq_domain *id;
|
||||
struct mp_ioapic_gsi *gsi_cfg;
|
||||
int ret;
|
||||
int num, legacy_irqs = nr_legacy_irqs();
|
||||
|
||||
gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
|
||||
num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
|
||||
|
||||
id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
|
||||
(void *)ioapic_num);
|
||||
BUG_ON(!id);
|
||||
if (gsi_cfg->gsi_base == 0) {
|
||||
/*
|
||||
* The first nr_legacy_irqs() irq descs are allocated in
|
||||
* early_irq_init() and need just a mapping. The
|
||||
* remaining irqs need both. All of them are preallocated
|
||||
* and assigned so we can keep the 1:1 mapping which the ioapic
|
||||
* is having.
|
||||
*/
|
||||
irq_domain_associate_many(id, 0, 0, legacy_irqs);
|
||||
|
||||
if (num > legacy_irqs) {
|
||||
ret = irq_create_strict_mappings(id, legacy_irqs,
|
||||
legacy_irqs, num - legacy_irqs);
|
||||
if (ret)
|
||||
pr_err("Error creating mapping for the "
|
||||
"remaining IRQs: %d\n", ret);
|
||||
}
|
||||
irq_set_default_host(id);
|
||||
} else {
|
||||
ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
|
||||
if (ret)
|
||||
pr_err("Error creating IRQ mapping: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
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 == mpc_ioapic_addr(i)) {
|
||||
dt_add_ioapic_domain(i, np);
|
||||
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 (!of_have_populated_dt())
|
||||
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
|
||||
|
|
|
@ -86,12 +86,6 @@ 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,
|
||||
|
|
Loading…
Reference in New Issue