Skip to content

Commit b432b61

Browse files
committed
[nrf fromtree] 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. Signed-off-by: Krzysztof Chruściński <[email protected]> (cherry picked from commit e11d050)
1 parent e578365 commit b432b61

File tree

1 file changed

+30
-45
lines changed

1 file changed

+30
-45
lines changed

drivers/pwm/pwm_nrfx.c

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -257,19 +257,12 @@ static const struct pwm_driver_api pwm_nrfx_drv_api_funcs = {
257257
.get_cycles_per_sec = pwm_nrfx_get_cycles_per_sec,
258258
};
259259

260-
static int pwm_nrfx_init(const struct device *dev)
260+
static void pwm_resume(const struct device *dev)
261261
{
262262
const struct pwm_nrfx_config *config = dev->config;
263263
uint8_t initially_inverted = 0;
264-
nrfx_err_t result;
265-
266-
int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
267-
268-
ANOMALY_109_EGU_IRQ_CONNECT(NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE);
269264

270-
if (ret < 0) {
271-
return ret;
272-
}
265+
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
273266

274267
for (size_t i = 0; i < NRF_PWM_CHANNEL_COUNT; i++) {
275268
uint32_t psel;
@@ -289,61 +282,53 @@ static int pwm_nrfx_init(const struct device *dev)
289282

290283
seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted);
291284
}
292-
293-
result = nrfx_pwm_init(&config->pwm, &config->initial_config, pwm_handler, dev->data);
294-
if (result != NRFX_SUCCESS) {
295-
LOG_ERR("Failed to initialize device: %s", dev->name);
296-
return -EBUSY;
297-
}
298-
299-
return 0;
300285
}
301286

302-
#ifdef CONFIG_PM_DEVICE
303-
static void pwm_nrfx_uninit(const struct device *dev)
287+
static void pwm_suspend(const struct device *dev)
304288
{
305289
const struct pwm_nrfx_config *config = dev->config;
306290

307-
nrfx_pwm_uninit(&config->pwm);
291+
nrfx_pwm_stop(&config->pwm, false);
292+
while (!nrfx_pwm_stopped_check(&config->pwm)) {
293+
}
308294

309295
memset(dev->data, 0, sizeof(struct pwm_nrfx_data));
296+
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
310297
}
311298

312299
static int pwm_nrfx_pm_action(const struct device *dev,
313300
enum pm_device_action action)
314301
{
315-
const struct pwm_nrfx_config *config = dev->config;
316-
int ret = 0;
302+
if (action == PM_DEVICE_ACTION_RESUME) {
303+
pwm_resume(dev);
304+
} else if (IS_ENABLED(CONFIG_PM_DEVICE) && (action == PM_DEVICE_ACTION_SUSPEND)) {
305+
pwm_suspend(dev);
306+
} else {
307+
return -ENOTSUP;
308+
}
317309

318-
switch (action) {
319-
case PM_DEVICE_ACTION_RESUME:
320-
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
321-
if (ret < 0) {
322-
return ret;
323-
}
324-
ret = pwm_nrfx_init(dev);
325-
break;
310+
return 0;
311+
}
326312

327-
case PM_DEVICE_ACTION_SUSPEND:
328-
pwm_nrfx_uninit(dev);
313+
static int pwm_nrfx_init(const struct device *dev)
314+
{
315+
const struct pwm_nrfx_config *config = dev->config;
316+
nrfx_err_t err;
329317

330-
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
331-
if (ret < 0) {
332-
return ret;
333-
}
334-
break;
318+
ANOMALY_109_EGU_IRQ_CONNECT(NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE);
335319

336-
default:
337-
return -ENOTSUP;
320+
if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
321+
(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
338322
}
339323

340-
return ret;
341-
}
342-
#else
343-
344-
#define pwm_nrfx_pm_action NULL
324+
err = nrfx_pwm_init(&config->pwm, &config->initial_config, pwm_handler, dev->data);
325+
if (err != NRFX_SUCCESS) {
326+
LOG_ERR("Failed to initialize device: %s", dev->name);
327+
return -EBUSY;
328+
}
345329

346-
#endif /* CONFIG_PM_DEVICE */
330+
return pm_device_driver_init(dev, pwm_nrfx_pm_action);
331+
}
347332

348333
#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx)
349334
#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop)

0 commit comments

Comments
 (0)