drivers: gpio: stm32: move EXTI line port configuration to proper driver

Move the functions that interact with EXTI configuration registers to
select or get the GPIO port that triggers events on a given EXTI line
to the EXTI driver.

Signed-off-by: Mathieu Choplain <mathieu.choplain@st.com>
This commit is contained in:
Mathieu Choplain 2024-08-22 17:04:32 +02:00 committed by Anas Nashif
parent d34f5f27bf
commit 0551825ca3
3 changed files with 100 additions and 90 deletions

View file

@ -15,7 +15,6 @@
#include <stm32_ll_exti.h>
#include <stm32_ll_gpio.h>
#include <stm32_ll_pwr.h>
#include <stm32_ll_system.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
#include <zephyr/sys/util.h>
@ -294,93 +293,6 @@ static int gpio_stm32_clock_request(const struct device *dev, bool on)
return ret;
}
static inline uint32_t gpio_stm32_pin_to_exti_src_cfg_line(gpio_pin_t pin)
{
#if defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32F0X)
return ((pin % 4 * 4) << 16) | (pin / 4);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
return ((pin & 0x3) << (16 + 3)) | (pin >> 2);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti)
/* Gives the LL_SBS_EXTI_LINEn corresponding to the pin */
return (((pin % 4 * 4) << LL_SBS_REGISTER_PINPOS_SHFT) | (pin / 4));
#else
return (0xF << ((pin % 4 * 4) + 16)) | (pin / 4);
#endif
}
/**
* @brief Set which GPIO port triggers events on specified EXTI line.
*
* @param line EXTI line number (= pin number)
* @param port GPIO port number (STM32_PORTA, STM32_PORTB, ...)
*/
static void gpio_stm32_set_exti_line_src_port(gpio_pin_t line, uint32_t port)
{
uint32_t ll_line = gpio_stm32_pin_to_exti_src_cfg_line(line);
#if defined(CONFIG_SOC_SERIES_STM32L0X) && defined(LL_SYSCFG_EXTI_PORTH)
/*
* Ports F and G are not present on some STM32L0 parts, so
* for these parts port H external interrupt should be enabled
* by writing value 0x5 instead of 0x7.
*/
if (port == STM32_PORTH) {
port = LL_SYSCFG_EXTI_PORTH;
}
#endif
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
#ifdef CONFIG_SOC_SERIES_STM32F1X
LL_GPIO_AF_SetEXTISource(port, ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
LL_EXTI_SetEXTISource(port, ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti)
LL_SBS_SetEXTISource(port, ll_line);
#else
LL_SYSCFG_SetEXTISource(port, ll_line);
#endif
z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
}
/**
* @brief Get port which is triggering events on specified EXTI line.
*
* @param line EXTI line number (= pin number)
* @returns GPIO port number (STM32_PORTA, STM32_PORTB, ...)
*/
static uint32_t gpio_stm32_get_exti_line_src_port(gpio_pin_t line)
{
uint32_t ll_line = gpio_stm32_pin_to_exti_src_cfg_line(line);
uint32_t port;
#ifdef CONFIG_SOC_SERIES_STM32F1X
port = LL_GPIO_AF_GetEXTISource(ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
port = LL_EXTI_GetEXTISource(ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti)
port = LL_SBS_GetEXTISource(ll_line);
#else
port = LL_SYSCFG_GetEXTISource(ll_line);
#endif
#if defined(CONFIG_SOC_SERIES_STM32L0X) && defined(LL_SYSCFG_EXTI_PORTH)
/*
* Ports F and G are not present on some STM32L0 parts, so
* for these parts port H external interrupt is enabled
* by writing value 0x5 instead of 0x7.
*/
if (port == LL_SYSCFG_EXTI_PORTH) {
port = STM32_PORTH;
}
#endif
return port;
}
static int gpio_stm32_port_get_raw(const struct device *dev, uint32_t *value)
{
const struct gpio_stm32_config *cfg = dev->config;
@ -607,7 +519,7 @@ static int gpio_stm32_pin_interrupt_configure(const struct device *dev,
#endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
if (mode == GPIO_INT_MODE_DISABLED) {
if (gpio_stm32_get_exti_line_src_port(pin) == cfg->port) {
if (stm32_exti_get_line_src_port(pin) == cfg->port) {
stm32_exti_disable(pin);
stm32_exti_unset_callback(pin);
stm32_exti_trigger(pin, STM32_EXTI_TRIG_NONE);
@ -642,7 +554,7 @@ static int gpio_stm32_pin_interrupt_configure(const struct device *dev,
goto exit;
}
gpio_stm32_set_exti_line_src_port(pin, cfg->port);
stm32_exti_set_line_src_port(pin, cfg->port);
stm32_exti_trigger(pin, edge);

View file

@ -15,9 +15,12 @@
#include <zephyr/device.h>
#include <soc.h>
#include <stm32_ll_bus.h>
#include <stm32_ll_gpio.h> /* For STM32F1 series */
#include <stm32_ll_exti.h>
#include <stm32_ll_system.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/util.h>
#include <zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h> /* For STM32L0 series */
#include <zephyr/drivers/interrupt_controller/exti_stm32.h>
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
#include <zephyr/irq.h>
@ -48,6 +51,25 @@ struct stm32_exti_data {
struct __exti_cb cb[NUM_EXTI_LINES];
};
/**
* @returns the LL_<PPP>_EXTI_LINE_xxx define that corresponds to specified @p linenum
* This value can be used with the LL EXTI source configuration functions.
*/
static inline uint32_t stm32_exti_linenum_to_src_cfg_line(gpio_pin_t linenum)
{
#if defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32F0X)
return ((linenum % 4 * 4) << 16) | (linenum / 4);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
return ((linenum & 0x3) << (16 + 3)) | (linenum >> 2);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti)
/* Gives the LL_SBS_EXTI_LINEn corresponding to the line number */
return (((linenum % 4 * 4) << LL_SBS_REGISTER_PINPOS_SHFT) | (linenum / 4));
#else
return (0xF << ((linenum % 4 * 4) + 16)) | (linenum / 4);
#endif
}
/**
* @brief Checks interrupt pending bit for specified EXTI line
*
@ -297,3 +319,62 @@ void stm32_exti_unset_callback(stm32_exti_line_t line)
data->cb[line].cb = NULL;
data->cb[line].data = NULL;
}
void stm32_exti_set_line_src_port(gpio_pin_t line, uint32_t port)
{
uint32_t ll_line = stm32_exti_linenum_to_src_cfg_line(line);
#if defined(CONFIG_SOC_SERIES_STM32L0X) && defined(LL_SYSCFG_EXTI_PORTH)
/*
* Ports F and G are not present on some STM32L0 parts, so
* for these parts port H external interrupt should be enabled
* by writing value 0x5 instead of 0x7.
*/
if (port == STM32_PORTH) {
port = LL_SYSCFG_EXTI_PORTH;
}
#endif
z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);
#ifdef CONFIG_SOC_SERIES_STM32F1X
LL_GPIO_AF_SetEXTISource(port, ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
LL_EXTI_SetEXTISource(port, ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti)
LL_SBS_SetEXTISource(port, ll_line);
#else
LL_SYSCFG_SetEXTISource(port, ll_line);
#endif
z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
}
uint32_t stm32_exti_get_line_src_port(gpio_pin_t line)
{
uint32_t ll_line = stm32_exti_linenum_to_src_cfg_line(line);
uint32_t port;
#ifdef CONFIG_SOC_SERIES_STM32F1X
port = LL_GPIO_AF_GetEXTISource(ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
port = LL_EXTI_GetEXTISource(ll_line);
#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti)
port = LL_SBS_GetEXTISource(ll_line);
#else
port = LL_SYSCFG_GetEXTISource(ll_line);
#endif
#if defined(CONFIG_SOC_SERIES_STM32L0X) && defined(LL_SYSCFG_EXTI_PORTH)
/*
* Ports F and G are not present on some STM32L0 parts, so
* for these parts port H external interrupt is enabled
* by writing value 0x5 instead of 0x7.
*/
if (port == LL_SYSCFG_EXTI_PORTH) {
port = STM32_PORTH;
}
#endif
return port;
}

View file

@ -22,6 +22,7 @@
#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_H_
#include <zephyr/types.h>
#include <zephyr/drivers/gpio.h>
/**
* @brief Type representing an EXTI line number
@ -91,4 +92,20 @@ int stm32_exti_set_callback(stm32_exti_line_t line, stm32_exti_callback_t cb, vo
*/
void stm32_exti_unset_callback(stm32_exti_line_t line);
/**
* @brief Set which GPIO port triggers events on specified EXTI line.
*
* @param line EXTI line number (= pin number)
* @param port GPIO port number (STM32_PORTA, STM32_PORTB, ...)
*/
void stm32_exti_set_line_src_port(gpio_pin_t line, uint32_t port);
/**
* @brief Get port which is triggering events on specified EXTI line.
*
* @param line EXTI line number (= pin number)
* @returns GPIO port number (STM32_PORTA, STM32_PORTB, ...)
*/
uint32_t stm32_exti_get_line_src_port(gpio_pin_t line);
#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_EXTI_STM32_H_ */