drivers: gpio: Add APIs for enabling/disabling interrupt

Add pin_interrupt_enable and pin_interrupt_disable in gpio_driver_api,
and add corresponding APIs in gpio.h for application to enable/disable
an interrupt without reconfiguring again.
This CL also Create a new Kconfig option for this feature.

Signed-off-by: Sung-Chi Li <lschyi@google.com>
This commit is contained in:
Sung-Chi Li 2022-11-15 08:13:52 +00:00 committed by Christopher Friedt
parent 4bb8b2523f
commit b78208960d
2 changed files with 40 additions and 1 deletions

View file

@ -59,6 +59,16 @@ config GPIO_HOGS_INIT_PRIORITY
GPIO hogs initialization priority. GPIO hogs must be initialized after the
GPIO controller drivers.
config GPIO_ENABLE_DISABLE_INTERRUPT
bool "Support for enable/disable interrupt without re-config [EXPERIMENTAL]"
select EXPERIMENTAL
help
This option enables the support for enabling/disabling interrupt with
previous configuration, and enabling/disabling the interrupt only turns
on/off the interrupt signal without changing other registers, such as
pending register, etc. The driver must implement it to work.
source "drivers/gpio/Kconfig.b91"
source "drivers/gpio/Kconfig.dw"

View file

@ -86,6 +86,11 @@ extern "C" {
* flag. If a pin was configured as Active Low, physical level low will be
* considered as logical level 1 (an active state), physical level high will
* be considered as logical level 0 (an inactive state).
* The GPIO controller should reset the interrupt status, such as clearing the
* pending bit, etc, when configuring the interrupt triggering properties.
* Applications should use the `GPIO_INT_MODE_ENABLE_ONLY` and
* `GPIO_INT_MODE_DISABLE_ONLY` flags to enable and disable interrupts on the
* pin without changing any GPIO settings.
* @{
*/
@ -129,6 +134,16 @@ extern "C" {
*/
#define GPIO_INT_HIGH_1 (1U << 26)
#ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
/* Disable/Enable interrupt functionality without changing other interrupt
* related register, such as clearing the pending register.
*
* This is a component flag that should be combined with `GPIO_INT_ENABLE` or
* `GPIO_INT_DISABLE` flags to produce a meaningful configuration.
*/
#define GPIO_INT_ENABLE_DISABLE_ONLY (1u << 27)
#endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
#define GPIO_INT_MASK (GPIO_INT_DISABLE | \
GPIO_INT_ENABLE | \
GPIO_INT_LEVELS_LOGICAL | \
@ -509,6 +524,10 @@ enum gpio_int_mode {
GPIO_INT_MODE_DISABLED = GPIO_INT_DISABLE,
GPIO_INT_MODE_LEVEL = GPIO_INT_ENABLE,
GPIO_INT_MODE_EDGE = GPIO_INT_ENABLE | GPIO_INT_EDGE,
#ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
GPIO_INT_MODE_DISABLE_ONLY = GPIO_INT_DISABLE | GPIO_INT_ENABLE_DISABLE_ONLY,
GPIO_INT_MODE_ENABLE_ONLY = GPIO_INT_ENABLE | GPIO_INT_ENABLE_DISABLE_ONLY,
#endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
};
enum gpio_int_trig {
@ -624,7 +643,12 @@ static inline int z_impl_gpio_pin_interrupt_configure(const struct device *port,
"enabled for a level interrupt.");
__ASSERT(((flags & GPIO_INT_ENABLE) == 0) ||
((flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1)) != 0),
#ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
((flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1)) != 0) ||
(flags & GPIO_INT_ENABLE_DISABLE_ONLY) != 0,
#else
((flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1)) != 0),
#endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
"At least one of GPIO_INT_LOW_0, GPIO_INT_HIGH_1 has to be "
"enabled.");
@ -638,7 +662,12 @@ static inline int z_impl_gpio_pin_interrupt_configure(const struct device *port,
}
trig = (enum gpio_int_trig)(flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1));
#ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
mode = (enum gpio_int_mode)(flags & (GPIO_INT_EDGE | GPIO_INT_DISABLE | GPIO_INT_ENABLE |
GPIO_INT_ENABLE_DISABLE_ONLY));
#else
mode = (enum gpio_int_mode)(flags & (GPIO_INT_EDGE | GPIO_INT_DISABLE | GPIO_INT_ENABLE));
#endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
return api->pin_interrupt_configure(port, pin, mode, trig);
}