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 int of_ioapic;
|
||||||
extern u64 initial_dtb;
|
extern u64 initial_dtb;
|
||||||
extern void add_dtb(u64 data);
|
extern void add_dtb(u64 data);
|
||||||
extern void x86_add_irq_domains(void);
|
|
||||||
void x86_of_pci_init(void);
|
void x86_of_pci_init(void);
|
||||||
void x86_dtb_init(void);
|
void x86_dtb_init(void);
|
||||||
#else
|
#else
|
||||||
static inline void add_dtb(u64 data) { }
|
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_of_pci_init(void) { }
|
||||||
static inline void x86_dtb_init(void) { }
|
static inline void x86_dtb_init(void) { }
|
||||||
#define of_ioapic 0
|
#define of_ioapic 0
|
||||||
|
@ -166,10 +166,82 @@ static void __init dtb_lapic_setup(void)
|
|||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
static unsigned int ioapic_id;
|
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)
|
static void __init dtb_add_ioapic(struct device_node *dn)
|
||||||
{
|
{
|
||||||
struct resource r;
|
struct resource r;
|
||||||
int ret;
|
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);
|
ret = of_address_to_resource(dn, 0, &r);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -177,7 +249,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
|
|||||||
dn->full_name);
|
dn->full_name);
|
||||||
return;
|
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)
|
static void __init dtb_ioapic_setup(void)
|
||||||
@ -239,148 +311,3 @@ void __init x86_dtb_init(void)
|
|||||||
dtb_setup_hpet();
|
dtb_setup_hpet();
|
||||||
dtb_apic_setup();
|
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;
|
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.
|
* 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,
|
* If these IRQ's are handled by legacy interrupt-controllers like PIC,
|
||||||
|
Loading…
Reference in New Issue
Block a user