diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index e8cc18a73fc..79ecfd4c813 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -13,9 +13,7 @@ #include #include #include -#ifdef CONFIG_CLOCK_CONTROL #include -#endif #ifdef CONFIG_SOC_NRF54H20_GPD #include #endif @@ -48,15 +46,10 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL); (IS_EQ(DT_PHA(PWM(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \ (0))), (0)) -#if NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0)) -#if CONFIG_CLOCK_CONTROL +#if (NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0))) && \ + CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL #define PWM_NRFX_USE_CLOCK_CONTROL 1 #endif -#define PWM_NRFX_INIT_PRIORITY 99 -#else -#define PWM_NRFX_INIT_PRIORITY CONFIG_PWM_INIT_PRIORITY -#endif - #define PWM_NRFX_CH_POLARITY_MASK BIT(15) #define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15) @@ -240,7 +233,13 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, out_level ^= 1; } +#if NRF_PWM_HAS_IDLEOUT + nrfx_pwm_stop(&config->pwm, true); + nrfy_pwm_channel_idle_set(config->pwm.p_reg, channel, out_level); + nrfy_pwm_enable(config->pwm.p_reg); +#else nrf_gpio_pin_write(psel, out_level); +#endif } data->pwm_needed &= ~BIT(channel); @@ -260,7 +259,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, */ nrfx_pwm_stop(&config->pwm, false); #if PWM_NRFX_USE_CLOCK_CONTROL - if (data->clock_requested) { + if (data->clock_requested && config->clk_dev) { int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec); if (ret < 0) { @@ -291,16 +290,18 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * loaded then) or the PWM peripheral is stopped. */ #if PWM_NRFX_USE_CLOCK_CONTROL + if (!data->clock_requested && config->clk_dev) { + int ret = nrf_clock_control_request_sync(config->clk_dev, + &config->clk_spec, + K_FOREVER); - int ret = nrf_clock_control_request_sync(config->clk_dev, &config->clk_spec, - K_FOREVER); + if (ret < 0) { + LOG_ERR("Global HSFLL request failed: %d", ret); + return ret; + } - if (ret < 0) { - LOG_ERR("Global HSFLL request failed: %d", ret); - return ret; + data->clock_requested = true; } - - data->clock_requested = true; #endif nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1, NRFX_PWM_FLAG_NO_EVT_FINISHED); @@ -324,7 +325,7 @@ static const struct pwm_driver_api pwm_nrfx_drv_api_funcs = { .get_cycles_per_sec = pwm_nrfx_get_cycles_per_sec, }; -static void pwm_resume(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; @@ -353,20 +354,28 @@ static void pwm_resume(const struct device *dev) seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted); } + + return 0; } -static void pwm_suspend(const struct device *dev) +static int pwm_suspend(const struct device *dev) { const struct pwm_nrfx_config *config = dev->config; nrfx_pwm_stop(&config->pwm, false); #if PWM_NRFX_USE_CLOCK_CONTROL + struct pwm_nrfx_data *data = dev->data; + if (data->clock_requested) { int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec); if (ret < 0) { LOG_ERR("Global HSFLL release failed: %d", ret); + return ret; } + + data->clock_requested = false; + } #endif while (!nrfx_pwm_stopped_check(&config->pwm)) { } @@ -377,15 +386,17 @@ static void pwm_suspend(const struct device *dev) memset(dev->data, 0, sizeof(struct pwm_nrfx_data)); (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + + return 0; } static int pwm_nrfx_pm_action(const struct device *dev, enum pm_device_action action) { if (action == PM_DEVICE_ACTION_RESUME) { - pwm_resume(dev); + return pwm_resume(dev); } else if (IS_ENABLED(CONFIG_PM_DEVICE) && (action == PM_DEVICE_ACTION_SUSPEND)) { - pwm_suspend(dev); + return pwm_suspend(dev); } else { return -ENOTSUP; } @@ -425,6 +436,11 @@ static int pwm_nrfx_init(const struct device *dev) COND_CODE_1(PWM_HAS_PROP(idx, memory_regions), \ (DT_PROP_OR(PWM_MEM_REGION(idx), zephyr_memory_attr, 0)), (0)) +#define PWM_INIT_PRIORITY(idx) \ + COND_CODE_1(PWM_NRFX_IS_FAST(_, /*empty*/, idx, _), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ + (CONFIG_PWM_INIT_PRIORITY)) + #define PWM_NRFX_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \ static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \ @@ -452,14 +468,13 @@ static int pwm_nrfx_init(const struct device *dev) (16ul * 1000ul * 1000ul)), \ IF_ENABLED(CONFIG_DCACHE, \ (.mem_attr = PWM_GET_MEM_ATTR(idx),)) \ - IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \ - (.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))), \ + IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \ + (.clk_dev = PWM_NRFX_IS_FAST(_, /*empty*/, idx, _) \ + ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \ + : NULL, \ .clk_spec = { \ .frequency = \ NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \ - .accuracy = 0, \ - .precision = \ - NRF_CLOCK_CONTROL_PRECISION_DEFAULT, \ },)) \ }; \ static int pwm_nrfx_init##idx(const struct device *dev) \ @@ -473,7 +488,7 @@ static int pwm_nrfx_init(const struct device *dev) pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \ &pwm_nrfx_##idx##_data, \ &pwm_nrfx_##idx##_config, \ - POST_KERNEL, PWM_NRFX_INIT_PRIORITY, \ + POST_KERNEL, PWM_INIT_PRIORITY(idx), \ &pwm_nrfx_drv_api_funcs) #define COND_PWM_NRFX_DEVICE(unused, prefix, i, _) \