Commit 0551825c authored by Mathieu Choplain's avatar Mathieu Choplain Committed by Anas Nashif
Browse files

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: default avatarMathieu Choplain <mathieu.choplain@st.com>
parent d34f5f27
Loading
Loading
Loading
Loading
+2 −90
Changes for drivers/gpio/gpio_stm32.c: 2 added lines, 90 removed lines.
Original line number Diff line number Diff line
@@ -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);

+81 −0
Changes for drivers/interrupt_controller/intc_exti_stm32.c: 81 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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;
}
+17 −0
Changes for include/zephyr/drivers/interrupt_controller/exti_stm32.h: 17 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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_ */