drivers: pwm: stm32: add support for pinmux

Add support for DT based pinmux configurations.

Signed-off-by: Gerard Marull-Paretas <gerard@teslabs.com>
This commit is contained in:
Gerard Marull-Paretas 2020-10-02 10:54:40 +02:00 committed by Kumar Gala
commit af1b9442ca
2 changed files with 167 additions and 1 deletions

View file

@ -16,6 +16,7 @@
#include <init.h>
#include <drivers/clock_control/stm32_clock_control.h>
#include <pinmux/stm32/pinmux_stm32.h>
#include <logging/log.h>
LOG_MODULE_REGISTER(pwm_stm32, CONFIG_PWM_LOG_LEVEL);
@ -34,6 +35,10 @@ struct pwm_stm32_config {
uint32_t prescaler;
/** Clock configuration. */
struct stm32_pclken pclken;
/** pinctrl configurations. */
const struct soc_gpio_pinctrl *pinctrl;
/** Number of pinctrl configurations. */
size_t pinctrl_len;
};
/** Series F3, F7, G0, G4, H7, L4, MP1 and WB have up to 6 channels, others up
@ -276,6 +281,153 @@ static int pwm_stm32_init(const struct device *dev)
return r;
}
/* configure pinmux */
if (cfg->pinctrl_len != 0U) {
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl)
/* apply F1 series remaps */
int remap;
remap = stm32_dt_pinctrl_remap_check(cfg->pinctrl,
cfg->pinctrl_len);
if (remap < 0) {
LOG_ERR("pinctrl remap check failed (%d)", remap);
return remap;
}
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_AFIO);
switch ((uint32_t)cfg->timer) {
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers1), okay)
case DT_REG_ADDR(DT_NODELABEL(timers1)):
if (remap == REMAP_1) {
LL_GPIO_AF_RemapPartial_TIM1();
} else if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM1();
} else {
LL_GPIO_AF_DisableRemap_TIM1();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers2), okay)
case DT_REG_ADDR(DT_NODELABEL(timers2)):
if (remap == REMAP_1) {
LL_GPIO_AF_RemapPartial1_TIM2();
} else if (remap == REMAP_2) {
LL_GPIO_AF_RemapPartial2_TIM2();
} else if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM2();
} else {
LL_GPIO_AF_DisableRemap_TIM2();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers3), okay)
case DT_REG_ADDR(DT_NODELABEL(timers3)):
if (remap == REMAP_1) {
LL_GPIO_AF_RemapPartial_TIM3();
} else if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM3();
} else {
LL_GPIO_AF_DisableRemap_TIM3();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers4), okay)
case DT_REG_ADDR(DT_NODELABEL(timers4)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM4();
} else {
LL_GPIO_AF_DisableRemap_TIM4();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers9), okay)
case DT_REG_ADDR(DT_NODELABEL(timers9)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM9();
} else {
LL_GPIO_AF_DisableRemap_TIM9();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers10), okay)
case DT_REG_ADDR(DT_NODELABEL(timers10)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM10();
} else {
LL_GPIO_AF_DisableRemap_TIM10();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers11), okay)
case DT_REG_ADDR(DT_NODELABEL(timers11)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM11();
} else {
LL_GPIO_AF_DisableRemap_TIM11();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers12), okay)
case DT_REG_ADDR(DT_NODELABEL(timers12)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM12();
} else {
LL_GPIO_AF_DisableRemap_TIM12();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers13), okay)
case DT_REG_ADDR(DT_NODELABEL(timers13)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM13();
} else {
LL_GPIO_AF_DisableRemap_TIM13();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers14), okay)
case DT_REG_ADDR(DT_NODELABEL(timers14)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM14();
} else {
LL_GPIO_AF_DisableRemap_TIM14();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers15), okay)
case DT_REG_ADDR(DT_NODELABEL(timers15)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM15();
} else {
LL_GPIO_AF_DisableRemap_TIM15();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers16), okay)
case DT_REG_ADDR(DT_NODELABEL(timers16)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM16();
} else {
LL_GPIO_AF_DisableRemap_TIM16();
}
break;
#endif
#if DT_NODE_HAS_STATUS(DT_NODELABEL(timers17), okay)
case DT_REG_ADDR(DT_NODELABEL(timers17)):
if (remap == REMAP_FULL) {
LL_GPIO_AF_EnableRemap_TIM17();
} else {
LL_GPIO_AF_DisableRemap_TIM17();
}
break;
#endif
}
#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_pinctrl) */
stm32_dt_pinctrl_configure(cfg->pinctrl, cfg->pinctrl_len);
}
/* initialize timer */
LL_TIM_StructInit(&init);
@ -308,11 +460,16 @@ static int pwm_stm32_init(const struct device *dev)
#define PWM_DEVICE_INIT(index) \
static struct pwm_stm32_data pwm_stm32_data_##index; \
\
static const struct soc_gpio_pinctrl pwm_pins_##index[] = \
ST_STM32_DT_PINCTRL(0, index); \
\
static const struct pwm_stm32_config pwm_stm32_config_##index = { \
.timer = (TIM_TypeDef *)DT_REG_ADDR( \
DT_INST(index, st_stm32_timers)), \
.prescaler = DT_INST_PROP(index, st_prescaler), \
.pclken = DT_INST_CLK(index, timer) \
.pclken = DT_INST_CLK(index, timer), \
.pinctrl = pwm_pins_##index, \
.pinctrl_len = ARRAY_SIZE(pwm_pins_##index), \
}; \
\
DEVICE_AND_API_INIT(pwm_stm32_##index, DT_INST_LABEL(index), \

View file

@ -13,6 +13,15 @@ properties:
required: true
description: Clock prescaler at the input of the timer
pinctrl-0:
type: phandles
required: false
description: |
GPIO pin configuration for PWM signal/s. We expect that the phandles
will reference pinctrl nodes, e.g.
pinctrl-0 = <&tim1_ch1_pwm_pa8 &tim1_ch2_pwm_pa9>;
"#pwm-cells":
const: 3