Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 31668
b: refs/heads/master
c: ea6dedd
h: refs/heads/master
v: v3
  • Loading branch information
Imre Deak authored and Tony Lindgren committed Jun 26, 2006
1 parent 45dbe13 commit 0307162
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 10 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7876284178b386ab6e97f96733ccbc19eda743a3
refs/heads/master: ea6dedd7fbd0f760ebf37eb0bcc8c64856475a13
88 changes: 79 additions & 9 deletions trunk/arch/arm/plat-omap/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,34 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio)
_clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio));
}

static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank)
{
void __iomem *reg = bank->base;

switch (bank->method) {
case METHOD_MPUIO:
reg += OMAP_MPUIO_GPIO_MASKIT;
break;
case METHOD_GPIO_1510:
reg += OMAP1510_GPIO_INT_MASK;
break;
case METHOD_GPIO_1610:
reg += OMAP1610_GPIO_IRQENABLE1;
break;
case METHOD_GPIO_730:
reg += OMAP730_GPIO_INT_MASK;
break;
case METHOD_GPIO_24XX:
reg += OMAP24XX_GPIO_IRQENABLE1;
break;
default:
BUG();
return 0;
}

return __raw_readl(reg);
}

static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
{
void __iomem *reg = bank->base;
Expand Down Expand Up @@ -736,6 +764,8 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
u32 isr;
unsigned int gpio_irq;
struct gpio_bank *bank;
u32 retrigger = 0;
int unmasked = 0;

desc->chip->ack(irq);

Expand All @@ -760,18 +790,22 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
#endif
while(1) {
u32 isr_saved, level_mask = 0;
u32 enabled;

isr_saved = isr = __raw_readl(isr_reg);
enabled = _get_gpio_irqbank_mask(bank);
isr_saved = isr = __raw_readl(isr_reg) & enabled;

if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
isr &= 0x0000ffff;

if (cpu_is_omap24xx())
if (cpu_is_omap24xx()) {
level_mask =
__raw_readl(bank->base +
OMAP24XX_GPIO_LEVELDETECT0) |
__raw_readl(bank->base +
OMAP24XX_GPIO_LEVELDETECT1);
level_mask &= enabled;
}

/* clear edge sensitive interrupts before handler(s) are
called so that we don't miss any interrupt occurred while
Expand All @@ -782,19 +816,54 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,

/* if there is only edge sensitive GPIO pin interrupts
configured, we could unmask GPIO bank interrupt immediately */
if (!level_mask)
if (!level_mask && !unmasked) {
unmasked = 1;
desc->chip->unmask(irq);
}

isr |= retrigger;
retrigger = 0;
if (!isr)
break;

gpio_irq = bank->virtual_irq_start;
for (; isr != 0; isr >>= 1, gpio_irq++) {
struct irqdesc *d;
int irq_mask;
if (!(isr & 1))
continue;
d = irq_desc + gpio_irq;
/* Don't run the handler if it's already running
* or was disabled lazely.
*/
if (unlikely((d->disable_depth || d->running))) {
irq_mask = 1 <<
(gpio_irq - bank->virtual_irq_start);
/* The unmasking will be done by
* enable_irq in case it is disabled or
* after returning from the handler if
* it's already running.
*/
_enable_gpio_irqbank(bank, irq_mask, 0);
if (!d->disable_depth) {
/* Level triggered interrupts
* won't ever be reentered
*/
BUG_ON(level_mask & irq_mask);
d->pending = 1;
}
continue;
}
d->running = 1;
desc_handle_irq(gpio_irq, d, regs);
d->running = 0;
if (unlikely(d->pending && !d->disable_depth)) {
irq_mask = 1 <<
(gpio_irq - bank->virtual_irq_start);
d->pending = 0;
_enable_gpio_irqbank(bank, irq_mask, 1);
retrigger |= irq_mask;
}
}

if (cpu_is_omap24xx()) {
Expand All @@ -804,13 +873,14 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
_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);
}
/* 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 (!unmasked)
desc->chip->unmask(irq);

}

static void gpio_ack_irq(unsigned int irq)
Expand Down

0 comments on commit 0307162

Please sign in to comment.