URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [sh/] [kernel/] [irq_microdev.c] - Rev 1765
Compare with Previous | Blame | View Log
/* * linux/arch/sh/kernel/irq_microdev.c * * Copyright (C) 2003 Sean McGoogan (Sean.McGoogan@superh.com) * * SuperH SH4-202 MicroDev board support. * * May be copied or modified under the terms of the GNU General Public * License. See linux/COPYING for more information. */ #include <linux/config.h> #include <linux/init.h> #include <linux/irq.h> #include <asm/system.h> #include <asm/io.h> #include <asm/irq_microdev.h> #define NUM_EXTERNAL_IRQS 16 /* IRL0 .. IRL15 */ static const struct { unsigned char fpgaIrq; unsigned char mapped; const char *name; } fpgaIrqTable[NUM_EXTERNAL_IRQS] = { { 0, 0, "unused" }, /* IRQ #0 IRL=15 0x200 */ { 0, 0, "unused" }, /* IRQ #1 IRL=14 0x220 */ { 0, 0, "unused" }, /* IRQ #2 IRL=13 0x240 */ { 18, 1, "Ethernet" }, /* IRQ #3 IRL=12 0x260 */ { 0, 0, "unused" }, /* IRQ #4 IRL=11 0x280 */ { 0, 0, "unused" }, /* IRQ #5 IRL=10 0x2a0 */ { 0, 0, "unused" }, /* IRQ #6 IRL=9 0x2c0 */ { 0, 0, "unused" }, /* IRQ #7 IRL=8 0x2e0 */ { 8, 1, "PCI INTA" }, /* IRQ #8 IRL=7 0x300 */ { 9, 1, "PCI INTB" }, /* IRQ #9 IRL=6 0x320 */ { 10, 1, "PCI INTC" }, /* IRQ #10 IRL=5 0x340 */ { 11, 1, "PCI INTD" }, /* IRQ #11 IRL=4 0x360 */ { 0, 0, "unused" }, /* IRQ #12 IRL=3 0x380 */ { 0, 0, "unused" }, /* IRQ #13 IRL=2 0x3a0 */ { 0, 0, "unused" }, /* IRQ #14 IRL=1 0x3c0 */ { 0, 0, "unused" }, /* IRQ #15 IRL=0 0x3e0 */ }; static void enable_microdev_irq(unsigned int irq); static void disable_microdev_irq(unsigned int irq); /* shutdown is same as "disable" */ #define shutdown_microdev_irq disable_microdev_irq static void mask_and_ack_microdev(unsigned int); static void end_microdev_irq(unsigned int irq); static unsigned int startup_microdev_irq(unsigned int irq) { enable_microdev_irq(irq); return 0; /* never anything pending */ } static struct hw_interrupt_type microdev_irq_type = { "MicroDev-IRQ", startup_microdev_irq, shutdown_microdev_irq, enable_microdev_irq, disable_microdev_irq, mask_and_ack_microdev, end_microdev_irq }; static void disable_microdev_irq(unsigned int irq) { unsigned int flags; unsigned int fpgaIrq; if (irq >= NUM_EXTERNAL_IRQS) return; if (!fpgaIrqTable[irq].mapped) return; fpgaIrq = fpgaIrqTable[irq].fpgaIrq; /* disable interrupts */ save_and_cli(flags); /* disable interupts on the FPGA INTC register */ ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG); /* restore interrupts */ restore_flags(flags); } static void enable_microdev_irq(unsigned int irq) { unsigned long priorityReg, priorities, pri; unsigned int flags; unsigned int fpgaIrq; if (irq >= NUM_EXTERNAL_IRQS) return; if (!fpgaIrqTable[irq].mapped) return; pri = 15 - irq; fpgaIrq = fpgaIrqTable[irq].fpgaIrq; priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq); /* disable interrupts */ save_and_cli(flags); /* set priority for the interrupt */ priorities = ctrl_inl(priorityReg); priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq); priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri); ctrl_outl(priorities, priorityReg); /* enable interupts on the FPGA INTC register */ ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG); /* restore interrupts */ restore_flags(flags); } /* This functions sets the desired irq handler to be a MicroDev type */ static void __init make_microdev_irq(unsigned int irq) { disable_irq_nosync(irq); irq_desc[irq].handler = µdev_irq_type; disable_microdev_irq(irq); } static void mask_and_ack_microdev(unsigned int irq) { disable_microdev_irq(irq); } static void end_microdev_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { enable_microdev_irq(irq); } } extern void __init init_microdev_irq(void) { int i; /* disable interupts on the FPGA INTC register */ ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG); for (i = 0; i < NUM_EXTERNAL_IRQS; i++) { make_microdev_irq(i); } }