import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / mips / mips-boards / sead / sead_int.c
1 /*
2  * Carsten Langgaard, carstenl@mips.com
3  * Copyright (C) 2002 MIPS Technologies, Inc.  All rights reserved.
4  *
5  * ########################################################################
6  *
7  *  This program is free software; you can distribute it and/or modify it
8  *  under the terms of the GNU General Public License (Version 2) as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope it will be useful, but WITHOUT
12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  *  for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19  *
20  * ########################################################################
21  *
22  * Routines for generic manipulation of the interrupts found on the MIPS
23  * Sead board.
24  *
25  */
26 #include <linux/config.h>
27 #include <linux/init.h>
28 #include <linux/irq.h>
29 #include <linux/sched.h>
30 #include <linux/slab.h>
31 #include <linux/interrupt.h>
32 #include <linux/kernel_stat.h>
33
34 #include <asm/mips-boards/sead.h>
35 #include <asm/mips-boards/seadint.h>
36
37 extern asmlinkage void mipsIRQ(void);
38
39 void disable_sead_irq(unsigned int irq_nr)
40 {
41         if (irq_nr == SEADINT_UART0)
42                 clear_c0_status(0x00000400);
43         else
44                 if (irq_nr == SEADINT_UART1)
45                         clear_c0_status(0x00000800);
46 }
47
48 void enable_sead_irq(unsigned int irq_nr)
49 {
50         if (irq_nr == SEADINT_UART0)
51                 set_c0_status(0x00000400);
52         else
53                 if (irq_nr == SEADINT_UART1)
54                         set_c0_status(0x00000800);
55 }
56
57 static unsigned int startup_sead_irq(unsigned int irq)
58 {
59         enable_sead_irq(irq);
60         return 0; /* never anything pending */
61 }
62
63 #define shutdown_sead_irq       disable_sead_irq
64
65 #define mask_and_ack_sead_irq disable_sead_irq
66
67 static void end_sead_irq(unsigned int irq)
68 {
69         if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
70                 enable_sead_irq(irq);
71 }
72
73 static struct hw_interrupt_type sead_irq_type = {
74         "SEAD",
75         startup_sead_irq,
76         shutdown_sead_irq,
77         enable_sead_irq,
78         disable_sead_irq,
79         mask_and_ack_sead_irq,
80         end_sead_irq,
81         NULL
82 };
83
84 void sead_hw0_irqdispatch(struct pt_regs *regs)
85 {
86         do_IRQ(0, regs);
87 }
88
89 void sead_hw1_irqdispatch(struct pt_regs *regs)
90 {
91         do_IRQ(1, regs);
92 }
93
94 void __init init_IRQ(void)
95 {
96         int i;
97
98         /*
99          * Mask out all interrupt
100          */
101         clear_c0_status(0x0000ff00);
102
103         /* Now safe to set the exception vector. */
104         set_except_vector(0, mipsIRQ);
105
106         init_generic_irq();
107
108         for (i = 0; i < SEADINT_END; i++) {
109                 irq_desc[i].status      = IRQ_DISABLED;
110                 irq_desc[i].action      = NULL;
111                 irq_desc[i].depth       = 1;
112                 irq_desc[i].lock        = SPIN_LOCK_UNLOCKED;
113                 irq_desc[i].handler     = &sead_irq_type;
114         }
115 }