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>
@@ -33,10 +36,7 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
3336#define ANOMALY_109_EGU_IRQ_CONNECT (idx )
3437#endif
3538
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))
4040
4141#if NRF_DT_INST_ANY_IS_FAST
4242#define PWM_NRFX_FAST_PRESENT 1
@@ -57,7 +57,6 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED));
5757 (compare_value | (inverted ? 0 : PWM_NRFX_CH_POLARITY_MASK))
5858
5959struct pwm_nrfx_config {
60- nrfx_pwm_t pwm ;
6160 nrfx_pwm_config_t initial_config ;
6261 nrf_pwm_sequence_t seq ;
6362 const struct pinctrl_dev_config * pcfg ;
@@ -72,6 +71,7 @@ struct pwm_nrfx_config {
7271};
7372
7473struct pwm_nrfx_data {
74+ nrfx_pwm_t pwm ;
7575 uint32_t period_cycles ;
7676 /* Bit mask indicating channels that need the PWM generation. */
7777 uint8_t pwm_needed ;
@@ -145,7 +145,7 @@ static bool pwm_period_check_and_set(const struct device *dev,
145145 data -> period_cycles = period_cycles ;
146146 data -> prescaler = prescaler ;
147147
148- nrf_pwm_configure (config -> pwm .p_reg ,
148+ nrf_pwm_configure (data -> pwm .p_reg ,
149149 data -> prescaler ,
150150 config -> initial_config .count_mode ,
151151 (uint16_t )countertop );
@@ -160,26 +160,25 @@ static bool pwm_period_check_and_set(const struct device *dev,
160160 return false;
161161}
162162
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 )
165164{
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 );
167166
168167 return (((* psel & PWM_PSEL_OUT_CONNECT_Msk ) >> PWM_PSEL_OUT_CONNECT_Pos )
169168 == PWM_PSEL_OUT_CONNECT_Connected );
170169}
171170
172171static int stop_pwm (const struct device * dev )
173172{
174- const struct pwm_nrfx_config * config = dev -> config ;
173+ struct pwm_nrfx_data * data = dev -> data ;
175174
176175 /* 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);
180179
181180#if PWM_NRFX_USE_CLOCK_CONTROL
182- struct pwm_nrfx_data * data = dev -> data ;
181+ const struct pwm_nrfx_config * config = dev -> config ;
183182
184183 if (data -> clock_requested ) {
185184 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,
268267 if (!needs_pwm ) {
269268 uint32_t psel ;
270269
271- if (channel_psel_get (channel , & psel , config )) {
270+ if (channel_psel_get (channel , & psel , data )) {
272271 uint32_t out_level = (pulse_cycles == 0 ) ? 0 : 1 ;
273272
274273 if (inverted ) {
@@ -323,7 +322,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
323322 * and till that moment, it ignores any start requests,
324323 * so ensure here that it is stopped.
325324 */
326- while (!nrfx_pwm_stopped_check (& config -> pwm )) {
325+ while (!nrfx_pwm_stopped_check (& data -> pwm )) {
327326 }
328327 }
329328
@@ -346,7 +345,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
346345 data -> clock_requested = true;
347346 }
348347#endif
349- nrfx_pwm_simple_playback (& config -> pwm , & config -> seq , 1 ,
348+ nrfx_pwm_simple_playback (& data -> pwm , & config -> seq , 1 ,
350349 NRFX_PWM_FLAG_NO_EVT_FINISHED );
351350 }
352351
@@ -371,14 +370,16 @@ static DEVICE_API(pwm, pwm_nrfx_drv_api_funcs) = {
371370static int pwm_resume (const struct device * dev )
372371{
373372 const struct pwm_nrfx_config * config = dev -> config ;
373+ struct pwm_nrfx_data * data = dev -> data ;
374+
374375 uint8_t initially_inverted = 0 ;
375376
376377 (void )pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_DEFAULT );
377378
378379 for (size_t i = 0 ; i < NRF_PWM_CHANNEL_COUNT ; i ++ ) {
379380 uint32_t psel ;
380381
381- if (channel_psel_get (i , & psel , config )) {
382+ if (channel_psel_get (i , & psel , data )) {
382383 /* Mark channels as inverted according to what initial
383384 * state of their outputs has been set by pinctrl (high
384385 * idle state means that the channel is inverted).
@@ -400,6 +401,7 @@ static int pwm_resume(const struct device *dev)
400401static int pwm_suspend (const struct device * dev )
401402{
402403 const struct pwm_nrfx_config * config = dev -> config ;
404+ const struct pwm_nrfx_data * data = dev -> data ;
403405
404406 int ret = stop_pwm (dev );
405407
@@ -408,7 +410,7 @@ static int pwm_suspend(const struct device *dev)
408410 return ret ;
409411 }
410412
411- while (!nrfx_pwm_stopped_check (& config -> pwm )) {
413+ while (!nrfx_pwm_stopped_check (& data -> pwm )) {
412414 }
413415
414416 memset (dev -> data , 0 , sizeof (struct pwm_nrfx_data ));
@@ -434,34 +436,36 @@ static int pwm_nrfx_pm_action(const struct device *dev,
434436static int pwm_nrfx_init (const struct device * dev )
435437{
436438 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 ;
438442
439443 ANOMALY_109_EGU_IRQ_CONNECT (NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE );
440444
441445 if (IS_ENABLED (CONFIG_PM_DEVICE_RUNTIME )) {
442446 (void )pinctrl_apply_state (config -> pcfg , PINCTRL_STATE_SLEEP );
443447 }
444448
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 ) {
447451 LOG_ERR ("Failed to initialize device: %s" , dev -> name );
448- return - EBUSY ;
452+ return err ;
449453 }
450454
451455 return pm_device_driver_init (dev , pwm_nrfx_pm_action );
452456}
453457
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)
455459
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), \
458462 (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \
459- PWM_MEM_REGION(idx )))))), \
463+ PWM_MEM_REGION(inst )))))), \
460464 ())
461465
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))
465469
466470/* Fast instances depend on the global HSFLL clock controller (as they need
467471 * 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)
470474 */
471475#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY ) && \
472476 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 ), \
475479 (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \
476480 (CONFIG_PWM_INIT_PRIORITY))
477481#else
478- #define PWM_INIT_PRIORITY (idx ) CONFIG_PWM_INIT_PRIORITY
482+ #define PWM_INIT_PRIORITY (inst ) CONFIG_PWM_INIT_PRIORITY
479483#endif
480484
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_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, \
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