aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c24xx
diff options
context:
space:
mode:
authorHeiko Stuebner <heiko@sntech.de>2013-02-12 13:12:09 -0500
committerKukjin Kim <kgene.kim@samsung.com>2013-03-05 06:21:31 -0500
commit1c8408e3137bcb78d9ab8af832111f455d11e99c (patch)
tree35d1896ca67c6f007179256678754243e63a97e6 /arch/arm/mach-s3c24xx
parent9eecbe509607265d28d76b39bc479f01b6d55e01 (diff)
ARM: S3C24XX: handle s3c2412 eints using new infrastructure
The s3c2412 handles the eints 0 to 3 different than all the other SoCs of the 24xx range. These eints must be acked and masked in the regular bits as well as the bits 0 to 3 of the eint registers, which are unused on the other SoCs. This of course can be realized using the new infrastructure with the eint bits in the main register being the parent interrupts of the same bits in the eint register. The s3c2412 therefore gets its own IRQ_EINT0 to 4 constants that reside in the newly created gap before IRQ_EINT4. gpio-samsung, as the only user of these is modified to return the correct values when handling gpio_to_irq requests on s3c2412 based machines. Due to lack of hardware this is compile tested only, but should hopefully work as intended. Signed-off-by: Heiko Stuebner <heiko@sntech.de> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-s3c24xx')
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/irqs.h4
-rw-r--r--arch/arm/mach-s3c24xx/irq.c118
2 files changed, 40 insertions, 82 deletions
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h
index ea589e4f0d8b..43cada8019b4 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -59,6 +59,10 @@
59#define IRQ_ADCPARENT S3C2410_IRQ(31) 59#define IRQ_ADCPARENT S3C2410_IRQ(31)
60 60
61/* interrupts generated from the external interrupts sources */ 61/* interrupts generated from the external interrupts sources */
62#define IRQ_EINT0_2412 S3C2410_IRQ(32)
63#define IRQ_EINT1_2412 S3C2410_IRQ(33)
64#define IRQ_EINT2_2412 S3C2410_IRQ(34)
65#define IRQ_EINT3_2412 S3C2410_IRQ(35)
62#define IRQ_EINT4 S3C2410_IRQ(36) /* 52 */ 66#define IRQ_EINT4 S3C2410_IRQ(36) /* 52 */
63#define IRQ_EINT5 S3C2410_IRQ(37) 67#define IRQ_EINT5 S3C2410_IRQ(37)
64#define IRQ_EINT6 S3C2410_IRQ(38) 68#define IRQ_EINT6 S3C2410_IRQ(38)
diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c
index c2205eb78dc1..3f3de7492094 100644
--- a/arch/arm/mach-s3c24xx/irq.c
+++ b/arch/arm/mach-s3c24xx/irq.c
@@ -342,7 +342,10 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
342 case S3C_IRQTYPE_NONE: 342 case S3C_IRQTYPE_NONE:
343 return 0; 343 return 0;
344 case S3C_IRQTYPE_EINT: 344 case S3C_IRQTYPE_EINT:
345 if (irq_data->parent_irq) 345 /* On the S3C2412, the EINT0to3 have a parent irq
346 * but need the s3c_irq_eint0t4 chip
347 */
348 if (irq_data->parent_irq && (!soc_is_s3c2412() || hw >= 4))
346 irq_set_chip_and_handler(virq, &s3c_irqext_chip, 349 irq_set_chip_and_handler(virq, &s3c_irqext_chip,
347 handle_edge_irq); 350 handle_edge_irq);
348 else 351 else
@@ -623,10 +626,10 @@ void __init s3c24xx_init_irq(void)
623 626
624#ifdef CONFIG_CPU_S3C2412 627#ifdef CONFIG_CPU_S3C2412
625static struct s3c_irq_data init_s3c2412base[32] = { 628static struct s3c_irq_data init_s3c2412base[32] = {
626 { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */ 629 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
627 { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */ 630 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
628 { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */ 631 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
629 { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */ 632 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
630 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */ 633 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
631 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */ 634 { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
632 { .type = S3C_IRQTYPE_NONE, }, /* reserved */ 635 { .type = S3C_IRQTYPE_NONE, }, /* reserved */
@@ -657,6 +660,33 @@ static struct s3c_irq_data init_s3c2412base[32] = {
657 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */ 660 { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
658}; 661};
659 662
663static struct s3c_irq_data init_s3c2412eint[32] = {
664 { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
665 { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
666 { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
667 { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
668 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
669 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
670 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
671 { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
672 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
673 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
674 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
675 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
676 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
677 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
678 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
679 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
680 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
681 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
682 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
683 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
684 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
685 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
686 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
687 { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
688};
689
660static struct s3c_irq_data init_s3c2412subint[32] = { 690static struct s3c_irq_data init_s3c2412subint[32] = {
661 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */ 691 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
662 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */ 692 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
@@ -675,77 +705,9 @@ static struct s3c_irq_data init_s3c2412subint[32] = {
675 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */ 705 { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
676}; 706};
677 707
678/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
679 * having them turn up in both the INT* and the EINT* registers. Whilst
680 * both show the status, they both now need to be acked when the IRQs
681 * go off.
682*/
683
684static void
685s3c2412_irq_mask(struct irq_data *data)
686{
687 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
688 unsigned long mask;
689
690 mask = __raw_readl(S3C2410_INTMSK);
691 __raw_writel(mask | bitval, S3C2410_INTMSK);
692
693 mask = __raw_readl(S3C2412_EINTMASK);
694 __raw_writel(mask | bitval, S3C2412_EINTMASK);
695}
696
697static inline void
698s3c2412_irq_ack(struct irq_data *data)
699{
700 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
701
702 __raw_writel(bitval, S3C2412_EINTPEND);
703 __raw_writel(bitval, S3C2410_SRCPND);
704 __raw_writel(bitval, S3C2410_INTPND);
705}
706
707static inline void
708s3c2412_irq_maskack(struct irq_data *data)
709{
710 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
711 unsigned long mask;
712
713 mask = __raw_readl(S3C2410_INTMSK);
714 __raw_writel(mask|bitval, S3C2410_INTMSK);
715
716 mask = __raw_readl(S3C2412_EINTMASK);
717 __raw_writel(mask | bitval, S3C2412_EINTMASK);
718
719 __raw_writel(bitval, S3C2412_EINTPEND);
720 __raw_writel(bitval, S3C2410_SRCPND);
721 __raw_writel(bitval, S3C2410_INTPND);
722}
723
724static void
725s3c2412_irq_unmask(struct irq_data *data)
726{
727 unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
728 unsigned long mask;
729
730 mask = __raw_readl(S3C2412_EINTMASK);
731 __raw_writel(mask & ~bitval, S3C2412_EINTMASK);
732
733 mask = __raw_readl(S3C2410_INTMSK);
734 __raw_writel(mask & ~bitval, S3C2410_INTMSK);
735}
736
737static struct irq_chip s3c2412_irq_eint0t4 = {
738 .irq_ack = s3c2412_irq_ack,
739 .irq_mask = s3c2412_irq_mask,
740 .irq_unmask = s3c2412_irq_unmask,
741 .irq_set_wake = s3c_irq_wake,
742 .irq_set_type = s3c_irqext_type,
743};
744
745void s3c2412_init_irq(void) 708void s3c2412_init_irq(void)
746{ 709{
747 struct s3c_irq_intc *main_intc; 710 struct s3c_irq_intc *main_intc;
748 unsigned int irqno;
749 711
750 pr_info("S3C2412: IRQ Support\n"); 712 pr_info("S3C2412: IRQ Support\n");
751 713
@@ -759,16 +721,8 @@ void s3c2412_init_irq(void)
759 return; 721 return;
760 } 722 }
761 723
762 s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4); 724 s3c24xx_init_intc(NULL, &init_s3c2412eint[0], main_intc, 0x560000a4);
763 s3c24xx_init_intc(NULL, &init_s3c2412subint[0], main_intc, 0x4a000018); 725 s3c24xx_init_intc(NULL, &init_s3c2412subint[0], main_intc, 0x4a000018);
764
765 /* special handling for eints 0 to 3 */
766
767 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
768 irq_set_chip_and_handler(irqno, &s3c2412_irq_eint0t4,
769 handle_edge_irq);
770 set_irq_flags(irqno, IRQF_VALID);
771 }
772} 726}
773#endif 727#endif
774 728