diff options
Diffstat (limited to 'arch/arm/mach-s3c2410/irq.c')
-rw-r--r-- | arch/arm/mach-s3c2410/irq.c | 267 |
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 | ||
181 | static struct irqchip s3c_irq_level_chip = { | 183 | struct 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 | |||
371 | static inline void | ||
372 | s3c_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 | |||
394 | static inline void | ||
395 | s3c_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 | |||
412 | static inline void | ||
413 | s3c_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 | |||
432 | static inline void | ||
433 | s3c_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 | |||
804 | static 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 | |||
836 | static void | ||
837 | s3c_irq_wdtac97_mask(unsigned int irqno) | ||
838 | { | ||
839 | s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13); | ||
840 | } | ||
841 | |||
842 | static void | ||
843 | s3c_irq_wdtac97_unmask(unsigned int irqno) | ||
844 | { | ||
845 | s3c_irqsub_unmask(irqno, INTMSK_WDT); | ||
846 | } | ||
847 | |||
848 | static void | ||
849 | s3c_irq_wdtac97_ack(unsigned int irqno) | ||
850 | { | ||
851 | s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13); | ||
852 | } | ||
853 | |||
854 | static 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 | |||
862 | static 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 | |||
893 | static void | ||
894 | s3c_irq_cam_mask(unsigned int irqno) | ||
895 | { | ||
896 | s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11); | ||
897 | } | ||
898 | |||
899 | static void | ||
900 | s3c_irq_cam_unmask(unsigned int irqno) | ||
901 | { | ||
902 | s3c_irqsub_unmask(irqno, INTMSK_CAM); | ||
903 | } | ||
904 | |||
905 | static void | ||
906 | s3c_irq_cam_ack(unsigned int irqno) | ||
907 | { | ||
908 | s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11); | ||
909 | } | ||
910 | |||
911 | static 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 | |||
917 | static 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 | |||
954 | static struct sysdev_driver s3c2440_irq_driver = { | ||
955 | .add = s3c2440_irq_add, | ||
956 | }; | ||
957 | |||
958 | static int s3c24xx_irq_driver(void) | ||
959 | { | ||
960 | return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver); | ||
961 | } | ||
962 | |||
963 | arch_initcall(s3c24xx_irq_driver); | ||
964 | |||
965 | #endif /* CONFIG_CPU_S3C2440 */ | ||
966 | |||