* Tony Lindgren <tony@xxxxxxxxxxx> [170311 12:13]: > Hi, > > * Ladislav Michl <ladis@xxxxxxxxxxxxxx> [170310 15:06]: > > Hi there, > > > > I'm using drivers/media/rc/gpio-ir-recv.c on DM3730 based board and getting > > a lot of IR protocol decoding failures: > > RC5(x/sz) decode failed at state 0 count 7 (855us space) > > RC5(x/sz) decode failed at state 1 count 4 (1740us space) > > RC5(x/sz) decode failed at state 4 count 1 (125000us space) > > RC5(x/sz) decode failed at state 0 count 1 (182348us space) > > RC5(x/sz) decode failed at state 0 count 1 (366us pulse) > > etc... > > Hacking gpio-ir-recv code to add debounce on GPIO pin makes situation > > a bit better, but still bad enough. > > It seems this problem is there since dawn of linux-omap time [1] and > > can be easily reproduced requesting edge trigerred gpio interrupt, > > feeding that gpio pin from signal generator and toggling another gpio > > in interrupt hangler with scope hooked. > > Last time patch [1] was updated to kernel 2.6.32 and you can find it > > below. > > > > So it seems noone is really using edge triggered interrupts, right? > > Interesting, adding Grygorii to cc as well. > > > Now, patch bellow is for ancient omap1 variant (and I'd love to give it > > a try with recent kernel, but everything I compiled so far is insanely > > huge) and does not support both rising and falling edge. > > > > To make interrupt code reliable I do not see other option than to read > > gpio input register and make loop similar as in patch bellow. However, > > this was repeatedly rejected in the past. So, better ideas, anyone? > > > [1] http://marc.info/?l=linux-omap&m=119634410025393&w=2 > > Oh that thing yeah I remember testing it too. If we don't have any > other options for edge interrupts I guess the loop is what we need to > do. If you have some experimental patch to play with against the > current mainline, please post it and I'll give it a try too. Hmm and we already seem to have a similar loop in the mainline kernel? At least I could not easily spot what we might be missing. Regards, Tony > > --- linux-2.6.32/arch/arm/plat-omap/gpio.c.orig 2009-12-29 20:56:29.000000000 +0100 > > +++ linux-2.6.32/arch/arm/plat-omap/gpio.c 2009-12-29 20:56:44.000000000 +0100 > > @@ -192,6 +192,7 @@ > > u32 saved_risingdetect; > > #endif > > u32 level_mask; > > + u32 serviced; > > spinlock_t lock; > > struct gpio_chip chip; > > struct clk *dbck; > > @@ -1204,6 +1205,28 @@ > > spin_unlock_irqrestore(&bank->lock, flags); > > } > > > > +static u32 _get_gpio_irq_status(struct gpio_bank *bank) > > +{ > > + u32 isr, ism, in, re; > > + u32 base = bank->base; > > + > > + switch (bank->method) { > > +#ifdef CONFIG_ARCH_OMAP15XX > > + case METHOD_GPIO_1510: > > + in = __raw_readl(base + OMAP1510_GPIO_DATA_INPUT); > > + isr = __raw_readl(base + OMAP1510_GPIO_INT_STATUS); > > + ism = __raw_readl(base + OMAP1510_GPIO_INT_MASK) | 0xffff0000; > > + re = __raw_readl(base + OMAP1510_GPIO_INT_CONTROL); > > + isr |= (~(in^re)) & (~ism); > > + break; > > +#endif > > + default: > > + BUG(); > > + return 0; > > + } > > + return isr; > > +} > > + > > /* > > * We need to unmask the GPIO bank interrupt as soon as possible to > > * avoid missing GPIO interrupts for other lines in the bank. > > @@ -1218,11 +1241,13 @@ > > void __iomem *isr_reg = NULL; > > u32 isr; > > unsigned int gpio_irq; > > + unsigned long flags; > > struct gpio_bank *bank; > > u32 retrigger = 0; > > int unmasked = 0; > > > > desc->chip->ack(irq); > > + desc->chip->unmask(irq); > > > > bank = get_irq_data(irq); > > #ifdef CONFIG_ARCH_OMAP1 > > @@ -1249,54 +1274,29 @@ > > if (bank->method == METHOD_GPIO_24XX) > > isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0; > > #endif > > + spin_lock_irqsave(&bank->lock, flags); > > while(1) { > > - u32 isr_saved, level_mask = 0; > > - u32 enabled; > > + u32 isr; > > + unsigned long serviced; > > > > - 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_class_is_omap2()) { > > - level_mask = bank->level_mask & enabled; > > - } > > - > > - /* 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 && !unmasked) { > > - unmasked = 1; > > - desc->chip->unmask(irq); > > - } > > - > > - isr |= retrigger; > > - retrigger = 0; > > + isr = _get_gpio_irq_status(bank) & ~bank->serviced; > > if (!isr) > > break; > > > > gpio_irq = bank->virtual_irq_start; > > - for (; isr != 0; isr >>= 1, gpio_irq++) { > > - if (!(isr & 1)) > > - continue; > > - > > - generic_handle_irq(gpio_irq); > > + serviced = 1; > > + for (; isr != 0; gpio_irq++, serviced <<= 1 ) { > > + if (isr & serviced) { > > + bank->serviced |= serviced; > > + spin_unlock_irqrestore(&bank->lock, flags); > > + generic_handle_irq(gpio_irq); > > + spin_lock_irqsave(&bank->lock, flags); > > + bank->serviced &= ~serviced; > > + isr &= ~serviced; > > + } > > } > > } > > - /* 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); > > - > > + spin_unlock_irqrestore(&bank->lock, flags); > > } > > > > static void gpio_irq_shutdown(unsigned int irq) > > @@ -1781,6 +1781,7 @@ > > #endif > > > > bank->mod_usage = 0; > > + bank->serviced = 0; > > /* REVISIT eventually switch from OMAP-specific gpio structs > > * over to the generic ones > > */ > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > > the body of a message to majordomo@xxxxxxxxxxxxxxx > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html