diff options
author | Ben Dooks <ben-linux@fluff.org> | 2007-02-16 07:02:42 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2007-02-16 07:08:00 -0500 |
commit | 72262e8b19034d2605d452d91717d56738598707 (patch) | |
tree | 9ea71ab251e1d914db4b3e51f3b829b4f36b066c /arch/arm/mach-s3c2443/irq.c | |
parent | 90bc8566fb40b12167b49d972c85d2e509eea55f (diff) |
[ARM] 4202/2: S3C2443: IRQ sub source handlers
Add IRQ handlers for the IRQs which originate
from the sub-interrupt register on the S3C2443
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-s3c2443/irq.c')
-rw-r--r-- | arch/arm/mach-s3c2443/irq.c | 238 |
1 files changed, 199 insertions, 39 deletions
diff --git a/arch/arm/mach-s3c2443/irq.c b/arch/arm/mach-s3c2443/irq.c index f7058823a0e1..7a45b6dcb73e 100644 --- a/arch/arm/mach-s3c2443/irq.c +++ b/arch/arm/mach-s3c2443/irq.c | |||
@@ -39,12 +39,12 @@ | |||
39 | #include <asm/plat-s3c24xx/pm.h> | 39 | #include <asm/plat-s3c24xx/pm.h> |
40 | #include <asm/plat-s3c24xx/irq.h> | 40 | #include <asm/plat-s3c24xx/irq.h> |
41 | 41 | ||
42 | /* WDT/AC97 */ | 42 | #define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) |
43 | 43 | ||
44 | static void s3c_irq_demux_wdtac97(unsigned int irq, | 44 | static inline void s3c2443_irq_demux(unsigned int irq, unsigned int len) |
45 | struct irq_desc *desc) | ||
46 | { | 45 | { |
47 | unsigned int subsrc, submsk; | 46 | unsigned int subsrc, submsk; |
47 | unsigned int end; | ||
48 | struct irq_desc *mydesc; | 48 | struct irq_desc *mydesc; |
49 | 49 | ||
50 | /* read the current pending interrupts, and the mask | 50 | /* read the current pending interrupts, and the mask |
@@ -53,63 +53,199 @@ static void s3c_irq_demux_wdtac97(unsigned int irq, | |||
53 | subsrc = __raw_readl(S3C2410_SUBSRCPND); | 53 | subsrc = __raw_readl(S3C2410_SUBSRCPND); |
54 | submsk = __raw_readl(S3C2410_INTSUBMSK); | 54 | submsk = __raw_readl(S3C2410_INTSUBMSK); |
55 | 55 | ||
56 | subsrc &= ~submsk; | 56 | subsrc &= ~submsk; |
57 | subsrc >>= 27; | 57 | subsrc >>= (irq - S3C2410_IRQSUB(0)); |
58 | subsrc &= 3; | 58 | subsrc &= (1 << len)-1; |
59 | 59 | ||
60 | if (subsrc != 0) { | 60 | end = len + irq; |
61 | if (subsrc & 1) { | 61 | mydesc = irq_desc + irq; |
62 | mydesc = irq_desc + IRQ_S3C2443_WDT; | 62 | |
63 | desc_handle_irq(IRQ_S3C2443_WDT, mydesc); | 63 | for (; irq < end && subsrc; irq++) { |
64 | } | 64 | if (subsrc & 1) |
65 | if (subsrc & 2) { | 65 | desc_handle_irq(irq, mydesc); |
66 | mydesc = irq_desc + IRQ_S3C2443_AC97; | 66 | |
67 | desc_handle_irq(IRQ_S3C2443_AC97, mydesc); | 67 | mydesc++; |
68 | } | 68 | subsrc >>= 1; |
69 | } | 69 | } |
70 | } | 70 | } |
71 | 71 | ||
72 | /* WDT/AC97 sub interrupts */ | ||
73 | |||
74 | static void s3c2443_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) | ||
75 | { | ||
76 | s3c2443_irq_demux(IRQ_S3C2443_WDT, 4); | ||
77 | } | ||
72 | 78 | ||
73 | #define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0)) | 79 | #define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) |
80 | #define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) | ||
74 | 81 | ||
75 | static void | 82 | static void s3c2443_irq_wdtac97_mask(unsigned int irqno) |
76 | s3c_irq_wdtac97_mask(unsigned int irqno) | ||
77 | { | 83 | { |
78 | s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<27); | 84 | s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); |
79 | } | 85 | } |
80 | 86 | ||
81 | static void | 87 | static void s3c2443_irq_wdtac97_unmask(unsigned int irqno) |
82 | s3c_irq_wdtac97_unmask(unsigned int irqno) | ||
83 | { | 88 | { |
84 | s3c_irqsub_unmask(irqno, INTMSK_WDT); | 89 | s3c_irqsub_unmask(irqno, INTMSK_WDTAC97); |
85 | } | 90 | } |
86 | 91 | ||
87 | static void | 92 | static void s3c2443_irq_wdtac97_ack(unsigned int irqno) |
88 | s3c_irq_wdtac97_ack(unsigned int irqno) | ||
89 | { | 93 | { |
90 | s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<27); | 94 | s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); |
91 | } | 95 | } |
92 | 96 | ||
93 | static struct irq_chip s3c_irq_wdtac97 = { | 97 | static struct irq_chip s3c2443_irq_wdtac97 = { |
94 | .mask = s3c_irq_wdtac97_mask, | 98 | .mask = s3c2443_irq_wdtac97_mask, |
95 | .unmask = s3c_irq_wdtac97_unmask, | 99 | .unmask = s3c2443_irq_wdtac97_unmask, |
96 | .ack = s3c_irq_wdtac97_ack, | 100 | .ack = s3c2443_irq_wdtac97_ack, |
97 | }; | 101 | }; |
98 | 102 | ||
99 | static int s3c2443_irq_add(struct sys_device *sysdev) | 103 | |
104 | /* LCD sub interrupts */ | ||
105 | |||
106 | static void s3c2443_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) | ||
100 | { | 107 | { |
101 | unsigned int irqno; | 108 | s3c2443_irq_demux(IRQ_S3C2443_LCD1, 4); |
109 | } | ||
102 | 110 | ||
103 | printk("S3C2443: IRQ Support\n"); | 111 | #define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) |
112 | #define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) | ||
113 | |||
114 | static void s3c2443_irq_lcd_mask(unsigned int irqno) | ||
115 | { | ||
116 | s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD); | ||
117 | } | ||
118 | |||
119 | static void s3c2443_irq_lcd_unmask(unsigned int irqno) | ||
120 | { | ||
121 | s3c_irqsub_unmask(irqno, INTMSK_LCD); | ||
122 | } | ||
123 | |||
124 | static void s3c2443_irq_lcd_ack(unsigned int irqno) | ||
125 | { | ||
126 | s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD); | ||
127 | } | ||
128 | |||
129 | static struct irq_chip s3c2443_irq_lcd = { | ||
130 | .mask = s3c2443_irq_lcd_mask, | ||
131 | .unmask = s3c2443_irq_lcd_unmask, | ||
132 | .ack = s3c2443_irq_lcd_ack, | ||
133 | }; | ||
134 | |||
135 | |||
136 | /* DMA sub interrupts */ | ||
137 | |||
138 | static void s3c2443_irq_demux_dma(unsigned int irq, struct irq_desc *desc) | ||
139 | { | ||
140 | s3c2443_irq_demux(IRQ_S3C2443_DMA1, 6); | ||
141 | } | ||
142 | |||
143 | #define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) | ||
144 | #define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) | ||
145 | |||
146 | |||
147 | static void s3c2443_irq_dma_mask(unsigned int irqno) | ||
148 | { | ||
149 | s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA); | ||
150 | } | ||
151 | |||
152 | static void s3c2443_irq_dma_unmask(unsigned int irqno) | ||
153 | { | ||
154 | s3c_irqsub_unmask(irqno, INTMSK_DMA); | ||
155 | } | ||
156 | |||
157 | static void s3c2443_irq_dma_ack(unsigned int irqno) | ||
158 | { | ||
159 | s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA); | ||
160 | } | ||
161 | |||
162 | static struct irq_chip s3c2443_irq_dma = { | ||
163 | .mask = s3c2443_irq_dma_mask, | ||
164 | .unmask = s3c2443_irq_dma_unmask, | ||
165 | .ack = s3c2443_irq_dma_ack, | ||
166 | }; | ||
167 | |||
168 | |||
169 | /* UART3 sub interrupts */ | ||
170 | |||
171 | static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) | ||
172 | { | ||
173 | s3c2443_irq_demux(IRQ_S3C2443_UART3, 3); | ||
174 | } | ||
104 | 175 | ||
105 | /* add new chained handler for wdt, ac7 */ | 176 | #define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) |
177 | #define SUBMSK_UART3 (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) | ||
106 | 178 | ||
107 | set_irq_chip(IRQ_WDT, &s3c_irq_level_chip); | ||
108 | set_irq_handler(IRQ_WDT, handle_level_irq); | ||
109 | set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97); | ||
110 | 179 | ||
111 | for (irqno = IRQ_S3C2443_WDT; irqno <= IRQ_S3C2443_AC97; irqno++) { | 180 | static void s3c2443_irq_uart3_mask(unsigned int irqno) |
112 | set_irq_chip(irqno, &s3c_irq_wdtac97); | 181 | { |
182 | s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3); | ||
183 | } | ||
184 | |||
185 | static void s3c2443_irq_uart3_unmask(unsigned int irqno) | ||
186 | { | ||
187 | s3c_irqsub_unmask(irqno, INTMSK_UART3); | ||
188 | } | ||
189 | |||
190 | static void s3c2443_irq_uart3_ack(unsigned int irqno) | ||
191 | { | ||
192 | s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3); | ||
193 | } | ||
194 | |||
195 | static struct irq_chip s3c2443_irq_uart3 = { | ||
196 | .mask = s3c2443_irq_uart3_mask, | ||
197 | .unmask = s3c2443_irq_uart3_unmask, | ||
198 | .ack = s3c2443_irq_uart3_ack, | ||
199 | }; | ||
200 | |||
201 | |||
202 | /* CAM sub interrupts */ | ||
203 | |||
204 | static void s3c2443_irq_demux_cam(unsigned int irq, struct irq_desc *desc) | ||
205 | { | ||
206 | s3c2443_irq_demux(IRQ_S3C2440_CAM_C, 4); | ||
207 | } | ||
208 | |||
209 | #define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) | ||
210 | #define SUBMSK_CAM INTMSK(IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P) | ||
211 | |||
212 | static void s3c2443_irq_cam_mask(unsigned int irqno) | ||
213 | { | ||
214 | s3c_irqsub_mask(irqno, INTMSK_CAM, SUBMSK_CAM); | ||
215 | } | ||
216 | |||
217 | static void s3c2443_irq_cam_unmask(unsigned int irqno) | ||
218 | { | ||
219 | s3c_irqsub_unmask(irqno, INTMSK_CAM); | ||
220 | } | ||
221 | |||
222 | static void s3c2443_irq_cam_ack(unsigned int irqno) | ||
223 | { | ||
224 | s3c_irqsub_maskack(irqno, INTMSK_CAM, SUBMSK_CAM); | ||
225 | } | ||
226 | |||
227 | static struct irq_chip s3c2443_irq_cam = { | ||
228 | .mask = s3c2443_irq_cam_mask, | ||
229 | .unmask = s3c2443_irq_cam_unmask, | ||
230 | .ack = s3c2443_irq_cam_ack, | ||
231 | }; | ||
232 | |||
233 | /* IRQ initialisation code */ | ||
234 | |||
235 | static int __init s3c2443_add_sub(unsigned int base, | ||
236 | void (*demux)(unsigned int, | ||
237 | struct irq_desc *), | ||
238 | struct irq_chip *chip, | ||
239 | unsigned int start, unsigned int end) | ||
240 | { | ||
241 | unsigned int irqno; | ||
242 | |||
243 | set_irq_chip(base, &s3c_irq_level_chip); | ||
244 | set_irq_handler(base, handle_level_irq); | ||
245 | set_irq_chained_handler(base, demux); | ||
246 | |||
247 | for (irqno = start; irqno <= end; irqno++) { | ||
248 | set_irq_chip(irqno, chip); | ||
113 | set_irq_handler(irqno, handle_level_irq); | 249 | set_irq_handler(irqno, handle_level_irq); |
114 | set_irq_flags(irqno, IRQF_VALID); | 250 | set_irq_flags(irqno, IRQF_VALID); |
115 | } | 251 | } |
@@ -117,6 +253,30 @@ static int s3c2443_irq_add(struct sys_device *sysdev) | |||
117 | return 0; | 253 | return 0; |
118 | } | 254 | } |
119 | 255 | ||
256 | static int s3c2443_irq_add(struct sys_device *sysdev) | ||
257 | { | ||
258 | printk("S3C2443: IRQ Support\n"); | ||
259 | |||
260 | s3c2443_add_sub(IRQ_CAM, s3c2443_irq_demux_cam, &s3c2443_irq_cam, | ||
261 | IRQ_S3C2440_CAM_C, IRQ_S3C2440_CAM_P); | ||
262 | |||
263 | s3c2443_add_sub(IRQ_LCD, s3c2443_irq_demux_lcd, &s3c2443_irq_lcd, | ||
264 | IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4); | ||
265 | |||
266 | s3c2443_add_sub(IRQ_S3C2443_DMA, s3c2443_irq_demux_dma, | ||
267 | &s3c2443_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); | ||
268 | |||
269 | s3c2443_add_sub(IRQ_S3C2443_UART3, s3c2443_irq_demux_uart3, | ||
270 | &s3c2443_irq_uart3, | ||
271 | IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); | ||
272 | |||
273 | s3c2443_add_sub(IRQ_WDT, s3c2443_irq_demux_wdtac97, | ||
274 | &s3c2443_irq_wdtac97, | ||
275 | IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
120 | static struct sysdev_driver s3c2443_irq_driver = { | 280 | static struct sysdev_driver s3c2443_irq_driver = { |
121 | .add = s3c2443_irq_add, | 281 | .add = s3c2443_irq_add, |
122 | }; | 282 | }; |