LCOV - code coverage report
Current view: top level - zephyr/drivers - pwm.h Hit Total Coverage
Test: new.info Lines: 39 39 100.0 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           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             :  * @since 1.0
      20             :  * @version 1.0.0
      21             :  * @ingroup io_interfaces
      22             :  * @{
      23             :  */
      24             : 
      25             : #include <errno.h>
      26             : #include <stdint.h>
      27             : 
      28             : #include <zephyr/device.h>
      29             : #include <zephyr/devicetree.h>
      30             : #include <zephyr/sys_clock.h>
      31             : #include <zephyr/sys/math_extras.h>
      32             : #include <zephyr/toolchain.h>
      33             : 
      34             : #include <zephyr/dt-bindings/pwm/pwm.h>
      35             : 
      36             : #ifdef __cplusplus
      37             : extern "C" {
      38             : #endif
      39             : 
      40             : /**
      41             :  * @name PWM capture configuration flags
      42             :  * @anchor PWM_CAPTURE_FLAGS
      43             :  * @{
      44             :  */
      45             : 
      46             : /** @cond INTERNAL_HIDDEN */
      47             : /* Bit 0 is used for PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED */
      48             : #define PWM_CAPTURE_TYPE_SHIFT          1U
      49             : #define PWM_CAPTURE_TYPE_MASK           (3U << PWM_CAPTURE_TYPE_SHIFT)
      50             : #define PWM_CAPTURE_MODE_SHIFT          3U
      51             : #define PWM_CAPTURE_MODE_MASK           (1U << PWM_CAPTURE_MODE_SHIFT)
      52             : /** @endcond */
      53             : 
      54             : /** PWM pin capture captures period. */
      55           1 : #define PWM_CAPTURE_TYPE_PERIOD         (1U << PWM_CAPTURE_TYPE_SHIFT)
      56             : 
      57             : /** PWM pin capture captures pulse width. */
      58           1 : #define PWM_CAPTURE_TYPE_PULSE          (2U << PWM_CAPTURE_TYPE_SHIFT)
      59             : 
      60             : /** PWM pin capture captures both period and pulse width. */
      61           1 : #define PWM_CAPTURE_TYPE_BOTH           (PWM_CAPTURE_TYPE_PERIOD | \
      62             :                                          PWM_CAPTURE_TYPE_PULSE)
      63             : 
      64             : /** PWM pin capture captures a single period/pulse width. */
      65           1 : #define PWM_CAPTURE_MODE_SINGLE         (0U << PWM_CAPTURE_MODE_SHIFT)
      66             : 
      67             : /** PWM pin capture captures period/pulse width continuously. */
      68           1 : #define PWM_CAPTURE_MODE_CONTINUOUS     (1U << PWM_CAPTURE_MODE_SHIFT)
      69             : 
      70             : /** @} */
      71             : 
      72             : /**
      73             :  * @brief Provides a type to hold PWM configuration flags.
      74             :  *
      75             :  * The lower 8 bits are used for standard flags.
      76             :  * The upper 8 bits are reserved for SoC specific flags.
      77             :  *
      78             :  * @see @ref PWM_CAPTURE_FLAGS.
      79             :  */
      80             : 
      81           1 : typedef uint16_t pwm_flags_t;
      82             : 
      83             : /**
      84             :  * @brief Container for PWM information specified in devicetree.
      85             :  *
      86             :  * This type contains a pointer to a PWM device, channel number (controlled by
      87             :  * the PWM device), the PWM signal period in nanoseconds and the flags
      88             :  * applicable to the channel. Note that not all PWM drivers support flags. In
      89             :  * such case, flags will be set to 0.
      90             :  *
      91             :  * @see PWM_DT_SPEC_GET_BY_NAME
      92             :  * @see PWM_DT_SPEC_GET_BY_NAME_OR
      93             :  * @see PWM_DT_SPEC_GET_BY_IDX
      94             :  * @see PWM_DT_SPEC_GET_BY_IDX_OR
      95             :  * @see PWM_DT_SPEC_GET
      96             :  * @see PWM_DT_SPEC_GET_OR
      97             :  */
      98           1 : struct pwm_dt_spec {
      99             :         /** PWM device instance. */
     100           1 :         const struct device *dev;
     101             :         /** Channel number. */
     102           1 :         uint32_t channel;
     103             :         /** Period in nanoseconds. */
     104           1 :         uint32_t period;
     105             :         /** Flags. */
     106           1 :         pwm_flags_t flags;
     107             : };
     108             : 
     109             : /**
     110             :  * @brief Static initializer for a struct pwm_dt_spec
     111             :  *
     112             :  * This returns a static initializer for a struct pwm_dt_spec given a devicetree
     113             :  * node identifier and an index.
     114             :  *
     115             :  * Example devicetree fragment:
     116             :  *
     117             :  * @code{.dts}
     118             :  *    n: node {
     119             :  *        pwms = <&pwm1 1 1000 PWM_POLARITY_NORMAL>,
     120             :  *               <&pwm2 3 2000 PWM_POLARITY_INVERTED>;
     121             :  *        pwm-names = "alpha", "beta";
     122             :  *    };
     123             :  * @endcode
     124             :  *
     125             :  * Example usage:
     126             :  *
     127             :  * @code{.c}
     128             :  *    const struct pwm_dt_spec spec =
     129             :  *        PWM_DT_SPEC_GET_BY_NAME(DT_NODELABEL(n), alpha);
     130             :  *
     131             :  *    // Initializes 'spec' to:
     132             :  *    // {
     133             :  *    //         .dev = DEVICE_DT_GET(DT_NODELABEL(pwm1)),
     134             :  *    //         .channel = 1,
     135             :  *    //         .period = 1000,
     136             :  *    //         .flags = PWM_POLARITY_NORMAL,
     137             :  *    // }
     138             :  * @endcode
     139             :  *
     140             :  * The device (dev) must still be checked for readiness, e.g. using
     141             :  * device_is_ready(). It is an error to use this macro unless the node exists,
     142             :  * has the 'pwms' property, and that 'pwms' property specifies a PWM controller,
     143             :  * a channel, a period in nanoseconds and optionally flags.
     144             :  *
     145             :  * @param node_id Devicetree node identifier.
     146             :  * @param name Lowercase-and-underscores name of a pwms element as defined by
     147             :  *             the node's pwm-names property.
     148             :  *
     149             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     150             :  *
     151             :  * @see PWM_DT_SPEC_INST_GET_BY_NAME
     152             :  */
     153           1 : #define PWM_DT_SPEC_GET_BY_NAME(node_id, name)                                 \
     154             :         {                                                                      \
     155             :                 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_NAME(node_id, name)),     \
     156             :                 .channel = DT_PWMS_CHANNEL_BY_NAME(node_id, name),             \
     157             :                 .period = DT_PWMS_PERIOD_BY_NAME(node_id, name),               \
     158             :                 .flags = DT_PWMS_FLAGS_BY_NAME(node_id, name),                 \
     159             :         }
     160             : 
     161             : /**
     162             :  * @brief Static initializer for a struct pwm_dt_spec from a DT_DRV_COMPAT
     163             :  *        instance.
     164             :  *
     165             :  * @param inst DT_DRV_COMPAT instance number
     166             :  * @param name Lowercase-and-underscores name of a pwms element as defined by
     167             :  *             the node's pwm-names property.
     168             :  *
     169             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     170             :  *
     171             :  * @see PWM_DT_SPEC_GET_BY_NAME
     172             :  */
     173           1 : #define PWM_DT_SPEC_INST_GET_BY_NAME(inst, name)                               \
     174             :         PWM_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
     175             : 
     176             : /**
     177             :  * @brief Like PWM_DT_SPEC_GET_BY_NAME(), with a fallback to a default value.
     178             :  *
     179             :  * If the devicetree node identifier 'node_id' refers to a node with a property
     180             :  * 'pwms', this expands to <tt>PWM_DT_SPEC_GET_BY_NAME(node_id, name)</tt>. The
     181             :  * @p default_value parameter is not expanded in this case. Otherwise, this
     182             :  * expands to @p default_value.
     183             :  *
     184             :  * @param node_id Devicetree node identifier.
     185             :  * @param name Lowercase-and-underscores name of a pwms element as defined by
     186             :  *             the node's pwm-names property
     187             :  * @param default_value Fallback value to expand to.
     188             :  *
     189             :  * @return Static initializer for a struct pwm_dt_spec for the property,
     190             :  *         or @p default_value if the node or property do not exist.
     191             :  *
     192             :  * @see PWM_DT_SPEC_INST_GET_BY_NAME_OR
     193             :  */
     194           1 : #define PWM_DT_SPEC_GET_BY_NAME_OR(node_id, name, default_value)               \
     195             :         COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms),                           \
     196             :                     (PWM_DT_SPEC_GET_BY_NAME(node_id, name)),                  \
     197             :                     (default_value))
     198             : 
     199             : /**
     200             :  * @brief Like PWM_DT_SPEC_INST_GET_BY_NAME(), with a fallback to a default
     201             :  *        value.
     202             :  *
     203             :  * @param inst DT_DRV_COMPAT instance number
     204             :  * @param name Lowercase-and-underscores name of a pwms element as defined by
     205             :  *             the node's pwm-names property.
     206             :  * @param default_value Fallback value to expand to.
     207             :  *
     208             :  * @return Static initializer for a struct pwm_dt_spec for the property,
     209             :  *         or @p default_value if the node or property do not exist.
     210             :  *
     211             :  * @see PWM_DT_SPEC_GET_BY_NAME_OR
     212             :  */
     213           1 : #define PWM_DT_SPEC_INST_GET_BY_NAME_OR(inst, name, default_value)             \
     214             :         PWM_DT_SPEC_GET_BY_NAME_OR(DT_DRV_INST(inst), name, default_value)
     215             : 
     216             : /**
     217             :  * @brief Static initializer for a struct pwm_dt_spec
     218             :  *
     219             :  * This returns a static initializer for a struct pwm_dt_spec given a devicetree
     220             :  * node identifier and an index.
     221             :  *
     222             :  * Example devicetree fragment:
     223             :  *
     224             :  * @code{.dts}
     225             :  *    n: node {
     226             :  *        pwms = <&pwm1 1 1000 PWM_POLARITY_NORMAL>,
     227             :  *               <&pwm2 3 2000 PWM_POLARITY_INVERTED>;
     228             :  *    };
     229             :  * @endcode
     230             :  *
     231             :  * Example usage:
     232             :  *
     233             :  * @code{.c}
     234             :  *    const struct pwm_dt_spec spec =
     235             :  *        PWM_DT_SPEC_GET_BY_IDX(DT_NODELABEL(n), 1);
     236             :  *
     237             :  *    // Initializes 'spec' to:
     238             :  *    // {
     239             :  *    //         .dev = DEVICE_DT_GET(DT_NODELABEL(pwm2)),
     240             :  *    //         .channel = 3,
     241             :  *    //         .period = 2000,
     242             :  *    //         .flags = PWM_POLARITY_INVERTED,
     243             :  *    // }
     244             :  * @endcode
     245             :  *
     246             :  * The device (dev) must still be checked for readiness, e.g. using
     247             :  * device_is_ready(). It is an error to use this macro unless the node exists,
     248             :  * has the 'pwms' property, and that 'pwms' property specifies a PWM controller,
     249             :  * a channel, a period in nanoseconds and optionally flags.
     250             :  *
     251             :  * @param node_id Devicetree node identifier.
     252             :  * @param idx Logical index into 'pwms' property.
     253             :  *
     254             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     255             :  *
     256             :  * @see PWM_DT_SPEC_INST_GET_BY_IDX
     257             :  */
     258           1 : #define PWM_DT_SPEC_GET_BY_IDX(node_id, idx)                                   \
     259             :         {                                                                      \
     260             :                 .dev = DEVICE_DT_GET(DT_PWMS_CTLR_BY_IDX(node_id, idx)),       \
     261             :                 .channel = DT_PWMS_CHANNEL_BY_IDX(node_id, idx),               \
     262             :                 .period = DT_PWMS_PERIOD_BY_IDX(node_id, idx),                 \
     263             :                 .flags = DT_PWMS_FLAGS_BY_IDX(node_id, idx),                   \
     264             :         }
     265             : 
     266             : /**
     267             :  * @brief Static initializer for a struct pwm_dt_spec from a DT_DRV_COMPAT
     268             :  *        instance.
     269             :  *
     270             :  * @param inst DT_DRV_COMPAT instance number
     271             :  * @param idx Logical index into 'pwms' property.
     272             :  *
     273             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     274             :  *
     275             :  * @see PWM_DT_SPEC_GET_BY_IDX
     276             :  */
     277           1 : #define PWM_DT_SPEC_INST_GET_BY_IDX(inst, idx)                                 \
     278             :         PWM_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
     279             : 
     280             : /**
     281             :  * @brief Like PWM_DT_SPEC_GET_BY_IDX(), with a fallback to a default value.
     282             :  *
     283             :  * If the devicetree node identifier 'node_id' refers to a node with a property
     284             :  * 'pwms', this expands to <tt>PWM_DT_SPEC_GET_BY_IDX(node_id, idx)</tt>. The
     285             :  * @p default_value parameter is not expanded in this case. Otherwise, this
     286             :  * expands to @p default_value.
     287             :  *
     288             :  * @param node_id Devicetree node identifier.
     289             :  * @param idx Logical index into 'pwms' property.
     290             :  * @param default_value Fallback value to expand to.
     291             :  *
     292             :  * @return Static initializer for a struct pwm_dt_spec for the property,
     293             :  *         or @p default_value if the node or property do not exist.
     294             :  *
     295             :  * @see PWM_DT_SPEC_INST_GET_BY_IDX_OR
     296             :  */
     297           1 : #define PWM_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value)                 \
     298             :         COND_CODE_1(DT_NODE_HAS_PROP(node_id, pwms),                           \
     299             :                     (PWM_DT_SPEC_GET_BY_IDX(node_id, idx)),                    \
     300             :                     (default_value))
     301             : 
     302             : /**
     303             :  * @brief Like PWM_DT_SPEC_INST_GET_BY_IDX(), with a fallback to a default
     304             :  *        value.
     305             :  *
     306             :  * @param inst DT_DRV_COMPAT instance number
     307             :  * @param idx Logical index into 'pwms' property.
     308             :  * @param default_value Fallback value to expand to.
     309             :  *
     310             :  * @return Static initializer for a struct pwm_dt_spec for the property,
     311             :  *         or @p default_value if the node or property do not exist.
     312             :  *
     313             :  * @see PWM_DT_SPEC_GET_BY_IDX_OR
     314             :  */
     315           1 : #define PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value)               \
     316             :         PWM_DT_SPEC_GET_BY_IDX_OR(DT_DRV_INST(inst), idx, default_value)
     317             : 
     318             : /**
     319             :  * @brief Equivalent to <tt>PWM_DT_SPEC_GET_BY_IDX(node_id, 0)</tt>.
     320             :  *
     321             :  * @param node_id Devicetree node identifier.
     322             :  *
     323             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     324             :  *
     325             :  * @see PWM_DT_SPEC_GET_BY_IDX
     326             :  * @see PWM_DT_SPEC_INST_GET
     327             :  */
     328           1 : #define PWM_DT_SPEC_GET(node_id) PWM_DT_SPEC_GET_BY_IDX(node_id, 0)
     329             : 
     330             : /**
     331             :  * @brief Equivalent to <tt>PWM_DT_SPEC_INST_GET_BY_IDX(inst, 0)</tt>.
     332             :  *
     333             :  * @param inst DT_DRV_COMPAT instance number
     334             :  *
     335             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     336             :  *
     337             :  * @see PWM_DT_SPEC_INST_GET_BY_IDX
     338             :  * @see PWM_DT_SPEC_GET
     339             :  */
     340           1 : #define PWM_DT_SPEC_INST_GET(inst) PWM_DT_SPEC_GET(DT_DRV_INST(inst))
     341             : 
     342             : /**
     343             :  * @brief Equivalent to
     344             :  *        <tt>PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)</tt>.
     345             :  *
     346             :  * @param node_id Devicetree node identifier.
     347             :  * @param default_value Fallback value to expand to.
     348             :  *
     349             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     350             :  *
     351             :  * @see PWM_DT_SPEC_GET_BY_IDX_OR
     352             :  * @see PWM_DT_SPEC_INST_GET_OR
     353             :  */
     354           1 : #define PWM_DT_SPEC_GET_OR(node_id, default_value)                             \
     355             :         PWM_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value)
     356             : 
     357             : /**
     358             :  * @brief Equivalent to
     359             :  *        <tt>PWM_DT_SPEC_INST_GET_BY_IDX_OR(inst, 0, default_value)</tt>.
     360             :  *
     361             :  * @param inst DT_DRV_COMPAT instance number
     362             :  * @param default_value Fallback value to expand to.
     363             :  *
     364             :  * @return Static initializer for a struct pwm_dt_spec for the property.
     365             :  *
     366             :  * @see PWM_DT_SPEC_INST_GET_BY_IDX_OR
     367             :  * @see PWM_DT_SPEC_GET_OR
     368             :  */
     369           1 : #define PWM_DT_SPEC_INST_GET_OR(inst, default_value)                           \
     370             :         PWM_DT_SPEC_GET_OR(DT_DRV_INST(inst), default_value)
     371             : 
     372             : /**
     373             :  * @brief PWM capture callback handler function signature
     374             :  *
     375             :  * @note The callback handler will be called in interrupt context.
     376             :  *
     377             :  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected to enable PWM capture
     378             :  * support.
     379             :  *
     380             :  * @param[in] dev PWM device instance.
     381             :  * @param channel PWM channel.
     382             : 
     383             :  * @param period_cycles Captured PWM period width (in clock cycles). HW
     384             :  *                      specific.
     385             :  * @param pulse_cycles Captured PWM pulse width (in clock cycles). HW specific.
     386             :  * @param status Status for the PWM capture (0 if no error, negative errno
     387             :  *               otherwise. See pwm_capture_cycles() return value
     388             :  *               descriptions for details).
     389             :  * @param user_data User data passed to pwm_configure_capture()
     390             :  */
     391           1 : typedef void (*pwm_capture_callback_handler_t)(const struct device *dev,
     392             :                                                uint32_t channel,
     393             :                                                uint32_t period_cycles,
     394             :                                                uint32_t pulse_cycles,
     395             :                                                int status, void *user_data);
     396             : 
     397             : /** @cond INTERNAL_HIDDEN */
     398             : /**
     399             :  * @brief PWM driver API call to configure PWM pin period and pulse width.
     400             :  * @see pwm_set_cycles() for argument description.
     401             :  */
     402             : typedef int (*pwm_set_cycles_t)(const struct device *dev, uint32_t channel,
     403             :                                 uint32_t period_cycles, uint32_t pulse_cycles,
     404             :                                 pwm_flags_t flags);
     405             : 
     406             : /**
     407             :  * @brief PWM driver API call to obtain the PWM cycles per second (frequency).
     408             :  * @see pwm_get_cycles_per_sec() for argument description
     409             :  */
     410             : typedef int (*pwm_get_cycles_per_sec_t)(const struct device *dev,
     411             :                                         uint32_t channel, uint64_t *cycles);
     412             : 
     413             : #ifdef CONFIG_PWM_CAPTURE
     414             : /**
     415             :  * @brief PWM driver API call to configure PWM capture.
     416             :  * @see pwm_configure_capture() for argument description.
     417             :  */
     418             : typedef int (*pwm_configure_capture_t)(const struct device *dev,
     419             :                                        uint32_t channel, pwm_flags_t flags,
     420             :                                        pwm_capture_callback_handler_t cb,
     421             :                                        void *user_data);
     422             : 
     423             : /**
     424             :  * @brief PWM driver API call to enable PWM capture.
     425             :  * @see pwm_enable_capture() for argument description.
     426             :  */
     427             : typedef int (*pwm_enable_capture_t)(const struct device *dev, uint32_t channel);
     428             : 
     429             : /**
     430             :  * @brief PWM driver API call to disable PWM capture.
     431             :  * @see pwm_disable_capture() for argument description
     432             :  */
     433             : typedef int (*pwm_disable_capture_t)(const struct device *dev,
     434             :                                      uint32_t channel);
     435             : #endif /* CONFIG_PWM_CAPTURE */
     436             : 
     437             : /** @brief PWM driver API definition. */
     438             : __subsystem struct pwm_driver_api {
     439             :         pwm_set_cycles_t set_cycles;
     440             :         pwm_get_cycles_per_sec_t get_cycles_per_sec;
     441             : #ifdef CONFIG_PWM_CAPTURE
     442             :         pwm_configure_capture_t configure_capture;
     443             :         pwm_enable_capture_t enable_capture;
     444             :         pwm_disable_capture_t disable_capture;
     445             : #endif /* CONFIG_PWM_CAPTURE */
     446             : };
     447             : /** @endcond */
     448             : 
     449             : /**
     450             :  * @brief Set the period and pulse width for a single PWM output.
     451             :  *
     452             :  * The PWM period and pulse width will synchronously be set to the new values
     453             :  * without glitches in the PWM signal, but the call will not block for the
     454             :  * change to take effect.
     455             :  *
     456             :  * @note Not all PWM controllers support synchronous, glitch-free updates of the
     457             :  * PWM period and pulse width. Depending on the hardware, changing the PWM
     458             :  * period and/or pulse width may cause a glitch in the generated PWM signal.
     459             :  *
     460             :  * @note Some multi-channel PWM controllers share the PWM period across all
     461             :  * channels. Depending on the hardware, changing the PWM period for one channel
     462             :  * may affect the PWM period for the other channels of the same PWM controller.
     463             :  *
     464             :  * Passing 0 as @p pulse will cause the pin to be driven to a constant
     465             :  * inactive level.
     466             :  * Passing a non-zero @p pulse equal to @p period will cause the pin
     467             :  * to be driven to a constant active level.
     468             :  *
     469             :  * @param[in] dev PWM device instance.
     470             :  * @param channel PWM channel.
     471             :  * @param period Period (in clock cycles) set to the PWM. HW specific.
     472             :  * @param pulse Pulse width (in clock cycles) set to the PWM. HW specific.
     473             :  * @param flags Flags for pin configuration.
     474             :  *
     475             :  * @retval 0 If successful.
     476             :  * @retval -EINVAL If pulse > period.
     477             :  * @retval -errno Negative errno code on failure.
     478             :  */
     479           1 : __syscall int pwm_set_cycles(const struct device *dev, uint32_t channel,
     480             :                              uint32_t period, uint32_t pulse,
     481             :                              pwm_flags_t flags);
     482             : 
     483             : static inline int z_impl_pwm_set_cycles(const struct device *dev,
     484             :                                         uint32_t channel, uint32_t period,
     485             :                                         uint32_t pulse, pwm_flags_t flags)
     486             : {
     487             :         const struct pwm_driver_api *api =
     488             :                 (const struct pwm_driver_api *)dev->api;
     489             : 
     490             :         if (pulse > period) {
     491             :                 return -EINVAL;
     492             :         }
     493             : 
     494             :         return api->set_cycles(dev, channel, period, pulse, flags);
     495             : }
     496             : 
     497             : /**
     498             :  * @brief Get the clock rate (cycles per second) for a single PWM output.
     499             :  *
     500             :  * @param[in] dev PWM device instance.
     501             :  * @param channel PWM channel.
     502             :  * @param[out] cycles Pointer to the memory to store clock rate (cycles per
     503             :  *                    sec). HW specific.
     504             :  *
     505             :  * @retval 0 If successful.
     506             :  * @retval -errno Negative errno code on failure.
     507             :  */
     508           1 : __syscall int pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel,
     509             :                                      uint64_t *cycles);
     510             : 
     511             : static inline int z_impl_pwm_get_cycles_per_sec(const struct device *dev,
     512             :                                                 uint32_t channel,
     513             :                                                 uint64_t *cycles)
     514             : {
     515             :         const struct pwm_driver_api *api =
     516             :                 (const struct pwm_driver_api *)dev->api;
     517             : 
     518             :         return api->get_cycles_per_sec(dev, channel, cycles);
     519             : }
     520             : 
     521             : /**
     522             :  * @brief Set the period and pulse width in nanoseconds for a single PWM output.
     523             :  *
     524             :  * @note Utility macros such as PWM_MSEC() can be used to convert from other
     525             :  * scales or units to nanoseconds, the units used by this function.
     526             :  *
     527             :  * @param[in] dev PWM device instance.
     528             :  * @param channel PWM channel.
     529             :  * @param period Period (in nanoseconds) set to the PWM.
     530             :  * @param pulse Pulse width (in nanoseconds) set to the PWM.
     531             :  * @param flags Flags for pin configuration (polarity).
     532             :  *
     533             :  * @retval 0 If successful.
     534             :  * @retval -ENOTSUP If requested period or pulse cycles are not supported.
     535             :  * @retval -errno Other negative errno code on failure.
     536             :  */
     537           1 : static inline int pwm_set(const struct device *dev, uint32_t channel,
     538             :                           uint32_t period, uint32_t pulse, pwm_flags_t flags)
     539             : {
     540             :         int err;
     541             :         uint64_t pulse_cycles;
     542             :         uint64_t period_cycles;
     543             :         uint64_t cycles_per_sec;
     544             : 
     545             :         err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
     546             :         if (err < 0) {
     547             :                 return err;
     548             :         }
     549             : 
     550             :         period_cycles = (period * cycles_per_sec) / NSEC_PER_SEC;
     551             :         if (period_cycles > UINT32_MAX) {
     552             :                 return -ENOTSUP;
     553             :         }
     554             : 
     555             :         pulse_cycles = (pulse * cycles_per_sec) / NSEC_PER_SEC;
     556             :         if (pulse_cycles > UINT32_MAX) {
     557             :                 return -ENOTSUP;
     558             :         }
     559             : 
     560             :         return pwm_set_cycles(dev, channel, (uint32_t)period_cycles,
     561             :                               (uint32_t)pulse_cycles, flags);
     562             : }
     563             : 
     564             : /**
     565             :  * @brief Set the period and pulse width in nanoseconds from a struct
     566             :  *        pwm_dt_spec (with custom period).
     567             :  *
     568             :  * This is equivalent to:
     569             :  *
     570             :  *     pwm_set(spec->dev, spec->channel, period, pulse, spec->flags)
     571             :  *
     572             :  * The period specified in @p spec is ignored. This API call can be used when
     573             :  * the period specified in Devicetree needs to be changed at runtime.
     574             :  *
     575             :  * @param[in] spec PWM specification from devicetree.
     576             :  * @param period Period (in nanoseconds) set to the PWM.
     577             :  * @param pulse Pulse width (in nanoseconds) set to the PWM.
     578             :  *
     579             :  * @return A value from pwm_set().
     580             :  *
     581             :  * @see pwm_set_pulse_dt()
     582             :  */
     583           1 : static inline int pwm_set_dt(const struct pwm_dt_spec *spec, uint32_t period,
     584             :                              uint32_t pulse)
     585             : {
     586             :         return pwm_set(spec->dev, spec->channel, period, pulse, spec->flags);
     587             : }
     588             : 
     589             : /**
     590             :  * @brief Set the period and pulse width in nanoseconds from a struct
     591             :  *        pwm_dt_spec.
     592             :  *
     593             :  * This is equivalent to:
     594             :  *
     595             :  *     pwm_set(spec->dev, spec->channel, spec->period, pulse, spec->flags)
     596             :  *
     597             :  * @param[in] spec PWM specification from devicetree.
     598             :  * @param pulse Pulse width (in nanoseconds) set to the PWM.
     599             :  *
     600             :  * @return A value from pwm_set().
     601             :  *
     602             :  * @see pwm_set_pulse_dt()
     603             :  */
     604           1 : static inline int pwm_set_pulse_dt(const struct pwm_dt_spec *spec,
     605             :                                    uint32_t pulse)
     606             : {
     607             :         return pwm_set(spec->dev, spec->channel, spec->period, pulse,
     608             :                        spec->flags);
     609             : }
     610             : 
     611             : /**
     612             :  * @brief Convert from PWM cycles to microseconds.
     613             :  *
     614             :  * @param[in] dev PWM device instance.
     615             :  * @param channel PWM channel.
     616             :  * @param cycles Cycles to be converted.
     617             :  * @param[out] usec Pointer to the memory to store calculated usec.
     618             :  *
     619             :  * @retval 0 If successful.
     620             :  * @retval -ERANGE If result is too large.
     621             :  * @retval -errno Other negative errno code on failure.
     622             :  */
     623           1 : static inline int pwm_cycles_to_usec(const struct device *dev, uint32_t channel,
     624             :                                      uint32_t cycles, uint64_t *usec)
     625             : {
     626             :         int err;
     627             :         uint64_t temp;
     628             :         uint64_t cycles_per_sec;
     629             : 
     630             :         err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
     631             :         if (err < 0) {
     632             :                 return err;
     633             :         }
     634             : 
     635             :         if (u64_mul_overflow(cycles, (uint64_t)USEC_PER_SEC, &temp)) {
     636             :                 return -ERANGE;
     637             :         }
     638             : 
     639             :         *usec = temp / cycles_per_sec;
     640             : 
     641             :         return 0;
     642             : }
     643             : 
     644             : /**
     645             :  * @brief Convert from PWM cycles to nanoseconds.
     646             :  *
     647             :  * @param[in] dev PWM device instance.
     648             :  * @param channel PWM channel.
     649             :  * @param cycles Cycles to be converted.
     650             :  * @param[out] nsec Pointer to the memory to store the calculated nsec.
     651             :  *
     652             :  * @retval 0 If successful.
     653             :  * @retval -ERANGE If result is too large.
     654             :  * @retval -errno Other negative errno code on failure.
     655             :  */
     656           1 : static inline int pwm_cycles_to_nsec(const struct device *dev, uint32_t channel,
     657             :                                      uint32_t cycles, uint64_t *nsec)
     658             : {
     659             :         int err;
     660             :         uint64_t temp;
     661             :         uint64_t cycles_per_sec;
     662             : 
     663             :         err = pwm_get_cycles_per_sec(dev, channel, &cycles_per_sec);
     664             :         if (err < 0) {
     665             :                 return err;
     666             :         }
     667             : 
     668             :         if (u64_mul_overflow(cycles, (uint64_t)NSEC_PER_SEC, &temp)) {
     669             :                 return -ERANGE;
     670             :         }
     671             : 
     672             :         *nsec = temp / cycles_per_sec;
     673             : 
     674             :         return 0;
     675             : }
     676             : 
     677             : #if defined(CONFIG_PWM_CAPTURE) || defined(__DOXYGEN__)
     678             : /**
     679             :  * @brief Configure PWM period/pulse width capture for a single PWM input.
     680             :  *
     681             :  * After configuring PWM capture using this function, the capture can be
     682             :  * enabled/disabled using pwm_enable_capture() and
     683             :  * pwm_disable_capture().
     684             :  *
     685             :  * @note This API function cannot be invoked from user space due to the use of a
     686             :  * function callback. In user space, one of the simpler API functions
     687             :  * (pwm_capture_cycles(), pwm_capture_usec(), or
     688             :  * pwm_capture_nsec()) can be used instead.
     689             :  *
     690             :  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
     691             :  * available.
     692             :  *
     693             :  * @param[in] dev PWM device instance.
     694             :  * @param channel PWM channel.
     695             :  * @param flags PWM capture flags
     696             :  * @param[in] cb Application callback handler function to be called upon capture
     697             :  * @param[in] user_data User data to pass to the application callback handler
     698             :  *                      function
     699             :  *
     700             :  * @retval -EINVAL if invalid function parameters were given
     701             :  * @retval -ENOSYS if PWM capture is not supported or the given flags are not
     702             :  *                  supported
     703             :  * @retval -EIO if IO error occurred while configuring
     704             :  * @retval -EBUSY if PWM capture is already in progress
     705             :  */
     706           1 : static inline int pwm_configure_capture(const struct device *dev,
     707             :                                         uint32_t channel, pwm_flags_t flags,
     708             :                                         pwm_capture_callback_handler_t cb,
     709             :                                         void *user_data)
     710             : {
     711             :         const struct pwm_driver_api *api =
     712             :                 (const struct pwm_driver_api *)dev->api;
     713             : 
     714             :         if (api->configure_capture == NULL) {
     715             :                 return -ENOSYS;
     716             :         }
     717             : 
     718             :         return api->configure_capture(dev, channel, flags, cb,
     719             :                                               user_data);
     720             : }
     721             : #endif /* CONFIG_PWM_CAPTURE */
     722             : 
     723             : /**
     724             :  * @brief Enable PWM period/pulse width capture for a single PWM input.
     725             :  *
     726             :  * The PWM pin must be configured using pwm_configure_capture() prior to
     727             :  * calling this function.
     728             :  *
     729             :  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
     730             :  * available.
     731             :  *
     732             :  * @param[in] dev PWM device instance.
     733             :  * @param channel PWM channel.
     734             :  *
     735             :  * @retval 0 If successful.
     736             :  * @retval -EINVAL if invalid function parameters were given
     737             :  * @retval -ENOSYS if PWM capture is not supported
     738             :  * @retval -EIO if IO error occurred while enabling PWM capture
     739             :  * @retval -EBUSY if PWM capture is already in progress
     740             :  */
     741           1 : __syscall int pwm_enable_capture(const struct device *dev, uint32_t channel);
     742             : 
     743             : #ifdef CONFIG_PWM_CAPTURE
     744             : static inline int z_impl_pwm_enable_capture(const struct device *dev,
     745             :                                             uint32_t channel)
     746             : {
     747             :         const struct pwm_driver_api *api =
     748             :                 (const struct pwm_driver_api *)dev->api;
     749             : 
     750             :         if (api->enable_capture == NULL) {
     751             :                 return -ENOSYS;
     752             :         }
     753             : 
     754             :         return api->enable_capture(dev, channel);
     755             : }
     756             : #endif /* CONFIG_PWM_CAPTURE */
     757             : 
     758             : /**
     759             :  * @brief Disable PWM period/pulse width capture for a single PWM input.
     760             :  *
     761             :  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
     762             :  * available.
     763             :  *
     764             :  * @param[in] dev PWM device instance.
     765             :  * @param channel PWM channel.
     766             :  *
     767             :  * @retval 0 If successful.
     768             :  * @retval -EINVAL if invalid function parameters were given
     769             :  * @retval -ENOSYS if PWM capture is not supported
     770             :  * @retval -EIO if IO error occurred while disabling PWM capture
     771             :  */
     772           1 : __syscall int pwm_disable_capture(const struct device *dev, uint32_t channel);
     773             : 
     774             : #ifdef CONFIG_PWM_CAPTURE
     775             : static inline int z_impl_pwm_disable_capture(const struct device *dev,
     776             :                                              uint32_t channel)
     777             : {
     778             :         const struct pwm_driver_api *api =
     779             :                 (const struct pwm_driver_api *)dev->api;
     780             : 
     781             :         if (api->disable_capture == NULL) {
     782             :                 return -ENOSYS;
     783             :         }
     784             : 
     785             :         return api->disable_capture(dev, channel);
     786             : }
     787             : #endif /* CONFIG_PWM_CAPTURE */
     788             : 
     789             : /**
     790             :  * @brief Capture a single PWM period/pulse width in clock cycles for a single
     791             :  *        PWM input.
     792             :  *
     793             :  * This API function wraps calls to pwm_configure_capture(),
     794             :  * pwm_enable_capture(), and pwm_disable_capture() and passes
     795             :  * the capture result to the caller. The function is blocking until either the
     796             :  * PWM capture is completed or a timeout occurs.
     797             :  *
     798             :  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
     799             :  * available.
     800             :  *
     801             :  * @param[in] dev PWM device instance.
     802             :  * @param channel PWM channel.
     803             :  * @param flags PWM capture flags.
     804             :  * @param[out] period Pointer to the memory to store the captured PWM period
     805             :  *                    width (in clock cycles). HW specific.
     806             :  * @param[out] pulse Pointer to the memory to store the captured PWM pulse width
     807             :  *                   (in clock cycles). HW specific.
     808             :  * @param timeout Waiting period for the capture to complete.
     809             :  *
     810             :  * @retval 0 If successful.
     811             :  * @retval -EBUSY PWM capture already in progress.
     812             :  * @retval -EAGAIN Waiting period timed out.
     813             :  * @retval -EIO IO error while capturing.
     814             :  * @retval -ERANGE If result is too large.
     815             :  */
     816           1 : __syscall int pwm_capture_cycles(const struct device *dev, uint32_t channel,
     817             :                                  pwm_flags_t flags, uint32_t *period,
     818             :                                  uint32_t *pulse, k_timeout_t timeout);
     819             : 
     820             : /**
     821             :  * @brief Capture a single PWM period/pulse width in microseconds for a single
     822             :  *        PWM input.
     823             :  *
     824             :  * This API function wraps calls to pwm_capture_cycles() and
     825             :  * pwm_cycles_to_usec() and passes the capture result to the caller. The
     826             :  * function is blocking until either the PWM capture is completed or a timeout
     827             :  * occurs.
     828             :  *
     829             :  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
     830             :  * available.
     831             :  *
     832             :  * @param[in] dev PWM device instance.
     833             :  * @param channel PWM channel.
     834             :  * @param flags PWM capture flags.
     835             :  * @param[out] period Pointer to the memory to store the captured PWM period
     836             :  *                    width (in usec).
     837             :  * @param[out] pulse Pointer to the memory to store the captured PWM pulse width
     838             :  *                   (in usec).
     839             :  * @param timeout Waiting period for the capture to complete.
     840             :  *
     841             :  * @retval 0 If successful.
     842             :  * @retval -EBUSY PWM capture already in progress.
     843             :  * @retval -EAGAIN Waiting period timed out.
     844             :  * @retval -EIO IO error while capturing.
     845             :  * @retval -ERANGE If result is too large.
     846             :  * @retval -errno Other negative errno code on failure.
     847             :  */
     848           1 : static inline int pwm_capture_usec(const struct device *dev, uint32_t channel,
     849             :                                    pwm_flags_t flags, uint64_t *period,
     850             :                                    uint64_t *pulse, k_timeout_t timeout)
     851             : {
     852             :         int err;
     853             :         uint32_t pulse_cycles;
     854             :         uint32_t period_cycles;
     855             : 
     856             :         err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
     857             :                                  &pulse_cycles, timeout);
     858             :         if (err < 0) {
     859             :                 return err;
     860             :         }
     861             : 
     862             :         err = pwm_cycles_to_usec(dev, channel, period_cycles, period);
     863             :         if (err < 0) {
     864             :                 return err;
     865             :         }
     866             : 
     867             :         err = pwm_cycles_to_usec(dev, channel, pulse_cycles, pulse);
     868             :         if (err < 0) {
     869             :                 return err;
     870             :         }
     871             : 
     872             :         return 0;
     873             : }
     874             : 
     875             : /**
     876             :  * @brief Capture a single PWM period/pulse width in nanoseconds for a single
     877             :  *        PWM input.
     878             :  *
     879             :  * This API function wraps calls to pwm_capture_cycles() and
     880             :  * pwm_cycles_to_nsec() and passes the capture result to the caller. The
     881             :  * function is blocking until either the PWM capture is completed or a timeout
     882             :  * occurs.
     883             :  *
     884             :  * @note @kconfig{CONFIG_PWM_CAPTURE} must be selected for this function to be
     885             :  * available.
     886             :  *
     887             :  * @param[in] dev PWM device instance.
     888             :  * @param channel PWM channel.
     889             :  * @param flags PWM capture flags.
     890             :  * @param[out] period Pointer to the memory to store the captured PWM period
     891             :  *                    width (in nsec).
     892             :  * @param[out] pulse Pointer to the memory to store the captured PWM pulse width
     893             :  *                   (in nsec).
     894             :  * @param timeout Waiting period for the capture to complete.
     895             :  *
     896             :  * @retval 0 If successful.
     897             :  * @retval -EBUSY PWM capture already in progress.
     898             :  * @retval -EAGAIN Waiting period timed out.
     899             :  * @retval -EIO IO error while capturing.
     900             :  * @retval -ERANGE If result is too large.
     901             :  * @retval -errno Other negative errno code on failure.
     902             :  */
     903           1 : static inline int pwm_capture_nsec(const struct device *dev, uint32_t channel,
     904             :                                    pwm_flags_t flags, uint64_t *period,
     905             :                                    uint64_t *pulse, k_timeout_t timeout)
     906             : {
     907             :         int err;
     908             :         uint32_t pulse_cycles;
     909             :         uint32_t period_cycles;
     910             : 
     911             :         err = pwm_capture_cycles(dev, channel, flags, &period_cycles,
     912             :                                  &pulse_cycles, timeout);
     913             :         if (err < 0) {
     914             :                 return err;
     915             :         }
     916             : 
     917             :         err = pwm_cycles_to_nsec(dev, channel, period_cycles, period);
     918             :         if (err < 0) {
     919             :                 return err;
     920             :         }
     921             : 
     922             :         err = pwm_cycles_to_nsec(dev, channel, pulse_cycles, pulse);
     923             :         if (err < 0) {
     924             :                 return err;
     925             :         }
     926             : 
     927             :         return 0;
     928             : }
     929             : 
     930             : /**
     931             :  * @brief Validate that the PWM device is ready.
     932             :  *
     933             :  * @param spec PWM specification from devicetree
     934             :  *
     935             :  * @retval true If the PWM device is ready for use
     936             :  * @retval false If the PWM device is not ready for use
     937             :  */
     938           1 : static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec)
     939             : {
     940             :         return device_is_ready(spec->dev);
     941             : }
     942             : 
     943             : #ifdef __cplusplus
     944             : }
     945             : #endif
     946             : 
     947             : /**
     948             :  * @}
     949             :  */
     950             : 
     951             : #include <zephyr/syscalls/pwm.h>
     952             : 
     953             : #endif /* ZEPHYR_INCLUDE_DRIVERS_PWM_H_ */

Generated by: LCOV version 1.14