diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-23 20:37:26 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-23 20:37:26 -0700 |
commit | 2f284c846331fa44be1300a3c2c3e85800268a00 (patch) | |
tree | be2704e6157613bd2cc2a278559a6c86a0b644f4 /arch/arm/plat-versatile/fpga-irq.c | |
parent | 93a72052be81823fa1584b9be037d51924f9efa4 (diff) | |
parent | 6f82f4db80189281a8ac42f2e72396accb719b57 (diff) | |
download | talos-op-linux-2f284c846331fa44be1300a3c2c3e85800268a00.tar.gz talos-op-linux-2f284c846331fa44be1300a3c2c3e85800268a00.zip |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (35 commits)
ARM: Update (and cut down) mach-types
ARM: 6771/1: vexpress: add support for multiple core tiles
ARM: 6797/1: hw_breakpoint: Fix newlines in WARNings
ARM: 6751/1: vexpress: select applicable errata workarounds in Kconfig
ARM: 6753/1: omap4: Enable ARM local timers with OMAP4430 es1.0 exception
ARM: 6759/1: smp: Select local timers vs broadcast timer support runtime
ARM: pgtable: add pud-level code
ARM: 6673/1: LPAE: use phys_addr_t instead of unsigned long for start of membanks
ARM: Use long long format when printing meminfo physical addresses
ARM: integrator: add Integrator/CP sched_clock support
ARM: realview/vexpress: consolidate SMP bringup code
ARM: realview/vexpress: consolidate localtimer support
ARM: integrator/versatile: consolidate FPGA IRQ handling code
ARM: rationalize versatile family Kconfig/Makefile
ARM: realview: remove old AMBA device DMA definitions
ARM: versatile: remove old AMBA device DMA definitions
ARM: vexpress: use new init_early for clock tree and sched_clock init
ARM: realview: use new init_early for clock tree and sched_clock init
ARM: versatile: use new init_early for clock tree and sched_clock init
ARM: integrator: use new init_early for clock tree init
...
Diffstat (limited to 'arch/arm/plat-versatile/fpga-irq.c')
-rw-r--r-- | arch/arm/plat-versatile/fpga-irq.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/arch/arm/plat-versatile/fpga-irq.c b/arch/arm/plat-versatile/fpga-irq.c new file mode 100644 index 000000000000..31d945d37e4f --- /dev/null +++ b/arch/arm/plat-versatile/fpga-irq.c @@ -0,0 +1,72 @@ +/* + * Support for Versatile FPGA-based IRQ controllers + */ +#include <linux/irq.h> +#include <linux/io.h> + +#include <asm/mach/irq.h> +#include <plat/fpga-irq.h> + +#define IRQ_STATUS 0x00 +#define IRQ_RAW_STATUS 0x04 +#define IRQ_ENABLE_SET 0x08 +#define IRQ_ENABLE_CLEAR 0x0c + +static void fpga_irq_mask(struct irq_data *d) +{ + struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - f->irq_start); + + writel(mask, f->base + IRQ_ENABLE_CLEAR); +} + +static void fpga_irq_unmask(struct irq_data *d) +{ + struct fpga_irq_data *f = irq_data_get_irq_chip_data(d); + u32 mask = 1 << (d->irq - f->irq_start); + + writel(mask, f->base + IRQ_ENABLE_SET); +} + +static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc) +{ + struct fpga_irq_data *f = get_irq_desc_data(desc); + u32 status = readl(f->base + IRQ_STATUS); + + if (status == 0) { + do_bad_IRQ(irq, desc); + return; + } + + do { + irq = ffs(status) - 1; + status &= ~(1 << irq); + + generic_handle_irq(irq + f->irq_start); + } while (status); +} + +void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f) +{ + unsigned int i; + + f->chip.irq_ack = fpga_irq_mask; + f->chip.irq_mask = fpga_irq_mask; + f->chip.irq_unmask = fpga_irq_unmask; + + if (parent_irq != -1) { + set_irq_data(parent_irq, f); + set_irq_chained_handler(parent_irq, fpga_irq_handle); + } + + for (i = 0; i < 32; i++) { + if (valid & (1 << i)) { + unsigned int irq = f->irq_start + i; + + set_irq_chip_data(irq, f); + set_irq_chip(irq, &f->chip); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } +} |