|
@@ -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);
|