1 /*
2 * FILE NAME
3 * arch/mips/vr41xx/nec-eagle/irq.c
4 *
5 * BRIEF MODULE DESCRIPTION
6 * Interrupt routines for the NEC Eagle/Hawk board.
7 *
8 * Author: Yoichi Yuasa
9 * yyuasa@mvista.com or source@mvista.com
10 *
11 * Copyright 2002 MontaVista Software Inc.
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33 /*
34 * Changes:
35 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
36 * - Added support for NEC Hawk.
37 *
38 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
39 * - New creation, NEC Eagle is supported.
40 */
41 #include <linux/init.h>
42 #include <linux/interrupt.h>
43
44 #include <asm/io.h>
45 #include <asm/vr41xx/eagle.h>
46
enable_pciint_irq(unsigned int irq)47 static void enable_pciint_irq(unsigned int irq)
48 {
49 u8 val;
50
51 val = readb(NEC_EAGLE_PCIINTMSKREG);
52 val |= (u8)1 << (irq - PCIINT_IRQ_BASE);
53 writeb(val, NEC_EAGLE_PCIINTMSKREG);
54 }
55
disable_pciint_irq(unsigned int irq)56 static void disable_pciint_irq(unsigned int irq)
57 {
58 u8 val;
59
60 val = readb(NEC_EAGLE_PCIINTMSKREG);
61 val &= ~((u8)1 << (irq - PCIINT_IRQ_BASE));
62 writeb(val, NEC_EAGLE_PCIINTMSKREG);
63 }
64
startup_pciint_irq(unsigned int irq)65 static unsigned int startup_pciint_irq(unsigned int irq)
66 {
67 enable_pciint_irq(irq);
68 return 0; /* never anything pending */
69 }
70
71 #define shutdown_pciint_irq disable_pciint_irq
72 #define ack_pciint_irq disable_pciint_irq
73
end_pciint_irq(unsigned int irq)74 static void end_pciint_irq(unsigned int irq)
75 {
76 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
77 enable_pciint_irq(irq);
78 }
79
80 static struct hw_interrupt_type pciint_irq_type = {
81 "PCIINT",
82 startup_pciint_irq,
83 shutdown_pciint_irq,
84 enable_pciint_irq,
85 disable_pciint_irq,
86 ack_pciint_irq,
87 end_pciint_irq,
88 NULL
89 };
90
enable_sdbint_irq(unsigned int irq)91 static void enable_sdbint_irq(unsigned int irq)
92 {
93 u8 val;
94
95 val = readb(NEC_EAGLE_SDBINTMSK);
96 val |= (u8)1 << (irq - SDBINT_IRQ_BASE);
97 writeb(val, NEC_EAGLE_SDBINTMSK);
98 }
99
disable_sdbint_irq(unsigned int irq)100 static void disable_sdbint_irq(unsigned int irq)
101 {
102 u8 val;
103
104 val = readb(NEC_EAGLE_SDBINTMSK);
105 val &= ~((u8)1 << (irq - SDBINT_IRQ_BASE));
106 writeb(val, NEC_EAGLE_SDBINTMSK);
107 }
108
startup_sdbint_irq(unsigned int irq)109 static unsigned int startup_sdbint_irq(unsigned int irq)
110 {
111 enable_sdbint_irq(irq);
112 return 0; /* never anything pending */
113 }
114
115 #define shutdown_sdbint_irq disable_sdbint_irq
116 #define ack_sdbint_irq disable_sdbint_irq
117
end_sdbint_irq(unsigned int irq)118 static void end_sdbint_irq(unsigned int irq)
119 {
120 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
121 enable_sdbint_irq(irq);
122 }
123
124 static struct hw_interrupt_type sdbint_irq_type = {
125 "SDBINT",
126 startup_sdbint_irq,
127 shutdown_sdbint_irq,
128 enable_sdbint_irq,
129 disable_sdbint_irq,
130 ack_sdbint_irq,
131 end_sdbint_irq,
132 NULL
133 };
134
eagle_get_irq_number(int irq)135 static int eagle_get_irq_number(int irq)
136 {
137 u8 sdbint, pciint;
138 int i;
139
140 sdbint = readb(NEC_EAGLE_SDBINT);
141 sdbint &= (NEC_EAGLE_SDBINT_DEG | NEC_EAGLE_SDBINT_ENUM |
142 NEC_EAGLE_SDBINT_SIO1INT | NEC_EAGLE_SDBINT_SIO2INT |
143 NEC_EAGLE_SDBINT_PARINT);
144 pciint = readb(NEC_EAGLE_PCIINTREG);
145 pciint &= (NEC_EAGLE_PCIINT_CP_INTA | NEC_EAGLE_PCIINT_CP_INTB |
146 NEC_EAGLE_PCIINT_CP_INTC | NEC_EAGLE_PCIINT_CP_INTD |
147 NEC_EAGLE_PCIINT_LANINT);
148
149 for (i = 1; i < 6; i++)
150 if (sdbint & (0x01 << i))
151 return SDBINT_IRQ_BASE + i;
152
153 for (i = 0; i < 5; i++)
154 if (pciint & (0x01 << i))
155 return PCIINT_IRQ_BASE + i;
156
157 return -EINVAL;
158 }
159
eagle_irq_init(void)160 void __init eagle_irq_init(void)
161 {
162 int i;
163
164 writeb(0, NEC_EAGLE_SDBINTMSK);
165 writeb(0, NEC_EAGLE_PCIINTMSKREG);
166
167 vr41xx_set_irq_trigger(PCISLOT_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
168 vr41xx_set_irq_level(PCISLOT_PIN, LEVEL_HIGH);
169
170 vr41xx_set_irq_trigger(FPGA_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
171 vr41xx_set_irq_level(FPGA_PIN, LEVEL_HIGH);
172
173 vr41xx_set_irq_trigger(DCD_PIN, TRIGGER_EDGE, SIGNAL_HOLD);
174 vr41xx_set_irq_level(DCD_PIN, LEVEL_LOW);
175
176 for (i = SDBINT_IRQ_BASE; i <= SDBINT_IRQ_LAST; i++)
177 irq_desc[i].handler = &sdbint_irq_type;
178
179 for (i = PCIINT_IRQ_BASE; i <= PCIINT_IRQ_LAST; i++)
180 irq_desc[i].handler = &pciint_irq_type;
181
182 vr41xx_cascade_irq(FPGA_CASCADE_IRQ, eagle_get_irq_number);
183 }
184