diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index c5dd8a283f98cd4..187a710e37c40e8 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -260,16 +260,13 @@ static const struct pwm_driver_api pwm_nrfx_drv_api_funcs = { .get_cycles_per_sec = pwm_nrfx_get_cycles_per_sec, }; -static int pwm_nrfx_init(const struct device *dev) +static int pwm_resume(const struct device *dev) { const struct pwm_nrfx_config *config = dev->config; uint8_t initially_inverted = 0; - nrfx_err_t result; int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - ANOMALY_109_EGU_IRQ_CONNECT(NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE); - if (ret < 0) { return ret; } @@ -293,60 +290,68 @@ static int pwm_nrfx_init(const struct device *dev) seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted); } - result = nrfx_pwm_init(&config->pwm, &config->initial_config, pwm_handler, dev->data); - if (result != NRFX_SUCCESS) { - LOG_ERR("Failed to initialize device: %s", dev->name); - return -EBUSY; - } - return 0; } -#ifdef CONFIG_PM_DEVICE -static void pwm_nrfx_uninit(const struct device *dev) +static int pwm_suspend(const struct device *dev, bool do_pinctrl) { const struct pwm_nrfx_config *config = dev->config; + struct pwm_nrfx_data *data = dev->data; - nrfx_pwm_uninit(&config->pwm); + if (data->active) { + /* PWM is still in use. Force stopping. */ + data->stop_requested = true; + nrfx_pwm_stop(&config->pwm, false); + while (data->stop_requested) { + } + } memset(dev->data, 0, sizeof(struct pwm_nrfx_data)); + + if (!do_pinctrl) { + return 0; + } + + return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); } static int pwm_nrfx_pm_action(const struct device *dev, enum pm_device_action action) { - const struct pwm_nrfx_config *config = dev->config; - int ret = 0; + int ret = -ENOTSUP; switch (action) { - case PM_DEVICE_ACTION_RESUME: - ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; - } - ret = pwm_nrfx_init(dev); + case PM_DEVICE_ACTION_TURN_ON: + ret = pwm_suspend(dev, false); break; - case PM_DEVICE_ACTION_SUSPEND: - pwm_nrfx_uninit(dev); - - ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); - if (ret < 0) { - return ret; + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + ret = pwm_suspend(dev, true); } break; - + case PM_DEVICE_ACTION_RESUME: + ret = pwm_resume(dev); + break; default: - return -ENOTSUP; + break; } return ret; } -#else -#define pwm_nrfx_pm_action NULL +static int pwm_nrfx_init(const struct device *dev) +{ + const struct pwm_nrfx_config *config = dev->config; + int result; + + result = nrfx_pwm_init(&config->pwm, &config->initial_config, pwm_handler, dev->data); + if (result != NRFX_SUCCESS) { + LOG_ERR("Failed to initialize device: %s", dev->name); + return -EBUSY; + } -#endif /* CONFIG_PM_DEVICE */ + return pm_device_driver_init(dev, pwm_nrfx_pm_action); +} #define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx) #define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop) @@ -385,6 +390,8 @@ static int pwm_nrfx_pm_action(const struct device *dev, { \ IRQ_CONNECT(DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority), \ nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0); \ + ANOMALY_109_EGU_IRQ_CONNECT( \ + NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE); \ return pwm_nrfx_init(dev); \ }; \ PM_DEVICE_DT_DEFINE(PWM(idx), pwm_nrfx_pm_action); \