Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (44 commits) [ARM] 3541/2: workaround for PXA27x erratum E7 [ARM] nommu: provide a way for correct control register value selection [ARM] 3705/1: add supersection support to ioremap() [ARM] 3707/1: iwmmxt: use the generic thread notifier infrastructure [ARM] 3706/2: ep93xx: add cirrus logic edb9315a support [ARM] 3704/1: format IOP Kconfig with tabs, create more consistency [ARM] 3703/1: Add help description for ARCH_EP80219 [ARM] 3678/1: MMC: Make OMAP MMC work [ARM] 3677/1: OMAP: Update H2 defconfig [ARM] 3676/1: ARM: OMAP: Fix dmtimers and timer32k to compile on OMAP1 [ARM] Add section support to ioremap [ARM] Fix sa11x0 SDRAM selection [ARM] Set bit 4 on section mappings correctly depending on CPU [ARM] 3666/1: TRIZEPS4 [1/5] core ARM: OMAP: Multiplexing for 24xx GPMC wait pin monitoring ARM: OMAP: Fix SRAM to use MT_MEMORY instead of MT_DEVICE ARM: OMAP: Update dmtimers ARM: OMAP: Make clock variables static ARM: OMAP: Fix GPMC compilation when DEBUG is defined ARM: OMAP: Mux updates for external DMA and GPIO ...
This commit is contained in:
@ -536,6 +536,49 @@ 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;
|
||||
int inv = 0;
|
||||
u32 l;
|
||||
u32 mask;
|
||||
|
||||
switch (bank->method) {
|
||||
case METHOD_MPUIO:
|
||||
reg += OMAP_MPUIO_GPIO_MASKIT;
|
||||
mask = 0xffff;
|
||||
inv = 1;
|
||||
break;
|
||||
case METHOD_GPIO_1510:
|
||||
reg += OMAP1510_GPIO_INT_MASK;
|
||||
mask = 0xffff;
|
||||
inv = 1;
|
||||
break;
|
||||
case METHOD_GPIO_1610:
|
||||
reg += OMAP1610_GPIO_IRQENABLE1;
|
||||
mask = 0xffff;
|
||||
break;
|
||||
case METHOD_GPIO_730:
|
||||
reg += OMAP730_GPIO_INT_MASK;
|
||||
mask = 0xffffffff;
|
||||
inv = 1;
|
||||
break;
|
||||
case METHOD_GPIO_24XX:
|
||||
reg += OMAP24XX_GPIO_IRQENABLE1;
|
||||
mask = 0xffffffff;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
l = __raw_readl(reg);
|
||||
if (inv)
|
||||
l = ~l;
|
||||
l &= mask;
|
||||
return l;
|
||||
}
|
||||
|
||||
static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable)
|
||||
{
|
||||
void __iomem *reg = bank->base;
|
||||
@ -735,6 +778,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);
|
||||
|
||||
@ -759,18 +804,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
|
||||
@ -781,19 +830,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()) {
|
||||
@ -803,13 +887,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)
|
||||
|
Reference in New Issue
Block a user