aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2410/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-s3c2410/irq.c')
-rw-r--r--arch/arm/mach-s3c2410/irq.c267
1 files changed, 9 insertions, 258 deletions
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index b668c48f4399..973a5fe6769c 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -40,8 +40,14 @@
40 * 04-Nov-2004 Ben Dooks 40 * 04-Nov-2004 Ben Dooks
41 * Fix standard IRQ wake for EINT0..4 and RTC 41 * Fix standard IRQ wake for EINT0..4 and RTC
42 * 42 *
43 * 22-Feb-2004 Ben Dooks 43 * 22-Feb-2005 Ben Dooks
44 * Fixed edge-triggering on ADC IRQ 44 * Fixed edge-triggering on ADC IRQ
45 *
46 * 28-Jun-2005 Ben Dooks
47 * Mark IRQ_LCD valid
48 *
49 * 25-Jul-2005 Ben Dooks
50 * Split the S3C2440 IRQ code to seperate file
45*/ 51*/
46 52
47#include <linux/init.h> 53#include <linux/init.h>
@@ -62,11 +68,7 @@
62 68
63#include "cpu.h" 69#include "cpu.h"
64#include "pm.h" 70#include "pm.h"
65 71#include "irq.h"
66#define irqdbf(x...)
67#define irqdbf2(x...)
68
69#define EXTINT_OFF (IRQ_EINT4 - 4)
70 72
71/* wakeup irq control */ 73/* wakeup irq control */
72 74
@@ -178,7 +180,7 @@ s3c_irq_unmask(unsigned int irqno)
178 __raw_writel(mask, S3C2410_INTMSK); 180 __raw_writel(mask, S3C2410_INTMSK);
179} 181}
180 182
181static struct irqchip s3c_irq_level_chip = { 183struct irqchip s3c_irq_level_chip = {
182 .ack = s3c_irq_maskack, 184 .ack = s3c_irq_maskack,
183 .mask = s3c_irq_mask, 185 .mask = s3c_irq_mask,
184 .unmask = s3c_irq_unmask, 186 .unmask = s3c_irq_unmask,
@@ -366,86 +368,7 @@ static struct irqchip s3c_irq_eint0t4 = {
366#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0)) 368#define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0))
367#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0)) 369#define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0))
368#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0)) 370#define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0))
369#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0))
370
371static inline void
372s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit,
373 int subcheck)
374{
375 unsigned long mask;
376 unsigned long submask;
377
378 submask = __raw_readl(S3C2410_INTSUBMSK);
379 mask = __raw_readl(S3C2410_INTMSK);
380
381 submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
382
383 /* check to see if we need to mask the parent IRQ */
384
385 if ((submask & subcheck) == subcheck) {
386 __raw_writel(mask | parentbit, S3C2410_INTMSK);
387 }
388
389 /* write back masks */
390 __raw_writel(submask, S3C2410_INTSUBMSK);
391
392}
393
394static inline void
395s3c_irqsub_unmask(unsigned int irqno, unsigned int parentbit)
396{
397 unsigned long mask;
398 unsigned long submask;
399
400 submask = __raw_readl(S3C2410_INTSUBMSK);
401 mask = __raw_readl(S3C2410_INTMSK);
402
403 submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
404 mask &= ~parentbit;
405
406 /* write back masks */
407 __raw_writel(submask, S3C2410_INTSUBMSK);
408 __raw_writel(mask, S3C2410_INTMSK);
409}
410
411
412static inline void
413s3c_irqsub_maskack(unsigned int irqno, unsigned int parentmask, unsigned int group)
414{
415 unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
416
417 s3c_irqsub_mask(irqno, parentmask, group);
418
419 __raw_writel(bit, S3C2410_SUBSRCPND);
420
421 /* only ack parent if we've got all the irqs (seems we must
422 * ack, all and hope that the irq system retriggers ok when
423 * the interrupt goes off again)
424 */
425
426 if (1) {
427 __raw_writel(parentmask, S3C2410_SRCPND);
428 __raw_writel(parentmask, S3C2410_INTPND);
429 }
430}
431
432static inline void
433s3c_irqsub_ack(unsigned int irqno, unsigned int parentmask, unsigned int group)
434{
435 unsigned int bit = 1UL << (irqno - IRQ_S3CUART_RX0);
436
437 __raw_writel(bit, S3C2410_SUBSRCPND);
438 371
439 /* only ack parent if we've got all the irqs (seems we must
440 * ack, all and hope that the irq system retriggers ok when
441 * the interrupt goes off again)
442 */
443
444 if (1) {
445 __raw_writel(parentmask, S3C2410_SRCPND);
446 __raw_writel(parentmask, S3C2410_INTPND);
447 }
448}
449 372
450/* UART0 */ 373/* UART0 */
451 374
@@ -716,7 +639,6 @@ void __init s3c24xx_init_irq(void)
716 case IRQ_UART0: 639 case IRQ_UART0:
717 case IRQ_UART1: 640 case IRQ_UART1:
718 case IRQ_UART2: 641 case IRQ_UART2:
719 case IRQ_LCD:
720 case IRQ_ADCPARENT: 642 case IRQ_ADCPARENT:
721 set_irq_chip(irqno, &s3c_irq_level_chip); 643 set_irq_chip(irqno, &s3c_irq_level_chip);
722 set_irq_handler(irqno, do_level_IRQ); 644 set_irq_handler(irqno, do_level_IRQ);
@@ -793,174 +715,3 @@ void __init s3c24xx_init_irq(void)
793 715
794 irqdbf("s3c2410: registered interrupt handlers\n"); 716 irqdbf("s3c2410: registered interrupt handlers\n");
795} 717}
796
797/* s3c2440 irq code
798*/
799
800#ifdef CONFIG_CPU_S3C2440
801
802/* WDT/AC97 */
803
804static void s3c_irq_demux_wdtac97(unsigned int irq,
805 struct irqdesc *desc,
806 struct pt_regs *regs)
807{
808 unsigned int subsrc, submsk;
809 struct irqdesc *mydesc;
810
811 /* read the current pending interrupts, and the mask
812 * for what it is available */
813
814 subsrc = __raw_readl(S3C2410_SUBSRCPND);
815 submsk = __raw_readl(S3C2410_INTSUBMSK);
816
817 subsrc &= ~submsk;
818 subsrc >>= 13;
819 subsrc &= 3;
820
821 if (subsrc != 0) {
822 if (subsrc & 1) {
823 mydesc = irq_desc + IRQ_S3C2440_WDT;
824 mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
825 }
826 if (subsrc & 2) {
827 mydesc = irq_desc + IRQ_S3C2440_AC97;
828 mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
829 }
830 }
831}
832
833
834#define INTMSK_WDT (1UL << (IRQ_WDT - IRQ_EINT0))
835
836static void
837s3c_irq_wdtac97_mask(unsigned int irqno)
838{
839 s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
840}
841
842static void
843s3c_irq_wdtac97_unmask(unsigned int irqno)
844{
845 s3c_irqsub_unmask(irqno, INTMSK_WDT);
846}
847
848static void
849s3c_irq_wdtac97_ack(unsigned int irqno)
850{
851 s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
852}
853
854static struct irqchip s3c_irq_wdtac97 = {
855 .mask = s3c_irq_wdtac97_mask,
856 .unmask = s3c_irq_wdtac97_unmask,
857 .ack = s3c_irq_wdtac97_ack,
858};
859
860/* camera irq */
861
862static void s3c_irq_demux_cam(unsigned int irq,
863 struct irqdesc *desc,
864 struct pt_regs *regs)
865{
866 unsigned int subsrc, submsk;
867 struct irqdesc *mydesc;
868
869 /* read the current pending interrupts, and the mask
870 * for what it is available */
871
872 subsrc = __raw_readl(S3C2410_SUBSRCPND);
873 submsk = __raw_readl(S3C2410_INTSUBMSK);
874
875 subsrc &= ~submsk;
876 subsrc >>= 11;
877 subsrc &= 3;
878
879 if (subsrc != 0) {
880 if (subsrc & 1) {
881 mydesc = irq_desc + IRQ_S3C2440_CAM_C;
882 mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
883 }
884 if (subsrc & 2) {
885 mydesc = irq_desc + IRQ_S3C2440_CAM_P;
886 mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
887 }
888 }
889}
890
891#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
892
893static void
894s3c_irq_cam_mask(unsigned int irqno)
895{
896 s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
897}
898
899static void
900s3c_irq_cam_unmask(unsigned int irqno)
901{
902 s3c_irqsub_unmask(irqno, INTMSK_CAM);
903}
904
905static void
906s3c_irq_cam_ack(unsigned int irqno)
907{
908 s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
909}
910
911static struct irqchip s3c_irq_cam = {
912 .mask = s3c_irq_cam_mask,
913 .unmask = s3c_irq_cam_unmask,
914 .ack = s3c_irq_cam_ack,
915};
916
917static int s3c2440_irq_add(struct sys_device *sysdev)
918{
919 unsigned int irqno;
920
921 printk("S3C2440: IRQ Support\n");
922
923 set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
924 set_irq_handler(IRQ_NFCON, do_level_IRQ);
925 set_irq_flags(IRQ_NFCON, IRQF_VALID);
926
927 /* add new chained handler for wdt, ac7 */
928
929 set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
930 set_irq_handler(IRQ_WDT, do_level_IRQ);
931 set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
932
933 for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
934 set_irq_chip(irqno, &s3c_irq_wdtac97);
935 set_irq_handler(irqno, do_level_IRQ);
936 set_irq_flags(irqno, IRQF_VALID);
937 }
938
939 /* add chained handler for camera */
940
941 set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
942 set_irq_handler(IRQ_CAM, do_level_IRQ);
943 set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
944
945 for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
946 set_irq_chip(irqno, &s3c_irq_cam);
947 set_irq_handler(irqno, do_level_IRQ);
948 set_irq_flags(irqno, IRQF_VALID);
949 }
950
951 return 0;
952}
953
954static struct sysdev_driver s3c2440_irq_driver = {
955 .add = s3c2440_irq_add,
956};
957
958static int s3c24xx_irq_driver(void)
959{
960 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
961}
962
963arch_initcall(s3c24xx_irq_driver);
964
965#endif /* CONFIG_CPU_S3C2440 */
966