Skip to content

Commit

Permalink
ARM: plat-versatile: use simple irqdomain for FPGA IRQ
Browse files Browse the repository at this point in the history
This switches the FPGA IRQ driver over to using the simple IRQ
domain. We can then use the same codepath for this in the
DT and non-DT cases.

To be able to use quicker irq_find_mapping() in the handlers
we first call irq_create_mapping() on all the valid HW IRQ
numbers so that descriptors will be created for them in the
DT case where a linear domain will be the outcome of the
call.

Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Linus Walleij committed Oct 26, 2012
1 parent 6f0c058 commit 3a6ca8c
Showing 1 changed file with 22 additions and 28 deletions.
50 changes: 22 additions & 28 deletions arch/arm/plat-versatile/fpga-irq.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Support for Versatile FPGA-based IRQ controllers
*/
#include <linux/bitops.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/irqdomain.h>
Expand Down Expand Up @@ -117,13 +118,12 @@ static int fpga_irqdomain_map(struct irq_domain *d, unsigned int irq,
struct fpga_irq_data *f = d->host_data;

/* Skip invalid IRQs, only register handlers for the real ones */
if (!(f->valid & (1 << hwirq)))
if (!(f->valid & BIT(hwirq)))
return -ENOTSUPP;
irq_set_chip_data(irq, f);
irq_set_chip_and_handler(irq, &f->chip,
handle_level_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
f->used_irqs++;
return 0;
}

Expand All @@ -132,13 +132,15 @@ static struct irq_domain_ops fpga_irqdomain_ops = {
.xlate = irq_domain_xlate_onetwocell,
};

static __init struct fpga_irq_data *
fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
int parent_irq, u32 valid, struct device_node *node)
{
struct fpga_irq_data *f;
int i;

if (fpga_irq_id >= ARRAY_SIZE(fpga_irq_devices)) {
printk(KERN_ERR "%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
return NULL;
pr_err("%s: too few FPGA IRQ controllers, increase CONFIG_PLAT_VERSATILE_FPGA_IRQ_NR\n", __func__);
return;
}
f = &fpga_irq_devices[fpga_irq_id];
f->base = base;
Expand All @@ -147,29 +149,28 @@ fpga_irq_prep_struct(void __iomem *base, const char *name, u32 valid) {
f->chip.irq_mask = fpga_irq_mask;
f->chip.irq_unmask = fpga_irq_unmask;
f->valid = valid;
fpga_irq_id++;

return f;
}

void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start,
int parent_irq, u32 valid, struct device_node *node)
{
struct fpga_irq_data *f;

f = fpga_irq_prep_struct(base, name, valid);
if (!f)
return;

if (parent_irq != -1) {
irq_set_handler_data(parent_irq, f);
irq_set_chained_handler(parent_irq, fpga_irq_handle);
}

f->domain = irq_domain_add_legacy(node, fls(valid), irq_start, 0,
/* This will also allocate irq descriptors */
f->domain = irq_domain_add_simple(node, fls(valid), irq_start,
&fpga_irqdomain_ops, f);

/* This will allocate all valid descriptors in the linear case */
for (i = 0; i < fls(valid); i++)
if (valid & BIT(i)) {
if (!irq_start)
irq_create_mapping(f->domain, i);
f->used_irqs++;
}

pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
fpga_irq_id, name, base, f->used_irqs);

fpga_irq_id++;
}

#ifdef CONFIG_OF
Expand All @@ -193,18 +194,11 @@ int __init fpga_irq_of_init(struct device_node *node,
if (of_property_read_u32(node, "valid-mask", &valid_mask))
valid_mask = 0;

f = fpga_irq_prep_struct(base, node->name, valid_mask);
if (!f)
return -ENOMEM;
fpga_irq_init(base, node->name, 0, -1, valid_mask, node);

writel(clear_mask, base + IRQ_ENABLE_CLEAR);
writel(clear_mask, base + FIQ_ENABLE_CLEAR);

f->domain = irq_domain_add_linear(node, fls(valid_mask), &fpga_irqdomain_ops, f);
f->used_irqs = hweight32(valid_mask);

pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n",
fpga_irq_id, node->name, base, f->used_irqs);
return 0;
}
#endif

0 comments on commit 3a6ca8c

Please sign in to comment.