From 655266b198ebc29fe97da8189bbd09f9af2630f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Stasiak?= Date: Thu, 2 Jan 2025 12:20:51 +0100 Subject: [PATCH 1/3] Revert "[nrf fromlist] drivers: pwm: nrfx: add global hsfll request for fast PWM" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 99faf47f0f758f7921764fb2b11b44554910c7fa. Signed-off-by: Michał Stasiak --- drivers/pwm/pwm_nrfx.c | 76 +++--------------------------------------- 1 file changed, 4 insertions(+), 72 deletions(-) diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index e8cc18a73fc..230a90d6cdf 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -13,9 +13,6 @@ #include #include #include -#ifdef CONFIG_CLOCK_CONTROL -#include -#endif #ifdef CONFIG_SOC_NRF54H20_GPD #include #endif @@ -38,26 +35,6 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL); #define ANOMALY_109_EGU_IRQ_CONNECT(idx) #endif -#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx) -#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop) -#define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop) - -#define PWM_NRFX_IS_FAST(unused, prefix, idx, _) \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(PWM(idx)), \ - (COND_CODE_1(PWM_HAS_PROP(idx, power_domains), \ - (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 -#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) #define PWM_NRFX_CH_VALUE(compare_value, inverted) \ @@ -72,10 +49,6 @@ struct pwm_nrfx_config { #ifdef CONFIG_DCACHE uint32_t mem_attr; #endif -#ifdef PWM_NRFX_USE_CLOCK_CONTROL - const struct device *clk_dev; - struct nrf_clock_spec clk_spec; -#endif }; struct pwm_nrfx_data { @@ -84,9 +57,6 @@ struct pwm_nrfx_data { uint8_t pwm_needed; uint8_t prescaler; bool stop_requested; -#ifdef PWM_NRFX_USE_CLOCK_CONTROL - bool clock_requested; -#endif }; /* Ensure the pwm_needed bit mask can accommodate all available channels. */ #if (NRF_PWM_CHANNEL_COUNT > 8) @@ -259,18 +229,6 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * ensure it is stopped before starting the next playback. */ nrfx_pwm_stop(&config->pwm, false); -#if PWM_NRFX_USE_CLOCK_CONTROL - 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 data->stop_requested = true; } else { if (data->stop_requested) { @@ -290,18 +248,6 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * until another playback is requested (new values will be * loaded then) or the PWM peripheral is stopped. */ -#if PWM_NRFX_USE_CLOCK_CONTROL - - 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; - } - - data->clock_requested = true; -#endif nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1, NRFX_PWM_FLAG_NO_EVT_FINISHED); } @@ -360,14 +306,6 @@ static void 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 - - int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec); - - if (ret < 0) { - LOG_ERR("Global HSFLL release failed: %d", ret); - } -#endif while (!nrfx_pwm_stopped_check(&config->pwm)) { } @@ -413,6 +351,9 @@ static int pwm_nrfx_init(const struct device *dev) 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) +#define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop) #define PWM_MEM_REGION(idx) DT_PHANDLE(PWM(idx), memory_regions) #define PWM_MEMORY_SECTION(idx) \ @@ -452,15 +393,6 @@ 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))), \ - .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 +405,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, CONFIG_PWM_INIT_PRIORITY, \ &pwm_nrfx_drv_api_funcs) #define COND_PWM_NRFX_DEVICE(unused, prefix, i, _) \ From efb35222c10de7d77743b861b29b2c064154efcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Stasiak?= Date: Thu, 12 Dec 2024 12:04:44 +0100 Subject: [PATCH 2/3] [nrf fromlist] drivers: pwm: nrfx: add global hsfll request for fast PWM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added clock control api for global hsfll used in fast PWM120 driver. Upstream PR #: 82133 Signed-off-by: Michał Stasiak --- drivers/pwm/pwm_nrfx.c | 93 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index 230a90d6cdf..065784ed80f 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_SOC_NRF54H20_GPD #include #endif @@ -35,6 +36,21 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL); #define ANOMALY_109_EGU_IRQ_CONNECT(idx) #endif +#define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx) +#define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop) +#define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop) + +#define PWM_NRFX_IS_FAST(unused, prefix, idx, _) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(PWM(idx)), \ + (COND_CODE_1(PWM_HAS_PROP(idx, power_domains), \ + (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))) && \ + CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL +#define PWM_NRFX_USE_CLOCK_CONTROL 1 +#endif + #define PWM_NRFX_CH_POLARITY_MASK BIT(15) #define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15) #define PWM_NRFX_CH_VALUE(compare_value, inverted) \ @@ -49,6 +65,10 @@ struct pwm_nrfx_config { #ifdef CONFIG_DCACHE uint32_t mem_attr; #endif +#ifdef PWM_NRFX_USE_CLOCK_CONTROL + const struct device *clk_dev; + struct nrf_clock_spec clk_spec; +#endif }; struct pwm_nrfx_data { @@ -57,6 +77,9 @@ struct pwm_nrfx_data { uint8_t pwm_needed; uint8_t prescaler; bool stop_requested; +#ifdef PWM_NRFX_USE_CLOCK_CONTROL + bool clock_requested; +#endif }; /* Ensure the pwm_needed bit mask can accommodate all available channels. */ #if (NRF_PWM_CHANNEL_COUNT > 8) @@ -229,6 +252,18 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * ensure it is stopped before starting the next playback. */ nrfx_pwm_stop(&config->pwm, false); +#if PWM_NRFX_USE_CLOCK_CONTROL + if (data->clock_requested && config->clk_dev) { + 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 data->stop_requested = true; } else { if (data->stop_requested) { @@ -248,6 +283,20 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * until another playback is requested (new values will be * 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); + + if (ret < 0) { + LOG_ERR("Global HSFLL request failed: %d", ret); + return ret; + } + + data->clock_requested = true; + } +#endif nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1, NRFX_PWM_FLAG_NO_EVT_FINISHED); } @@ -270,7 +319,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; @@ -299,13 +348,29 @@ 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)) { } @@ -315,15 +380,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; } @@ -351,9 +418,6 @@ static int pwm_nrfx_init(const struct device *dev) 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) -#define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop) #define PWM_MEM_REGION(idx) DT_PHANDLE(PWM(idx), memory_regions) #define PWM_MEMORY_SECTION(idx) \ @@ -366,6 +430,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; \ @@ -393,6 +462,14 @@ 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 = PWM_NRFX_IS_FAST(_, /*empty*/, idx, _) \ + ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \ + : NULL, \ + .clk_spec = { \ + .frequency = \ + NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \ + },)) \ }; \ static int pwm_nrfx_init##idx(const struct device *dev) \ { \ @@ -405,7 +482,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, CONFIG_PWM_INIT_PRIORITY, \ + POST_KERNEL, PWM_INIT_PRIORITY(idx), \ &pwm_nrfx_drv_api_funcs) #define COND_PWM_NRFX_DEVICE(unused, prefix, i, _) \ From 7c1a85218eb959db7ec11773b9aefb55e6d33f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Stasiak?= Date: Tue, 7 Jan 2025 14:51:23 +0100 Subject: [PATCH 3/3] [nrf fromlist] drivers: pwm: nrfx: Add idle output to PWM driver. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fast PWM120 prevents GPIO from driving pin with low/high state when PWM duty is 0% or 100%. Idleout feature needs to be used. It can be configured when PWM is disabled and works while it is enabled. Upstream PR #: 83652 Signed-off-by: Michał Stasiak --- drivers/pwm/pwm_nrfx.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index 065784ed80f..79ecfd4c813 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -233,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);