linux/arch/arm/plat-versatile/fpga-irq.c
<<
>>
Prefs
   1/*
   2 *  Support for Versatile FPGA-based IRQ controllers
   3 */
   4#include <linux/irq.h>
   5#include <linux/io.h>
   6
   7#include <asm/mach/irq.h>
   8#include <plat/fpga-irq.h>
   9
  10#define IRQ_STATUS              0x00
  11#define IRQ_RAW_STATUS          0x04
  12#define IRQ_ENABLE_SET          0x08
  13#define IRQ_ENABLE_CLEAR        0x0c
  14
  15static void fpga_irq_mask(struct irq_data *d)
  16{
  17        struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
  18        u32 mask = 1 << (d->irq - f->irq_start);
  19
  20        writel(mask, f->base + IRQ_ENABLE_CLEAR);
  21}
  22
  23static void fpga_irq_unmask(struct irq_data *d)
  24{
  25        struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
  26        u32 mask = 1 << (d->irq - f->irq_start);
  27
  28        writel(mask, f->base + IRQ_ENABLE_SET);
  29}
  30
  31static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
  32{
  33        struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
  34        u32 status = readl(f->base + IRQ_STATUS);
  35
  36        if (status == 0) {
  37                do_bad_IRQ(irq, desc);
  38                return;
  39        }
  40
  41        do {
  42                irq = ffs(status) - 1;
  43                status &= ~(1 << irq);
  44
  45                generic_handle_irq(irq + f->irq_start);
  46        } while (status);
  47}
  48
  49void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f)
  50{
  51        unsigned int i;
  52
  53        f->chip.irq_ack = fpga_irq_mask;
  54        f->chip.irq_mask = fpga_irq_mask;
  55        f->chip.irq_unmask = fpga_irq_unmask;
  56
  57        if (parent_irq != -1) {
  58                irq_set_handler_data(parent_irq, f);
  59                irq_set_chained_handler(parent_irq, fpga_irq_handle);
  60        }
  61
  62        for (i = 0; i < 32; i++) {
  63                if (valid & (1 << i)) {
  64                        unsigned int irq = f->irq_start + i;
  65
  66                        irq_set_chip_data(irq, f);
  67                        irq_set_chip_and_handler(irq, &f->chip,
  68                                                 handle_level_irq);
  69                        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
  70                }
  71        }
  72}
  73