[ARM] 3429/1: ARM: OMAP: 4/8 Update GPIO
Patch from Tony Lindgren Update OMAP GPIO code from linux-omap tree: - Fix omap16xx edge control by Juha Yrjola - Support for additional omap16xx trigger modes by Dirk Behme - Fix edge detection by Tony Lindgren et al. - Better support for omap15xx and omap310 by Andrej Zaborowski - Fix omap15xx interrupt bug by Petukhov Nikolay Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
8d7f9f5037
commit
6e60e79a1d
1 changed files with 61 additions and 25 deletions
|
@ -174,7 +174,7 @@ static int gpio_bank_count;
|
||||||
static inline struct gpio_bank *get_gpio_bank(int gpio)
|
static inline struct gpio_bank *get_gpio_bank(int gpio)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ARCH_OMAP15XX
|
#ifdef CONFIG_ARCH_OMAP15XX
|
||||||
if (cpu_is_omap1510()) {
|
if (cpu_is_omap15xx()) {
|
||||||
if (OMAP_GPIO_IS_MPUIO(gpio))
|
if (OMAP_GPIO_IS_MPUIO(gpio))
|
||||||
return &gpio_bank[0];
|
return &gpio_bank[0];
|
||||||
return &gpio_bank[1];
|
return &gpio_bank[1];
|
||||||
|
@ -223,7 +223,7 @@ static inline int gpio_valid(int gpio)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_ARCH_OMAP15XX
|
#ifdef CONFIG_ARCH_OMAP15XX
|
||||||
if (cpu_is_omap1510() && gpio < 16)
|
if (cpu_is_omap15xx() && gpio < 16)
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_ARCH_OMAP16XX)
|
#if defined(CONFIG_ARCH_OMAP16XX)
|
||||||
|
@ -402,13 +402,13 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr
|
||||||
u32 gpio_bit = 1 << gpio;
|
u32 gpio_bit = 1 << gpio;
|
||||||
|
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
|
||||||
trigger & IRQT_LOW);
|
trigger & __IRQT_LOWLVL);
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
|
||||||
trigger & IRQT_HIGH);
|
trigger & __IRQT_HIGHLVL);
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
|
||||||
trigger & IRQT_RISING);
|
trigger & __IRQT_RISEDGE);
|
||||||
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
|
MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
|
||||||
trigger & IRQT_FALLING);
|
trigger & __IRQT_FALEDGE);
|
||||||
/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
|
/* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
|
||||||
* triggering requested. */
|
* triggering requested. */
|
||||||
}
|
}
|
||||||
|
@ -422,9 +422,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
|
||||||
case METHOD_MPUIO:
|
case METHOD_MPUIO:
|
||||||
reg += OMAP_MPUIO_GPIO_INT_EDGE;
|
reg += OMAP_MPUIO_GPIO_INT_EDGE;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (trigger == IRQT_RISING)
|
if (trigger & __IRQT_RISEDGE)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else if (trigger == IRQT_FALLING)
|
else if (trigger & __IRQT_FALEDGE)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
else
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -432,9 +432,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
|
||||||
case METHOD_GPIO_1510:
|
case METHOD_GPIO_1510:
|
||||||
reg += OMAP1510_GPIO_INT_CONTROL;
|
reg += OMAP1510_GPIO_INT_CONTROL;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (trigger == IRQT_RISING)
|
if (trigger & __IRQT_RISEDGE)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else if (trigger == IRQT_FALLING)
|
else if (trigger & __IRQT_FALEDGE)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
else
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -446,20 +446,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
|
||||||
reg += OMAP1610_GPIO_EDGE_CTRL1;
|
reg += OMAP1610_GPIO_EDGE_CTRL1;
|
||||||
gpio &= 0x07;
|
gpio &= 0x07;
|
||||||
/* We allow only edge triggering, i.e. two lowest bits */
|
/* We allow only edge triggering, i.e. two lowest bits */
|
||||||
if (trigger & ~IRQT_BOTHEDGE)
|
if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
|
||||||
BUG();
|
BUG();
|
||||||
/* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
|
|
||||||
trigger &= 0x03;
|
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
l &= ~(3 << (gpio << 1));
|
l &= ~(3 << (gpio << 1));
|
||||||
l |= trigger << (gpio << 1);
|
if (trigger & __IRQT_RISEDGE)
|
||||||
|
l |= 2 << (gpio << 1);
|
||||||
|
if (trigger & __IRQT_FALEDGE)
|
||||||
|
l |= 1 << (gpio << 1);
|
||||||
break;
|
break;
|
||||||
case METHOD_GPIO_730:
|
case METHOD_GPIO_730:
|
||||||
reg += OMAP730_GPIO_INT_CONTROL;
|
reg += OMAP730_GPIO_INT_CONTROL;
|
||||||
l = __raw_readl(reg);
|
l = __raw_readl(reg);
|
||||||
if (trigger == IRQT_RISING)
|
if (trigger & __IRQT_RISEDGE)
|
||||||
l |= 1 << gpio;
|
l |= 1 << gpio;
|
||||||
else if (trigger == IRQT_FALLING)
|
else if (trigger & __IRQT_FALEDGE)
|
||||||
l &= ~(1 << gpio);
|
l &= ~(1 << gpio);
|
||||||
else
|
else
|
||||||
goto bad;
|
goto bad;
|
||||||
|
@ -491,7 +492,9 @@ static int gpio_irq_type(unsigned irq, unsigned type)
|
||||||
if (check_gpio(gpio) < 0)
|
if (check_gpio(gpio) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE))
|
if (type & IRQT_PROBE)
|
||||||
|
return -EINVAL;
|
||||||
|
if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
bank = get_gpio_bank(gpio);
|
bank = get_gpio_bank(gpio);
|
||||||
|
@ -755,12 +758,31 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
if (bank->method == METHOD_GPIO_24XX)
|
if (bank->method == METHOD_GPIO_24XX)
|
||||||
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
|
isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
isr = __raw_readl(isr_reg);
|
u32 isr_saved, level_mask = 0;
|
||||||
_enable_gpio_irqbank(bank, isr, 0);
|
|
||||||
_clear_gpio_irqbank(bank, isr);
|
isr_saved = isr = __raw_readl(isr_reg);
|
||||||
_enable_gpio_irqbank(bank, isr, 1);
|
|
||||||
|
if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
|
||||||
|
isr &= 0x0000ffff;
|
||||||
|
|
||||||
|
if (cpu_is_omap24xx())
|
||||||
|
level_mask =
|
||||||
|
__raw_readl(bank->base +
|
||||||
|
OMAP24XX_GPIO_LEVELDETECT0) |
|
||||||
|
__raw_readl(bank->base +
|
||||||
|
OMAP24XX_GPIO_LEVELDETECT1);
|
||||||
|
|
||||||
|
/* clear edge sensitive interrupts before handler(s) are
|
||||||
|
called so that we don't miss any interrupt occurred while
|
||||||
|
executing them */
|
||||||
|
_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
|
||||||
|
_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
|
||||||
|
_enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
|
||||||
|
|
||||||
|
/* if there is only edge sensitive GPIO pin interrupts
|
||||||
|
configured, we could unmask GPIO bank interrupt immediately */
|
||||||
|
if (!level_mask)
|
||||||
desc->chip->unmask(irq);
|
desc->chip->unmask(irq);
|
||||||
|
|
||||||
if (!isr)
|
if (!isr)
|
||||||
|
@ -774,6 +796,20 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
d = irq_desc + gpio_irq;
|
d = irq_desc + gpio_irq;
|
||||||
desc_handle_irq(gpio_irq, d, regs);
|
desc_handle_irq(gpio_irq, d, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpu_is_omap24xx()) {
|
||||||
|
/* clear level sensitive interrupts after handler(s) */
|
||||||
|
_enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
|
||||||
|
_clear_gpio_irqbank(bank, isr_saved & level_mask);
|
||||||
|
_enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if bank has any level sensitive GPIO pin interrupt
|
||||||
|
configured, we must unmask the bank interrupt only after
|
||||||
|
handler(s) are executed in order to avoid spurious bank
|
||||||
|
interrupt */
|
||||||
|
if (level_mask)
|
||||||
|
desc->chip->unmask(irq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,7 +884,7 @@ static int __init _omap_gpio_init(void)
|
||||||
|
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
|
|
||||||
if (cpu_is_omap1510()) {
|
if (cpu_is_omap15xx()) {
|
||||||
gpio_ick = clk_get(NULL, "arm_gpio_ck");
|
gpio_ick = clk_get(NULL, "arm_gpio_ck");
|
||||||
if (IS_ERR(gpio_ick))
|
if (IS_ERR(gpio_ick))
|
||||||
printk("Could not get arm_gpio_ck\n");
|
printk("Could not get arm_gpio_ck\n");
|
||||||
|
@ -869,7 +905,7 @@ static int __init _omap_gpio_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_OMAP15XX
|
#ifdef CONFIG_ARCH_OMAP15XX
|
||||||
if (cpu_is_omap1510()) {
|
if (cpu_is_omap15xx()) {
|
||||||
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
|
printk(KERN_INFO "OMAP1510 GPIO hardware\n");
|
||||||
gpio_bank_count = 2;
|
gpio_bank_count = 2;
|
||||||
gpio_bank = gpio_bank_1510;
|
gpio_bank = gpio_bank_1510;
|
||||||
|
|
Reference in a new issue