diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 88 |
1 files changed, 79 insertions, 9 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index d3c8ea7eecfd..cd1e508f90c1 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c | |||
@@ -537,6 +537,34 @@ static inline void _clear_gpio_irqstatus(struct gpio_bank *bank, int gpio) | |||
537 | _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); | 537 | _clear_gpio_irqbank(bank, 1 << get_gpio_index(gpio)); |
538 | } | 538 | } |
539 | 539 | ||
540 | static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) | ||
541 | { | ||
542 | void __iomem *reg = bank->base; | ||
543 | |||
544 | switch (bank->method) { | ||
545 | case METHOD_MPUIO: | ||
546 | reg += OMAP_MPUIO_GPIO_MASKIT; | ||
547 | break; | ||
548 | case METHOD_GPIO_1510: | ||
549 | reg += OMAP1510_GPIO_INT_MASK; | ||
550 | break; | ||
551 | case METHOD_GPIO_1610: | ||
552 | reg += OMAP1610_GPIO_IRQENABLE1; | ||
553 | break; | ||
554 | case METHOD_GPIO_730: | ||
555 | reg += OMAP730_GPIO_INT_MASK; | ||
556 | break; | ||
557 | case METHOD_GPIO_24XX: | ||
558 | reg += OMAP24XX_GPIO_IRQENABLE1; | ||
559 | break; | ||
560 | default: | ||
561 | BUG(); | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | return __raw_readl(reg); | ||
566 | } | ||
567 | |||
540 | static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) | 568 | static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enable) |
541 | { | 569 | { |
542 | void __iomem *reg = bank->base; | 570 | void __iomem *reg = bank->base; |
@@ -736,6 +764,8 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
736 | u32 isr; | 764 | u32 isr; |
737 | unsigned int gpio_irq; | 765 | unsigned int gpio_irq; |
738 | struct gpio_bank *bank; | 766 | struct gpio_bank *bank; |
767 | u32 retrigger = 0; | ||
768 | int unmasked = 0; | ||
739 | 769 | ||
740 | desc->chip->ack(irq); | 770 | desc->chip->ack(irq); |
741 | 771 | ||
@@ -760,18 +790,22 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
760 | #endif | 790 | #endif |
761 | while(1) { | 791 | while(1) { |
762 | u32 isr_saved, level_mask = 0; | 792 | u32 isr_saved, level_mask = 0; |
793 | u32 enabled; | ||
763 | 794 | ||
764 | isr_saved = isr = __raw_readl(isr_reg); | 795 | enabled = _get_gpio_irqbank_mask(bank); |
796 | isr_saved = isr = __raw_readl(isr_reg) & enabled; | ||
765 | 797 | ||
766 | if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) | 798 | if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO)) |
767 | isr &= 0x0000ffff; | 799 | isr &= 0x0000ffff; |
768 | 800 | ||
769 | if (cpu_is_omap24xx()) | 801 | if (cpu_is_omap24xx()) { |
770 | level_mask = | 802 | level_mask = |
771 | __raw_readl(bank->base + | 803 | __raw_readl(bank->base + |
772 | OMAP24XX_GPIO_LEVELDETECT0) | | 804 | OMAP24XX_GPIO_LEVELDETECT0) | |
773 | __raw_readl(bank->base + | 805 | __raw_readl(bank->base + |
774 | OMAP24XX_GPIO_LEVELDETECT1); | 806 | OMAP24XX_GPIO_LEVELDETECT1); |
807 | level_mask &= enabled; | ||
808 | } | ||
775 | 809 | ||
776 | /* clear edge sensitive interrupts before handler(s) are | 810 | /* clear edge sensitive interrupts before handler(s) are |
777 | called so that we don't miss any interrupt occurred while | 811 | called so that we don't miss any interrupt occurred while |
@@ -782,19 +816,54 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
782 | 816 | ||
783 | /* if there is only edge sensitive GPIO pin interrupts | 817 | /* if there is only edge sensitive GPIO pin interrupts |
784 | configured, we could unmask GPIO bank interrupt immediately */ | 818 | configured, we could unmask GPIO bank interrupt immediately */ |
785 | if (!level_mask) | 819 | if (!level_mask && !unmasked) { |
820 | unmasked = 1; | ||
786 | desc->chip->unmask(irq); | 821 | desc->chip->unmask(irq); |
822 | } | ||
787 | 823 | ||
824 | isr |= retrigger; | ||
825 | retrigger = 0; | ||
788 | if (!isr) | 826 | if (!isr) |
789 | break; | 827 | break; |
790 | 828 | ||
791 | gpio_irq = bank->virtual_irq_start; | 829 | gpio_irq = bank->virtual_irq_start; |
792 | for (; isr != 0; isr >>= 1, gpio_irq++) { | 830 | for (; isr != 0; isr >>= 1, gpio_irq++) { |
793 | struct irqdesc *d; | 831 | struct irqdesc *d; |
832 | int irq_mask; | ||
794 | if (!(isr & 1)) | 833 | if (!(isr & 1)) |
795 | continue; | 834 | continue; |
796 | d = irq_desc + gpio_irq; | 835 | d = irq_desc + gpio_irq; |
836 | /* Don't run the handler if it's already running | ||
837 | * or was disabled lazely. | ||
838 | */ | ||
839 | if (unlikely((d->disable_depth || d->running))) { | ||
840 | irq_mask = 1 << | ||
841 | (gpio_irq - bank->virtual_irq_start); | ||
842 | /* The unmasking will be done by | ||
843 | * enable_irq in case it is disabled or | ||
844 | * after returning from the handler if | ||
845 | * it's already running. | ||
846 | */ | ||
847 | _enable_gpio_irqbank(bank, irq_mask, 0); | ||
848 | if (!d->disable_depth) { | ||
849 | /* Level triggered interrupts | ||
850 | * won't ever be reentered | ||
851 | */ | ||
852 | BUG_ON(level_mask & irq_mask); | ||
853 | d->pending = 1; | ||
854 | } | ||
855 | continue; | ||
856 | } | ||
857 | d->running = 1; | ||
797 | desc_handle_irq(gpio_irq, d, regs); | 858 | desc_handle_irq(gpio_irq, d, regs); |
859 | d->running = 0; | ||
860 | if (unlikely(d->pending && !d->disable_depth)) { | ||
861 | irq_mask = 1 << | ||
862 | (gpio_irq - bank->virtual_irq_start); | ||
863 | d->pending = 0; | ||
864 | _enable_gpio_irqbank(bank, irq_mask, 1); | ||
865 | retrigger |= irq_mask; | ||
866 | } | ||
798 | } | 867 | } |
799 | 868 | ||
800 | if (cpu_is_omap24xx()) { | 869 | if (cpu_is_omap24xx()) { |
@@ -804,13 +873,14 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc, | |||
804 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 1); | 873 | _enable_gpio_irqbank(bank, isr_saved & level_mask, 1); |
805 | } | 874 | } |
806 | 875 | ||
807 | /* if bank has any level sensitive GPIO pin interrupt | ||
808 | configured, we must unmask the bank interrupt only after | ||
809 | handler(s) are executed in order to avoid spurious bank | ||
810 | interrupt */ | ||
811 | if (level_mask) | ||
812 | desc->chip->unmask(irq); | ||
813 | } | 876 | } |
877 | /* if bank has any level sensitive GPIO pin interrupt | ||
878 | configured, we must unmask the bank interrupt only after | ||
879 | handler(s) are executed in order to avoid spurious bank | ||
880 | interrupt */ | ||
881 | if (!unmasked) | ||
882 | desc->chip->unmask(irq); | ||
883 | |||
814 | } | 884 | } |
815 | 885 | ||
816 | static void gpio_ack_irq(unsigned int irq) | 886 | static void gpio_ack_irq(unsigned int irq) |