Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / arm / mach-rpc / irq.c
diff --git a/kernel/arch/arm/mach-rpc/irq.c b/kernel/arch/arm/mach-rpc/irq.c
new file mode 100644 (file)
index 0000000..3e4fa84
--- /dev/null
@@ -0,0 +1,168 @@
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#include <asm/mach/irq.h>
+#include <asm/hardware/iomd.h>
+#include <asm/irq.h>
+#include <asm/fiq.h>
+
+static void iomd_ack_irq_a(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << d->irq;
+       val = iomd_readb(IOMD_IRQMASKA);
+       iomd_writeb(val & ~mask, IOMD_IRQMASKA);
+       iomd_writeb(mask, IOMD_IRQCLRA);
+}
+
+static void iomd_mask_irq_a(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << d->irq;
+       val = iomd_readb(IOMD_IRQMASKA);
+       iomd_writeb(val & ~mask, IOMD_IRQMASKA);
+}
+
+static void iomd_unmask_irq_a(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << d->irq;
+       val = iomd_readb(IOMD_IRQMASKA);
+       iomd_writeb(val | mask, IOMD_IRQMASKA);
+}
+
+static struct irq_chip iomd_a_chip = {
+       .irq_ack        = iomd_ack_irq_a,
+       .irq_mask       = iomd_mask_irq_a,
+       .irq_unmask     = iomd_unmask_irq_a,
+};
+
+static void iomd_mask_irq_b(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << (d->irq & 7);
+       val = iomd_readb(IOMD_IRQMASKB);
+       iomd_writeb(val & ~mask, IOMD_IRQMASKB);
+}
+
+static void iomd_unmask_irq_b(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << (d->irq & 7);
+       val = iomd_readb(IOMD_IRQMASKB);
+       iomd_writeb(val | mask, IOMD_IRQMASKB);
+}
+
+static struct irq_chip iomd_b_chip = {
+       .irq_ack        = iomd_mask_irq_b,
+       .irq_mask       = iomd_mask_irq_b,
+       .irq_unmask     = iomd_unmask_irq_b,
+};
+
+static void iomd_mask_irq_dma(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << (d->irq & 7);
+       val = iomd_readb(IOMD_DMAMASK);
+       iomd_writeb(val & ~mask, IOMD_DMAMASK);
+}
+
+static void iomd_unmask_irq_dma(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << (d->irq & 7);
+       val = iomd_readb(IOMD_DMAMASK);
+       iomd_writeb(val | mask, IOMD_DMAMASK);
+}
+
+static struct irq_chip iomd_dma_chip = {
+       .irq_ack        = iomd_mask_irq_dma,
+       .irq_mask       = iomd_mask_irq_dma,
+       .irq_unmask     = iomd_unmask_irq_dma,
+};
+
+static void iomd_mask_irq_fiq(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << (d->irq & 7);
+       val = iomd_readb(IOMD_FIQMASK);
+       iomd_writeb(val & ~mask, IOMD_FIQMASK);
+}
+
+static void iomd_unmask_irq_fiq(struct irq_data *d)
+{
+       unsigned int val, mask;
+
+       mask = 1 << (d->irq & 7);
+       val = iomd_readb(IOMD_FIQMASK);
+       iomd_writeb(val | mask, IOMD_FIQMASK);
+}
+
+static struct irq_chip iomd_fiq_chip = {
+       .irq_ack        = iomd_mask_irq_fiq,
+       .irq_mask       = iomd_mask_irq_fiq,
+       .irq_unmask     = iomd_unmask_irq_fiq,
+};
+
+extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
+
+void __init rpc_init_irq(void)
+{
+       unsigned int irq, flags;
+
+       iomd_writeb(0, IOMD_IRQMASKA);
+       iomd_writeb(0, IOMD_IRQMASKB);
+       iomd_writeb(0, IOMD_FIQMASK);
+       iomd_writeb(0, IOMD_DMAMASK);
+
+       set_fiq_handler(&rpc_default_fiq_start,
+               &rpc_default_fiq_end - &rpc_default_fiq_start);
+
+       for (irq = 0; irq < NR_IRQS; irq++) {
+               flags = IRQF_VALID;
+
+               if (irq <= 6 || (irq >= 9 && irq <= 15))
+                       flags |= IRQF_PROBE;
+
+               if (irq == 21 || (irq >= 16 && irq <= 19) ||
+                   irq == IRQ_KEYBOARDTX)
+                       flags |= IRQF_NOAUTOEN;
+
+               switch (irq) {
+               case 0 ... 7:
+                       irq_set_chip_and_handler(irq, &iomd_a_chip,
+                                                handle_level_irq);
+                       set_irq_flags(irq, flags);
+                       break;
+
+               case 8 ... 15:
+                       irq_set_chip_and_handler(irq, &iomd_b_chip,
+                                                handle_level_irq);
+                       set_irq_flags(irq, flags);
+                       break;
+
+               case 16 ... 21:
+                       irq_set_chip_and_handler(irq, &iomd_dma_chip,
+                                                handle_level_irq);
+                       set_irq_flags(irq, flags);
+                       break;
+
+               case 64 ... 71:
+                       irq_set_chip(irq, &iomd_fiq_chip);
+                       set_irq_flags(irq, IRQF_VALID);
+                       break;
+               }
+       }
+
+       init_FIQ(FIQ_START);
+}
+