drivers: gpio_mcux: Add support for GPIO ICR
Add support for devices that use the kinetis GPIO/PORT scheme but with the slight modification that the interrupt control bits are in the GPIO peripheral instead of the PORT peripheral. Signed-off-by: Declan Snyder <declan.snyder@nxp.com>
This commit is contained in:
parent
205a8fed79
commit
5254fcbd0a
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Freescale Semiconductor, Inc.
|
||||
* Copyright (c) 2017, NXP
|
||||
* Copyright 2017, 2023-2024 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -96,7 +96,7 @@ static int gpio_mcux_configure(const struct device *dev,
|
|||
pcr |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
|
||||
|
||||
} else if ((flags & GPIO_PULL_DOWN) != 0) {
|
||||
/* Enable the pull and select the pulldown resistor (deselect
|
||||
/* Enable the pull and select the pulldown resistor, deselect
|
||||
* the pullup resistor.
|
||||
*/
|
||||
pcr |= PORT_PCR_PE_MASK;
|
||||
|
@ -178,6 +178,7 @@ static int gpio_mcux_port_toggle_bits(const struct device *dev, uint32_t mask)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
static uint32_t get_port_pcr_irqc_value_from_flags(const struct device *dev,
|
||||
uint32_t pin,
|
||||
enum gpio_int_mode mode,
|
||||
|
@ -213,6 +214,54 @@ static uint32_t get_port_pcr_irqc_value_from_flags(const struct device *dev,
|
|||
|
||||
return PORT_PCR_IRQC(port_interrupt);
|
||||
}
|
||||
#endif /* !defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT */
|
||||
|
||||
#if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
|
||||
|
||||
#define GPIO_MCUX_INTERRUPT_DISABLED 0
|
||||
#define GPIO_MCUX_INTERRUPT_LOGIC_0 0x8
|
||||
#define GPIO_MCUX_INTERRUPT_RISING_EDGE 0x9
|
||||
#define GPIO_MCUX_INTERRUPT_FALLING_EDGE 0xA
|
||||
#define GPIO_MCUX_INTERRUPT_BOTH_EDGE 0xB
|
||||
#define GPIO_MCUX_INTERRUPT_LOGIC_1 0xC
|
||||
|
||||
static uint32_t get_gpio_icr_irqc_value_from_flags(const struct device *dev,
|
||||
uint32_t pin,
|
||||
enum gpio_int_mode mode,
|
||||
enum gpio_int_trig trig)
|
||||
{
|
||||
uint8_t gpio_interrupt = 0;
|
||||
|
||||
if (mode == GPIO_INT_MODE_DISABLED) {
|
||||
gpio_interrupt = GPIO_MCUX_INTERRUPT_DISABLED;
|
||||
} else {
|
||||
if (mode == GPIO_INT_MODE_LEVEL) {
|
||||
if (trig == GPIO_INT_TRIG_LOW) {
|
||||
gpio_interrupt = GPIO_MCUX_INTERRUPT_LOGIC_0;
|
||||
} else {
|
||||
gpio_interrupt = GPIO_MCUX_INTERRUPT_LOGIC_1;
|
||||
}
|
||||
} else {
|
||||
switch (trig) {
|
||||
case GPIO_INT_TRIG_LOW:
|
||||
gpio_interrupt = GPIO_MCUX_INTERRUPT_FALLING_EDGE;
|
||||
break;
|
||||
case GPIO_INT_TRIG_HIGH:
|
||||
gpio_interrupt = GPIO_MCUX_INTERRUPT_RISING_EDGE;
|
||||
break;
|
||||
case GPIO_INT_TRIG_BOTH:
|
||||
gpio_interrupt = GPIO_MCUX_INTERRUPT_BOTH_EDGE;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GPIO_ICR_IRQC(gpio_interrupt);
|
||||
}
|
||||
#endif /* (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) */
|
||||
|
||||
static int gpio_mcux_pin_interrupt_configure(const struct device *dev,
|
||||
gpio_pin_t pin, enum gpio_int_mode mode,
|
||||
|
@ -239,9 +288,16 @@ static int gpio_mcux_pin_interrupt_configure(const struct device *dev,
|
|||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
uint32_t pcr = get_port_pcr_irqc_value_from_flags(dev, pin, mode, trig);
|
||||
|
||||
port_base->PCR[pin] = (port_base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | pcr;
|
||||
#elif (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
|
||||
uint32_t icr = get_gpio_icr_irqc_value_from_flags(dev, pin, mode, trig);
|
||||
|
||||
gpio_base->ICR[pin] = (gpio_base->ICR[pin] & ~GPIO_ICR_IRQC_MASK) | icr;
|
||||
#endif /* !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -260,10 +316,18 @@ static void gpio_mcux_port_isr(const struct device *dev)
|
|||
struct gpio_mcux_data *data = dev->data;
|
||||
uint32_t int_status;
|
||||
|
||||
#if !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) && FSL_FEATURE_PORT_HAS_NO_INTERRUPT)
|
||||
int_status = config->port_base->ISFR;
|
||||
|
||||
/* Clear the port interrupts */
|
||||
config->port_base->ISFR = int_status;
|
||||
#elif (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT) && \
|
||||
FSL_FEATURE_GPIO_HAS_INTERRUPT_CHANNEL_SELECT)
|
||||
int_status = config->gpio_base->ISFR[0];
|
||||
|
||||
/* Clear the gpio interrupts */
|
||||
config->gpio_base->ISFR[0] = int_status;
|
||||
#endif /* !(defined(FSL_FEATURE_PORT_HAS_NO_INTERRUPT) */
|
||||
|
||||
gpio_fire_callbacks(&data->callbacks, dev, int_status);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue