ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / arm / mach-s3c2410 / irq.c
1 /* linux/arch/arm/mach-s3c2410/irq.c
2  *
3  * Copyright (c) 2003 Simtec Electronics
4  * Ben Dooks <ben@simtec.co.uk>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22
23 #include <linux/init.h>
24 #include <linux/module.h>
25 #include <linux/interrupt.h>
26 #include <linux/ioport.h>
27 #include <linux/ptrace.h>
28 #include <linux/sysdev.h>
29
30 #include <asm/hardware.h>
31 #include <asm/irq.h>
32 #include <asm/io.h>
33
34 #include <asm/mach/irq.h>
35
36 #include <asm/arch/regs-irq.h>
37 #include <asm/arch/regs-lcd.h>
38
39 #if 0
40 #include <asm/debug-ll.h>
41 #endif
42
43 #define irqdbf(x...)
44 #define irqdbf2(x...)
45
46 static void
47 s3c_irq_mask(unsigned int irqno)
48 {
49         unsigned long mask;
50
51         irqno -= IRQ_EINT0;
52
53         mask = __raw_readl(S3C2410_INTMSK);
54         mask |= 1UL << irqno;
55         __raw_writel(mask, S3C2410_INTMSK);
56 }
57
58 static inline void
59 s3c_irq_ack(unsigned int irqno)
60 {
61         unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
62
63         __raw_writel(bitval, S3C2410_SRCPND);
64         __raw_writel(bitval, S3C2410_INTPND);
65 }
66
67 static inline void
68 s3c_irq_maskack(unsigned int irqno)
69 {
70         unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
71         unsigned long mask;
72
73         mask = __raw_readl(S3C2410_INTMSK);
74         __raw_writel(mask|bitval, S3C2410_INTMSK);
75
76         __raw_writel(bitval, S3C2410_SRCPND);
77         __raw_writel(bitval, S3C2410_INTPND);
78 }
79
80
81 static void
82 s3c_irq_unmask(unsigned int irqno)
83 {
84         unsigned long mask;
85
86         if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
87                 irqdbf2("s3c_irq_unmask %d\n", irqno);
88
89         irqno -= IRQ_EINT0;
90
91         mask = __raw_readl(S3C2410_INTMSK);
92         mask &= ~(1UL << irqno);
93         __raw_writel(mask, S3C2410_INTMSK);
94 }
95
96 static struct irqchip s3c_irq_level_chip = {
97         .ack       = s3c_irq_maskack,
98         .mask      = s3c_irq_mask,
99         .unmask    = s3c_irq_unmask
100 };
101
102 static struct irqchip s3c_irq_chip = {
103         .ack       = s3c_irq_ack,
104         .mask      = s3c_irq_mask,
105         .unmask    = s3c_irq_unmask
106 };
107
108 /* S3C2410_EINTMASK
109  * S3C2410_EINTPEND
110  */
111
112 #define EXTINT_OFF (IRQ_EINT4 - 4)
113
114 static void
115 s3c_irqext_mask(unsigned int irqno)
116 {
117         unsigned long mask;
118
119         irqno -= EXTINT_OFF;
120
121         mask = __raw_readl(S3C2410_EINTMASK);
122         mask |= ( 1UL << irqno);
123         __raw_writel(mask, S3C2410_EINTMASK);
124
125         if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
126                 /* check to see if all need masking */
127
128                 if ((mask & (0xf << 4)) == (0xf << 4)) {
129                         /* all masked, mask the parent */
130                         s3c_irq_mask(IRQ_EINT4t7);
131                 }
132         } else {
133                 /* todo: the same check as above for the rest of the irq regs...*/
134
135         }
136 }
137
138 static void
139 s3c_irqext_ack(unsigned int irqno)
140 {
141         unsigned long req;
142         unsigned long bit;
143         unsigned long mask;
144
145         bit = 1UL << (irqno - EXTINT_OFF);
146
147
148         mask = __raw_readl(S3C2410_EINTMASK);
149
150         __raw_writel(bit, S3C2410_EINTPEND);
151
152         req = __raw_readl(S3C2410_EINTPEND);
153         req &= ~mask;
154
155         /* not sure if we should be acking the parent irq... */
156
157         if (irqno <= IRQ_EINT7 ) {
158                 if ((req & 0xf0) == 0)
159                         s3c_irq_ack(IRQ_EINT4t7);
160         } else {
161                 if ((req >> 8) == 0)
162                         s3c_irq_ack(IRQ_EINT8t23);
163         }
164 }
165
166 static void
167 s3c_irqext_unmask(unsigned int irqno)
168 {
169         unsigned long mask;
170
171         irqno -= EXTINT_OFF;
172
173         mask = __raw_readl(S3C2410_EINTMASK);
174         mask &= ~( 1UL << irqno);
175         __raw_writel(mask, S3C2410_EINTMASK);
176
177         s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
178 }
179
180 /* todo - put type handler in here */
181
182 static int
183 s3c_irqext_type(unsigned int irq, unsigned int type)
184 {
185         irqdbf("s3c_irqext_type: called for irq %d, type %d\n", irq, type);
186
187         return 0;
188 }
189
190 static struct irqchip s3c_irqext_chip = {
191         .mask       = s3c_irqext_mask,
192         .unmask     = s3c_irqext_unmask,
193         .ack        = s3c_irqext_ack,
194         .type       = s3c_irqext_type
195 };
196
197 /* mask values for the parent registers for each of the interrupt types */
198
199 #define INTMSK_UART0     (1UL << (IRQ_UART0 - IRQ_EINT0))
200 #define INTMSK_UART1     (1UL << (IRQ_UART1 - IRQ_EINT0))
201 #define INTMSK_UART2     (1UL << (IRQ_UART2 - IRQ_EINT0))
202 #define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
203 #define INTMSK_LCD       (1UL << (IRQ_LCD - IRQ_EINT0))
204
205 static inline void
206 s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
207                 int subcheck)
208 {
209         unsigned long mask;
210         unsigned long submask;
211
212         submask = __raw_readl(S3C2410_INTSUBMSK);
213         mask = __raw_readl(S3C2410_INTMSK);
214
215         submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
216
217         /* check to see if we need to mask the parent IRQ */
218
219         if ((submask  & subcheck) == subcheck) {
220                 __raw_writel(mask | parentbit, S3C2410_INTMSK);
221         }
222
223         /* write back masks */
224         __raw_writel(submask, S3C2410_INTSUBMSK);
225
226 }
227
228 static inline void
229 s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
230 {
231         unsigned long mask;
232         unsigned long submask;
233
234         submask = __raw_readl(S3C2410_INTSUBMSK);
235         mask = __raw_readl(S3C2410_INTMSK);
236
237         submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
238         mask &= ~parentbit;
239
240         /* write back masks */
241         __raw_writel(submask, S3C2410_INTSUBMSK);
242         __raw_writel(mask, S3C2410_INTMSK);
243 }
244
245
246 static inline void
247 s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
248 {
249         unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
250
251         s3c_irqsub_mask(irqno, parentmask, group);
252
253         __raw_writel(bit, S3C2410_SUBSRCPND);
254
255         /* only ack parent if we've got all the irqs (seems we must
256          * ack, all and hope that the irq system retriggers ok when
257          * the interrupt goes off again)
258          */
259
260         if (1) {
261                 __raw_writel(parentmask, S3C2410_SRCPND);
262                 __raw_writel(parentmask, S3C2410_INTPND);
263         }
264 }
265
266
267 /* UART0 */
268
269 static void
270 s3c_irq_uart0_mask(unsigned int irqno)
271 {
272         s3c_irqsub_mask(irqno, INTMSK_UART0, 7);
273 }
274
275 static void
276 s3c_irq_uart0_unmask(unsigned int irqno)
277 {
278         s3c_irqsub_unmask(irqno, INTMSK_UART0);
279 }
280
281 static void
282 s3c_irq_uart0_ack(unsigned int irqno)
283 {
284         s3c_irqsub_maskack(irqno, INTMSK_UART0, 7);
285 }
286
287 static struct irqchip s3c_irq_uart0 = {
288         .mask       = s3c_irq_uart0_mask,
289         .unmask     = s3c_irq_uart0_unmask,
290         .ack        = s3c_irq_uart0_ack,
291 };
292
293 /* UART1 */
294
295 static void
296 s3c_irq_uart1_mask(unsigned int irqno)
297 {
298         s3c_irqsub_mask(irqno, INTMSK_UART1, 7 << 3);
299 }
300
301 static void
302 s3c_irq_uart1_unmask(unsigned int irqno)
303 {
304         s3c_irqsub_unmask(irqno, INTMSK_UART1);
305 }
306
307 static void
308 s3c_irq_uart1_ack(unsigned int irqno)
309 {
310         s3c_irqsub_maskack(irqno, INTMSK_UART1, 7 << 3);
311 }
312
313 static struct irqchip s3c_irq_uart1 = {
314         .mask       = s3c_irq_uart1_mask,
315         .unmask     = s3c_irq_uart1_unmask,
316         .ack        = s3c_irq_uart1_ack,
317 };
318
319 /* UART2 */
320
321 static void
322 s3c_irq_uart2_mask(unsigned int irqno)
323 {
324         s3c_irqsub_mask(irqno, INTMSK_UART2, 7 << 6);
325 }
326
327 static void
328 s3c_irq_uart2_unmask(unsigned int irqno)
329 {
330         s3c_irqsub_unmask(irqno, INTMSK_UART2);
331 }
332
333 static void
334 s3c_irq_uart2_ack(unsigned int irqno)
335 {
336         s3c_irqsub_maskack(irqno, INTMSK_UART2, 7 << 6);
337 }
338
339 static struct irqchip s3c_irq_uart2 = {
340         .mask       = s3c_irq_uart2_mask,
341         .unmask     = s3c_irq_uart2_unmask,
342         .ack        = s3c_irq_uart2_ack,
343 };
344
345 /* ADC and Touchscreen */
346
347 static void
348 s3c_irq_adc_mask(unsigned int irqno)
349 {
350         s3c_irqsub_mask(irqno, INTMSK_ADCPARENT, 3 << 9);
351 }
352
353 static void
354 s3c_irq_adc_unmask(unsigned int irqno)
355 {
356         s3c_irqsub_unmask(irqno, INTMSK_ADCPARENT);
357 }
358
359 static void
360 s3c_irq_adc_ack(unsigned int irqno)
361 {
362         s3c_irqsub_maskack(irqno, INTMSK_ADCPARENT, 3 << 9);
363 }
364
365 static struct irqchip s3c_irq_adc = {
366         .mask       = s3c_irq_adc_mask,
367         .unmask     = s3c_irq_adc_unmask,
368         .ack        = s3c_irq_adc_ack,
369 };
370
371 #if 0
372 /* LCD (todo) */
373
374 static void
375 s3c_irq_lcd_mask(unsigned int irqno)
376 {
377
378 }
379
380 static void
381 s3c_irq_lcd_unmask(unsigned int irqno)
382 {
383
384 }
385
386 static void
387 s3c_irq_lcd_ack(unsigned int irqno)
388 {
389
390 }
391
392 static struct irqchip s3c_irq_lcd = {
393         .mask       = s3c_irq_lcd_mask,
394         .unmask     = s3c_irq_lcd_unmask,
395         .ack        = s3c_irq_lcd_ack,
396 };
397 #endif
398
399 /* irq demux */
400
401
402 static void s3c_irq_demux_uart(unsigned int start,
403                                struct pt_regs *regs)
404 {
405         unsigned int subsrc, submsk;
406         unsigned int offset = start - IRQ_S3CUART_RX0;
407         struct irqdesc *desc;
408
409         /* read the current pending interrupts, and the mask
410          * for what it is available */
411
412         subsrc = __raw_readl(S3C2410_SUBSRCPND);
413         submsk = __raw_readl(S3C2410_INTSUBMSK);
414
415         irqdbf2("s3c_irq_demux_uart: start=%d (%d), subsrc=0x%08x,0x%08x\n",
416                 start, offset, subsrc, submsk);
417
418         subsrc &= ~submsk;
419         subsrc >>= offset;
420         subsrc &= 7;
421
422         if (subsrc != 0) {
423                 desc = irq_desc + start;
424
425                 if (subsrc & 1)
426                         desc->handle(start, desc, regs);
427
428                 desc++;
429
430                 if (subsrc & 2)
431                         desc->handle(start+1, desc, regs);
432
433                 desc++;
434
435                 if (subsrc & 4)
436                         desc->handle(start+2, desc, regs);
437         }
438 }
439
440 /* uart demux entry points */
441
442 static void
443 s3c_irq_demux_uart0(unsigned int irq,
444                     struct irqdesc *desc,
445                     struct pt_regs *regs)
446 {
447         irq = irq;
448         s3c_irq_demux_uart(IRQ_S3CUART_RX0, regs);
449 }
450
451 static void
452 s3c_irq_demux_uart1(unsigned int irq,
453                     struct irqdesc *desc,
454                     struct pt_regs *regs)
455 {
456         irq = irq;
457         s3c_irq_demux_uart(IRQ_S3CUART_RX1, regs);
458 }
459
460 static void
461 s3c_irq_demux_uart2(unsigned int irq,
462                     struct irqdesc *desc,
463                     struct pt_regs *regs)
464 {
465         irq = irq;
466         s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
467 }
468
469
470
471 void __init s3c2410_init_irq(void)
472 {
473         unsigned long pend;
474         int irqno;
475         int i;
476
477         irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
478
479         /* first, clear all interrupts pending... */
480
481         for (i = 0; i < 4; i++) {
482                 pend = __raw_readl(S3C2410_EINTPEND);
483                 if (pend == 0)
484                         break;
485                 __raw_writel(pend, S3C2410_EINTPEND);
486                 printk("irq: clearing pending ext status %08x\n", (int)pend);
487         }
488
489         for (i = 0; i < 4; i++) {
490                 pend = __raw_readl(S3C2410_INTPND);
491                 if (pend == 0)
492                         break;
493                 __raw_writel(pend, S3C2410_SRCPND);
494                 __raw_writel(pend, S3C2410_INTPND);
495                 printk("irq: clearing pending status %08x\n", (int)pend);
496         }
497
498         for (i = 0; i < 4; i++) {
499                 pend = __raw_readl(S3C2410_SUBSRCPND);
500
501                 if (pend == 0)
502                         break;
503
504                 printk("irq: clearing subpending status %08x\n", (int)pend);
505                 __raw_writel(pend, S3C2410_SUBSRCPND);
506         }
507
508         /* register the main interrupts */
509
510         irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
511
512         for (irqno = IRQ_EINT0; irqno < IRQ_ADCPARENT; irqno++) {
513                 /* set all the s3c2410 internal irqs */
514
515                 switch (irqno) {
516
517                 case IRQ_EINT4t7:
518                 case IRQ_EINT8t23:
519                         /* these are already dealt with, so should never
520                          * appear */
521                         break;
522
523                         /* deal with the special IRQs (cascaded) */
524
525                 case IRQ_UART0:
526                 case IRQ_UART1:
527                 case IRQ_UART2:
528                 case IRQ_LCD:
529                 case IRQ_ADCPARENT:
530                         set_irq_chip(irqno, &s3c_irq_level_chip);
531                         set_irq_handler(irqno, do_level_IRQ);
532                         break;
533
534                 case IRQ_RESERVED6:
535                 case IRQ_RESERVED24:
536                         /* no IRQ here */
537                         break;
538
539                 default:
540                         //irqdbf("registering irq %d (s3c irq)\n", irqno);
541                         set_irq_chip(irqno, &s3c_irq_chip);
542                         set_irq_handler(irqno, do_edge_IRQ);
543                         set_irq_flags(irqno, IRQF_VALID);
544                 }
545         }
546
547         /* setup the cascade irq handlers */
548
549         set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
550         set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
551         set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
552         //set_irq_chained_handler(IRQ_LCD, s3c_irq_demux_);
553         //set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_);
554
555
556         /* external interrupts */
557
558         for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
559                 irqdbf("registering irq %d (extended s3c irq)\n", irqno);
560                 set_irq_chip(irqno, &s3c_irqext_chip);
561                 set_irq_handler(irqno, do_edge_IRQ);
562                 set_irq_flags(irqno, IRQF_VALID);
563         }
564
565         /* register the uart interrupts */
566
567         irqdbf("s3c2410: registering external interrupts\n");
568
569         for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
570                 irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
571                 set_irq_chip(irqno, &s3c_irq_uart0);
572                 set_irq_handler(irqno, do_level_IRQ);
573                 set_irq_flags(irqno, IRQF_VALID);
574         }
575
576         for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
577                 irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
578                 set_irq_chip(irqno, &s3c_irq_uart1);
579                 set_irq_handler(irqno, do_level_IRQ);
580                 set_irq_flags(irqno, IRQF_VALID);
581         }
582
583         for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
584                 irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
585                 set_irq_chip(irqno, &s3c_irq_uart2);
586                 set_irq_handler(irqno, do_level_IRQ);
587                 set_irq_flags(irqno, IRQF_VALID);
588         }
589
590         for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
591                 irqdbf("registering irq %d (s3c adc irq)\n", irqno);
592                 set_irq_chip(irqno, &s3c_irq_adc);
593                 set_irq_handler(irqno, do_edge_IRQ);
594                 set_irq_flags(irqno, IRQF_VALID);
595         }
596
597         irqdbf("s3c2410: registered interrupt handlers\n");
598 }