Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 108 additions & 43 deletions drivers/gpio/gpio_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,49 +185,32 @@ int gpio_stm32_configure(u32_t *base_addr, int pin, int conf, int altf)
return 0;
}

/**
* @brief Enable EXTI of the specific line
*/
const int gpio_stm32_enable_int(int port, int pin)
static inline uint32_t gpio_stm32_pin_to_exti_line(int pin)
{
#if defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32F3X) || \
defined(CONFIG_SOC_SERIES_STM32F4X) || \
defined(CONFIG_SOC_SERIES_STM32F7X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \
defined(CONFIG_SOC_SERIES_STM32L1X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32G4X)
struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
struct stm32_pclken pclken = {
#ifdef CONFIG_SOC_SERIES_STM32H7X
.bus = STM32_CLOCK_BUS_APB4,
.enr = LL_APB4_GRP1_PERIPH_SYSCFG
#if defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32F0X)
return ((pin % 4 * 4) << 16) | (pin / 4);
#elif defined(CONFIG_SOC_SERIES_STM32MP1X)
return (((pin * 8) % 32) << 16) | (pin / 4);
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
return ((pin & 0x3) << (16 + 3)) | (pin >> 2);
#else
.bus = STM32_CLOCK_BUS_APB2,
.enr = LL_APB2_GRP1_PERIPH_SYSCFG
#endif /* CONFIG_SOC_SERIES_STM32H7X */
};
/* Enable SYSCFG clock */
clock_control_on(clk, (clock_control_subsys_t *) &pclken);
return (0xF << ((pin % 4 * 4) + 16)) | (pin / 4);
#endif
}

/**
* @brief Set GPIO port as EXTI source for the specific pin number
*/
static int gpio_stm32_set_exti_source(int port, int pin)
{
uint32_t line;

if (pin > 15) {
return -EINVAL;
}

#if defined(CONFIG_SOC_SERIES_STM32L0X) || \
defined(CONFIG_SOC_SERIES_STM32F0X)
line = ((pin % 4 * 4) << 16) | (pin / 4);
#elif defined(CONFIG_SOC_SERIES_STM32MP1X)
line = (((pin * 8) % 32) << 16) | (pin / 4);
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
line = ((pin & 0x3) << (16 + 3)) | (pin >> 2);
#else
line = (0xF << ((pin % 4 * 4) + 16)) | (pin / 4);
#endif
line = gpio_stm32_pin_to_exti_line(pin);

#if defined(CONFIG_SOC_SERIES_STM32L0X) && defined(LL_SYSCFG_EXTI_PORTH)
/*
Expand All @@ -240,9 +223,9 @@ const int gpio_stm32_enable_int(int port, int pin)
}
#endif

#ifdef CONFIG_SOC_SERIES_STM32F1X
#if defined(CONFIG_SOC_SERIES_STM32F1X)
LL_GPIO_AF_SetEXTISource(port, line);
#elif CONFIG_SOC_SERIES_STM32MP1X
#elif defined(CONFIG_SOC_SERIES_STM32MP1X)
LL_EXTI_SetEXTISource(port, line);
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
LL_EXTI_SetEXTISource(port, line);
Expand All @@ -253,13 +236,82 @@ const int gpio_stm32_enable_int(int port, int pin)
return 0;
}

/**
* @brief Get enabled GPIO port for EXTI of the specific pin number
*/
static int gpio_stm32_get_exti_source(int pin)
{
uint32_t line;
int port;

if (pin > 15) {
return -EINVAL;
}

line = gpio_stm32_pin_to_exti_line(pin);

#if defined(CONFIG_SOC_SERIES_STM32F1X)
port = LL_GPIO_AF_GetEXTISource(line);
#elif defined(CONFIG_SOC_SERIES_STM32MP1X)
port = LL_EXTI_GetEXTISource(line);
#elif defined(CONFIG_SOC_SERIES_STM32G0X)
port = LL_EXTI_GetEXTISource(line);
#else
port = LL_SYSCFG_GetEXTISource(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;
}

/**
* @brief Enable EXTI of the specific line
*/
static int gpio_stm32_enable_int(int port, int pin)
{
#if defined(CONFIG_SOC_SERIES_STM32F2X) || \
defined(CONFIG_SOC_SERIES_STM32F3X) || \
defined(CONFIG_SOC_SERIES_STM32F4X) || \
defined(CONFIG_SOC_SERIES_STM32F7X) || \
defined(CONFIG_SOC_SERIES_STM32H7X) || \
defined(CONFIG_SOC_SERIES_STM32L1X) || \
defined(CONFIG_SOC_SERIES_STM32L4X) || \
defined(CONFIG_SOC_SERIES_STM32G4X)
struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
struct stm32_pclken pclken = {
#ifdef CONFIG_SOC_SERIES_STM32H7X
.bus = STM32_CLOCK_BUS_APB4,
.enr = LL_APB4_GRP1_PERIPH_SYSCFG
#else
.bus = STM32_CLOCK_BUS_APB2,
.enr = LL_APB2_GRP1_PERIPH_SYSCFG
#endif /* CONFIG_SOC_SERIES_STM32H7X */
};
/* Enable SYSCFG clock */
clock_control_on(clk, (clock_control_subsys_t *) &pclken);
#endif

return gpio_stm32_set_exti_source(port, pin);
}

/**
* @brief Configure pin or port
*/
static int gpio_stm32_config(struct device *dev, int access_op,
u32_t pin, int flags)
{
const struct gpio_stm32_config *cfg = dev->config->config_info;
int err = 0;
int pincfg;
int map_res;

Expand All @@ -282,18 +334,24 @@ static int gpio_stm32_config(struct device *dev, int access_op,
*/
map_res = gpio_stm32_flags_to_conf(flags, &pincfg);
if (map_res != 0) {
return map_res;
err = map_res;
goto release_lock;
}

if (gpio_stm32_configure(cfg->base, pin, pincfg, 0) != 0) {
return -EIO;
err = -EIO;
goto release_lock;
}

if (IS_ENABLED(CONFIG_EXTI_STM32) && (flags & GPIO_INT) != 0) {
if (!IS_ENABLED(CONFIG_EXTI_STM32)) {
goto release_lock;
}

if (flags & GPIO_INT) {
if (stm32_exti_set_callback(pin, cfg->port,
gpio_stm32_isr, dev) != 0) {
return -EBUSY;
err = -EBUSY;
goto release_lock;
}

gpio_stm32_enable_int(cfg->port, pin);
Expand All @@ -313,20 +371,27 @@ static int gpio_stm32_config(struct device *dev, int access_op,
stm32_exti_trigger(pin, edge);
} else {
/* Level trigger interrupts not supported */
return -ENOTSUP;
err = -ENOTSUP;
goto release_lock;
}

if (stm32_exti_enable(pin) != 0) {
return -ENOSYS;
err = -EIO;
goto release_lock;
}
} else {
if (gpio_stm32_get_exti_source(pin) == cfg->port) {
stm32_exti_disable(pin);
stm32_exti_unset_callback(pin);
}

}

release_lock:
#if defined(CONFIG_STM32H7_DUAL_CORE)
LL_HSEM_ReleaseLock(HSEM, LL_HSEM_ID_1, 0);
#endif /* CONFIG_STM32H7_DUAL_CORE */

return 0;
return err;
}

/**
Expand Down