diff options
author | Heiko Stuebner <heiko@sntech.de> | 2013-01-29 13:25:22 -0500 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2013-02-03 18:52:49 -0500 |
commit | 20f6c781c7d801e142fccbc04ec9c6dc639f5943 (patch) | |
tree | 3a9674c691a28ab7877b2c86ddc63e4fe446e0cb /arch/arm/plat-s3c24xx/irq.c | |
parent | 4a282dd3b616a1e7a7f170973ed2a12332544dc3 (diff) |
ARM: S3C24XX: transform s3c2416 irqs into new structure
Share the common irq code by simply defining a correct mapping declaration
for the s3c2416.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/plat-s3c24xx/irq.c')
-rw-r--r-- | arch/arm/plat-s3c24xx/irq.c | 342 |
1 files changed, 87 insertions, 255 deletions
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c index 5b325b26f771..21b2c9d55e77 100644 --- a/arch/arm/plat-s3c24xx/irq.c +++ b/arch/arm/plat-s3c24xx/irq.c | |||
@@ -352,7 +352,8 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq, | |||
352 | handle_edge_irq); | 352 | handle_edge_irq); |
353 | break; | 353 | break; |
354 | case S3C_IRQTYPE_EDGE: | 354 | case S3C_IRQTYPE_EDGE: |
355 | if (irq_data->parent_irq) | 355 | if (irq_data->parent_irq || |
356 | intc->reg_pending == S3C2416_SRCPND2) | ||
356 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, | 357 | irq_set_chip_and_handler(virq, &s3c_irq_level_chip, |
357 | handle_edge_irq); | 358 | handle_edge_irq); |
358 | else | 359 | else |
@@ -628,273 +629,104 @@ void __init s3c24xx_init_irq(void) | |||
628 | } | 629 | } |
629 | 630 | ||
630 | #ifdef CONFIG_CPU_S3C2416 | 631 | #ifdef CONFIG_CPU_S3C2416 |
631 | #define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) | 632 | static struct s3c_irq_data init_s3c2416base[32] = { |
632 | 633 | { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ | |
633 | static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len) | 634 | { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ |
634 | { | 635 | { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ |
635 | unsigned int subsrc, submsk; | 636 | { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ |
636 | unsigned int end; | 637 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ |
637 | 638 | { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ | |
638 | /* read the current pending interrupts, and the mask | 639 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ |
639 | * for what it is available */ | 640 | { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */ |
640 | 641 | { .type = S3C_IRQTYPE_EDGE, }, /* TICK */ | |
641 | subsrc = __raw_readl(S3C2410_SUBSRCPND); | 642 | { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */ |
642 | submsk = __raw_readl(S3C2410_INTSUBMSK); | 643 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */ |
643 | 644 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */ | |
644 | subsrc &= ~submsk; | 645 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */ |
645 | subsrc >>= (irq - S3C2410_IRQSUB(0)); | 646 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */ |
646 | subsrc &= (1 << len)-1; | 647 | { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */ |
647 | 648 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */ | |
648 | end = len + irq; | 649 | { .type = S3C_IRQTYPE_LEVEL, }, /* LCD */ |
649 | 650 | { .type = S3C_IRQTYPE_LEVEL, }, /* DMA */ | |
650 | for (; irq < end && subsrc; irq++) { | 651 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART3 */ |
651 | if (subsrc & 1) | 652 | { .type = S3C_IRQTYPE_NONE, }, /* reserved */ |
652 | generic_handle_irq(irq); | 653 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI1 */ |
653 | 654 | { .type = S3C_IRQTYPE_EDGE, }, /* SDI0 */ | |
654 | subsrc >>= 1; | 655 | { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */ |
655 | } | 656 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */ |
656 | } | 657 | { .type = S3C_IRQTYPE_EDGE, }, /* NAND */ |
657 | 658 | { .type = S3C_IRQTYPE_EDGE, }, /* USBD */ | |
658 | /* WDT/AC97 sub interrupts */ | 659 | { .type = S3C_IRQTYPE_EDGE, }, /* USBH */ |
659 | 660 | { .type = S3C_IRQTYPE_EDGE, }, /* IIC */ | |
660 | static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) | 661 | { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */ |
661 | { | 662 | { .type = S3C_IRQTYPE_NONE, }, |
662 | s3c2416_irq_demux(IRQ_S3C2443_WDT, 4); | 663 | { .type = S3C_IRQTYPE_EDGE, }, /* RTC */ |
663 | } | 664 | { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ |
664 | |||
665 | #define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) | ||
666 | #define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) | ||
667 | |||
668 | static void s3c2416_irq_wdtac97_mask(struct irq_data *data) | ||
669 | { | ||
670 | s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
671 | } | ||
672 | |||
673 | static void s3c2416_irq_wdtac97_unmask(struct irq_data *data) | ||
674 | { | ||
675 | s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97); | ||
676 | } | ||
677 | |||
678 | static void s3c2416_irq_wdtac97_ack(struct irq_data *data) | ||
679 | { | ||
680 | s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97); | ||
681 | } | ||
682 | |||
683 | static struct irq_chip s3c2416_irq_wdtac97 = { | ||
684 | .irq_mask = s3c2416_irq_wdtac97_mask, | ||
685 | .irq_unmask = s3c2416_irq_wdtac97_unmask, | ||
686 | .irq_ack = s3c2416_irq_wdtac97_ack, | ||
687 | }; | ||
688 | |||
689 | /* LCD sub interrupts */ | ||
690 | |||
691 | static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) | ||
692 | { | ||
693 | s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4); | ||
694 | } | ||
695 | |||
696 | #define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) | ||
697 | #define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) | ||
698 | |||
699 | static void s3c2416_irq_lcd_mask(struct irq_data *data) | ||
700 | { | ||
701 | s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD); | ||
702 | } | ||
703 | |||
704 | static void s3c2416_irq_lcd_unmask(struct irq_data *data) | ||
705 | { | ||
706 | s3c_irqsub_unmask(data->irq, INTMSK_LCD); | ||
707 | } | ||
708 | |||
709 | static void s3c2416_irq_lcd_ack(struct irq_data *data) | ||
710 | { | ||
711 | s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD); | ||
712 | } | ||
713 | |||
714 | static struct irq_chip s3c2416_irq_lcd = { | ||
715 | .irq_mask = s3c2416_irq_lcd_mask, | ||
716 | .irq_unmask = s3c2416_irq_lcd_unmask, | ||
717 | .irq_ack = s3c2416_irq_lcd_ack, | ||
718 | }; | ||
719 | |||
720 | /* DMA sub interrupts */ | ||
721 | |||
722 | static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc) | ||
723 | { | ||
724 | s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6); | ||
725 | } | ||
726 | |||
727 | #define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) | ||
728 | #define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) | ||
729 | |||
730 | |||
731 | static void s3c2416_irq_dma_mask(struct irq_data *data) | ||
732 | { | ||
733 | s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA); | ||
734 | } | ||
735 | |||
736 | static void s3c2416_irq_dma_unmask(struct irq_data *data) | ||
737 | { | ||
738 | s3c_irqsub_unmask(data->irq, INTMSK_DMA); | ||
739 | } | ||
740 | |||
741 | static void s3c2416_irq_dma_ack(struct irq_data *data) | ||
742 | { | ||
743 | s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA); | ||
744 | } | ||
745 | |||
746 | static struct irq_chip s3c2416_irq_dma = { | ||
747 | .irq_mask = s3c2416_irq_dma_mask, | ||
748 | .irq_unmask = s3c2416_irq_dma_unmask, | ||
749 | .irq_ack = s3c2416_irq_dma_ack, | ||
750 | }; | 665 | }; |
751 | 666 | ||
752 | /* UART3 sub interrupts */ | 667 | static struct s3c_irq_data init_s3c2416subint[32] = { |
753 | 668 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ | |
754 | static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) | 669 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ |
755 | { | 670 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */ |
756 | s3c2416_irq_demux(IRQ_S3C2443_RX3, 3); | 671 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */ |
757 | } | 672 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */ |
758 | 673 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */ | |
759 | #define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) | 674 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */ |
760 | #define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) | 675 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */ |
761 | 676 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */ | |
762 | static void s3c2416_irq_uart3_mask(struct irq_data *data) | 677 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */ |
763 | { | 678 | { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */ |
764 | s3c_irqsub_mask(data->irq, INTMSK_UART3, SUBMSK_UART3); | 679 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ |
765 | } | 680 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ |
766 | 681 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ | |
767 | static void s3c2416_irq_uart3_unmask(struct irq_data *data) | 682 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ |
768 | { | 683 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD2 */ |
769 | s3c_irqsub_unmask(data->irq, INTMSK_UART3); | 684 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD3 */ |
770 | } | 685 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 16 }, /* LCD4 */ |
771 | 686 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA0 */ | |
772 | static void s3c2416_irq_uart3_ack(struct irq_data *data) | 687 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA1 */ |
773 | { | 688 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA2 */ |
774 | s3c_irqsub_maskack(data->irq, INTMSK_UART3, SUBMSK_UART3); | 689 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA3 */ |
775 | } | 690 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA4 */ |
776 | 691 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 17 }, /* DMA5 */ | |
777 | static struct irq_chip s3c2416_irq_uart3 = { | 692 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-RX */ |
778 | .irq_mask = s3c2416_irq_uart3_mask, | 693 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-TX */ |
779 | .irq_unmask = s3c2416_irq_uart3_unmask, | 694 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 18 }, /* UART3-ERR */ |
780 | .irq_ack = s3c2416_irq_uart3_ack, | 695 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */ |
696 | { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */ | ||
781 | }; | 697 | }; |
782 | 698 | ||
783 | /* second interrupt register */ | 699 | static struct s3c_irq_data init_s3c2416_second[32] = { |
784 | 700 | { .type = S3C_IRQTYPE_EDGE }, /* 2D */ | |
785 | static inline void s3c2416_irq_ack_second(struct irq_data *data) | 701 | { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */ |
786 | { | 702 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ |
787 | unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); | 703 | { .type = S3C_IRQTYPE_NONE }, /* reserved */ |
788 | 704 | { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */ | |
789 | __raw_writel(bitval, S3C2416_SRCPND2); | 705 | { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */ |
790 | __raw_writel(bitval, S3C2416_INTPND2); | 706 | { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */ |
791 | } | 707 | { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */ |
792 | |||
793 | static void s3c2416_irq_mask_second(struct irq_data *data) | ||
794 | { | ||
795 | unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); | ||
796 | unsigned long mask; | ||
797 | |||
798 | mask = __raw_readl(S3C2416_INTMSK2); | ||
799 | mask |= bitval; | ||
800 | __raw_writel(mask, S3C2416_INTMSK2); | ||
801 | } | ||
802 | |||
803 | static void s3c2416_irq_unmask_second(struct irq_data *data) | ||
804 | { | ||
805 | unsigned long bitval = 1UL << (data->irq - IRQ_S3C2416_2D); | ||
806 | unsigned long mask; | ||
807 | |||
808 | mask = __raw_readl(S3C2416_INTMSK2); | ||
809 | mask &= ~bitval; | ||
810 | __raw_writel(mask, S3C2416_INTMSK2); | ||
811 | } | ||
812 | |||
813 | static struct irq_chip s3c2416_irq_second = { | ||
814 | .irq_ack = s3c2416_irq_ack_second, | ||
815 | .irq_mask = s3c2416_irq_mask_second, | ||
816 | .irq_unmask = s3c2416_irq_unmask_second, | ||
817 | }; | 708 | }; |
818 | 709 | ||
819 | |||
820 | /* IRQ initialisation code */ | ||
821 | |||
822 | static int s3c2416_add_sub(unsigned int base, | ||
823 | void (*demux)(unsigned int, | ||
824 | struct irq_desc *), | ||
825 | struct irq_chip *chip, | ||
826 | unsigned int start, unsigned int end) | ||
827 | { | ||
828 | unsigned int irqno; | ||
829 | |||
830 | irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq); | ||
831 | irq_set_chained_handler(base, demux); | ||
832 | |||
833 | for (irqno = start; irqno <= end; irqno++) { | ||
834 | irq_set_chip_and_handler(irqno, chip, handle_level_irq); | ||
835 | set_irq_flags(irqno, IRQF_VALID); | ||
836 | } | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static void s3c2416_irq_add_second(void) | ||
842 | { | ||
843 | unsigned long pend; | ||
844 | unsigned long last; | ||
845 | int irqno; | ||
846 | int i; | ||
847 | |||
848 | /* first, clear all interrupts pending... */ | ||
849 | last = 0; | ||
850 | for (i = 0; i < 4; i++) { | ||
851 | pend = __raw_readl(S3C2416_INTPND2); | ||
852 | |||
853 | if (pend == 0 || pend == last) | ||
854 | break; | ||
855 | |||
856 | __raw_writel(pend, S3C2416_SRCPND2); | ||
857 | __raw_writel(pend, S3C2416_INTPND2); | ||
858 | printk(KERN_INFO "irq: clearing pending status %08x\n", | ||
859 | (int)pend); | ||
860 | last = pend; | ||
861 | } | ||
862 | |||
863 | for (irqno = IRQ_S3C2416_2D; irqno <= IRQ_S3C2416_I2S1; irqno++) { | ||
864 | switch (irqno) { | ||
865 | case IRQ_S3C2416_RESERVED2: | ||
866 | case IRQ_S3C2416_RESERVED3: | ||
867 | /* no IRQ here */ | ||
868 | break; | ||
869 | default: | ||
870 | irq_set_chip_and_handler(irqno, &s3c2416_irq_second, | ||
871 | handle_edge_irq); | ||
872 | set_irq_flags(irqno, IRQF_VALID); | ||
873 | } | ||
874 | } | ||
875 | } | ||
876 | |||
877 | void __init s3c2416_init_irq(void) | 710 | void __init s3c2416_init_irq(void) |
878 | { | 711 | { |
879 | pr_info("S3C2416: IRQ Support\n"); | 712 | struct s3c_irq_intc *main_intc; |
880 | |||
881 | s3c24xx_init_irq(); | ||
882 | 713 | ||
883 | s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd, | 714 | pr_info("S3C2416: IRQ Support\n"); |
884 | IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4); | ||
885 | 715 | ||
886 | s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma, | 716 | #ifdef CONFIG_FIQ |
887 | &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); | 717 | init_FIQ(FIQ_START); |
718 | #endif | ||
888 | 719 | ||
889 | s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3, | 720 | main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000); |
890 | &s3c2416_irq_uart3, | 721 | if (IS_ERR(main_intc)) { |
891 | IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); | 722 | pr_err("irq: could not create main interrupt controller\n"); |
723 | return; | ||
724 | } | ||
892 | 725 | ||
893 | s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97, | 726 | s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); |
894 | &s3c2416_irq_wdtac97, | 727 | s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018); |
895 | IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); | ||
896 | 728 | ||
897 | s3c2416_irq_add_second(); | 729 | s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040); |
898 | } | 730 | } |
899 | 731 | ||
900 | #endif | 732 | #endif |