33 *
44 * SPDX-License-Identifier: Apache-2.0
55 */
6+
7+ #define DT_DRV_COMPAT nordic_nrf_pwm
8+
69#include <nrfx_pwm.h>
710#include <zephyr/drivers/pwm.h>
811#include <zephyr/pm/device.h>
@@ -30,10 +33,7 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
3033#define ANOMALY_109_EGU_IRQ_CONNECT (idx )
3134#endif
3235
33- #define PWM (dev_idx ) DT_NODELABEL(pwm##dev_idx)
34- #define PWM_PROP (dev_idx , prop ) DT_PROP(PWM(dev_idx), prop)
35- #define PWM_HAS_PROP (idx , prop ) DT_NODE_HAS_PROP(PWM(idx), prop)
36- #define PWM_NRFX_IS_FAST (idx ) NRF_DT_IS_FAST(PWM(idx))
36+ #define PWM_NRFX_IS_FAST (inst ) NRF_DT_IS_FAST(DT_DRV_INST(inst))
3737
3838#if NRF_DT_INST_ANY_IS_FAST
3939#define PWM_NRFX_FAST_PRESENT 1
@@ -54,7 +54,6 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED));
5454 (compare_value | (inverted ? 0 : PWM_NRFX_CH_POLARITY_MASK))
5555
5656struct pwm_nrfx_config {
57- nrfx_pwm_t pwm ;
5857 nrfx_pwm_config_t initial_config ;
5958 nrf_pwm_sequence_t seq ;
6059 const struct pinctrl_dev_config * pcfg ;
@@ -69,6 +68,7 @@ struct pwm_nrfx_config {
6968};
7069
7170struct pwm_nrfx_data {
71+ nrfx_pwm_t pwm ;
7272 uint32_t period_cycles ;
7373 /* Bit mask indicating channels that need the PWM generation. */
7474 uint8_t pwm_needed ;
@@ -102,7 +102,7 @@ static uint16_t *seq_values_ptr_get(const struct device *dev)
102102 return (uint16_t * )config -> seq .values .p_raw ;
103103}
104104
105- static void pwm_handler (nrfx_pwm_evt_type_t event_type , void * p_context )
105+ static void pwm_handler (nrfx_pwm_event_type_t event_type , void * p_context )
106106{
107107 ARG_UNUSED (event_type );
108108 ARG_UNUSED (p_context );
@@ -142,7 +142,7 @@ static bool pwm_period_check_and_set(const struct device *dev,
142142 data -> period_cycles = period_cycles ;
143143 data -> prescaler = prescaler ;
144144
145- nrf_pwm_configure (config -> pwm .p_reg ,
145+ nrf_pwm_configure (data -> pwm .p_reg ,
146146 data -> prescaler ,
147147 config -> initial_config .count_mode ,
148148 (uint16_t )countertop );
@@ -157,26 +157,25 @@ static bool pwm_period_check_and_set(const struct device *dev,
157157 return false;
158158}
159159
160- static bool channel_psel_get (uint32_t channel , uint32_t * psel ,
161- const struct pwm_nrfx_config * config )
160+ static bool channel_psel_get (uint32_t channel , uint32_t * psel , struct pwm_nrfx_data * data )
162161{
163- * psel = nrf_pwm_pin_get (config -> pwm .p_reg , (uint8_t )channel );
162+ * psel = nrf_pwm_pin_get (data -> pwm .p_reg , (uint8_t )channel );
164163
165164 return (((* psel & PWM_PSEL_OUT_CONNECT_Msk ) >> PWM_PSEL_OUT_CONNECT_Pos )
166165 == PWM_PSEL_OUT_CONNECT_Connected );
167166}
168167
169168static int stop_pwm (const struct device * dev )
170169{
171- const struct pwm_nrfx_config * config = dev -> config ;
170+ struct pwm_nrfx_data * data = dev -> data ;
172171
173172 /* Don't wait here for the peripheral to actually stop. Instead,
174- * ensure it is stopped before starting the next playback.
175- */
176- nrfx_pwm_stop (& config -> pwm , false);
173+ * ensure it is stopped before starting the next playback.
174+ */
175+ nrfx_pwm_stop (& data -> pwm , false);
177176
178177#if PWM_NRFX_USE_CLOCK_CONTROL
179- struct pwm_nrfx_data * data = dev -> data ;
178+ const struct pwm_nrfx_config * config = dev -> config ;
180179
181180 if (data -> clock_requested ) {
182181 int ret = nrf_clock_control_release (config -> clk_dev , & config -> clk_spec );
@@ -265,7 +264,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
265264 if (!needs_pwm ) {
266265 uint32_t psel ;
267266
268- if (channel_psel_get (channel , & psel , config )) {
267+ if (channel_psel_get (channel , & psel , data )) {
269268 uint32_t out_level = (pulse_cycles == 0 ) ? 0 : 1 ;
270269
271270 if (inverted ) {
@@ -320,7 +319,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
320319 * and till that moment, it ignores any start requests,
321320 * so ensure here that it is stopped.
322321 */
323- while (!nrfx_pwm_stopped_check (& config -> pwm )) {
322+ while (!nrfx_pwm_stopped_check (& data -> pwm )) {
324323 }
325324 }
326325
@@ -343,7 +342,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
343342 data -> clock_requested = true;
344343 }
345344#endif
346- nrfx_pwm_simple_playback (& config -> pwm , & config -> seq , 1 ,
345+ nrfx_pwm_simple_playback (& data -> pwm , & config -> seq , 1 ,
347346 NRFX_PWM_FLAG_NO_EVT_FINISHED );
348347 }
349348
@@ -368,14 +367,16 @@ static DEVICE_API(pwm, pwm_nrfx_drv_api_funcs) = {
368367static int pwm_resume (const struct device * dev )
369368{
370369 const struct pwm_nrfx_config * config = dev -> config ;
370+ struct pwm_nrfx_data * data = dev -> data ;
371+
371372 uint8_t initially_inverted = 0 ;
372373
373374 (void )pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_DEFAULT );
374375
375376 for (size_t i = 0 ; i < NRF_PWM_CHANNEL_COUNT ; i ++ ) {
376377 uint32_t psel ;
377378
378- if (channel_psel_get (i , & psel , config )) {
379+ if (channel_psel_get (i , & psel , data )) {
379380 /* Mark channels as inverted according to what initial
380381 * state of their outputs has been set by pinctrl (high
381382 * idle state means that the channel is inverted).
@@ -397,6 +398,7 @@ static int pwm_resume(const struct device *dev)
397398static int pwm_suspend (const struct device * dev )
398399{
399400 const struct pwm_nrfx_config * config = dev -> config ;
401+ struct pwm_nrfx_data * data = dev -> data ;
400402
401403 int ret = stop_pwm (dev );
402404
@@ -405,7 +407,7 @@ static int pwm_suspend(const struct device *dev)
405407 return ret ;
406408 }
407409
408- while (!nrfx_pwm_stopped_check (& config -> pwm )) {
410+ while (!nrfx_pwm_stopped_check (& data -> pwm )) {
409411 }
410412
411413 memset (dev -> data , 0 , sizeof (struct pwm_nrfx_data ));
@@ -431,34 +433,36 @@ static int pwm_nrfx_pm_action(const struct device *dev,
431433static int pwm_nrfx_init (const struct device * dev )
432434{
433435 const struct pwm_nrfx_config * config = dev -> config ;
434- nrfx_err_t err ;
436+ struct pwm_nrfx_data * data = dev -> data ;
437+
438+ int err ;
435439
436440 ANOMALY_109_EGU_IRQ_CONNECT (NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE );
437441
438442 if (IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME )) {
439443 (void )pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_SLEEP );
440444 }
441445
442- err = nrfx_pwm_init (& config -> pwm , & config -> initial_config , pwm_handler , dev -> data );
443- if (err != NRFX_SUCCESS ) {
446+ err = nrfx_pwm_init (& data -> pwm , & config -> initial_config , pwm_handler , dev -> data );
447+ if (err < 0 ) {
444448 LOG_ERR ("Failed to initialize device: %s" , dev -> name );
445- return - EBUSY ;
449+ return err ;
446450 }
447451
448452 return pm_device_driver_init (dev , pwm_nrfx_pm_action );
449453}
450454
451- #define PWM_MEM_REGION (idx ) DT_PHANDLE(PWM(idx ), memory_regions)
455+ #define PWM_MEM_REGION (inst ) DT_PHANDLE(DT_DRV_INST(inst ), memory_regions)
452456
453- #define PWM_MEMORY_SECTION (idx ) \
454- COND_CODE_1(PWM_HAS_PROP(idx , memory_regions), \
457+ #define PWM_MEMORY_SECTION (inst ) \
458+ COND_CODE_1(DT_NODE_HAS_PROP(inst , memory_regions), \
455459 (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \
456- PWM_MEM_REGION(idx )))))), \
460+ PWM_MEM_REGION(inst )))))), \
457461 ())
458462
459- #define PWM_GET_MEM_ATTR (idx ) \
460- COND_CODE_1(PWM_HAS_PROP(idx , memory_regions), \
461- (DT_PROP_OR(PWM_MEM_REGION(idx ), zephyr_memory_attr, 0)), (0))
463+ #define PWM_GET_MEM_ATTR (inst ) \
464+ COND_CODE_1(DT_NODE_HAS_PROP(inst , memory_regions), \
465+ (DT_PROP_OR(PWM_MEM_REGION(inst ), zephyr_memory_attr, 0)), (0))
462466
463467/* Fast instances depend on the global HSFLL clock controller (as they need
464468 * to request the highest frequency from it to operate correctly), so they
@@ -467,66 +471,65 @@ static int pwm_nrfx_init(const struct device *dev)
467471 */
468472#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY ) && \
469473 CONFIG_PWM_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY
470- #define PWM_INIT_PRIORITY (idx ) \
471- COND_CODE_1(PWM_NRFX_IS_FAST(idx ), \
474+ #define PWM_INIT_PRIORITY (inst ) \
475+ COND_CODE_1(PWM_NRFX_IS_FAST(inst ), \
472476 (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \
473477 (CONFIG_PWM_INIT_PRIORITY))
474478#else
475- #define PWM_INIT_PRIORITY (idx ) CONFIG_PWM_INIT_PRIORITY
479+ #define PWM_INIT_PRIORITY (inst ) CONFIG_PWM_INIT_PRIORITY
476480#endif
477481
478- #define PWM_NRFX_DEVICE (idx ) \
479- NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \
480- NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(PWM(idx)); \
481- static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \
482- static uint16_t pwm_##idx##_seq_values[NRF_PWM_CHANNEL_COUNT] \
483- PWM_MEMORY_SECTION(idx); \
484- PINCTRL_DT_DEFINE(PWM(idx)); \
485- static const struct pwm_nrfx_config pwm_nrfx_##idx##_config = { \
486- .pwm = NRFX_PWM_INSTANCE(idx), \
487- .initial_config = { \
488- .skip_gpio_cfg = true, \
489- .skip_psel_cfg = true, \
490- .base_clock = NRF_PWM_CLK_1MHz, \
491- .count_mode = (PWM_PROP(idx, center_aligned) \
492- ? NRF_PWM_MODE_UP_AND_DOWN \
493- : NRF_PWM_MODE_UP), \
494- .top_value = 1000, \
495- .load_mode = NRF_PWM_LOAD_INDIVIDUAL, \
496- .step_mode = NRF_PWM_STEP_TRIGGERED, \
497- }, \
498- .seq.values.p_raw = pwm_##idx##_seq_values, \
499- .seq.length = NRF_PWM_CHANNEL_COUNT, \
500- .pcfg = PINCTRL_DT_DEV_CONFIG_GET(PWM(idx)), \
501- .clock_freq = COND_CODE_1(DT_CLOCKS_HAS_IDX(PWM(idx), 0), \
502- (DT_PROP(DT_CLOCKS_CTLR(PWM(idx)), clock_frequency)), \
503- (16ul * 1000ul * 1000ul)), \
504- IF_ENABLED(CONFIG_DCACHE, \
505- (.mem_attr = PWM_GET_MEM_ATTR(idx),)) \
506- IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
507- (.clk_dev = PWM_NRFX_IS_FAST(idx) \
508- ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \
509- : NULL, \
510- .clk_spec = { \
511- .frequency = \
512- NRF_PERIPH_GET_FREQUENCY(PWM(idx)), \
513- },)) \
514- }; \
515- static int pwm_nrfx_init##idx(const struct device *dev) \
516- { \
517- IRQ_CONNECT(DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority), \
518- nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0); \
519- return pwm_nrfx_init(dev); \
520- }; \
521- PM_DEVICE_DT_DEFINE(PWM(idx), pwm_nrfx_pm_action); \
522- DEVICE_DT_DEFINE(PWM(idx), \
523- pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)), \
524- &pwm_nrfx_##idx##_data, \
525- &pwm_nrfx_##idx##_config, \
526- POST_KERNEL, PWM_INIT_PRIORITY(idx), \
527- &pwm_nrfx_drv_api_funcs)
528-
529- #define COND_PWM_NRFX_DEVICE (unused , prefix , i , _ ) \
530- IF_ENABLED(CONFIG_HAS_HW_NRF_PWM##prefix##i, (PWM_NRFX_DEVICE(prefix##i);))
531-
532- NRFX_FOREACH_PRESENT (PWM , COND_PWM_NRFX_DEVICE , ( ), ( ), _ )
482+ #define PWM_NRFX_DEFINE (inst ) \
483+ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(DT_DRV_INST(inst)); \
484+ NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(DT_DRV_INST(inst)); \
485+ static struct pwm_nrfx_data pwm_nrfx_##inst##_data = { \
486+ .pwm = NRFX_PWM_INSTANCE(DT_INST_REG_ADDR(inst)), \
487+ }; \
488+ static uint16_t pwm_##inst##_seq_values[NRF_PWM_CHANNEL_COUNT] \
489+ PWM_MEMORY_SECTION(inst); \
490+ PINCTRL_DT_INST_DEFINE(inst); \
491+ static const struct pwm_nrfx_config pwm_nrfx_##inst##_config = { \
492+ .initial_config = { \
493+ .skip_gpio_cfg = true, \
494+ .skip_psel_cfg = true, \
495+ .base_clock = NRF_PWM_CLK_1MHz, \
496+ .count_mode = (DT_INST_PROP(inst, center_aligned) \
497+ ? NRF_PWM_MODE_UP_AND_DOWN \
498+ : NRF_PWM_MODE_UP), \
499+ .top_value = 1000, \
500+ .load_mode = NRF_PWM_LOAD_INDIVIDUAL, \
501+ .step_mode = NRF_PWM_STEP_TRIGGERED, \
502+ }, \
503+ .seq.values.p_raw = pwm_##inst##_seq_values, \
504+ .seq.length = NRF_PWM_CHANNEL_COUNT, \
505+ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
506+ .clock_freq = COND_CODE_1(DT_INST_CLOCKS_HAS_IDX(inst, 0), \
507+ (DT_PROP(DT_INST_CLOCKS_CTLR(inst), clock_frequency)), \
508+ (16ul * 1000ul * 1000ul)), \
509+ IF_ENABLED(CONFIG_DCACHE, \
510+ (.mem_attr = PWM_GET_MEM_ATTR(inst),)) \
511+ IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \
512+ (.clk_dev = PWM_NRFX_IS_FAST(inst) \
513+ ? DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)) \
514+ : NULL, \
515+ .clk_spec = { \
516+ .frequency = \
517+ NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(inst)), \
518+ },)) \
519+ }; \
520+ static int pwm_nrfx_init##inst(const struct device *dev) \
521+ { \
522+ IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), \
523+ nrfx_pwm_irq_handler, &pwm_nrfx_##inst##_data.pwm, 0); \
524+ return pwm_nrfx_init(dev); \
525+ }; \
526+ PM_DEVICE_DT_INST_DEFINE(inst, pwm_nrfx_pm_action); \
527+ DEVICE_DT_INST_DEINIT_DEFINE(inst, \
528+ pwm_nrfx_init##inst, NULL, \
529+ PM_DEVICE_DT_INST_GET(inst), \
530+ &pwm_nrfx_##inst##_data, \
531+ &pwm_nrfx_##inst##_config, \
532+ POST_KERNEL, PWM_INIT_PRIORITY(inst), \
533+ &pwm_nrfx_drv_api_funcs)
534+
535+ DT_INST_FOREACH_STATUS_OKAY (PWM_NRFX_DEFINE )
0 commit comments