aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos
diff options
context:
space:
mode:
authorEunki Kim <eunki_kim@samsung.com>2012-03-14 04:43:31 -0400
committerKukjin Kim <kgene.kim@samsung.com>2012-03-14 05:35:14 -0400
commit330c90a54c82596dfe355163c4d888e51a0fe65b (patch)
treee3dd1ff6c29b0b77af15df24dc8f5b1316f83e5e /arch/arm/mach-exynos
parentbb19a7513dffc82f4b474ed90fc8ed691b54768b (diff)
ARM: EXYNOS: support EINT for EXYNOS4 and EXYNOS5
The GPIOs of EXYNOS4 and EXYNOS5 are changed to use ioremap instead of static mapping. It alse causes the change of external interrupt IO mapping. This patch changes EXYNOS4 to EXYNOS for common use and changes EINT_x macros for supporting dynamic IO mapping. Signed-off-by: Eunki Kim <eunki_kim@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-exynos')
-rw-r--r--arch/arm/mach-exynos/common.c147
-rw-r--r--arch/arm/mach-exynos/include/mach/regs-gpio.h20
2 files changed, 105 insertions, 62 deletions
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4ef0cb513c83..cbbaca54966a 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -665,10 +665,60 @@ static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no)
665 s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no); 665 s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
666} 666}
667 667
668static void __iomem *exynos_eint_base;
669
668static DEFINE_SPINLOCK(eint_lock); 670static DEFINE_SPINLOCK(eint_lock);
669 671
670static unsigned int eint0_15_data[16]; 672static unsigned int eint0_15_data[16];
671 673
674static inline int exynos4_irq_to_gpio(unsigned int irq)
675{
676 if (irq < IRQ_EINT(0))
677 return -EINVAL;
678
679 irq -= IRQ_EINT(0);
680 if (irq < 8)
681 return EXYNOS4_GPX0(irq);
682
683 irq -= 8;
684 if (irq < 8)
685 return EXYNOS4_GPX1(irq);
686
687 irq -= 8;
688 if (irq < 8)
689 return EXYNOS4_GPX2(irq);
690
691 irq -= 8;
692 if (irq < 8)
693 return EXYNOS4_GPX3(irq);
694
695 return -EINVAL;
696}
697
698static inline int exynos5_irq_to_gpio(unsigned int irq)
699{
700 if (irq < IRQ_EINT(0))
701 return -EINVAL;
702
703 irq -= IRQ_EINT(0);
704 if (irq < 8)
705 return EXYNOS5_GPX0(irq);
706
707 irq -= 8;
708 if (irq < 8)
709 return EXYNOS5_GPX1(irq);
710
711 irq -= 8;
712 if (irq < 8)
713 return EXYNOS5_GPX2(irq);
714
715 irq -= 8;
716 if (irq < 8)
717 return EXYNOS5_GPX3(irq);
718
719 return -EINVAL;
720}
721
672static unsigned int exynos4_eint0_15_src_int[16] = { 722static unsigned int exynos4_eint0_15_src_int[16] = {
673 EXYNOS4_IRQ_EINT0, 723 EXYNOS4_IRQ_EINT0,
674 EXYNOS4_IRQ_EINT1, 724 EXYNOS4_IRQ_EINT1,
@@ -706,41 +756,41 @@ static unsigned int exynos5_eint0_15_src_int[16] = {
706 EXYNOS5_IRQ_EINT14, 756 EXYNOS5_IRQ_EINT14,
707 EXYNOS5_IRQ_EINT15, 757 EXYNOS5_IRQ_EINT15,
708}; 758};
709static inline void exynos4_irq_eint_mask(struct irq_data *data) 759static inline void exynos_irq_eint_mask(struct irq_data *data)
710{ 760{
711 u32 mask; 761 u32 mask;
712 762
713 spin_lock(&eint_lock); 763 spin_lock(&eint_lock);
714 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); 764 mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
715 mask |= eint_irq_to_bit(data->irq); 765 mask |= EINT_OFFSET_BIT(data->irq);
716 __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); 766 __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
717 spin_unlock(&eint_lock); 767 spin_unlock(&eint_lock);
718} 768}
719 769
720static void exynos4_irq_eint_unmask(struct irq_data *data) 770static void exynos_irq_eint_unmask(struct irq_data *data)
721{ 771{
722 u32 mask; 772 u32 mask;
723 773
724 spin_lock(&eint_lock); 774 spin_lock(&eint_lock);
725 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq))); 775 mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
726 mask &= ~(eint_irq_to_bit(data->irq)); 776 mask &= ~(EINT_OFFSET_BIT(data->irq));
727 __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq))); 777 __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
728 spin_unlock(&eint_lock); 778 spin_unlock(&eint_lock);
729} 779}
730 780
731static inline void exynos4_irq_eint_ack(struct irq_data *data) 781static inline void exynos_irq_eint_ack(struct irq_data *data)
732{ 782{
733 __raw_writel(eint_irq_to_bit(data->irq), 783 __raw_writel(EINT_OFFSET_BIT(data->irq),
734 S5P_EINT_PEND(EINT_REG_NR(data->irq))); 784 EINT_PEND(exynos_eint_base, data->irq));
735} 785}
736 786
737static void exynos4_irq_eint_maskack(struct irq_data *data) 787static void exynos_irq_eint_maskack(struct irq_data *data)
738{ 788{
739 exynos4_irq_eint_mask(data); 789 exynos_irq_eint_mask(data);
740 exynos4_irq_eint_ack(data); 790 exynos_irq_eint_ack(data);
741} 791}
742 792
743static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type) 793static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
744{ 794{
745 int offs = EINT_OFFSET(data->irq); 795 int offs = EINT_OFFSET(data->irq);
746 int shift; 796 int shift;
@@ -777,39 +827,27 @@ static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
777 mask = 0x7 << shift; 827 mask = 0x7 << shift;
778 828
779 spin_lock(&eint_lock); 829 spin_lock(&eint_lock);
780 ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq))); 830 ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq));
781 ctrl &= ~mask; 831 ctrl &= ~mask;
782 ctrl |= newvalue << shift; 832 ctrl |= newvalue << shift;
783 __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq))); 833 __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq));
784 spin_unlock(&eint_lock); 834 spin_unlock(&eint_lock);
785 835
786 switch (offs) { 836 if (soc_is_exynos5250())
787 case 0 ... 7: 837 s3c_gpio_cfgpin(exynos5_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
788 s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE); 838 else
789 break; 839 s3c_gpio_cfgpin(exynos4_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
790 case 8 ... 15:
791 s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
792 break;
793 case 16 ... 23:
794 s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
795 break;
796 case 24 ... 31:
797 s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
798 break;
799 default:
800 printk(KERN_ERR "No such irq number %d", offs);
801 }
802 840
803 return 0; 841 return 0;
804} 842}
805 843
806static struct irq_chip exynos4_irq_eint = { 844static struct irq_chip exynos_irq_eint = {
807 .name = "exynos4-eint", 845 .name = "exynos-eint",
808 .irq_mask = exynos4_irq_eint_mask, 846 .irq_mask = exynos_irq_eint_mask,
809 .irq_unmask = exynos4_irq_eint_unmask, 847 .irq_unmask = exynos_irq_eint_unmask,
810 .irq_mask_ack = exynos4_irq_eint_maskack, 848 .irq_mask_ack = exynos_irq_eint_maskack,
811 .irq_ack = exynos4_irq_eint_ack, 849 .irq_ack = exynos_irq_eint_ack,
812 .irq_set_type = exynos4_irq_eint_set_type, 850 .irq_set_type = exynos_irq_eint_set_type,
813#ifdef CONFIG_PM 851#ifdef CONFIG_PM
814 .irq_set_wake = s3c_irqext_wake, 852 .irq_set_wake = s3c_irqext_wake,
815#endif 853#endif
@@ -824,12 +862,12 @@ static struct irq_chip exynos4_irq_eint = {
824 * 862 *
825 * Each EINT pend/mask registers handle eight of them. 863 * Each EINT pend/mask registers handle eight of them.
826 */ 864 */
827static inline void exynos4_irq_demux_eint(unsigned int start) 865static inline void exynos_irq_demux_eint(unsigned int start)
828{ 866{
829 unsigned int irq; 867 unsigned int irq;
830 868
831 u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start))); 869 u32 status = __raw_readl(EINT_PEND(exynos_eint_base, start));
832 u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start))); 870 u32 mask = __raw_readl(EINT_MASK(exynos_eint_base, start));
833 871
834 status &= ~mask; 872 status &= ~mask;
835 status &= 0xff; 873 status &= 0xff;
@@ -841,12 +879,12 @@ static inline void exynos4_irq_demux_eint(unsigned int start)
841 } 879 }
842} 880}
843 881
844static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc) 882static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
845{ 883{
846 struct irq_chip *chip = irq_get_chip(irq); 884 struct irq_chip *chip = irq_get_chip(irq);
847 chained_irq_enter(chip, desc); 885 chained_irq_enter(chip, desc);
848 exynos4_irq_demux_eint(IRQ_EINT(16)); 886 exynos_irq_demux_eint(IRQ_EINT(16));
849 exynos4_irq_demux_eint(IRQ_EINT(24)); 887 exynos_irq_demux_eint(IRQ_EINT(24));
850 chained_irq_exit(chip, desc); 888 chained_irq_exit(chip, desc);
851} 889}
852 890
@@ -867,20 +905,27 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
867 chained_irq_exit(chip, desc); 905 chained_irq_exit(chip, desc);
868} 906}
869 907
870static int __init exynos4_init_irq_eint(void) 908static int __init exynos_init_irq_eint(void)
871{ 909{
872 int irq; 910 int irq;
873 911
874 if (soc_is_exynos5250()) 912 if (soc_is_exynos5250())
875 return 0; 913 exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
914 else
915 exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
916
917 if (exynos_eint_base == NULL) {
918 pr_err("unable to ioremap for EINT base address\n");
919 return -ENOMEM;
920 }
876 921
877 for (irq = 0 ; irq <= 31 ; irq++) { 922 for (irq = 0 ; irq <= 31 ; irq++) {
878 irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint, 923 irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
879 handle_level_irq); 924 handle_level_irq);
880 set_irq_flags(IRQ_EINT(irq), IRQF_VALID); 925 set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
881 } 926 }
882 927
883 irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos4_irq_demux_eint16_31); 928 irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
884 929
885 for (irq = 0 ; irq <= 15 ; irq++) { 930 for (irq = 0 ; irq <= 15 ; irq++) {
886 eint0_15_data[irq] = IRQ_EINT(irq); 931 eint0_15_data[irq] = IRQ_EINT(irq);
@@ -900,4 +945,4 @@ static int __init exynos4_init_irq_eint(void)
900 945
901 return 0; 946 return 0;
902} 947}
903arch_initcall(exynos4_init_irq_eint); 948arch_initcall(exynos_init_irq_eint);
diff --git a/arch/arm/mach-exynos/include/mach/regs-gpio.h b/arch/arm/mach-exynos/include/mach/regs-gpio.h
index 1401b21663a5..e4b5b60dcb85 100644
--- a/arch/arm/mach-exynos/include/mach/regs-gpio.h
+++ b/arch/arm/mach-exynos/include/mach/regs-gpio.h
@@ -16,6 +16,15 @@
16#include <mach/map.h> 16#include <mach/map.h>
17#include <mach/irqs.h> 17#include <mach/irqs.h>
18 18
19#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
20#define EINT_CON(b, x) (b + 0xE00 + (EINT_REG_NR(x) * 4))
21#define EINT_FLTCON(b, x) (b + 0xE80 + (EINT_REG_NR(x) * 4))
22#define EINT_MASK(b, x) (b + 0xF00 + (EINT_REG_NR(x) * 4))
23#define EINT_PEND(b, x) (b + 0xF40 + (EINT_REG_NR(x) * 4))
24
25#define EINT_OFFSET_BIT(x) (1 << (EINT_OFFSET(x) & 0x7))
26
27/* compatibility for plat-s5p/irq-pm.c */
19#define EXYNOS4_EINT40CON (S5P_VA_GPIO2 + 0xE00) 28#define EXYNOS4_EINT40CON (S5P_VA_GPIO2 + 0xE00)
20#define S5P_EINT_CON(x) (EXYNOS4_EINT40CON + ((x) * 0x4)) 29#define S5P_EINT_CON(x) (EXYNOS4_EINT40CON + ((x) * 0x4))
21 30
@@ -28,15 +37,4 @@
28#define EXYNOS4_EINT40PEND (S5P_VA_GPIO2 + 0xF40) 37#define EXYNOS4_EINT40PEND (S5P_VA_GPIO2 + 0xF40)
29#define S5P_EINT_PEND(x) (EXYNOS4_EINT40PEND + ((x) * 0x4)) 38#define S5P_EINT_PEND(x) (EXYNOS4_EINT40PEND + ((x) * 0x4))
30 39
31#define EINT_REG_NR(x) (EINT_OFFSET(x) >> 3)
32
33#define eint_irq_to_bit(irq) (1 << (EINT_OFFSET(irq) & 0x7))
34
35#define EINT_MODE S3C_GPIO_SFN(0xf)
36
37#define EINT_GPIO_0(x) EXYNOS4_GPX0(x)
38#define EINT_GPIO_1(x) EXYNOS4_GPX1(x)
39#define EINT_GPIO_2(x) EXYNOS4_GPX2(x)
40#define EINT_GPIO_3(x) EXYNOS4_GPX3(x)
41
42#endif /* __ASM_ARCH_REGS_GPIO_H */ 40#endif /* __ASM_ARCH_REGS_GPIO_H */