Archived
14
0
Fork 0

[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:
Tony Lindgren 2006-04-02 17:46:23 +01:00 committed by Russell King
parent 8d7f9f5037
commit 6e60e79a1d

View file

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