summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/common.c')
-rw-r--r--arch/arm/mach-exynos/common.c147
1 files changed, 96 insertions, 51 deletions
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 4ef0cb513c8..cbbaca54966 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)
s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
}
+static void __iomem *exynos_eint_base;
+
static DEFINE_SPINLOCK(eint_lock);
static unsigned int eint0_15_data[16];
+static inline int exynos4_irq_to_gpio(unsigned int irq)
+{
+ if (irq < IRQ_EINT(0))
+ return -EINVAL;
+
+ irq -= IRQ_EINT(0);
+ if (irq < 8)
+ return EXYNOS4_GPX0(irq);
+
+ irq -= 8;
+ if (irq < 8)
+ return EXYNOS4_GPX1(irq);
+
+ irq -= 8;
+ if (irq < 8)
+ return EXYNOS4_GPX2(irq);
+
+ irq -= 8;
+ if (irq < 8)
+ return EXYNOS4_GPX3(irq);
+
+ return -EINVAL;
+}
+
+static inline int exynos5_irq_to_gpio(unsigned int irq)
+{
+ if (irq < IRQ_EINT(0))
+ return -EINVAL;
+
+ irq -= IRQ_EINT(0);
+ if (irq < 8)
+ return EXYNOS5_GPX0(irq);
+
+ irq -= 8;
+ if (irq < 8)
+ return EXYNOS5_GPX1(irq);
+
+ irq -= 8;
+ if (irq < 8)
+ return EXYNOS5_GPX2(irq);
+
+ irq -= 8;
+ if (irq < 8)
+ return EXYNOS5_GPX3(irq);
+
+ return -EINVAL;
+}
+
static unsigned int exynos4_eint0_15_src_int[16] = {
EXYNOS4_IRQ_EINT0,
EXYNOS4_IRQ_EINT1,
@@ -706,41 +756,41 @@ static unsigned int exynos5_eint0_15_src_int[16] = {
EXYNOS5_IRQ_EINT14,
EXYNOS5_IRQ_EINT15,
};
-static inline void exynos4_irq_eint_mask(struct irq_data *data)
+static inline void exynos_irq_eint_mask(struct irq_data *data)
{
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
- mask |= eint_irq_to_bit(data->irq);
- __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
+ mask |= EINT_OFFSET_BIT(data->irq);
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
spin_unlock(&eint_lock);
}
-static void exynos4_irq_eint_unmask(struct irq_data *data)
+static void exynos_irq_eint_unmask(struct irq_data *data)
{
u32 mask;
spin_lock(&eint_lock);
- mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
- mask &= ~(eint_irq_to_bit(data->irq));
- __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+ mask = __raw_readl(EINT_MASK(exynos_eint_base, data->irq));
+ mask &= ~(EINT_OFFSET_BIT(data->irq));
+ __raw_writel(mask, EINT_MASK(exynos_eint_base, data->irq));
spin_unlock(&eint_lock);
}
-static inline void exynos4_irq_eint_ack(struct irq_data *data)
+static inline void exynos_irq_eint_ack(struct irq_data *data)
{
- __raw_writel(eint_irq_to_bit(data->irq),
- S5P_EINT_PEND(EINT_REG_NR(data->irq)));
+ __raw_writel(EINT_OFFSET_BIT(data->irq),
+ EINT_PEND(exynos_eint_base, data->irq));
}
-static void exynos4_irq_eint_maskack(struct irq_data *data)
+static void exynos_irq_eint_maskack(struct irq_data *data)
{
- exynos4_irq_eint_mask(data);
- exynos4_irq_eint_ack(data);
+ exynos_irq_eint_mask(data);
+ exynos_irq_eint_ack(data);
}
-static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
+static int exynos_irq_eint_set_type(struct irq_data *data, unsigned int type)
{
int offs = EINT_OFFSET(data->irq);
int shift;
@@ -777,39 +827,27 @@ static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
mask = 0x7 << shift;
spin_lock(&eint_lock);
- ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
+ ctrl = __raw_readl(EINT_CON(exynos_eint_base, data->irq));
ctrl &= ~mask;
ctrl |= newvalue << shift;
- __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
+ __raw_writel(ctrl, EINT_CON(exynos_eint_base, data->irq));
spin_unlock(&eint_lock);
- switch (offs) {
- case 0 ... 7:
- s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
- break;
- case 8 ... 15:
- s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
- break;
- case 16 ... 23:
- s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
- break;
- case 24 ... 31:
- s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
- break;
- default:
- printk(KERN_ERR "No such irq number %d", offs);
- }
+ if (soc_is_exynos5250())
+ s3c_gpio_cfgpin(exynos5_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
+ else
+ s3c_gpio_cfgpin(exynos4_irq_to_gpio(data->irq), S3C_GPIO_SFN(0xf));
return 0;
}
-static struct irq_chip exynos4_irq_eint = {
- .name = "exynos4-eint",
- .irq_mask = exynos4_irq_eint_mask,
- .irq_unmask = exynos4_irq_eint_unmask,
- .irq_mask_ack = exynos4_irq_eint_maskack,
- .irq_ack = exynos4_irq_eint_ack,
- .irq_set_type = exynos4_irq_eint_set_type,
+static struct irq_chip exynos_irq_eint = {
+ .name = "exynos-eint",
+ .irq_mask = exynos_irq_eint_mask,
+ .irq_unmask = exynos_irq_eint_unmask,
+ .irq_mask_ack = exynos_irq_eint_maskack,
+ .irq_ack = exynos_irq_eint_ack,
+ .irq_set_type = exynos_irq_eint_set_type,
#ifdef CONFIG_PM
.irq_set_wake = s3c_irqext_wake,
#endif
@@ -824,12 +862,12 @@ static struct irq_chip exynos4_irq_eint = {
*
* Each EINT pend/mask registers handle eight of them.
*/
-static inline void exynos4_irq_demux_eint(unsigned int start)
+static inline void exynos_irq_demux_eint(unsigned int start)
{
unsigned int irq;
- u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
- u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
+ u32 status = __raw_readl(EINT_PEND(exynos_eint_base, start));
+ u32 mask = __raw_readl(EINT_MASK(exynos_eint_base, start));
status &= ~mask;
status &= 0xff;
@@ -841,12 +879,12 @@ static inline void exynos4_irq_demux_eint(unsigned int start)
}
}
-static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
{
struct irq_chip *chip = irq_get_chip(irq);
chained_irq_enter(chip, desc);
- exynos4_irq_demux_eint(IRQ_EINT(16));
- exynos4_irq_demux_eint(IRQ_EINT(24));
+ exynos_irq_demux_eint(IRQ_EINT(16));
+ exynos_irq_demux_eint(IRQ_EINT(24));
chained_irq_exit(chip, desc);
}
@@ -867,20 +905,27 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
-static int __init exynos4_init_irq_eint(void)
+static int __init exynos_init_irq_eint(void)
{
int irq;
if (soc_is_exynos5250())
- return 0;
+ exynos_eint_base = ioremap(EXYNOS5_PA_GPIO1, SZ_4K);
+ else
+ exynos_eint_base = ioremap(EXYNOS4_PA_GPIO2, SZ_4K);
+
+ if (exynos_eint_base == NULL) {
+ pr_err("unable to ioremap for EINT base address\n");
+ return -ENOMEM;
+ }
for (irq = 0 ; irq <= 31 ; irq++) {
- irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
+ irq_set_chip_and_handler(IRQ_EINT(irq), &exynos_irq_eint,
handle_level_irq);
set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
}
- irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
+ irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos_irq_demux_eint16_31);
for (irq = 0 ; irq <= 15 ; irq++) {
eint0_15_data[irq] = IRQ_EINT(irq);
@@ -900,4 +945,4 @@ static int __init exynos4_init_irq_eint(void)
return 0;
}
-arch_initcall(exynos4_init_irq_eint);
+arch_initcall(exynos_init_irq_eint);