From 3b498e32b3901782c18d39baa04f1585647393b0 Mon Sep 17 00:00:00 2001 From: Martin Hoff Date: Tue, 7 Jul 2026 09:31:21 +0200 Subject: [PATCH 1/2] drivers: clock_control: siwx91x: fix PWM clock rate retrieval This patch ensure that clock_control_get_rate function returns the correct clock rate for the PWM peripheral. PWM is clocked from M4 processor clock. Upstream-status: pending Signed-off-by: Martin Hoff --- drivers/clock_control/clock_control_silabs_siwx91x.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/clock_control/clock_control_silabs_siwx91x.c b/drivers/clock_control/clock_control_silabs_siwx91x.c index d46324c8ae7f..21fdda6af02b 100644 --- a/drivers/clock_control/clock_control_silabs_siwx91x.c +++ b/drivers/clock_control/clock_control_silabs_siwx91x.c @@ -187,8 +187,13 @@ static int siwx91x_clock_get_rate(const struct device *dev, clock_control_subsys *rate = RSI_CLK_GetBaseClock(M4_UART1); return 0; case SIWX91X_CLK_PWM: - /* PWM peripheral operates at the system clock frequency */ - *rate = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + /* + * PWM peripheral runs from the M4 core clock domain. + * Do not use CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC here because it may be + * 32.768 kHz when the sleeptimer system timer is selected, which breaks + * pwm_set() nsec-to-cycles conversion. + */ + *rate = SystemCoreClock; return 0; case SIWX91X_CLK_WATCHDOG: *rate = LF_FSM_CLOCK_FREQUENCY; From 772f6dbcc3eeaabcdab9a1e6da15d0320acc5cbe Mon Sep 17 00:00:00 2001 From: Martin Hoff Date: Tue, 7 Jul 2026 09:34:14 +0200 Subject: [PATCH 2/2] drivers: pwm: siwx91x: add PM runtime management for PWM This patch adds PM runtime management for the PWM peripheral. It allows to block CPU from entering the sleep state when PWM is active. Upstream-status: pending Signed-off-by: Martin Hoff --- drivers/pwm/pwm_silabs_siwx91x.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm_silabs_siwx91x.c b/drivers/pwm/pwm_silabs_siwx91x.c index f7564728d008..8679bd32dce3 100644 --- a/drivers/pwm/pwm_silabs_siwx91x.c +++ b/drivers/pwm/pwm_silabs_siwx91x.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "sl_si91x_pwm.h" @@ -121,24 +122,28 @@ static int pwm_siwx91x_set_cycles(const struct device *dev, uint32_t channel, return -ENOTSUP; } + if (pulse_cycles > 0 && data->pwm_channel_cfg[channel].is_chan_active == false) { + pm_device_runtime_get(dev); + } + if (data->pwm_channel_cfg[channel].is_chan_active == false) { /* Configure the channel with default parameters */ ret = siwx91x_default_channel_config(dev, channel); if (ret) { - return -EINVAL; + goto out; } } ret = sl_si91x_pwm_get_time_period(channel, (uint16_t *)&prev_period); if (ret) { - return -EINVAL; + goto out; } if (period_cycles != prev_period) { ret = sl_si91x_pwm_set_time_period(channel, period_cycles, 0); if (ret) { /* Programmed value must be out of range (>65535) */ - return -EINVAL; + goto out; } } @@ -149,7 +154,7 @@ static int pwm_siwx91x_set_cycles(const struct device *dev, uint32_t channel, if (duty_cycle != data->pwm_channel_cfg[channel].duty_cycle) { ret = sl_si91x_pwm_set_duty_cycle(pulse_cycles, channel); if (ret) { - return -EINVAL; + goto out; } data->pwm_channel_cfg[channel].duty_cycle = duty_cycle; } @@ -158,12 +163,22 @@ static int pwm_siwx91x_set_cycles(const struct device *dev, uint32_t channel, /* Start PWM after configuring the channel for first time */ ret = sl_si91x_pwm_start(channel); if (ret) { - return -EINVAL; + goto out; } data->pwm_channel_cfg[channel].is_chan_active = true; } + if (pulse_cycles == 0 && data->pwm_channel_cfg[channel].is_chan_active == true) { + pm_device_runtime_put(dev); + data->pwm_channel_cfg[channel].is_chan_active = false; + } + return 0; + +out: + pm_device_runtime_put(dev); + data->pwm_channel_cfg[channel].is_chan_active = false; + return -EINVAL; } static int pwm_siwx91x_get_cycles_per_sec(const struct device *dev, uint32_t channel,