1313#include <zephyr/linker/devicetree_regions.h>
1414#include <zephyr/cache.h>
1515#include <zephyr/mem_mgmt/mem_attr.h>
16+ #ifdef CONFIG_CLOCK_CONTROL
17+ #include <zephyr/drivers/clock_control/nrf_clock_control.h>
18+ #endif
1619#ifdef CONFIG_SOC_NRF54H20_GPD
1720#include <nrf/gpd.h>
1821#endif
@@ -35,6 +38,26 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
3538#define ANOMALY_109_EGU_IRQ_CONNECT (idx )
3639#endif
3740
41+ #define PWM (dev_idx ) DT_NODELABEL(pwm##dev_idx)
42+ #define PWM_PROP (dev_idx , prop ) DT_PROP(PWM(dev_idx), prop)
43+ #define PWM_HAS_PROP (idx , prop ) DT_NODE_HAS_PROP(PWM(idx), prop)
44+
45+ #define PWM_NRFX_IS_FAST (unused , prefix , idx , _ ) \
46+ COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(PWM(idx)), \
47+ (COND_CODE_1(PWM_HAS_PROP(idx, power_domains), \
48+ (IS_EQ(DT_PHA(PWM(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \
49+ (0))), (0))
50+
51+ #if NRFX_FOREACH_PRESENT (PWM , PWM_NRFX_IS_FAST , (|| ), (0 ))
52+ #if CONFIG_CLOCK_CONTROL
53+ #define PWM_NRFX_USE_CLOCK_CONTROL 1
54+ #endif
55+ #define PWM_NRFX_INIT_PRIORITY 99
56+ #else
57+ #define PWM_NRFX_INIT_PRIORITY CONFIG_PWM_INIT_PRIORITY
58+ #endif
59+
60+
3861#define PWM_NRFX_CH_POLARITY_MASK BIT(15)
3962#define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15)
4063#define PWM_NRFX_CH_VALUE (compare_value , inverted ) \
@@ -49,6 +72,10 @@ struct pwm_nrfx_config {
4972#ifdef CONFIG_DCACHE
5073 uint32_t mem_attr ;
5174#endif
75+ #ifdef PWM_NRFX_USE_CLOCK_CONTROL
76+ const struct device * clk_dev ;
77+ struct nrf_clock_spec clk_spec ;
78+ #endif
5279};
5380
5481struct pwm_nrfx_data {
@@ -57,6 +84,9 @@ struct pwm_nrfx_data {
5784 uint8_t pwm_needed ;
5885 uint8_t prescaler ;
5986 bool stop_requested ;
87+ #ifdef PWM_NRFX_USE_CLOCK_CONTROL
88+ bool clock_requested ;
89+ #endif
6090};
6191/* Ensure the pwm_needed bit mask can accommodate all available channels. */
6292#if (NRF_PWM_CHANNEL_COUNT > 8 )
@@ -229,6 +259,18 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
229259 * ensure it is stopped before starting the next playback.
230260 */
231261 nrfx_pwm_stop (& config -> pwm , false);
262+ #if PWM_NRFX_USE_CLOCK_CONTROL
263+ if (data -> clock_requested ) {
264+ int ret = nrf_clock_control_release (config -> clk_dev , & config -> clk_spec );
265+
266+ if (ret < 0 ) {
267+ LOG_ERR ("Global HSFLL release failed: %d" , ret );
268+ return ret ;
269+ }
270+
271+ data -> clock_requested = false;
272+ }
273+ #endif
232274 data -> stop_requested = true;
233275 } else {
234276 if (data -> stop_requested ) {
@@ -248,6 +290,18 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
248290 * until another playback is requested (new values will be
249291 * loaded then) or the PWM peripheral is stopped.
250292 */
293+ #if PWM_NRFX_USE_CLOCK_CONTROL
294+
295+ int ret = nrf_clock_control_request_sync (config -> clk_dev , & config -> clk_spec ,
296+ K_FOREVER );
297+
298+ if (ret < 0 ) {
299+ LOG_ERR ("Global HSFLL request failed: %d" , ret );
300+ return ret ;
301+ }
302+
303+ data -> clock_requested = true;
304+ #endif
251305 nrfx_pwm_simple_playback (& config -> pwm , & config -> seq , 1 ,
252306 NRFX_PWM_FLAG_NO_EVT_FINISHED );
253307 }
@@ -306,6 +360,14 @@ static void pwm_suspend(const struct device *dev)
306360 const struct pwm_nrfx_config * config = dev -> config ;
307361
308362 nrfx_pwm_stop (& config -> pwm , false);
363+ #if PWM_NRFX_USE_CLOCK_CONTROL
364+
365+ int ret = nrf_clock_control_release (config -> clk_dev , & config -> clk_spec );
366+
367+ if (ret < 0 ) {
368+ LOG_ERR ("Global HSFLL release failed: %d" , ret );
369+ }
370+ #endif
309371 while (!nrfx_pwm_stopped_check (& config -> pwm )) {
310372 }
311373
@@ -351,9 +413,6 @@ static int pwm_nrfx_init(const struct device *dev)
351413 return pm_device_driver_init (dev , pwm_nrfx_pm_action );
352414}
353415
354- #define PWM (dev_idx ) DT_NODELABEL(pwm##dev_idx)
355- #define PWM_PROP (dev_idx , prop ) DT_PROP(PWM(dev_idx), prop)
356- #define PWM_HAS_PROP (idx , prop ) DT_NODE_HAS_PROP(PWM(idx), prop)
357416#define PWM_MEM_REGION (idx ) DT_PHANDLE(PWM(idx), memory_regions)
358417
359418#define PWM_MEMORY_SECTION (idx ) \
@@ -393,6 +452,15 @@ static int pwm_nrfx_init(const struct device *dev)
393452 (16ul * 1000ul * 1000ul)), \
394453 IF_ENABLED(CONFIG_DCACHE, \
395454 (.mem_attr = PWM_GET_MEM_ATTR(idx),)) \
455+ IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
456+ (.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))), \
457+ .clk_spec = { \
458+ .frequency = \
459+ NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \
460+ .accuracy = 0, \
461+ .precision = \
462+ NRF_CLOCK_CONTROL_PRECISION_DEFAULT, \
463+ },)) \
396464 }; \
397465 static int pwm_nrfx_init##idx(const struct device *dev) \
398466 { \
@@ -405,7 +473,7 @@ static int pwm_nrfx_init(const struct device *dev)
405473 pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \
406474 &pwm_nrfx_##idx##_data, \
407475 &pwm_nrfx_##idx##_config, \
408- POST_KERNEL, CONFIG_PWM_INIT_PRIORITY , \
476+ POST_KERNEL, PWM_NRFX_INIT_PRIORITY , \
409477 &pwm_nrfx_drv_api_funcs)
410478
411479#define COND_PWM_NRFX_DEVICE (unused , prefix , i , _ ) \
0 commit comments