irq.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
- /*
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * linux/arch/mips/vr4181/common/irq.c
- * Completely re-written to use the new irq.c
- *
- * Credits to Bradley D. LaRonde and Michael Klar for writing the original
- * irq.c file which was derived from the common irq.c file.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- */
- #include <linux/config.h>
- #include <linux/types.h>
- #include <linux/init.h>
- #include <linux/kernel_stat.h>
- #include <linux/signal.h>
- #include <linux/sched.h>
- #include <linux/interrupt.h>
- #include <linux/slab.h>
- #include <linux/random.h>
- #include <asm/irq.h>
- #include <asm/mipsregs.h>
- #include <asm/gdb-stub.h>
- #include <asm/vr4181/vr4181.h>
- /*
- * Strategy:
- *
- * We essentially have three irq controllers, CPU, system, and gpio.
- *
- * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and
- * CONFIG_IRQ_CPU config option.
- *
- * We here provide sys_irq and gpio_irq controller code.
- */
- static int sys_irq_base;
- static int gpio_irq_base;
- /* ---------------------- sys irq ------------------------ */
- static void
- sys_irq_enable(unsigned int irq)
- {
- irq -= sys_irq_base;
- if (irq < 16) {
- *VR4181_MSYSINT1REG |= (u16)(1 << irq);
- } else {
- irq -= 16;
- *VR4181_MSYSINT2REG |= (u16)(1 << irq);
- }
- }
- static void
- sys_irq_disable(unsigned int irq)
- {
- irq -= sys_irq_base;
- if (irq < 16) {
- *VR4181_MSYSINT1REG &= ~((u16)(1 << irq));
- } else {
- irq -= 16;
- *VR4181_MSYSINT2REG &= ~((u16)(1 << irq));
- }
- }
- static unsigned int
- sys_irq_startup(unsigned int irq)
- {
- sys_irq_enable(irq);
- return 0;
- }
- #define sys_irq_shutdown sys_irq_disable
- #define sys_irq_ack sys_irq_disable
- static void
- sys_irq_end(unsigned int irq)
- {
- if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- sys_irq_enable(irq);
- }
- static hw_irq_controller sys_irq_controller = {
- "vr4181_sys_irq",
- sys_irq_startup,
- sys_irq_shutdown,
- sys_irq_enable,
- sys_irq_disable,
- sys_irq_ack,
- sys_irq_end,
- NULL /* no affinity stuff for UP */
- };
- /* ---------------------- gpio irq ------------------------ */
- /* gpio irq lines use reverse logic */
- static void
- gpio_irq_enable(unsigned int irq)
- {
- irq -= gpio_irq_base;
- *VR4181_GPINTMSK &= ~((u16)(1 << irq));
- }
- static void
- gpio_irq_disable(unsigned int irq)
- {
- irq -= gpio_irq_base;
- *VR4181_GPINTMSK |= (u16)(1 << irq);
- }
- static unsigned int
- gpio_irq_startup(unsigned int irq)
- {
- gpio_irq_enable(irq);
- irq -= gpio_irq_base;
- *VR4181_GPINTEN |= (u16)(1 << irq );
- return 0;
- }
- static void
- gpio_irq_shutdown(unsigned int irq)
- {
- gpio_irq_disable(irq);
- irq -= gpio_irq_base;
- *VR4181_GPINTEN &= ~((u16)(1 << irq ));
- }
- static void
- gpio_irq_ack(unsigned int irq)
- {
- u16 irqtype;
- u16 irqshift;
- gpio_irq_disable(irq);
- /* we clear interrupt if it is edge triggered */
- irq -= gpio_irq_base;
- if (irq < 8) {
- irqtype = *VR4181_GPINTTYPL;
- irqshift = 2 << (irq*2);
- } else {
- irqtype = *VR4181_GPINTTYPH;
- irqshift = 2 << ((irq-8)*2);
- }
- if ( ! (irqtype & irqshift) ) {
- *VR4181_GPINTSTAT = (u16) (1 << irq);
- }
- }
- static void
- gpio_irq_end(unsigned int irq)
- {
- if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
- gpio_irq_enable(irq);
- }
- static hw_irq_controller gpio_irq_controller = {
- "vr4181_gpio_irq",
- gpio_irq_startup,
- gpio_irq_shutdown,
- gpio_irq_enable,
- gpio_irq_disable,
- gpio_irq_ack,
- gpio_irq_end,
- NULL /* no affinity stuff for UP */
- };
- /* --------------------- IRQ init stuff ---------------------- */
- extern asmlinkage void vr4181_handle_irq(void);
- extern void breakpoint(void);
- extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
- extern void mips_cpu_irq_init(u32 irq_base);
- static struct irqaction cascade =
- { no_action, SA_INTERRUPT, 0, "cascade", NULL, NULL };
- static struct irqaction reserved =
- { no_action, SA_INTERRUPT, 0, "cascade", NULL, NULL };
- void __init init_IRQ(void)
- {
- int i;
- extern irq_desc_t irq_desc[];
- set_except_vector(0, vr4181_handle_irq);
- /* init CPU irqs */
- mips_cpu_irq_init(VR4181_CPU_IRQ_BASE);
- /* init sys irqs */
- sys_irq_base = VR4181_SYS_IRQ_BASE;
- for (i=sys_irq_base; i < sys_irq_base + VR4181_NUM_SYS_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].handler = &sys_irq_controller;
- }
- /* init gpio irqs */
- gpio_irq_base = VR4181_GPIO_IRQ_BASE;
- for (i=gpio_irq_base; i < gpio_irq_base + VR4181_NUM_GPIO_IRQ; i++) {
- irq_desc[i].status = IRQ_DISABLED;
- irq_desc[i].action = NULL;
- irq_desc[i].depth = 1;
- irq_desc[i].handler = &gpio_irq_controller;
- }
- /* Default all ICU IRQs to off ... */
- *VR4181_MSYSINT1REG = 0;
- *VR4181_MSYSINT2REG = 0;
-
- /* We initialize the level 2 ICU registers to all bits disabled. */
- *VR4181_MPIUINTREG = 0;
- *VR4181_MAIUINTREG = 0;
- *VR4181_MKIUINTREG = 0;
- /* disable all GPIO intrs */
- *VR4181_GPINTMSK = 0xffff;
- /* vector handler. What these do is register the IRQ as non-sharable */
- setup_irq(VR4181_IRQ_INT0, &cascade);
- setup_irq(VR4181_IRQ_GIU, &cascade);
- /*
- * RTC interrupts are interesting. They have two destinations.
- * One is at sys irq controller, and the other is at CPU IP3 and IP4.
- * RTC timer is used as system timer.
- * We enable them here, but timer routine will register later
- * with CPU IP3/IP4.
- */
- setup_irq(VR4181_IRQ_RTCL1, &reserved);
- setup_irq(VR4181_IRQ_RTCL2, &reserved);
- #ifdef CONFIG_REMOTE_DEBUG
- printk("Setting debug traps - please connect the remote debugger.n");
- set_debug_traps();
- // you may move this line to whereever you want
- breakpoint();
- #endif
- }