1 /*
2  * Copyright (c) 2018, Cue Health Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <nrfx_pwm.h>
7 #include <zephyr/drivers/pwm.h>
8 #include <zephyr/pm/device.h>
9 #include <zephyr/drivers/pinctrl.h>
10 #include <soc.h>
11 #include <hal/nrf_gpio.h>
12 #include <stdbool.h>
13 #include <zephyr/linker/devicetree_regions.h>
14 #include <zephyr/cache.h>
15 #include <zephyr/mem_mgmt/mem_attr.h>
16 #include <zephyr/drivers/clock_control/nrf_clock_control.h>
17 #ifdef CONFIG_SOC_NRF54H20_GPD
18 #include <nrf/gpd.h>
19 #endif
20 
21 #include <zephyr/logging/log.h>
22 
23 LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL);
24 
25 /* NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED can be undefined or defined
26  * to 0 or 1, hence the use of #if IS_ENABLED().
27  */
28 #if IS_ENABLED(NRFX_PWM_NRF52_ANOMALY_109_WORKAROUND_ENABLED)
29 #define ANOMALY_109_EGU_IRQ_CONNECT(idx) _EGU_IRQ_CONNECT(idx)
30 #define _EGU_IRQ_CONNECT(idx) \
31 	extern void nrfx_egu_##idx##_irq_handler(void); \
32 	IRQ_CONNECT(DT_IRQN(DT_NODELABEL(egu##idx)), \
33 		    DT_IRQ(DT_NODELABEL(egu##idx), priority), \
34 		    nrfx_isr, nrfx_egu_##idx##_irq_handler, 0)
35 #else
36 #define ANOMALY_109_EGU_IRQ_CONNECT(idx)
37 #endif
38 
39 #define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx)
40 #define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop)
41 #define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop)
42 
43 #define PWM_NRFX_IS_FAST(unused, prefix, idx, _)					\
44 	COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(PWM(idx)),					\
45 		(COND_CODE_1(PWM_HAS_PROP(idx, power_domains),				\
46 		    (IS_EQ(DT_PHA(PWM(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)),	\
47 		    (0))), (0))
48 
49 #if NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0))
50 #define PWM_NRFX_FAST_PRESENT 1
51 #endif
52 
53 #if defined(PWM_NRFX_FAST_PRESENT) && CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL
54 #define PWM_NRFX_USE_CLOCK_CONTROL 1
55 #endif
56 
57 #define PWM_NRFX_CH_POLARITY_MASK BIT(15)
58 #define PWM_NRFX_CH_COMPARE_MASK  BIT_MASK(15)
59 #define PWM_NRFX_CH_VALUE(compare_value, inverted) \
60 	(compare_value | (inverted ? 0 : PWM_NRFX_CH_POLARITY_MASK))
61 
62 struct pwm_nrfx_config {
63 	nrfx_pwm_t pwm;
64 	nrfx_pwm_config_t initial_config;
65 	nrf_pwm_sequence_t seq;
66 	const struct pinctrl_dev_config *pcfg;
67 	uint32_t clock_freq;
68 #ifdef CONFIG_DCACHE
69 	uint32_t mem_attr;
70 #endif
71 #ifdef PWM_NRFX_USE_CLOCK_CONTROL
72 	const struct device *clk_dev;
73 	struct nrf_clock_spec clk_spec;
74 #endif
75 };
76 
77 struct pwm_nrfx_data {
78 	uint32_t period_cycles;
79 	/* Bit mask indicating channels that need the PWM generation. */
80 	uint8_t  pwm_needed;
81 	uint8_t  prescaler;
82 	bool     stop_requested;
83 #ifdef PWM_NRFX_USE_CLOCK_CONTROL
84 	bool     clock_requested;
85 #endif
86 };
87 /* Ensure the pwm_needed bit mask can accommodate all available channels. */
88 #if (NRF_PWM_CHANNEL_COUNT > 8)
89 #error "Current implementation supports maximum 8 channels."
90 #endif
91 
92 #ifdef PWM_NRFX_FAST_PRESENT
pwm_is_fast(const struct pwm_nrfx_config * config)93 static bool pwm_is_fast(const struct pwm_nrfx_config *config)
94 {
95 	return config->clock_freq > MHZ(16);
96 }
97 #else
pwm_is_fast(const struct pwm_nrfx_config * config)98 static bool pwm_is_fast(const struct pwm_nrfx_config *config)
99 {
100 	return false;
101 }
102 #endif
103 
seq_values_ptr_get(const struct device * dev)104 static uint16_t *seq_values_ptr_get(const struct device *dev)
105 {
106 	const struct pwm_nrfx_config *config = dev->config;
107 
108 	return (uint16_t *)config->seq.values.p_raw;
109 }
110 
pwm_handler(nrfx_pwm_evt_type_t event_type,void * p_context)111 static void pwm_handler(nrfx_pwm_evt_type_t event_type, void *p_context)
112 {
113 	ARG_UNUSED(event_type);
114 	ARG_UNUSED(p_context);
115 }
116 
pwm_period_check_and_set(const struct device * dev,uint32_t channel,uint32_t period_cycles)117 static bool pwm_period_check_and_set(const struct device *dev,
118 				     uint32_t channel, uint32_t period_cycles)
119 {
120 	const struct pwm_nrfx_config *config = dev->config;
121 	struct pwm_nrfx_data *data = dev->data;
122 	uint8_t prescaler;
123 	uint32_t countertop;
124 
125 	/* If the currently configured period matches the requested one,
126 	 * nothing more needs to be done.
127 	 */
128 	if (period_cycles == data->period_cycles) {
129 		return true;
130 	}
131 
132 	/* If any other channel is driven by the PWM peripheral, the period
133 	 * that is currently set cannot be changed, as this would influence
134 	 * the output for that channel.
135 	 */
136 	if ((data->pwm_needed & ~BIT(channel)) != 0) {
137 		LOG_ERR("Incompatible period.");
138 		return false;
139 	}
140 
141 	/* Try to find a prescaler that will allow setting the requested period
142 	 * after prescaling as the countertop value for the PWM peripheral.
143 	 */
144 	prescaler = 0;
145 	countertop = period_cycles;
146 	do {
147 		if (countertop <= PWM_COUNTERTOP_COUNTERTOP_Msk) {
148 			data->period_cycles = period_cycles;
149 			data->prescaler     = prescaler;
150 
151 			nrf_pwm_configure(config->pwm.p_reg,
152 					  data->prescaler,
153 					  config->initial_config.count_mode,
154 					  (uint16_t)countertop);
155 			return true;
156 		}
157 
158 		countertop >>= 1;
159 		++prescaler;
160 	} while (prescaler <= PWM_PRESCALER_PRESCALER_Msk);
161 
162 	LOG_ERR("Prescaler for period_cycles %u not found.", period_cycles);
163 	return false;
164 }
165 
channel_psel_get(uint32_t channel,uint32_t * psel,const struct pwm_nrfx_config * config)166 static bool channel_psel_get(uint32_t channel, uint32_t *psel,
167 			     const struct pwm_nrfx_config *config)
168 {
169 	*psel = nrf_pwm_pin_get(config->pwm.p_reg, (uint8_t)channel);
170 
171 	return (((*psel & PWM_PSEL_OUT_CONNECT_Msk) >> PWM_PSEL_OUT_CONNECT_Pos)
172 		== PWM_PSEL_OUT_CONNECT_Connected);
173 }
174 
stop_pwm(const struct device * dev)175 static int stop_pwm(const struct device *dev)
176 {
177 	const struct pwm_nrfx_config *config = dev->config;
178 
179 	/* Don't wait here for the peripheral to actually stop. Instead,
180 	 * ensure it is stopped before starting the next playback.
181 	 */
182 	nrfx_pwm_stop(&config->pwm, false);
183 
184 #if PWM_NRFX_USE_CLOCK_CONTROL
185 	struct pwm_nrfx_data *data = dev->data;
186 
187 	if (data->clock_requested) {
188 		int ret = nrf_clock_control_release(config->clk_dev, &config->clk_spec);
189 
190 		if (ret < 0) {
191 			LOG_ERR("Global HSFLL release failed: %d", ret);
192 			return ret;
193 		}
194 
195 		data->clock_requested = false;
196 	}
197 #endif
198 
199 	return 0;
200 }
201 
pwm_nrfx_set_cycles(const struct device * dev,uint32_t channel,uint32_t period_cycles,uint32_t pulse_cycles,pwm_flags_t flags)202 static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel,
203 			       uint32_t period_cycles, uint32_t pulse_cycles,
204 			       pwm_flags_t flags)
205 {
206 	/* We assume here that period_cycles will always be 16MHz
207 	 * peripheral clock. Since pwm_nrfx_get_cycles_per_sec() function might
208 	 * be removed, see ISSUE #6958.
209 	 * TODO: Remove this comment when issue has been resolved.
210 	 */
211 	const struct pwm_nrfx_config *config = dev->config;
212 	struct pwm_nrfx_data *data = dev->data;
213 	uint16_t compare_value;
214 	bool inverted = (flags & PWM_POLARITY_INVERTED);
215 	bool needs_pwm = false;
216 
217 	if (channel >= NRF_PWM_CHANNEL_COUNT) {
218 		LOG_ERR("Invalid channel: %u.", channel);
219 		return -EINVAL;
220 	}
221 
222 	/* If this PWM is in center-aligned mode, pulse and period lengths
223 	 * are effectively doubled by the up-down count, so halve them here
224 	 * to compensate.
225 	 */
226 	if (config->initial_config.count_mode == NRF_PWM_MODE_UP_AND_DOWN) {
227 		period_cycles /= 2;
228 		pulse_cycles /= 2;
229 	}
230 
231 	if (pulse_cycles == 0) {
232 		/* Constantly inactive (duty 0%). */
233 		compare_value = 0;
234 	} else if (pulse_cycles >= period_cycles) {
235 		/* Constantly active (duty 100%). */
236 		/* This value is always greater than or equal to COUNTERTOP. */
237 		compare_value = PWM_NRFX_CH_COMPARE_MASK;
238 	} else {
239 		/* PWM generation needed. Check if the requested period matches
240 		 * the one that is currently set, or the PWM peripheral can be
241 		 * reconfigured accordingly.
242 		 */
243 		if (!pwm_period_check_and_set(dev, channel, period_cycles)) {
244 			return -EINVAL;
245 		}
246 
247 		compare_value = (uint16_t)(pulse_cycles >> data->prescaler);
248 		needs_pwm = true;
249 	}
250 
251 	seq_values_ptr_get(dev)[channel] = PWM_NRFX_CH_VALUE(compare_value, inverted);
252 
253 #ifdef CONFIG_DCACHE
254 	if (config->mem_attr & DT_MEM_CACHEABLE) {
255 		sys_cache_data_flush_range(seq_values_ptr_get(dev), config->seq.length);
256 	}
257 #endif
258 
259 	LOG_DBG("channel %u, pulse %u, period %u, prescaler: %u.",
260 		channel, pulse_cycles, period_cycles, data->prescaler);
261 
262 	/* If this channel does not need to be driven by the PWM peripheral
263 	 * because its state is to be constant (duty 0% or 100%), set properly
264 	 * the GPIO configuration for its output pin. This will provide
265 	 * the correct output state for this channel when the PWM peripheral
266 	 * is stopped.
267 	 */
268 	if (!needs_pwm) {
269 		uint32_t psel;
270 
271 		if (channel_psel_get(channel, &psel, config)) {
272 			uint32_t out_level = (pulse_cycles == 0) ? 0 : 1;
273 
274 			if (inverted) {
275 				out_level ^= 1;
276 			}
277 			/* Output of fast PWM instance is directly connected to GPIO pads,
278 			 * thus it cannot controlled by GPIO. Use regular 0%/100% duty cycle
279 			 * playback instead.
280 			 */
281 #ifdef PWM_NRFX_FAST_PRESENT
282 			if (pwm_is_fast(config)) {
283 				nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1,
284 							 NRFX_PWM_FLAG_NO_EVT_FINISHED);
285 			} else {
286 #else
287 			{
288 #endif
289 				nrf_gpio_pin_write(psel, out_level);
290 			}
291 		}
292 
293 		data->pwm_needed &= ~BIT(channel);
294 	} else {
295 		data->pwm_needed |= BIT(channel);
296 	}
297 
298 	/* If the PWM generation is not needed for any channel (all are set
299 	 * to constant inactive or active state), stop the PWM peripheral.
300 	 * Otherwise, request a playback of the defined sequence so that
301 	 * the PWM peripheral loads `seq_values` into its internal compare
302 	 * registers and drives its outputs accordingly.
303 	 */
304 	if (data->pwm_needed == 0) {
305 		if (pwm_is_fast(config)) {
306 #if PWM_NRFX_USE_CLOCK_CONTROL
307 			if (data->clock_requested) {
308 				int ret = nrf_clock_control_release(config->clk_dev,
309 							    &config->clk_spec);
310 
311 				if (ret < 0) {
312 					LOG_ERR("Global HSFLL release failed: %d", ret);
313 					return ret;
314 				}
315 
316 				data->clock_requested = false;
317 			}
318 #endif
319 			return 0;
320 		}
321 		int ret = stop_pwm(dev);
322 
323 		if (ret < 0) {
324 			LOG_ERR("PWM stop failed: %d", ret);
325 			return ret;
326 		}
327 
328 		data->stop_requested = true;
329 	} else {
330 		if (data->stop_requested) {
331 			data->stop_requested = false;
332 
333 			/* After a stop is requested, the PWM peripheral stops
334 			 * pulse generation at the end of the current period,
335 			 * and till that moment, it ignores any start requests,
336 			 * so ensure here that it is stopped.
337 			 */
338 			while (!nrfx_pwm_stopped_check(&config->pwm)) {
339 			}
340 		}
341 
342 		/* It is sufficient to play the sequence once without looping.
343 		 * The PWM generation will continue with the loaded values
344 		 * until another playback is requested (new values will be
345 		 * loaded then) or the PWM peripheral is stopped.
346 		 */
347 #if PWM_NRFX_USE_CLOCK_CONTROL
348 		if (config->clk_dev && !data->clock_requested) {
349 			int ret = nrf_clock_control_request_sync(config->clk_dev,
350 								 &config->clk_spec,
351 								 K_FOREVER);
352 
353 			if (ret < 0) {
354 				LOG_ERR("Global HSFLL request failed: %d", ret);
355 				return ret;
356 			}
357 
358 			data->clock_requested = true;
359 		}
360 #endif
361 		nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1,
362 					 NRFX_PWM_FLAG_NO_EVT_FINISHED);
363 	}
364 
365 	return 0;
366 }
367 
368 static int pwm_nrfx_get_cycles_per_sec(const struct device *dev, uint32_t channel,
369 				       uint64_t *cycles)
370 {
371 	const struct pwm_nrfx_config *config = dev->config;
372 
373 	*cycles = config->clock_freq;
374 
375 	return 0;
376 }
377 
378 static DEVICE_API(pwm, pwm_nrfx_drv_api_funcs) = {
379 	.set_cycles = pwm_nrfx_set_cycles,
380 	.get_cycles_per_sec = pwm_nrfx_get_cycles_per_sec,
381 };
382 
383 static int pwm_resume(const struct device *dev)
384 {
385 	const struct pwm_nrfx_config *config = dev->config;
386 	uint8_t initially_inverted = 0;
387 
388 	(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
389 
390 #ifdef CONFIG_SOC_NRF54H20_GPD
391 	nrf_gpd_retain_pins_set(config->pcfg, false);
392 #endif
393 
394 	for (size_t i = 0; i < NRF_PWM_CHANNEL_COUNT; i++) {
395 		uint32_t psel;
396 
397 		if (channel_psel_get(i, &psel, config)) {
398 			/* Mark channels as inverted according to what initial
399 			 * state of their outputs has been set by pinctrl (high
400 			 * idle state means that the channel is inverted).
401 			 */
402 			initially_inverted |= nrf_gpio_pin_out_read(psel) ?
403 					      BIT(i) : 0;
404 		}
405 	}
406 
407 	for (size_t i = 0; i < NRF_PWM_CHANNEL_COUNT; i++) {
408 		bool inverted = initially_inverted & BIT(i);
409 
410 		seq_values_ptr_get(dev)[i] = PWM_NRFX_CH_VALUE(0, inverted);
411 	}
412 
413 	return 0;
414 }
415 
416 static int pwm_suspend(const struct device *dev)
417 {
418 	const struct pwm_nrfx_config *config = dev->config;
419 
420 	int ret = stop_pwm(dev);
421 
422 	if (ret < 0) {
423 		LOG_ERR("PWM stop failed: %d", ret);
424 		return ret;
425 	}
426 
427 	while (!nrfx_pwm_stopped_check(&config->pwm)) {
428 	}
429 
430 #ifdef CONFIG_SOC_NRF54H20_GPD
431 	nrf_gpd_retain_pins_set(config->pcfg, true);
432 #endif
433 
434 	memset(dev->data, 0, sizeof(struct pwm_nrfx_data));
435 	(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
436 
437 	return 0;
438 }
439 
440 static int pwm_nrfx_pm_action(const struct device *dev,
441 			      enum pm_device_action action)
442 {
443 	if (action == PM_DEVICE_ACTION_RESUME) {
444 		return pwm_resume(dev);
445 	} else if (IS_ENABLED(CONFIG_PM_DEVICE) && (action == PM_DEVICE_ACTION_SUSPEND)) {
446 		return pwm_suspend(dev);
447 	} else {
448 		return -ENOTSUP;
449 	}
450 
451 	return 0;
452 }
453 
454 static int pwm_nrfx_init(const struct device *dev)
455 {
456 	const struct pwm_nrfx_config *config = dev->config;
457 	nrfx_err_t err;
458 
459 	ANOMALY_109_EGU_IRQ_CONNECT(NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE);
460 
461 	if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
462 		(void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP);
463 	}
464 
465 	err = nrfx_pwm_init(&config->pwm, &config->initial_config, pwm_handler, dev->data);
466 	if (err != NRFX_SUCCESS) {
467 		LOG_ERR("Failed to initialize device: %s", dev->name);
468 		return -EBUSY;
469 	}
470 
471 	return pm_device_driver_init(dev, pwm_nrfx_pm_action);
472 }
473 
474 #define PWM_MEM_REGION(idx)     DT_PHANDLE(PWM(idx), memory_regions)
475 
476 #define PWM_MEMORY_SECTION(idx)						      \
477 	COND_CODE_1(PWM_HAS_PROP(idx, memory_regions),			      \
478 		(__attribute__((__section__(LINKER_DT_NODE_REGION_NAME(	      \
479 			PWM_MEM_REGION(idx)))))),			      \
480 		())
481 
482 #define PWM_GET_MEM_ATTR(idx)						      \
483 	COND_CODE_1(PWM_HAS_PROP(idx, memory_regions),			      \
484 		(DT_PROP_OR(PWM_MEM_REGION(idx), zephyr_memory_attr, 0)), (0))
485 
486 /* Fast instances depend on the global HSFLL clock controller (as they need
487  * to request the highest frequency from it to operate correctly), so they
488  * must be initialized after that controller driver, hence the default PWM
489  * initialization priority may be too early for them.
490  */
491 #if defined(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY) && \
492 	CONFIG_PWM_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY
493 #define PWM_INIT_PRIORITY(idx)								\
494 	COND_CODE_1(PWM_NRFX_IS_FAST(_, /*empty*/, idx, _),				\
495 		    (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)),	\
496 		    (CONFIG_PWM_INIT_PRIORITY))
497 #else
498 #define PWM_INIT_PRIORITY(idx) CONFIG_PWM_INIT_PRIORITY
499 #endif
500 
501 #define PWM_NRFX_DEVICE(idx)						      \
502 	NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx));			      \
503 	static struct pwm_nrfx_data pwm_nrfx_##idx##_data;		      \
504 	static uint16_t pwm_##idx##_seq_values[NRF_PWM_CHANNEL_COUNT]	      \
505 			PWM_MEMORY_SECTION(idx);			      \
506 	PINCTRL_DT_DEFINE(PWM(idx));					      \
507 	static const struct pwm_nrfx_config pwm_nrfx_##idx##_config = {	      \
508 		.pwm = NRFX_PWM_INSTANCE(idx),				      \
509 		.initial_config = {					      \
510 			.skip_gpio_cfg = true,				      \
511 			.skip_psel_cfg = true,				      \
512 			.base_clock = NRF_PWM_CLK_1MHz,			      \
513 			.count_mode = (PWM_PROP(idx, center_aligned)	      \
514 				       ? NRF_PWM_MODE_UP_AND_DOWN	      \
515 				       : NRF_PWM_MODE_UP),		      \
516 			.top_value = 1000,				      \
517 			.load_mode = NRF_PWM_LOAD_INDIVIDUAL,		      \
518 			.step_mode = NRF_PWM_STEP_TRIGGERED,		      \
519 		},							      \
520 		.seq.values.p_raw = pwm_##idx##_seq_values,		      \
521 		.seq.length = NRF_PWM_CHANNEL_COUNT,			      \
522 		.pcfg = PINCTRL_DT_DEV_CONFIG_GET(PWM(idx)),		      \
523 		.clock_freq = COND_CODE_1(DT_CLOCKS_HAS_IDX(PWM(idx), 0),     \
524 			(DT_PROP(DT_CLOCKS_CTLR(PWM(idx)), clock_frequency)), \
525 			(16ul * 1000ul * 1000ul)),			      \
526 		IF_ENABLED(CONFIG_DCACHE,				      \
527 			(.mem_attr = PWM_GET_MEM_ATTR(idx),))		      \
528 		IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL,			      \
529 			(.clk_dev = PWM_NRFX_IS_FAST(_, /*empty*/, idx, _)    \
530 				    ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \
531 				    : NULL,				      \
532 			 .clk_spec = {					      \
533 				.frequency =				      \
534 					NRF_PERIPH_GET_FREQUENCY(PWM(idx)),   \
535 			 },))						      \
536 	};								      \
537 	static int pwm_nrfx_init##idx(const struct device *dev)		      \
538 	{								      \
539 		IRQ_CONNECT(DT_IRQN(PWM(idx)), DT_IRQ(PWM(idx), priority),    \
540 			    nrfx_isr, nrfx_pwm_##idx##_irq_handler, 0);	      \
541 		return pwm_nrfx_init(dev);				      \
542 	};								      \
543 	PM_DEVICE_DT_DEFINE(PWM(idx), pwm_nrfx_pm_action);		      \
544 	DEVICE_DT_DEFINE(PWM(idx),					      \
545 			 pwm_nrfx_init##idx, PM_DEVICE_DT_GET(PWM(idx)),      \
546 			 &pwm_nrfx_##idx##_data,			      \
547 			 &pwm_nrfx_##idx##_config,			      \
548 			 POST_KERNEL, PWM_INIT_PRIORITY(idx),		      \
549 			 &pwm_nrfx_drv_api_funcs)
550 
551 #define COND_PWM_NRFX_DEVICE(unused, prefix, i, _) \
552 	IF_ENABLED(CONFIG_HAS_HW_NRF_PWM##prefix##i, (PWM_NRFX_DEVICE(prefix##i);))
553 
554 NRFX_FOREACH_PRESENT(PWM, COND_PWM_NRFX_DEVICE, (), (), _)
555