aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-s3c24xx/irq.c
diff options
context:
space:
mode:
authorHeiko Stuebner <heiko@sntech.de>2013-01-29 13:25:22 -0500
committerKukjin Kim <kgene.kim@samsung.com>2013-02-03 18:52:49 -0500
commit20f6c781c7d801e142fccbc04ec9c6dc639f5943 (patch)
tree3a9674c691a28ab7877b2c86ddc63e4fe446e0cb /arch/arm/plat-s3c24xx/irq.c
parent4a282dd3b616a1e7a7f170973ed2a12332544dc3 (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.c342
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) 632static struct s3c_irq_data init_s3c2416base[32] = {
632 633 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
633static 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 */
660static 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
668static void s3c2416_irq_wdtac97_mask(struct irq_data *data)
669{
670 s3c_irqsub_mask(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
671}
672
673static void s3c2416_irq_wdtac97_unmask(struct irq_data *data)
674{
675 s3c_irqsub_unmask(data->irq, INTMSK_WDTAC97);
676}
677
678static void s3c2416_irq_wdtac97_ack(struct irq_data *data)
679{
680 s3c_irqsub_maskack(data->irq, INTMSK_WDTAC97, SUBMSK_WDTAC97);
681}
682
683static 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
691static 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
699static void s3c2416_irq_lcd_mask(struct irq_data *data)
700{
701 s3c_irqsub_mask(data->irq, INTMSK_LCD, SUBMSK_LCD);
702}
703
704static void s3c2416_irq_lcd_unmask(struct irq_data *data)
705{
706 s3c_irqsub_unmask(data->irq, INTMSK_LCD);
707}
708
709static void s3c2416_irq_lcd_ack(struct irq_data *data)
710{
711 s3c_irqsub_maskack(data->irq, INTMSK_LCD, SUBMSK_LCD);
712}
713
714static 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
722static 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
731static void s3c2416_irq_dma_mask(struct irq_data *data)
732{
733 s3c_irqsub_mask(data->irq, INTMSK_DMA, SUBMSK_DMA);
734}
735
736static void s3c2416_irq_dma_unmask(struct irq_data *data)
737{
738 s3c_irqsub_unmask(data->irq, INTMSK_DMA);
739}
740
741static void s3c2416_irq_dma_ack(struct irq_data *data)
742{
743 s3c_irqsub_maskack(data->irq, INTMSK_DMA, SUBMSK_DMA);
744}
745
746static 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 */ 667static struct s3c_irq_data init_s3c2416subint[32] = {
753 668 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
754static 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 */
762static 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 */
767static 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 */
772static 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 */
777static 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 */ 699static struct s3c_irq_data init_s3c2416_second[32] = {
784 700 { .type = S3C_IRQTYPE_EDGE }, /* 2D */
785static 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
793static 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
803static 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
813static 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
822static 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
841static 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
877void __init s3c2416_init_irq(void) 710void __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