Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | /* * linux/arch/arm/mach-iop3xx/iop310-irq.c * * Generic IOP310 IRQ handling functionality * * Author: Nicolas Pitre * Copyright: (C) 2001 MontaVista Software Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Added IOP310 chipset and IQ80310 board demuxing, masking code. - DS * */ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/list.h> #include <asm/mach/irq.h> #include <asm/irq.h> #include <asm/hardware.h> #include <asm/mach-types.h> extern void xs80200_irq_mask(unsigned int); extern void xs80200_irq_unmask(unsigned int); extern void xs80200_init_irq(void); extern void do_IRQ(int, struct pt_regs *); static u32 iop310_mask /* = 0 */; static void iop310_irq_mask (unsigned int irq) { iop310_mask ++; /* * No mask bits on the 80312, so we have to * mask everything from the outside! */ if (iop310_mask == 1) { disable_irq(IRQ_XS80200_EXTIRQ); irq_desc[IRQ_XS80200_EXTIRQ].chip->mask(IRQ_XS80200_EXTIRQ); } } static void iop310_irq_unmask (unsigned int irq) { if (iop310_mask) iop310_mask --; /* * Check if all 80312 sources are unmasked now */ if (iop310_mask == 0) enable_irq(IRQ_XS80200_EXTIRQ); } struct irqchip ext_chip = { .ack = iop310_irq_mask, .mask = iop310_irq_mask, .unmask = iop310_irq_unmask, }; void iop310_irq_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { u32 fiq1isr = *((volatile u32*)IOP310_FIQ1ISR); u32 fiq2isr = *((volatile u32*)IOP310_FIQ2ISR); struct irqdesc *d; unsigned int irqno = 0; if(fiq1isr) { if(fiq1isr & 0x1) irqno = IRQ_IOP310_DMA0; if(fiq1isr & 0x2) irqno = IRQ_IOP310_DMA1; if(fiq1isr & 0x4) irqno = IRQ_IOP310_DMA2; if(fiq1isr & 0x10) irqno = IRQ_IOP310_PMON; if(fiq1isr & 0x20) irqno = IRQ_IOP310_AAU; } else { if(fiq2isr & 0x2) irqno = IRQ_IOP310_I2C; if(fiq2isr & 0x4) irqno = IRQ_IOP310_MU; } if (irqno) { d = irq_desc + irqno; d->handle(irqno, d, regs); } } void __init iop310_init_irq(void) { unsigned int i; for(i = IOP310_IRQ_OFS; i < NR_IOP310_IRQS; i++) { set_irq_chip(i, &ext_chip); set_irq_handler(i, do_level_IRQ); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); } xs80200_init_irq(); } |