3
3
*
4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
6
+
7
+ #define DT_DRV_COMPAT nordic_nrf_pwm
8
+
6
9
#include <nrfx_pwm.h>
7
10
#include <zephyr/drivers/pwm.h>
8
11
#include <zephyr/pm/device.h>
@@ -33,10 +36,7 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
33
36
#define ANOMALY_109_EGU_IRQ_CONNECT (idx )
34
37
#endif
35
38
36
- #define PWM (dev_idx ) DT_NODELABEL(pwm##dev_idx)
37
- #define PWM_PROP (dev_idx , prop ) DT_PROP(PWM(dev_idx), prop)
38
- #define PWM_HAS_PROP (idx , prop ) DT_NODE_HAS_PROP(PWM(idx), prop)
39
- #define PWM_NRFX_IS_FAST (idx ) NRF_DT_IS_FAST(PWM(idx))
39
+ #define PWM_NRFX_IS_FAST (inst ) NRF_DT_IS_FAST(DT_DRV_INST(inst))
40
40
41
41
#if NRF_DT_INST_ANY_IS_FAST
42
42
#define PWM_NRFX_FAST_PRESENT 1
@@ -57,7 +57,6 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED));
57
57
(compare_value | (inverted ? 0 : PWM_NRFX_CH_POLARITY_MASK))
58
58
59
59
struct pwm_nrfx_config {
60
- nrfx_pwm_t pwm ;
61
60
nrfx_pwm_config_t initial_config ;
62
61
nrf_pwm_sequence_t seq ;
63
62
const struct pinctrl_dev_config * pcfg ;
@@ -72,6 +71,7 @@ struct pwm_nrfx_config {
72
71
};
73
72
74
73
struct pwm_nrfx_data {
74
+ nrfx_pwm_t pwm ;
75
75
uint32_t period_cycles ;
76
76
/* Bit mask indicating channels that need the PWM generation. */
77
77
uint8_t pwm_needed ;
@@ -145,7 +145,7 @@ static bool pwm_period_check_and_set(const struct device *dev,
145
145
data -> period_cycles = period_cycles ;
146
146
data -> prescaler = prescaler ;
147
147
148
- nrf_pwm_configure (config -> pwm .p_reg ,
148
+ nrf_pwm_configure (data -> pwm .p_reg ,
149
149
data -> prescaler ,
150
150
config -> initial_config .count_mode ,
151
151
(uint16_t )countertop );
@@ -160,26 +160,25 @@ static bool pwm_period_check_and_set(const struct device *dev,
160
160
return false;
161
161
}
162
162
163
- static bool channel_psel_get (uint32_t channel , uint32_t * psel ,
164
- const struct pwm_nrfx_config * config )
163
+ static bool channel_psel_get (uint32_t channel , uint32_t * psel , struct pwm_nrfx_data * data )
165
164
{
166
- * psel = nrf_pwm_pin_get (config -> pwm .p_reg , (uint8_t )channel );
165
+ * psel = nrf_pwm_pin_get (data -> pwm .p_reg , (uint8_t )channel );
167
166
168
167
return (((* psel & PWM_PSEL_OUT_CONNECT_Msk ) >> PWM_PSEL_OUT_CONNECT_Pos )
169
168
== PWM_PSEL_OUT_CONNECT_Connected );
170
169
}
171
170
172
171
static int stop_pwm (const struct device * dev )
173
172
{
174
- const struct pwm_nrfx_config * config = dev -> config ;
173
+ struct pwm_nrfx_data * data = dev -> data ;
175
174
176
175
/* Don't wait here for the peripheral to actually stop. Instead,
177
- * ensure it is stopped before starting the next playback.
178
- */
179
- nrfx_pwm_stop (& config -> pwm , false);
176
+ * ensure it is stopped before starting the next playback.
177
+ */
178
+ nrfx_pwm_stop (& data -> pwm , false);
180
179
181
180
#if PWM_NRFX_USE_CLOCK_CONTROL
182
- struct pwm_nrfx_data * data = dev -> data ;
181
+ const struct pwm_nrfx_config * config = dev -> config ;
183
182
184
183
if (data -> clock_requested ) {
185
184
int ret = nrf_clock_control_release (config -> clk_dev , & config -> clk_spec );
@@ -268,7 +267,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
268
267
if (!needs_pwm ) {
269
268
uint32_t psel ;
270
269
271
- if (channel_psel_get (channel , & psel , config )) {
270
+ if (channel_psel_get (channel , & psel , data )) {
272
271
uint32_t out_level = (pulse_cycles == 0 ) ? 0 : 1 ;
273
272
274
273
if (inverted ) {
@@ -323,7 +322,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
323
322
* and till that moment, it ignores any start requests,
324
323
* so ensure here that it is stopped.
325
324
*/
326
- while (!nrfx_pwm_stopped_check (& config -> pwm )) {
325
+ while (!nrfx_pwm_stopped_check (& data -> pwm )) {
327
326
}
328
327
}
329
328
@@ -346,7 +345,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
346
345
data -> clock_requested = true;
347
346
}
348
347
#endif
349
- nrfx_pwm_simple_playback (& config -> pwm , & config -> seq , 1 ,
348
+ nrfx_pwm_simple_playback (& data -> pwm , & config -> seq , 1 ,
350
349
NRFX_PWM_FLAG_NO_EVT_FINISHED );
351
350
}
352
351
@@ -371,14 +370,16 @@ static DEVICE_API(pwm, pwm_nrfx_drv_api_funcs) = {
371
370
static int pwm_resume (const struct device * dev )
372
371
{
373
372
const struct pwm_nrfx_config * config = dev -> config ;
373
+ struct pwm_nrfx_data * data = dev -> data ;
374
+
374
375
uint8_t initially_inverted = 0 ;
375
376
376
377
(void )pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_DEFAULT );
377
378
378
379
for (size_t i = 0 ; i < NRF_PWM_CHANNEL_COUNT ; i ++ ) {
379
380
uint32_t psel ;
380
381
381
- if (channel_psel_get (i , & psel , config )) {
382
+ if (channel_psel_get (i , & psel , data )) {
382
383
/* Mark channels as inverted according to what initial
383
384
* state of their outputs has been set by pinctrl (high
384
385
* idle state means that the channel is inverted).
@@ -400,6 +401,7 @@ static int pwm_resume(const struct device *dev)
400
401
static int pwm_suspend (const struct device * dev )
401
402
{
402
403
const struct pwm_nrfx_config * config = dev -> config ;
404
+ struct pwm_nrfx_data * data = dev -> data ;
403
405
404
406
int ret = stop_pwm (dev );
405
407
@@ -408,7 +410,7 @@ static int pwm_suspend(const struct device *dev)
408
410
return ret ;
409
411
}
410
412
411
- while (!nrfx_pwm_stopped_check (& config -> pwm )) {
413
+ while (!nrfx_pwm_stopped_check (& data -> pwm )) {
412
414
}
413
415
414
416
memset (dev -> data , 0 , sizeof (struct pwm_nrfx_data ));
@@ -434,34 +436,36 @@ static int pwm_nrfx_pm_action(const struct device *dev,
434
436
static int pwm_nrfx_init (const struct device * dev )
435
437
{
436
438
const struct pwm_nrfx_config * config = dev -> config ;
437
- nrfx_err_t err ;
439
+ struct pwm_nrfx_data * data = dev -> data ;
440
+
441
+ int err ;
438
442
439
443
ANOMALY_109_EGU_IRQ_CONNECT (NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE );
440
444
441
445
if (IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME )) {
442
446
(void )pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_SLEEP );
443
447
}
444
448
445
- err = nrfx_pwm_init (& config -> pwm , & config -> initial_config , pwm_handler , dev -> data );
446
- if (err != NRFX_SUCCESS ) {
449
+ err = nrfx_pwm_init (& data -> pwm , & config -> initial_config , pwm_handler , dev -> data );
450
+ if (err < 0 ) {
447
451
LOG_ERR ("Failed to initialize device: %s" , dev -> name );
448
- return - EBUSY ;
452
+ return err ;
449
453
}
450
454
451
455
return pm_device_driver_init (dev , pwm_nrfx_pm_action );
452
456
}
453
457
454
- #define PWM_MEM_REGION (idx ) DT_PHANDLE(PWM(idx ), memory_regions)
458
+ #define PWM_MEM_REGION (inst ) DT_PHANDLE(DT_DRV_INST(inst ), memory_regions)
455
459
456
- #define PWM_MEMORY_SECTION (idx ) \
457
- COND_CODE_1(PWM_HAS_PROP(idx , memory_regions), \
460
+ #define PWM_MEMORY_SECTION (inst ) \
461
+ COND_CODE_1(DT_NODE_HAS_PROP(inst , memory_regions), \
458
462
(__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \
459
- PWM_MEM_REGION(idx )))))), \
463
+ PWM_MEM_REGION(inst )))))), \
460
464
())
461
465
462
- #define PWM_GET_MEM_ATTR (idx ) \
463
- COND_CODE_1(PWM_HAS_PROP(idx , memory_regions), \
464
- (DT_PROP_OR(PWM_MEM_REGION(idx ), zephyr_memory_attr, 0)), (0))
466
+ #define PWM_GET_MEM_ATTR (inst ) \
467
+ COND_CODE_1(DT_NODE_HAS_PROP(inst , memory_regions), \
468
+ (DT_PROP_OR(PWM_MEM_REGION(inst ), zephyr_memory_attr, 0)), (0))
465
469
466
470
/* Fast instances depend on the global HSFLL clock controller (as they need
467
471
* to request the highest frequency from it to operate correctly), so they
@@ -470,66 +474,65 @@ static int pwm_nrfx_init(const struct device *dev)
470
474
*/
471
475
#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY ) && \
472
476
CONFIG_PWM_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY
473
- #define PWM_INIT_PRIORITY (idx ) \
474
- COND_CODE_1(PWM_NRFX_IS_FAST(idx ), \
477
+ #define PWM_INIT_PRIORITY (inst ) \
478
+ COND_CODE_1(PWM_NRFX_IS_FAST(inst ), \
475
479
(UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \
476
480
(CONFIG_PWM_INIT_PRIORITY))
477
481
#else
478
- #define PWM_INIT_PRIORITY (idx ) CONFIG_PWM_INIT_PRIORITY
482
+ #define PWM_INIT_PRIORITY (inst ) CONFIG_PWM_INIT_PRIORITY
479
483
#endif
480
484
481
- #define PWM_NRFX_DEVICE (idx ) \
482
- NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \
483
- NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(PWM(idx)); \
484
- static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \
485
- static uint16_t pwm_##idx##_seq_values[NRF_PWM_CHANNEL_COUNT] \
486
- PWM_MEMORY_SECTION(idx); \
487
- PINCTRL_DT_DEFINE(PWM(idx)); \
488
- static const struct pwm_nrfx_config pwm_nrfx_##idx##_config = { \
489
- .pwm = NRFX_PWM_INSTANCE(idx), \
490
- .initial_config = { \
491
- .skip_gpio_cfg = true, \
492
- .skip_psel_cfg = true, \
493
- .base_clock = NRF_PWM_CLK_1MHz, \
494
- .count_mode = (PWM_PROP(idx, center_aligned) \
495
- ? NRF_PWM_MODE_UP_AND_DOWN \
496
- : NRF_PWM_MODE_UP), \
497
- .top_value = 1000, \
498
- .load_mode = NRF_PWM_LOAD_INDIVIDUAL, \
499
- .step_mode = NRF_PWM_STEP_TRIGGERED, \
500
- }, \
501
- .seq.values.p_raw = pwm_##idx##_seq_values, \
502
- .seq.length = NRF_PWM_CHANNEL_COUNT, \
503
- .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PWM(idx)), \
504
- .clock_freq = COND_CODE_1(DT_CLOCKS_HAS_IDX(PWM(idx), 0), \
505
- (DT_PROP(DT_CLOCKS_CTLR(PWM(idx)), clock_frequency)), \
506
- (16ul * 1000ul * 1000ul)), \
507
- IF_ENABLED(CONFIG_DCACHE, \
508
- (.mem_attr = PWM_GET_MEM_ATTR(idx),)) \
509
- IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
510
- (.clk_dev = PWM_NRFX_IS_FAST(idx) \
511
- ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \
512
- : NULL, \
513
- .clk_spec = { \
514
- .frequency = \
515
- NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \
516
- },)) \
517
- }; \
518
- static int pwm_nrfx_init##idx(const struct device *dev) \
519
- { \
520
- IRQ_CONNECT(DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority), \
521
- nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0); \
522
- return pwm_nrfx_init(dev); \
523
- }; \
524
- PM_DEVICE_DT_DEFINE(PWM(idx), pwm_nrfx_pm_action); \
525
- DEVICE_DT_DEFINE(PWM(idx), \
526
- pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \
527
- &pwm_nrfx_##idx##_data, \
528
- &pwm_nrfx_##idx##_config, \
529
- POST_KERNEL, PWM_INIT_PRIORITY(idx), \
530
- &pwm_nrfx_drv_api_funcs)
531
-
532
- #define COND_PWM_NRFX_DEVICE (unused , prefix , i , _ ) \
533
- IF_ENABLED(CONFIG_HAS_HW_NRF_PWM##prefix##i, (PWM_NRFX_DEVICE(prefix##i);))
534
-
535
- NRFX_FOREACH_PRESENT (PWM , COND_PWM_NRFX_DEVICE , ( ), ( ), _ )
485
+ #define PWM_NRFX_DEFINE (inst ) \
486
+ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(DT_DRV_INST(inst)); \
487
+ NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(DT_DRV_INST(inst)); \
488
+ static struct pwm_nrfx_data pwm_nrfx_##inst##_data = { \
489
+ .pwm = NRFX_PWM_INSTANCE(DT_INST_REG_ADDR(inst)), \
490
+ }; \
491
+ static uint16_t pwm_##inst##_seq_values[NRF_PWM_CHANNEL_COUNT] \
492
+ PWM_MEMORY_SECTION(inst); \
493
+ PINCTRL_DT_INST_DEFINE(inst); \
494
+ static const struct pwm_nrfx_config pwm_nrfx_##inst##_config = { \
495
+ .initial_config = { \
496
+ .skip_gpio_cfg = true, \
497
+ .skip_psel_cfg = true, \
498
+ .base_clock = NRF_PWM_CLK_1MHz, \
499
+ .count_mode = (DT_INST_PROP(inst, center_aligned) \
500
+ ? NRF_PWM_MODE_UP_AND_DOWN \
501
+ : NRF_PWM_MODE_UP), \
502
+ .top_value = 1000, \
503
+ .load_mode = NRF_PWM_LOAD_INDIVIDUAL, \
504
+ .step_mode = NRF_PWM_STEP_TRIGGERED, \
505
+ }, \
506
+ .seq.values.p_raw = pwm_##inst##_seq_values, \
507
+ .seq.length = NRF_PWM_CHANNEL_COUNT, \
508
+ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
509
+ .clock_freq = COND_CODE_1(DT_INST_CLOCKS_HAS_IDX(inst, 0), \
510
+ (DT_PROP(DT_INST_CLOCKS_CTLR(inst), clock_frequency)), \
511
+ (16ul * 1000ul * 1000ul)), \
512
+ IF_ENABLED(CONFIG_DCACHE, \
513
+ (.mem_attr = PWM_GET_MEM_ATTR(inst),)) \
514
+ IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
515
+ (.clk_dev = PWM_NRFX_IS_FAST(inst) \
516
+ ? DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)) \
517
+ : NULL, \
518
+ .clk_spec = { \
519
+ .frequency = \
520
+ NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(inst)), \
521
+ },)) \
522
+ }; \
523
+ static int pwm_nrfx_init##inst(const struct device *dev) \
524
+ { \
525
+ IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), \
526
+ nrfx_pwm_irq_handler, &pwm_nrfx_##inst##_data.pwm, 0); \
527
+ return pwm_nrfx_init(dev); \
528
+ }; \
529
+ PM_DEVICE_DT_INST_DEFINE(inst, pwm_nrfx_pm_action); \
530
+ DEVICE_DT_INST_DEINIT_DEFINE(inst, \
531
+ pwm_nrfx_init##inst, NULL, \
532
+ PM_DEVICE_DT_INST_GET(inst), \
533
+ &pwm_nrfx_##inst##_data, \
534
+ &pwm_nrfx_##inst##_config, \
535
+ POST_KERNEL, PWM_INIT_PRIORITY(inst), \
536
+ &pwm_nrfx_drv_api_funcs)
537
+
538
+ DT_INST_FOREACH_STATUS_OKAY (PWM_NRFX_DEFINE )
0 commit comments