13
13
#include <zephyr/linker/devicetree_regions.h>
14
14
#include <zephyr/cache.h>
15
15
#include <zephyr/mem_mgmt/mem_attr.h>
16
+ #ifdef CONFIG_CLOCK_CONTROL
17
+ #include <zephyr/drivers/clock_control/nrf_clock_control.h>
18
+ #endif
16
19
#ifdef CONFIG_SOC_NRF54H20_GPD
17
20
#include <nrf/gpd.h>
18
21
#endif
@@ -35,6 +38,26 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
35
38
#define ANOMALY_109_EGU_IRQ_CONNECT (idx )
36
39
#endif
37
40
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
+
38
61
#define PWM_NRFX_CH_POLARITY_MASK BIT(15)
39
62
#define PWM_NRFX_CH_COMPARE_MASK BIT_MASK(15)
40
63
#define PWM_NRFX_CH_VALUE (compare_value , inverted ) \
@@ -49,6 +72,10 @@ struct pwm_nrfx_config {
49
72
#ifdef CONFIG_DCACHE
50
73
uint32_t mem_attr ;
51
74
#endif
75
+ #ifdef PWM_NRFX_USE_CLOCK_CONTROL
76
+ const struct device * clk_dev ;
77
+ struct nrf_clock_spec clk_spec ;
78
+ #endif
52
79
};
53
80
54
81
struct pwm_nrfx_data {
@@ -57,6 +84,9 @@ struct pwm_nrfx_data {
57
84
uint8_t pwm_needed ;
58
85
uint8_t prescaler ;
59
86
bool stop_requested ;
87
+ #ifdef PWM_NRFX_USE_CLOCK_CONTROL
88
+ bool clock_requested ;
89
+ #endif
60
90
};
61
91
/* Ensure the pwm_needed bit mask can accommodate all available channels. */
62
92
#if (NRF_PWM_CHANNEL_COUNT > 8 )
@@ -229,6 +259,18 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
229
259
* ensure it is stopped before starting the next playback.
230
260
*/
231
261
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
232
274
data -> stop_requested = true;
233
275
} else {
234
276
if (data -> stop_requested ) {
@@ -248,6 +290,18 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
248
290
* until another playback is requested (new values will be
249
291
* loaded then) or the PWM peripheral is stopped.
250
292
*/
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
251
305
nrfx_pwm_simple_playback (& config -> pwm , & config -> seq , 1 ,
252
306
NRFX_PWM_FLAG_NO_EVT_FINISHED );
253
307
}
@@ -306,6 +360,14 @@ static void pwm_suspend(const struct device *dev)
306
360
const struct pwm_nrfx_config * config = dev -> config ;
307
361
308
362
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
309
371
while (!nrfx_pwm_stopped_check (& config -> pwm )) {
310
372
}
311
373
@@ -351,9 +413,6 @@ static int pwm_nrfx_init(const struct device *dev)
351
413
return pm_device_driver_init (dev , pwm_nrfx_pm_action );
352
414
}
353
415
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)
357
416
#define PWM_MEM_REGION (idx ) DT_PHANDLE(PWM(idx), memory_regions)
358
417
359
418
#define PWM_MEMORY_SECTION (idx ) \
@@ -393,6 +452,15 @@ static int pwm_nrfx_init(const struct device *dev)
393
452
(16ul * 1000ul * 1000ul)), \
394
453
IF_ENABLED(CONFIG_DCACHE, \
395
454
(.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
+ },)) \
396
464
}; \
397
465
static int pwm_nrfx_init##idx(const struct device *dev) \
398
466
{ \
@@ -405,7 +473,7 @@ static int pwm_nrfx_init(const struct device *dev)
405
473
pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \
406
474
&pwm_nrfx_##idx##_data, \
407
475
&pwm_nrfx_##idx##_config, \
408
- POST_KERNEL, CONFIG_PWM_INIT_PRIORITY , \
476
+ POST_KERNEL, PWM_NRFX_INIT_PRIORITY , \
409
477
&pwm_nrfx_drv_api_funcs)
410
478
411
479
#define COND_PWM_NRFX_DEVICE (unused , prefix , i , _ ) \
0 commit comments