We are developing firmware for a custom AM437x based board. We are not using the TI SDK, but rather the Linux based firmware is created using Buildroot and a standard kernel. While upgrading our previous kernel 4.19.45 to 5.7.1 I noticed an issue with a Wiznet Ethernet driver where the ISR was often being called in cases where no physical interrupt had occurred. Our device uses an active high, level sensitive interrupt signal which is connected to GPIO 2.25. It is handled by a threaded ISR.
The problem appears to be related to some changes made in gpio-omap.c. After our threaded ISR has run and has cleared the physical interrupt, omap_gpio_unmask_irq() is called to re-enable the GPIO interrupt. The current code clears the interrupt status register, then enables the interrupt for the appropriate pin (sets bit 25 in GPIO_LEVELDETECT1 register). However, this appears to immediately set the associated bit in the GPIO_IRQSTS_0 register, even though the physical interrupt line state at the time (as indicated in the GPIO_DATAIN register) is low (inactive). This results in a spurious call to the ISR. This appears to be incorrect chip behaviour, but it didn't cause spurious interrupts with the 4.19.45 code because it did these two operations in the reverse order, ie. enabled the interrupt then cleared the interrupt status.
So my workaround at the moment is to move the omap_set_gpio_triggering() call to be before the call to omap_clear_gpio_irqstatus().
The commit where the issue appears to have been introduced is https://github.com/torvalds/linux/commit/c859e0d479b3b4f6132fc12637c51e01492f31f6
My questions are: Is the observed register behaviour expected? Is the workaround valid, and if so can the standard driver be updated in due course?
thanks
Jeremy