Skip to content

Commit 1373a27

Browse files
committed
[nrf fromlist] drivers: pwm: nrfx: Improve runtime PM
Rework PM handling to use pm_device_driver_init(). Shim is not using put and get internally as there is no api that disables or stops pwm so it is hard to determine when to put the device. There are cases when PWM peripheral is stopped but PWM is still active because duty cycle is 100% or 0% and pin is driven by GPIO and not PWM. If user want to use runtime PM with PWM it is possible and getting the device will initialize internal data and putting will suspend by forcing PWM stop if used and setting pins to sleep state. However, from power consumption perspective it is enough to set 0% or 100% duty cycle on all channels. Upstream PR: zephyrproject-rtos/zephyr#78759 Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent a9a0b33 commit 1373a27

File tree

1 file changed

+42
-34
lines changed

1 file changed

+42
-34
lines changed

drivers/pwm/pwm_nrfx.c

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -260,16 +260,13 @@ static const struct pwm_driver_api pwm_nrfx_drv_api_funcs = {
260260
.get_cycles_per_sec = pwm_nrfx_get_cycles_per_sec,
261261
};
262262

263-
static int pwm_nrfx_init(const struct device *dev)
263+
static int pwm_resume(const struct device *dev)
264264
{
265265
const struct pwm_nrfx_config *config = dev->config;
266266
uint8_t initially_inverted = 0;
267-
nrfx_err_t result;
268267

269268
int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
270269

271-
ANOMALY_109_EGU_IRQ_CONNECT(NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE);
272-
273270
if (ret < 0) {
274271
return ret;
275272
}
@@ -293,60 +290,71 @@ static int pwm_nrfx_init(const struct device *dev)
293290
seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted);
294291
}
295292

296-
result = nrfx_pwm_init(&config->pwm, &config->initial_config, pwm_handler, dev->data);
297-
if (result != NRFX_SUCCESS) {
298-
LOG_ERR("Failed to initialize device: %s", dev->name);
299-
return -EBUSY;
300-
}
301-
302293
return 0;
303294
}
304295

305-
#ifdef CONFIG_PM_DEVICE
306-
static void pwm_nrfx_uninit(const struct device *dev)
296+
static int pwm_suspend(const struct device *dev)
307297
{
308298
const struct pwm_nrfx_config *config = dev->config;
299+
struct pwm_nrfx_data *data = dev->data;
309300

310-
nrfx_pwm_uninit(&config->pwm);
301+
if (data->active) {
302+
/* PWM is still in use. Force stopping. */
303+
data->stop_requested = true;
304+
nrfx_pwm_stop(&config->pwm, false);
305+
while (data->stop_requested) {
306+
}
307+
}
311308

312309
memset(dev->data, 0, sizeof(struct pwm_nrfx_data));
310+
311+
if (IS_ENABLED(CONFIG_PM_DEVICE)) {
312+
return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
313+
}
314+
315+
return 0;
313316
}
314317

315318
static int pwm_nrfx_pm_action(const struct device *dev,
316319
enum pm_device_action action)
317320
{
318-
const struct pwm_nrfx_config *config = dev->config;
319-
int ret = 0;
321+
int ret = -ENOTSUP;
320322

321323
switch (action) {
322-
case PM_DEVICE_ACTION_RESUME:
323-
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
324-
if (ret < 0) {
325-
return ret;
326-
}
327-
ret = pwm_nrfx_init(dev);
328-
break;
329-
330324
case PM_DEVICE_ACTION_SUSPEND:
331-
pwm_nrfx_uninit(dev);
332-
333-
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
334-
if (ret < 0) {
335-
return ret;
336-
}
325+
ret = pwm_suspend(dev);
326+
break;
327+
case PM_DEVICE_ACTION_RESUME:
328+
ret = pwm_resume(dev);
337329
break;
338-
339330
default:
340-
return -ENOTSUP;
331+
break;
341332
}
342333

343334
return ret;
344335
}
345-
#else
346336

347-
#define pwm_nrfx_pm_action NULL
337+
static int pwm_nrfx_init(const struct device *dev)
338+
{
339+
const struct pwm_nrfx_config *config = dev->config;
340+
nrfx_err_t err;
341+
int ret;
342+
343+
ANOMALY_109_EGU_IRQ_CONNECT(NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE);
344+
345+
err = nrfx_pwm_init(&config->pwm, &config->initial_config, pwm_handler, dev->data);
346+
if (err != NRFX_SUCCESS) {
347+
LOG_ERR("Failed to initialize device: %s", dev->name);
348+
return -EBUSY;
349+
}
350+
351+
ret = pwm_suspend(dev);
352+
if (ret != 0) {
353+
return ret;
354+
}
348355

349-
#endif /* CONFIG_PM_DEVICE */
356+
return pm_device_driver_init(dev, pwm_nrfx_pm_action);
357+
}
350358

351359
#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx)
352360
#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop)

0 commit comments

Comments
 (0)