2 * irq.c, Interrupt routines for the NEC Eagle/Hawk board.
4 * Copyright (C) 2002 MontaVista Software, Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
6 * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
25 * - New creation, NEC Eagle is supported.
26 * - Added support for NEC Hawk.
28 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
29 * - Changed from board_irq_init to driver module.
31 #include <linux/config.h>
32 #include <linux/init.h>
33 #include <linux/interrupt.h>
34 #include <linux/module.h>
35 #include <linux/types.h>
38 #include <asm/vr41xx/eagle.h>
40 MODULE_DESCRIPTION("IRQ module driver for NEC Eagle/Hawk");
41 MODULE_AUTHOR("Yoichi Yuasa <yyuasa@mvista.com>");
42 MODULE_LICENSE("GPL");
44 static void enable_pciint_irq(unsigned int irq)
48 val = readb(NEC_EAGLE_PCIINTMSKREG);
49 val |= (uint8_t)1 << (irq - PCIINT_IRQ_BASE);
50 writeb(val, NEC_EAGLE_PCIINTMSKREG);
53 static void disable_pciint_irq(unsigned int irq)
57 val = readb(NEC_EAGLE_PCIINTMSKREG);
58 val &= ~((uint8_t)1 << (irq - PCIINT_IRQ_BASE));
59 writeb(val, NEC_EAGLE_PCIINTMSKREG);
62 static unsigned int startup_pciint_irq(unsigned int irq)
64 enable_pciint_irq(irq);
65 return 0; /* never anything pending */
68 #define shutdown_pciint_irq disable_pciint_irq
69 #define ack_pciint_irq disable_pciint_irq
71 static void end_pciint_irq(unsigned int irq)
73 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
74 enable_pciint_irq(irq);
77 static struct hw_interrupt_type pciint_irq_type = {
79 .startup = startup_pciint_irq,
80 .shutdown = shutdown_pciint_irq,
81 .enable = enable_pciint_irq,
82 .disable = disable_pciint_irq,
83 .ack = ack_pciint_irq,
84 .end = end_pciint_irq,
87 static void enable_sdbint_irq(unsigned int irq)
91 val = readb(NEC_EAGLE_SDBINTMSK);
92 val |= (uint8_t)1 << (irq - SDBINT_IRQ_BASE);
93 writeb(val, NEC_EAGLE_SDBINTMSK);
96 static void disable_sdbint_irq(unsigned int irq)
100 val = readb(NEC_EAGLE_SDBINTMSK);
101 val &= ~((uint8_t)1 << (irq - SDBINT_IRQ_BASE));
102 writeb(val, NEC_EAGLE_SDBINTMSK);
105 static unsigned int startup_sdbint_irq(unsigned int irq)
107 enable_sdbint_irq(irq);
108 return 0; /* never anything pending */
111 #define shutdown_sdbint_irq disable_sdbint_irq
112 #define ack_sdbint_irq disable_sdbint_irq
114 static void end_sdbint_irq(unsigned int irq)
116 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
117 enable_sdbint_irq(irq);
120 static struct hw_interrupt_type sdbint_irq_type = {
121 .typename = "SDBINT",
122 .startup = startup_sdbint_irq,
123 .shutdown = shutdown_sdbint_irq,
124 .enable = enable_sdbint_irq,
125 .disable = disable_sdbint_irq,
126 .ack = ack_sdbint_irq,
127 .end = end_sdbint_irq,
130 static int eagle_get_irq_number(int irq)
132 uint8_t sdbint, pciint;
135 sdbint = readb(NEC_EAGLE_SDBINT);
136 sdbint &= (NEC_EAGLE_SDBINT_DEG | NEC_EAGLE_SDBINT_ENUM |
137 NEC_EAGLE_SDBINT_SIO1INT | NEC_EAGLE_SDBINT_SIO2INT |
138 NEC_EAGLE_SDBINT_PARINT);
139 pciint = readb(NEC_EAGLE_PCIINTREG);
140 pciint &= (NEC_EAGLE_PCIINT_CP_INTA | NEC_EAGLE_PCIINT_CP_INTB |
141 NEC_EAGLE_PCIINT_CP_INTC | NEC_EAGLE_PCIINT_CP_INTD |
142 NEC_EAGLE_PCIINT_LANINT);
144 for (i = 1; i < 6; i++)
145 if (sdbint & (0x01 << i))
146 return SDBINT_IRQ_BASE + i;
148 for (i = 0; i < 5; i++)
149 if (pciint & (0x01 << i))
150 return PCIINT_IRQ_BASE + i;
155 static int __devinit eagle_irq_init(void)
159 writeb(0, NEC_EAGLE_SDBINTMSK);
160 writeb(0, NEC_EAGLE_PCIINTMSKREG);
162 vr41xx_set_irq_trigger(PCISLOT_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
163 vr41xx_set_irq_level(PCISLOT_PIN, LEVEL_HIGH);
165 vr41xx_set_irq_trigger(FPGA_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
166 vr41xx_set_irq_level(FPGA_PIN, LEVEL_HIGH);
168 vr41xx_set_irq_trigger(DCD_PIN, TRIGGER_EDGE, SIGNAL_HOLD);
169 vr41xx_set_irq_level(DCD_PIN, LEVEL_LOW);
171 for (i = SDBINT_IRQ_BASE; i <= SDBINT_IRQ_LAST; i++)
172 irq_desc[i].handler = &sdbint_irq_type;
174 for (i = PCIINT_IRQ_BASE; i <= PCIINT_IRQ_LAST; i++)
175 irq_desc[i].handler = &pciint_irq_type;
177 retval = vr41xx_cascade_irq(FPGA_CASCADE_IRQ, eagle_get_irq_number);
179 printk(KERN_ERR "eagle: Cannot cascade IRQ %d\n", FPGA_CASCADE_IRQ);
184 static void __devexit eagle_irq_exit(void)
186 free_irq(FPGA_CASCADE_IRQ, NULL);
189 module_init(eagle_irq_init);
190 module_exit(eagle_irq_exit);