1 /*
2  * Copyright (c) 2016 Intel Corporation.
3  * Copyright (c) 2020-2021 Vestas Wind Systems A/S
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /**
9  * @file
10  * @brief Public PWM Driver APIs
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_DRIVERS_PWM_H_
14 #define ZEPHYR_INCLUDE_DRIVERS_PWM_H_
15 
16 /**
17  * @brief PWM Interface
18  * @defgroup pwm_interface PWM Interface
19  * @ingroup io_interfaces
20  * @{
21  */
22 
23 #include <errno.h>
24 #include <zephyr/types.h>
25 #include <stddef.h>
26 #include <sys/math_extras.h>
27 #include <device.h>
28 #include <dt-bindings/pwm/pwm.h>
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 /**
35  * @name PWM capture configuration flags
36  * @{
37  */
38 
39 /** @cond INTERNAL_HIDDEN */
40 /* Bit 0 is used for PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED */
41 #define PWM_CAPTURE_TYPE_SHIFT		1U
42 #define PWM_CAPTURE_TYPE_MASK		(3U << PWM_CAPTURE_TYPE_SHIFT)
43 #define PWM_CAPTURE_MODE_SHIFT		3U
44 #define PWM_CAPTURE_MODE_MASK		(1U << PWM_CAPTURE_MODE_SHIFT)
45 /** @endcond */
46 
47 /** PWM pin capture captures period. */
48 #define PWM_CAPTURE_TYPE_PERIOD		(1U << PWM_CAPTURE_TYPE_SHIFT)
49 
50 /** PWM pin capture captures pulse width. */
51 #define PWM_CAPTURE_TYPE_PULSE		(2U << PWM_CAPTURE_TYPE_SHIFT)
52 
53 /** PWM pin capture captures both period and pulse width. */
54 #define PWM_CAPTURE_TYPE_BOTH		(PWM_CAPTURE_TYPE_PERIOD | \
55 					 PWM_CAPTURE_TYPE_PULSE)
56 
57 /** PWM pin capture captures a single period/pulse width. */
58 #define PWM_CAPTURE_MODE_SINGLE		(0U << PWM_CAPTURE_MODE_SHIFT)
59 
60 /** PWM pin capture captures period/pulse width continuously. */
61 #define PWM_CAPTURE_MODE_CONTINUOUS	(1U << PWM_CAPTURE_MODE_SHIFT)
62 
63 /** @} */
64 
65 /**
66  * @brief Provides a type to hold PWM configuration flags.
67  */
68 typedef uint8_t pwm_flags_t;
69 
70 /**
71  * @typedef pwm_pin_set_t
72  * @brief Callback API upon setting the pin
73  * See @a pwm_pin_set_cycles() for argument description
74  */
75 typedef int (*pwm_pin_set_t)(const struct device *dev, uint32_t pwm,
76 			     uint32_t period_cycles, uint32_t pulse_cycles,
77 			     pwm_flags_t flags);
78 
79 /**
80  * @typedef pwm_capture_callback_handler_t
81  * @brief PWM capture callback handler function signature
82  *
83  * @note The callback handler will be called in interrupt context.
84  *
85  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected to enable PWM capture
86  * support.
87  *
88  * @param dev Pointer to the device structure for the driver instance.
89  * @param pwm PWM pin.
90 
91  * @param period_cycles Captured PWM period width (in clock cycles). HW
92  *                      specific.
93  * @param pulse_cycles Captured PWM pulse width (in clock cycles). HW specific.
94  * @param status Status for the PWM capture (0 if no error, negative errno
95  *               otherwise. See @a pwm_pin_capture_cycles() return value
96  *               descriptions for details).
97  * @param user_data User data passed to @a pwm_pin_configure_capture()
98  */
99 typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
100 					       uint32_t pwm,
101 					       uint32_t period_cycles,
102 					       uint32_t pulse_cycles,
103 					       int status,
104 					       void *user_data);
105 
106 /**
107  * @typedef pwm_pin_configure_capture_t
108  * @brief Callback API upon configuring PWM pin capture
109  * See @a pwm_pin_configure_capture() for argument description
110  */
111 typedef int (*pwm_pin_configure_capture_t)(const struct device *dev,
112 					   uint32_t pwm,
113 					   pwm_flags_t flags,
114 					   pwm_capture_callback_handler_t cb,
115 					   void *user_data);
116 /**
117  * @typedef pwm_pin_enable_capture_t
118  * @brief Callback API upon enabling PWM pin capture
119  * See @a pwm_pin_enable_capture() for argument description
120  */
121 typedef int (*pwm_pin_enable_capture_t)(const struct device *dev,
122 					uint32_t pwm);
123 
124 /**
125  * @typedef pwm_pin_disable_capture_t
126  * @brief Callback API upon disabling PWM pin capture
127  * See @a pwm_pin_disable_capture() for argument description
128  */
129 typedef int (*pwm_pin_disable_capture_t)(const struct device *dev,
130 					 uint32_t pwm);
131 
132 /**
133  * @typedef pwm_get_cycles_per_sec_t
134  * @brief Callback API upon getting cycles per second
135  * See @a pwm_get_cycles_per_sec() for argument description
136  */
137 typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
138 					uint32_t pwm,
139 					uint64_t *cycles);
140 
141 /** @brief PWM driver API definition. */
142 __subsystem struct pwm_driver_api {
143 	pwm_pin_set_t pin_set;
144 #ifdef CONFIG_PWM_CAPTURE
145 	pwm_pin_configure_capture_t pin_configure_capture;
146 	pwm_pin_enable_capture_t pin_enable_capture;
147 	pwm_pin_disable_capture_t pin_disable_capture;
148 #endif /* CONFIG_PWM_CAPTURE */
149 	pwm_get_cycles_per_sec_t get_cycles_per_sec;
150 };
151 
152 /**
153  * @brief Set the period and pulse width for a single PWM output.
154  *
155  * The PWM period and pulse width will synchronously be set to the new values
156  * without glitches in the PWM signal, but the call will not block for the
157  * change to take effect.
158  *
159  * @note Not all PWM controllers support synchronous, glitch-free updates of the
160  * PWM period and pulse width. Depending on the hardware, changing the PWM
161  * period and/or pulse width may cause a glitch in the generated PWM signal.
162  *
163  * @note Some multi-channel PWM controllers share the PWM period across all
164  * channels. Depending on the hardware, changing the PWM period for one channel
165  * may affect the PWM period for the other channels of the same PWM controller.
166  *
167  * Passing 0 as @p pulse will cause the pin to be driven to a constant
168  * inactive level.
169  * Passing a non-zero @p pulse equal to @p period will cause the pin
170  * to be driven to a constant active level.
171  *
172  * @param dev Pointer to the device structure for the driver instance.
173  * @param pwm PWM pin.
174  * @param period Period (in clock cycle) set to the PWM. HW specific.
175  * @param pulse Pulse width (in clock cycle) set to the PWM. HW specific.
176  * @param flags Flags for pin configuration (polarity).
177  *
178  * @retval 0 If successful.
179  * @retval Negative errno code if failure.
180  */
181 __syscall int pwm_pin_set_cycles(const struct device *dev, uint32_t pwm,
182 				 uint32_t period, uint32_t pulse, pwm_flags_t flags);
183 
z_impl_pwm_pin_set_cycles(const struct device * dev,uint32_t pwm,uint32_t period,uint32_t pulse,pwm_flags_t flags)184 static inline int z_impl_pwm_pin_set_cycles(const struct device *dev,
185 					    uint32_t pwm,
186 					    uint32_t period, uint32_t pulse,
187 					    pwm_flags_t flags)
188 {
189 	struct pwm_driver_api *api;
190 
191 	api = (struct pwm_driver_api *)dev->api;
192 	return api->pin_set(dev, pwm, period, pulse, flags);
193 }
194 
195 /**
196  * @brief Configure PWM period/pulse width capture for a single PWM input.
197  *
198  * After configuring PWM capture using this function, the capture can be
199  * enabled/disabled using @a pwm_pin_enable_capture() and @a
200  * pwm_pin_disable_capture().
201  *
202  * @note This API function cannot be invoked from user space due to the use of a
203  * function callback. In user space, one of the simpler API functions (@a
204  * pwm_pin_capture_cycles(), @a pwm_pin_capture_usec(), or @a
205  * pwm_pin_capture_nsec()) can be used instead.
206  *
207  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
208  * available.
209  *
210  * @param dev Pointer to the device structure for the driver instance.
211  * @param pwm PWM pin.
212  * @param flags PWM capture flags
213  * @param cb Application callback handler function to be called upon capture
214  * @param user_data User data to pass to the application callback handler
215  *                  function
216  *
217  * @retval -EINVAL if invalid function parameters were given
218  * @retval -ENOSYS if PWM capture is not supported or the given flags are not
219  *                  supported
220  * @retval -EIO if IO error occurred while configuring
221  * @retval -EBUSY if PWM capture is already in progress
222  */
223 #ifdef CONFIG_PWM_CAPTURE
pwm_pin_configure_capture(const struct device * dev,uint32_t pwm,pwm_flags_t flags,pwm_capture_callback_handler_t cb,void * user_data)224 static inline int pwm_pin_configure_capture(const struct device *dev,
225 					    uint32_t pwm,
226 					    pwm_flags_t flags,
227 					    pwm_capture_callback_handler_t cb,
228 					    void *user_data)
229 {
230 	const struct pwm_driver_api *api = (struct pwm_driver_api *)dev->api;
231 
232 	if (api->pin_configure_capture == NULL) {
233 		return -ENOSYS;
234 	}
235 
236 	return api->pin_configure_capture(dev, pwm, flags, cb, user_data);
237 }
238 #endif /* CONFIG_PWM_CAPTURE */
239 
240 /**
241  * @brief Enable PWM period/pulse width capture for a single PWM input.
242  *
243  * The PWM pin must be configured using @a pwm_pin_configure_capture() prior to
244  * calling this function.
245  *
246  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
247  * available.
248  *
249  * @param dev Pointer to the device structure for the driver instance.
250  * @param pwm PWM pin.
251  *
252  * @retval 0 If successful.
253  * @retval -EINVAL if invalid function parameters were given
254  * @retval -ENOSYS if PWM capture is not supported
255  * @retval -EIO if IO error occurred while enabling PWM capture
256  * @retval -EBUSY if PWM capture is already in progress
257  */
258 __syscall int pwm_pin_enable_capture(const struct device *dev, uint32_t pwm);
259 
260 #ifdef CONFIG_PWM_CAPTURE
z_impl_pwm_pin_enable_capture(const struct device * dev,uint32_t pwm)261 static inline int z_impl_pwm_pin_enable_capture(const struct device *dev,
262 						uint32_t pwm)
263 {
264 	const struct pwm_driver_api *api = (struct pwm_driver_api *)dev->api;
265 
266 	if (api->pin_enable_capture == NULL) {
267 		return -ENOSYS;
268 	}
269 
270 	return api->pin_enable_capture(dev, pwm);
271 }
272 #endif /* CONFIG_PWM_CAPTURE */
273 
274 /**
275  * @brief Disable PWM period/pulse width capture for a single PWM input.
276  *
277  *
278  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
279  * available.
280  *
281  * @param dev Pointer to the device structure for the driver instance.
282  * @param pwm PWM pin.
283  *
284  * @retval 0 If successful.
285  * @retval -EINVAL if invalid function parameters were given
286  * @retval -ENOSYS if PWM capture is not supported
287  * @retval -EIO if IO error occurred while disabling PWM capture
288  */
289 __syscall int pwm_pin_disable_capture(const struct device *dev, uint32_t pwm);
290 
291 #ifdef CONFIG_PWM_CAPTURE
z_impl_pwm_pin_disable_capture(const struct device * dev,uint32_t pwm)292 static inline int z_impl_pwm_pin_disable_capture(const struct device *dev,
293 						 uint32_t pwm)
294 {
295 	const struct pwm_driver_api *api = (struct pwm_driver_api *)dev->api;
296 
297 	if (api->pin_disable_capture == NULL) {
298 		return -ENOSYS;
299 	}
300 
301 	return api->pin_disable_capture(dev, pwm);
302 }
303 #endif /* CONFIG_PWM_CAPTURE */
304 
305 /**
306  * @brief Capture a single PWM period/pulse width in clock cycles for a single
307  *        PWM input.
308  *
309  * This API function wraps calls to @a pwm_pin_configure_capture(), @a
310  * pwm_pin_enable_capture(), and @a pwm_pin_disable_capture() and passes the
311  * capture result to the caller. The function is blocking until either the PWM
312  * capture is completed or a timeout occurs.
313  *
314  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
315  * available.
316  *
317  * @param dev Pointer to the device structure for the driver instance.
318  * @param pwm PWM pin.
319  * @param flags PWM capture flags.
320  * @param period Pointer to the memory to store the captured PWM period width
321  *               (in clock cycles). HW specific.
322  * @param pulse Pointer to the memory to store the captured PWM pulse width (in
323  *              clock cycles). HW specific.
324  * @param timeout Waiting period for the capture to complete.
325  *
326  * @retval 0 If successful.
327  * @retval -EBUSY PWM capture already in progress.
328  * @retval -EAGAIN Waiting period timed out.
329  * @retval -EIO IO error while capturing.
330  * @retval -ERANGE If result is too large.
331  */
332 __syscall int pwm_pin_capture_cycles(const struct device *dev, uint32_t pwm,
333 				     pwm_flags_t flags,
334 				     uint32_t *period,
335 				     uint32_t *pulse,
336 				     k_timeout_t timeout);
337 
338 /**
339  * @brief Get the clock rate (cycles per second) for a single PWM output.
340  *
341  * @param dev Pointer to the device structure for the driver instance.
342  * @param pwm PWM pin.
343  * @param cycles Pointer to the memory to store clock rate (cycles per sec).
344  *		 HW specific.
345  *
346  * @retval 0 If successful.
347  * @retval Negative errno code if failure.
348  */
349 __syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t pwm,
350 				     uint64_t *cycles);
351 
z_impl_pwm_get_cycles_per_sec(const struct device * dev,uint32_t pwm,uint64_t * cycles)352 static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
353 						uint32_t pwm,
354 						uint64_t *cycles)
355 {
356 	struct pwm_driver_api *api;
357 
358 	api = (struct pwm_driver_api *)dev->api;
359 	return api->get_cycles_per_sec(dev, pwm, cycles);
360 }
361 
362 /**
363  * @brief Set the period and pulse width for a single PWM output.
364  *
365  * @param dev Pointer to the device structure for the driver instance.
366  * @param pwm PWM pin.
367  * @param period Period (in microseconds) set to the PWM.
368  * @param pulse Pulse width (in microseconds) set to the PWM.
369  * @param flags Flags for pin configuration (polarity).
370  *
371  * @retval 0 If successful.
372  * @retval Negative errno code if failure.
373  */
pwm_pin_set_usec(const struct device * dev,uint32_t pwm,uint32_t period,uint32_t pulse,pwm_flags_t flags)374 static inline int pwm_pin_set_usec(const struct device *dev, uint32_t pwm,
375 				   uint32_t period, uint32_t pulse,
376 				   pwm_flags_t flags)
377 {
378 	uint64_t period_cycles, pulse_cycles, cycles_per_sec;
379 
380 	if (pwm_get_cycles_per_sec(dev, pwm, &cycles_per_sec) != 0) {
381 		return -EIO;
382 	}
383 
384 	period_cycles = (period * cycles_per_sec) / USEC_PER_SEC;
385 	if (period_cycles >= ((uint64_t)1 << 32)) {
386 		return -ENOTSUP;
387 	}
388 
389 	pulse_cycles = (pulse * cycles_per_sec) / USEC_PER_SEC;
390 	if (pulse_cycles >= ((uint64_t)1 << 32)) {
391 		return -ENOTSUP;
392 	}
393 
394 	return pwm_pin_set_cycles(dev, pwm, (uint32_t)period_cycles,
395 				  (uint32_t)pulse_cycles, flags);
396 }
397 
398 /**
399  * @brief Set the period and pulse width for a single PWM output.
400  *
401  * @param dev Pointer to the device structure for the driver instance.
402  * @param pwm PWM pin.
403  * @param period Period (in nanoseconds) set to the PWM.
404  * @param pulse Pulse width (in nanoseconds) set to the PWM.
405  * @param flags Flags for pin configuration (polarity).
406  *
407  * @retval 0 If successful.
408  * @retval Negative errno code if failure.
409  */
pwm_pin_set_nsec(const struct device * dev,uint32_t pwm,uint32_t period,uint32_t pulse,pwm_flags_t flags)410 static inline int pwm_pin_set_nsec(const struct device *dev, uint32_t pwm,
411 				   uint32_t period, uint32_t pulse,
412 				   pwm_flags_t flags)
413 {
414 	uint64_t period_cycles, pulse_cycles, cycles_per_sec;
415 
416 	if (pwm_get_cycles_per_sec(dev, pwm, &cycles_per_sec) != 0) {
417 		return -EIO;
418 	}
419 
420 	period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
421 	if (period_cycles >= ((uint64_t)1 << 32)) {
422 		return -ENOTSUP;
423 	}
424 
425 	pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
426 	if (pulse_cycles >= ((uint64_t)1 << 32)) {
427 		return -ENOTSUP;
428 	}
429 
430 	return pwm_pin_set_cycles(dev, pwm, (uint32_t)period_cycles,
431 				  (uint32_t)pulse_cycles, flags);
432 }
433 
434 /**
435  * @brief Convert from PWM cycles to microseconds.
436  *
437  * @param dev Pointer to the device structure for the driver instance.
438  * @param pwm PWM pin.
439  * @param cycles Cycles to be converted.
440  * @param usec Pointer to the memory to store calculated usec.
441  *
442  * @retval 0 If successful.
443  * @retval -EIO If cycles per second cannot be determined.
444  * @retval -ERANGE If result is too large.
445  */
pwm_pin_cycles_to_usec(const struct device * dev,uint32_t pwm,uint32_t cycles,uint64_t * usec)446 static inline int pwm_pin_cycles_to_usec(const struct device *dev, uint32_t pwm,
447 					 uint32_t cycles, uint64_t *usec)
448 {
449 	uint64_t cycles_per_sec;
450 	uint64_t temp;
451 
452 	if (pwm_get_cycles_per_sec(dev, pwm, &cycles_per_sec) != 0) {
453 		return -EIO;
454 	}
455 
456 	if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
457 		return -ERANGE;
458 	}
459 
460 	*usec = temp / cycles_per_sec;
461 
462 	return 0;
463 }
464 
465 /**
466  * @brief Convert from PWM cycles to nanoseconds.
467  *
468  * @param dev Pointer to the device structure for the driver instance.
469  * @param pwm PWM pin.
470  * @param cycles Cycles to be converted.
471  * @param nsec Pointer to the memory to store the calculated nsec.
472  *
473  * @retval 0 If successful.
474  * @retval -EIO If cycles per second cannot be determined.
475  * @retval -ERANGE If result is too large.
476  */
pwm_pin_cycles_to_nsec(const struct device * dev,uint32_t pwm,uint32_t cycles,uint64_t * nsec)477 static inline int pwm_pin_cycles_to_nsec(const struct device *dev, uint32_t pwm,
478 					 uint32_t cycles, uint64_t *nsec)
479 {
480 	uint64_t cycles_per_sec;
481 	uint64_t temp;
482 
483 	if (pwm_get_cycles_per_sec(dev, pwm, &cycles_per_sec) != 0) {
484 		return -EIO;
485 	}
486 
487 	if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
488 		return -ERANGE;
489 	}
490 
491 	*nsec = temp / cycles_per_sec;
492 
493 	return 0;
494 }
495 
496 /**
497  * @brief Capture a single PWM period/pulse width in microseconds for a single
498  *        PWM input.
499  *
500  * This API function wraps calls to @a pwm_pin_capture_cycles() and @a
501  * pwm_pin_cycles_to_usec() and passes the capture result to the caller. The
502  * function is blocking until either the PWM capture is completed or a timeout
503  * occurs.
504  *
505  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
506  * available.
507  *
508  * @param dev Pointer to the device structure for the driver instance.
509  * @param pwm PWM pin.
510  * @param flags PWM capture flags.
511  * @param period Pointer to the memory to store the captured PWM period width
512  *               (in usec).
513  * @param pulse Pointer to the memory to store the captured PWM pulse width (in
514  *              usec).
515  * @param timeout Waiting period for the capture to complete.
516  *
517  * @retval 0 If successful.
518  * @retval -EBUSY PWM capture already in progress.
519  * @retval -EAGAIN Waiting period timed out.
520  * @retval -EIO IO error while capturing.
521  * @retval -ERANGE If result is too large.
522  */
pwm_pin_capture_usec(const struct device * dev,uint32_t pwm,pwm_flags_t flags,uint64_t * period,uint64_t * pulse,k_timeout_t timeout)523 static inline int pwm_pin_capture_usec(const struct device *dev, uint32_t pwm,
524 				       pwm_flags_t flags,
525 				       uint64_t *period,
526 				       uint64_t *pulse,
527 				       k_timeout_t timeout)
528 {
529 	uint32_t period_cycles;
530 	uint32_t pulse_cycles;
531 	int err;
532 
533 	err = pwm_pin_capture_cycles(dev, pwm, flags, &period_cycles,
534 				     &pulse_cycles, timeout);
535 	if (err) {
536 		return err;
537 	}
538 
539 	err = pwm_pin_cycles_to_usec(dev, pwm, period_cycles, period);
540 	if (err) {
541 		return err;
542 	}
543 
544 	err = pwm_pin_cycles_to_usec(dev, pwm, pulse_cycles, pulse);
545 	if (err) {
546 		return err;
547 	}
548 
549 	return 0;
550 }
551 
552 /**
553  * @brief Capture a single PWM period/pulse width in nanoseconds for a single
554  *        PWM input.
555  *
556  * This API function wraps calls to @a pwm_pin_capture_cycles() and @a
557  * pwm_pin_cycles_to_nsec() and passes the capture result to the caller. The
558  * function is blocking until either the PWM capture is completed or a timeout
559  * occurs.
560  *
561  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
562  * available.
563  *
564  * @param dev Pointer to the device structure for the driver instance.
565  * @param pwm PWM pin.
566  * @param flags PWM capture flags.
567  * @param period Pointer to the memory to store the captured PWM period width
568  *               (in nsec).
569  * @param pulse Pointer to the memory to store the captured PWM pulse width (in
570  *              nsec).
571  * @param timeout Waiting period for the capture to complete.
572  *
573  * @retval 0 If successful.
574  * @retval -EBUSY PWM capture already in progress.
575  * @retval -EAGAIN Waiting period timed out.
576  * @retval -EIO IO error while capturing.
577  * @retval -ERANGE If result is too large.
578  */
pwm_pin_capture_nsec(const struct device * dev,uint32_t pwm,pwm_flags_t flags,uint64_t * period,uint64_t * pulse,k_timeout_t timeout)579 static inline int pwm_pin_capture_nsec(const struct device *dev, uint32_t pwm,
580 				       pwm_flags_t flags,
581 				       uint64_t *period,
582 				       uint64_t *pulse,
583 				       k_timeout_t timeout)
584 {
585 	uint32_t period_cycles;
586 	uint32_t pulse_cycles;
587 	int err;
588 
589 	err = pwm_pin_capture_cycles(dev, pwm, flags, &period_cycles,
590 				     &pulse_cycles, timeout);
591 	if (err) {
592 		return err;
593 	}
594 
595 	err = pwm_pin_cycles_to_nsec(dev, pwm, period_cycles, period);
596 	if (err) {
597 		return err;
598 	}
599 
600 	err = pwm_pin_cycles_to_nsec(dev, pwm, pulse_cycles, pulse);
601 	if (err) {
602 		return err;
603 	}
604 
605 	return 0;
606 }
607 
608 #ifdef __cplusplus
609 }
610 #endif
611 
612 /**
613  * @}
614  */
615 
616 #include <syscalls/pwm.h>
617 
618 #endif /* ZEPHYR_INCLUDE_DRIVERS_PWM_H_ */
619