Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * arch/mips/vr41xx/nec-cmbvr4133/irq.c | |
3 | * | |
4 | * Interrupt routines for the NEC CMB-VR4133 board. | |
5 | * | |
6 | * Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com> and | |
7 | * Alex Sapkov <asapkov@ru.mvista.com> | |
8 | * | |
9 | * 2003-2004 (c) MontaVista, Software, Inc. This file is licensed under | |
10 | * the terms of the GNU General Public License version 2. This program | |
11 | * is licensed "as is" without any warranty of any kind, whether express | |
12 | * or implied. | |
13 | * | |
14 | * Support for NEC-CMBVR4133 in 2.6 | |
15 | * Manish Lachwani (mlachwani@mvista.com) | |
16 | */ | |
17 | #include <linux/bitops.h> | |
18 | #include <linux/errno.h> | |
19 | #include <linux/init.h> | |
20 | #include <linux/ioport.h> | |
21 | #include <linux/interrupt.h> | |
22 | ||
23 | #include <asm/io.h> | |
24 | #include <asm/vr41xx/cmbvr4133.h> | |
25 | ||
26 | extern void enable_8259A_irq(unsigned int irq); | |
27 | extern void disable_8259A_irq(unsigned int irq); | |
28 | extern void mask_and_ack_8259A(unsigned int irq); | |
29 | extern void init_8259A(int hoge); | |
30 | ||
31 | extern int vr4133_rockhopper; | |
32 | ||
1da177e4 LT |
33 | static void enable_i8259_irq(unsigned int irq) |
34 | { | |
35 | enable_8259A_irq(irq - I8259_IRQ_BASE); | |
36 | } | |
37 | ||
38 | static void disable_i8259_irq(unsigned int irq) | |
39 | { | |
40 | disable_8259A_irq(irq - I8259_IRQ_BASE); | |
41 | } | |
42 | ||
43 | static void ack_i8259_irq(unsigned int irq) | |
44 | { | |
45 | mask_and_ack_8259A(irq - I8259_IRQ_BASE); | |
46 | } | |
47 | ||
48 | static void end_i8259_irq(unsigned int irq) | |
49 | { | |
50 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | |
51 | enable_8259A_irq(irq - I8259_IRQ_BASE); | |
52 | } | |
53 | ||
94dee171 | 54 | static struct irq_chip i8259_irq_type = { |
1da177e4 | 55 | .typename = "XT-PIC", |
1da177e4 | 56 | .ack = ack_i8259_irq, |
1603b5ac AN |
57 | .mask = disable_i8259_irq, |
58 | .mask_ack = ack_i8259_irq, | |
59 | .unmask = enable_i8259_irq, | |
1da177e4 LT |
60 | .end = end_i8259_irq, |
61 | }; | |
62 | ||
63 | static int i8259_get_irq_number(int irq) | |
64 | { | |
65 | unsigned long isr; | |
66 | ||
67 | isr = inb(0x20); | |
68 | irq = ffz(~isr); | |
69 | if (irq == 2) { | |
70 | isr = inb(0xa0); | |
71 | irq = 8 + ffz(~isr); | |
72 | } | |
73 | ||
74 | if (irq < 0 || irq > 15) | |
75 | return -EINVAL; | |
76 | ||
77 | return I8259_IRQ_BASE + irq; | |
78 | } | |
79 | ||
80 | static struct irqaction i8259_slave_cascade = { | |
81 | .handler = &no_action, | |
82 | .name = "cascade", | |
83 | }; | |
84 | ||
85 | void __init rockhopper_init_irq(void) | |
86 | { | |
87 | int i; | |
88 | ||
89 | if(!vr4133_rockhopper) { | |
90 | printk(KERN_ERR "Not a Rockhopper Board \n"); | |
91 | return; | |
92 | } | |
93 | ||
94 | for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++) | |
1603b5ac | 95 | set_irq_chip(i, &i8259_irq_type); |
1da177e4 LT |
96 | |
97 | setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade); | |
98 | ||
99 | vr41xx_set_irq_trigger(CMBVR41XX_INTC_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH); | |
100 | vr41xx_set_irq_level(CMBVR41XX_INTC_PIN, LEVEL_HIGH); | |
101 | vr41xx_cascade_irq(CMBVR41XX_INTC_IRQ, i8259_get_irq_number); | |
102 | } |