diff --git a/drivers/pwm/pwm_stm32.c b/drivers/pwm/pwm_stm32.c index 740bd5abac0de2..675985900541fb 100644 --- a/drivers/pwm/pwm_stm32.c +++ b/drivers/pwm/pwm_stm32.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -77,11 +78,28 @@ struct pwm_stm32_capture_data { struct pwm_stm32_data { /** Timer clock (Hz). */ uint32_t tim_clk; + /* Reset controller device configuration */ + const struct reset_dt_spec reset; #ifdef CONFIG_PWM_CAPTURE struct pwm_stm32_capture_data capture; #endif /* CONFIG_PWM_CAPTURE */ }; +#define TIMING_NR_CELLS 4 + +/** + * @brief structure to convey optional pwm channel timings settings + */ +struct pwm_config_channel_timing { + uint32_t channel; + /* pwm period in nanoseconds */ + uint32_t period_ns; + /* pwm pulse in nanoseconds */ + uint32_t pulse_ns; + /* flags in 16 bit value*/ + pwm_flags_t flags; +}; + /** PWM configuration. */ struct pwm_stm32_config { TIM_TypeDef *timer; @@ -93,6 +111,8 @@ struct pwm_stm32_config { void (*irq_config_func)(const struct device *dev); const bool four_channel_capture_support; #endif /* CONFIG_PWM_CAPTURE */ + const struct pwm_config_channel_timing *timings; + size_t n_timings; }; /** Maximum number of timer channels : some stm32 soc have 6 else only 4 */ @@ -760,6 +780,7 @@ static int pwm_stm32_init(const struct device *dev) const struct pwm_stm32_config *cfg = dev->config; int r; + int i; const struct device *clk; LL_TIM_InitTypeDef init; @@ -783,6 +804,9 @@ static int pwm_stm32_init(const struct device *dev) return r; } + /* Reset timer to default state using RCC */ + (void)reset_line_toggle_dt(&data->reset); + /* configure pinmux */ r = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); if (r < 0) { @@ -816,6 +840,18 @@ static int pwm_stm32_init(const struct device *dev) cfg->irq_config_func(dev); #endif /* CONFIG_PWM_CAPTURE */ + /* set optional timing value for channels */ + for (i = 0; i < cfg->n_timings; i++) { + const struct pwm_config_channel_timing *preset = &cfg->timings[i]; + r = pwm_set(dev, preset->channel, preset->period_ns, + preset->pulse_ns, preset->flags); + if (r < 0) { + LOG_ERR("PWM timing setup on channel %d failed (%d)", + preset->channel, r); + return r; + } + } + return 0; } @@ -830,12 +866,20 @@ static void pwm_stm32_irq_config_func_##index(const struct device *dev) \ } #define CAPTURE_INIT(index) \ .irq_config_func = pwm_stm32_irq_config_func_##index, \ - .four_channel_capture_support = DT_INST_PROP(index, four_channel_capture_support) + .four_channel_capture_support = DT_INST_PROP(index, four_channel_capture_support), #else #define IRQ_CONFIG_FUNC(index) #define CAPTURE_INIT(index) #endif /* CONFIG_PWM_CAPTURE */ +#define DEFINE_TIMINGS(index) \ + static const uint32_t pwm_channel_timings_##index[] = \ + DT_INST_PROP_OR(index, timings, {}); + +#define USE_TIMINGS(index) \ + .timings = (const struct pwm_config_channel_timing *) pwm_channel_timings_##index, \ + .n_timings = ARRAY_SIZE(pwm_channel_timings_##index)/TIMING_NR_CELLS, + #define DT_INST_CLK(index, inst) \ { \ .bus = DT_CLOCKS_CELL(DT_INST_PARENT(index), bus), \ @@ -843,9 +887,14 @@ static void pwm_stm32_irq_config_func_##index(const struct device *dev) \ } #define PWM_DEVICE_INIT(index) \ - static struct pwm_stm32_data pwm_stm32_data_##index; \ + static struct pwm_stm32_data pwm_stm32_data_##index = { \ + .reset = RESET_DT_SPEC_GET(DT_INST_PARENT(index)), \ + }; \ + \ IRQ_CONFIG_FUNC(index) \ \ + DEFINE_TIMINGS(index) \ + \ PINCTRL_DT_INST_DEFINE(index); \ \ static const struct pwm_stm32_config pwm_stm32_config_##index = { \ @@ -855,6 +904,7 @@ static void pwm_stm32_irq_config_func_##index(const struct device *dev) \ .pclken = DT_INST_CLK(index, timer), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ CAPTURE_INIT(index) \ + USE_TIMINGS(index) \ }; \ \ DEVICE_DT_INST_DEFINE(index, &pwm_stm32_init, NULL, \ diff --git a/dts/bindings/pwm/st,stm32-pwm.yaml b/dts/bindings/pwm/st,stm32-pwm.yaml index 1a1f9ee02eaddf..118cad65608a4c 100644 --- a/dts/bindings/pwm/st,stm32-pwm.yaml +++ b/dts/bindings/pwm/st,stm32-pwm.yaml @@ -11,6 +11,15 @@ properties: pinctrl-names: required: true + timings: + required: false + type: array + description: | + defines the pwm values per channel defined in pinctrl-0 + set during driver init + <1 /*channel*/ PWM_USEC(10000) /*period*/ PWM_USEC(5000) /*pulse*/ 0 /*flags*/>, + <2 /*channel*/ PWM_USEC(10000) /*period*/ PWM_USEC(5000) /*pulse*/ 0 /*flags*/>; + four-channel-capture-support: type: boolean description: |