[IPV6]: Bring Type 0 routing header in-line with rfc3542.
[pandora-kernel.git] / arch / sh / boards / harp / irq.c
1 /* 
2  * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
3  *
4  * May be copied or modified under the terms of the GNU General Public
5  * License.  See linux/COPYING for more information.                            
6  *
7  * Looks after interrupts on the HARP board.
8  *
9  * Bases on the IPR irq system
10  */
11
12 #include <linux/config.h>
13 #include <linux/init.h>
14 #include <linux/irq.h>
15
16 #include <asm/system.h>
17 #include <asm/io.h>
18 #include <asm/harp/harp.h>
19
20
21 #define NUM_EXTERNAL_IRQS 16
22
23 // Early versions of the STB1 Overdrive required this nasty frig
24 //#define INVERT_INTMASK_WRITES
25
26 static void enable_harp_irq(unsigned int irq);
27 static void disable_harp_irq(unsigned int irq);
28
29 /* shutdown is same as "disable" */
30 #define shutdown_harp_irq disable_harp_irq
31
32 static void mask_and_ack_harp(unsigned int);
33 static void end_harp_irq(unsigned int irq);
34
35 static unsigned int startup_harp_irq(unsigned int irq)
36 {
37         enable_harp_irq(irq);
38         return 0;               /* never anything pending */
39 }
40
41 static struct hw_interrupt_type harp_irq_type = {
42         "Harp-IRQ",
43         startup_harp_irq,
44         shutdown_harp_irq,
45         enable_harp_irq,
46         disable_harp_irq,
47         mask_and_ack_harp,
48         end_harp_irq
49 };
50
51 static void disable_harp_irq(unsigned int irq)
52 {
53         unsigned val, flags;
54         unsigned maskReg;
55         unsigned mask;
56         int pri;
57
58         if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
59                 return;
60
61         pri = 15 - irq;
62
63         if (pri < 8) {
64                 maskReg = EPLD_INTMASK0;
65         } else {
66                 maskReg = EPLD_INTMASK1;
67                 pri -= 8;
68         }
69
70         local_irq_save(flags);
71         mask = ctrl_inl(maskReg);
72         mask &= (~(1 << pri));
73 #if defined(INVERT_INTMASK_WRITES)
74         mask ^= 0xff;
75 #endif
76         ctrl_outl(mask, maskReg);
77         local_irq_restore(flags);
78 }
79
80 static void enable_harp_irq(unsigned int irq)
81 {
82         unsigned flags;
83         unsigned maskReg;
84         unsigned mask;
85         int pri;
86
87         if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
88                 return;
89
90         pri = 15 - irq;
91
92         if (pri < 8) {
93                 maskReg = EPLD_INTMASK0;
94         } else {
95                 maskReg = EPLD_INTMASK1;
96                 pri -= 8;
97         }
98
99         local_irq_save(flags);
100         mask = ctrl_inl(maskReg);
101
102
103         mask |= (1 << pri);
104
105 #if defined(INVERT_INTMASK_WRITES)
106         mask ^= 0xff;
107 #endif
108         ctrl_outl(mask, maskReg);
109
110         local_irq_restore(flags);
111 }
112
113 /* This functions sets the desired irq handler to be an overdrive type */
114 static void __init make_harp_irq(unsigned int irq)
115 {
116         disable_irq_nosync(irq);
117         irq_desc[irq].handler = &harp_irq_type;
118         disable_harp_irq(irq);
119 }
120
121 static void mask_and_ack_harp(unsigned int irq)
122 {
123         disable_harp_irq(irq);
124 }
125
126 static void end_harp_irq(unsigned int irq)
127 {
128         enable_harp_irq(irq);
129 }
130
131 void __init init_harp_irq(void)
132 {
133         int i;
134
135 #if !defined(INVERT_INTMASK_WRITES)
136         // On the harp these are set to enable an interrupt
137         ctrl_outl(0x00, EPLD_INTMASK0);
138         ctrl_outl(0x00, EPLD_INTMASK1);
139 #else
140         // On the Overdrive the data is inverted before being stored in the reg
141         ctrl_outl(0xff, EPLD_INTMASK0);
142         ctrl_outl(0xff, EPLD_INTMASK1);
143 #endif
144
145         for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
146                 make_harp_irq(i);
147         }
148 }