diff options
Diffstat (limited to 'drivers/gpio/gpio-omap.c')
-rw-r--r-- | drivers/gpio/gpio-omap.c | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index dbf869fb63ce..3233b72b6828 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c | |||
@@ -518,7 +518,13 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) | |||
518 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | 518 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) |
519 | irq_set_handler_locked(d, handle_level_irq); | 519 | irq_set_handler_locked(d, handle_level_irq); |
520 | else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | 520 | else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
521 | irq_set_handler_locked(d, handle_edge_irq); | 521 | /* |
522 | * Edge IRQs are already cleared/acked in irq_handler and | ||
523 | * not need to be masked, as result handle_edge_irq() | ||
524 | * logic is excessed here and may cause lose of interrupts. | ||
525 | * So just use handle_simple_irq. | ||
526 | */ | ||
527 | irq_set_handler_locked(d, handle_simple_irq); | ||
522 | 528 | ||
523 | return 0; | 529 | return 0; |
524 | 530 | ||
@@ -678,7 +684,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) | |||
678 | static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) | 684 | static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) |
679 | { | 685 | { |
680 | void __iomem *isr_reg = NULL; | 686 | void __iomem *isr_reg = NULL; |
681 | u32 isr; | 687 | u32 enabled, isr, level_mask; |
682 | unsigned int bit; | 688 | unsigned int bit; |
683 | struct gpio_bank *bank = gpiobank; | 689 | struct gpio_bank *bank = gpiobank; |
684 | unsigned long wa_lock_flags; | 690 | unsigned long wa_lock_flags; |
@@ -691,23 +697,21 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) | |||
691 | pm_runtime_get_sync(bank->chip.parent); | 697 | pm_runtime_get_sync(bank->chip.parent); |
692 | 698 | ||
693 | while (1) { | 699 | while (1) { |
694 | u32 isr_saved, level_mask = 0; | ||
695 | u32 enabled; | ||
696 | |||
697 | raw_spin_lock_irqsave(&bank->lock, lock_flags); | 700 | raw_spin_lock_irqsave(&bank->lock, lock_flags); |
698 | 701 | ||
699 | enabled = omap_get_gpio_irqbank_mask(bank); | 702 | enabled = omap_get_gpio_irqbank_mask(bank); |
700 | isr_saved = isr = readl_relaxed(isr_reg) & enabled; | 703 | isr = readl_relaxed(isr_reg) & enabled; |
701 | 704 | ||
702 | if (bank->level_mask) | 705 | if (bank->level_mask) |
703 | level_mask = bank->level_mask & enabled; | 706 | level_mask = bank->level_mask & enabled; |
707 | else | ||
708 | level_mask = 0; | ||
704 | 709 | ||
705 | /* clear edge sensitive interrupts before handler(s) are | 710 | /* clear edge sensitive interrupts before handler(s) are |
706 | called so that we don't miss any interrupt occurred while | 711 | called so that we don't miss any interrupt occurred while |
707 | executing them */ | 712 | executing them */ |
708 | omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask); | 713 | if (isr & ~level_mask) |
709 | omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask); | 714 | omap_clear_gpio_irqbank(bank, isr & ~level_mask); |
710 | omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask); | ||
711 | 715 | ||
712 | raw_spin_unlock_irqrestore(&bank->lock, lock_flags); | 716 | raw_spin_unlock_irqrestore(&bank->lock, lock_flags); |
713 | 717 | ||
@@ -1010,7 +1014,7 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
1010 | 1014 | ||
1011 | /*---------------------------------------------------------------------*/ | 1015 | /*---------------------------------------------------------------------*/ |
1012 | 1016 | ||
1013 | static void __init omap_gpio_show_rev(struct gpio_bank *bank) | 1017 | static void omap_gpio_show_rev(struct gpio_bank *bank) |
1014 | { | 1018 | { |
1015 | static bool called; | 1019 | static bool called; |
1016 | u32 rev; | 1020 | u32 rev; |