LCOV - code coverage report
Current view: top level - zephyr/pm - device.h Coverage Total Hit
Test: new.info Lines: 97.8 % 45 44
Test Date: 2025-09-25 19:22:35

            Line data    Source code
       1            0 : /*
       2              :  * Copyright (c) 2015 Intel Corporation.
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : #ifndef ZEPHYR_INCLUDE_PM_DEVICE_H_
       8              : #define ZEPHYR_INCLUDE_PM_DEVICE_H_
       9              : 
      10              : #include <zephyr/device.h>
      11              : #include <zephyr/kernel.h>
      12              : #include <zephyr/sys/atomic.h>
      13              : #include <zephyr/sys/iterable_sections.h>
      14              : 
      15              : #ifdef __cplusplus
      16              : extern "C" {
      17              : #endif
      18              : 
      19              : /**
      20              :  * @brief Device Power Management API
      21              :  * @defgroup subsys_pm_device Device
      22              :  * @ingroup subsys_pm
      23              :  * @{
      24              :  */
      25              : 
      26              : /** @cond INTERNAL_HIDDEN */
      27              : 
      28              : struct device;
      29              : 
      30              : /** @brief Device PM flags. */
      31              : enum pm_device_flag {
      32              :         /** Indicate if the device is busy or not. */
      33              :         PM_DEVICE_FLAG_BUSY,
      34              :         /** Indicate if the device failed to power up. */
      35              :         PM_DEVICE_FLAG_TURN_ON_FAILED,
      36              :         /** Indicate if the device has claimed a power domain */
      37              :         PM_DEVICE_FLAG_PD_CLAIMED,
      38              :         /**
      39              :          * Indicates whether or not the device is capable of waking the system
      40              :          * up.
      41              :          */
      42              :         PM_DEVICE_FLAG_WS_CAPABLE,
      43              :         /** Indicates if the device is being used as wakeup source. */
      44              :         PM_DEVICE_FLAG_WS_ENABLED,
      45              :         /** Indicates if device runtime is enabled  */
      46              :         PM_DEVICE_FLAG_RUNTIME_ENABLED,
      47              :         /** Indicates if the device is used as a power domain */
      48              :         PM_DEVICE_FLAG_PD,
      49              :         /** Indicates if device runtime PM should be automatically enabled */
      50              :         PM_DEVICE_FLAG_RUNTIME_AUTO,
      51              :         /** Indicates that device runtime PM supports suspending and resuming from any context. */
      52              :         PM_DEVICE_FLAG_ISR_SAFE,
      53              : };
      54              : 
      55              : /** @endcond */
      56              : 
      57              : /** @brief Flag indicating that runtime PM API for the device can be called from any context.
      58              :  *
      59              :  * If @ref PM_DEVICE_ISR_SAFE flag is used for device definition, it indicates that PM actions
      60              :  * are synchronous and can be executed from any context. This approach can be used for cases where
      61              :  * suspending and resuming is short as it is executed in the critical section. This mode requires
      62              :  * less resources (~80 byte less RAM) and allows to use device runtime PM from any context
      63              :  * (including interrupts).
      64              :  */
      65            1 : #define PM_DEVICE_ISR_SAFE 1
      66              : 
      67              : /** @brief Device power states. */
      68            1 : enum pm_device_state {
      69              :         /**
      70              :          * @brief Device hardware is powered, and the device is needed by the system.
      71              :          *
      72              :          * @details The device should be enabled in this state. Any device driver API
      73              :          * may be called in this state.
      74              :          */
      75              :         PM_DEVICE_STATE_ACTIVE,
      76              :         /**
      77              :          * @brief Device hardware is powered, but the device is not needed by the
      78              :          * system.
      79              :          *
      80              :          * @details The device should be put into its lowest internal power state,
      81              :          * commonly named "disabled" or "stopped".
      82              :          *
      83              :          * If a device has been specified as this device's power domain, and said
      84              :          * device is no longer needed by the system, this device will be
      85              :          * transitioned into the @ref PM_DEVICE_STATE_OFF state, followed by the
      86              :          * power domain device being transitioned to the
      87              :          * @ref PM_DEVICE_STATE_SUSPENDED state.
      88              :          *
      89              :          * A device driver may be deinitialized in this state. Once the device
      90              :          * driver has been deinitialized, we implicitly move to the
      91              :          * @ref PM_DEVICE_STATE_OFF state as the device hardware may lose power,
      92              :          * with no device driver to respond to the corresponding
      93              :          * @ref PM_DEVICE_ACTION_TURN_OFF action.
      94              :          *
      95              :          * @note This state is NOT a "low-power"/"partially operable" state,
      96              :          * those are configured using device driver specific APIs, and apply only
      97              :          * while the device is in the @ref PM_DEVICE_STATE_ACTIVE state.
      98              :          */
      99              :         PM_DEVICE_STATE_SUSPENDED,
     100              :         /**
     101              :          * @brief Device hardware is powered, but the device has been scheduled to
     102              :          * be suspended, as it is no longer needed by the system.
     103              :          *
     104              :          * @details This state is used when delegating suspension of a device to
     105              :          * the PM subsystem, optionally with residency to avoid unnecessary
     106              :          * suspend/resume cycles, resulting from a call to
     107              :          * @ref pm_device_runtime_put_async. The device will be unscheduled in case
     108              :          * the device becomes needed by the system.
     109              :          *
     110              :          * No device driver API calls must occur in this state.
     111              :          *
     112              :          * @note that this state is opaque to the device driver (no
     113              :          * @ref pm_device_action is called as this state is entered) and is used
     114              :          * solely by PM_DEVICE_RUNTIME.
     115              :          */
     116              :         PM_DEVICE_STATE_SUSPENDING,
     117              :         /**
     118              :          * @brief Device hardware is not powered. This is the initial state from
     119              :          * which a device driver is initialized.
     120              :          *
     121              :          * @details When a device driver is initialized, we do not know the state
     122              :          * of the device. As a result, the @ref PM_DEVICE_ACTION_TURN_ON action
     123              :          * should be able to transition the device from any internal state into
     124              :          * @ref PM_DEVICE_STATE_SUSPENDED, since no guarantees can be made across
     125              :          * resets. This is typically achieved through toggling a reset pin or
     126              :          * triggering a software reset through a register write before performing
     127              :          * any additional configuration needed to meet the requirements of
     128              :          * @ref PM_DEVICE_STATE_SUSPENDED. For devices where this is not possible,
     129              :          * the device driver must presume the device is in either the
     130              :          * @ref PM_DEVICE_STATE_OFF or @ref PM_DEVICE_STATE_SUSPENDED state at
     131              :          * time of initialization, as these are the states within which device
     132              :          * drivers may be deinitialized.
     133              :          *
     134              :          * If a device has been specified as this device's power domain, and said
     135              :          * device becomes needed by the system, the power domain device will be
     136              :          * transitioned into the @ref PM_DEVICE_STATE_ACTIVE state, followed by this
     137              :          * device being transitioned to the
     138              :          * @ref PM_DEVICE_STATE_SUSPENDED state.
     139              :          */
     140              :         PM_DEVICE_STATE_OFF
     141              : };
     142              : 
     143              : /** @brief Device PM actions. */
     144            1 : enum pm_device_action {
     145              :         /** Suspend. */
     146              :         PM_DEVICE_ACTION_SUSPEND,
     147              :         /** Resume. */
     148              :         PM_DEVICE_ACTION_RESUME,
     149              :         /**
     150              :          * Turn off.
     151              :          * @note
     152              :          *     Action triggered only by a power domain.
     153              :          */
     154              :         PM_DEVICE_ACTION_TURN_OFF,
     155              :         /**
     156              :          * Turn on.
     157              :          * @note
     158              :          *     Action triggered only by a power domain.
     159              :          */
     160              :         PM_DEVICE_ACTION_TURN_ON,
     161              : };
     162              : 
     163              : /**
     164              :  * @brief Device PM action callback.
     165              :  *
     166              :  * @param dev Device instance.
     167              :  * @param action Requested action.
     168              :  *
     169              :  * @retval 0 If successful.
     170              :  * @retval -ENOTSUP If the requested action is not supported.
     171              :  * @retval Errno Other negative errno on failure.
     172              :  */
     173            1 : typedef int (*pm_device_action_cb_t)(const struct device *dev,
     174              :                                      enum pm_device_action action);
     175              : 
     176              : /**
     177              :  * @brief Device PM action failed callback
     178              :  *
     179              :  * @param dev Device that failed the action.
     180              :  * @param err Return code of action failure.
     181              :  *
     182              :  * @return True to continue iteration, false to halt iteration.
     183              :  */
     184            1 : typedef bool (*pm_device_action_failed_cb_t)(const struct device *dev,
     185              :                                          int err);
     186              : 
     187              : /**
     188              :  * @brief Device PM info
     189              :  *
     190              :  * Structure holds fields which are common for two PM devices: generic and
     191              :  * synchronous.
     192              :  */
     193            1 : struct pm_device_base {
     194              :         /** Device PM status flags. */
     195            1 :         atomic_t flags;
     196              :         /** Device power state */
     197            1 :         enum pm_device_state state;
     198              :         /** Device PM action callback */
     199            1 :         pm_device_action_cb_t action_cb;
     200              : #if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
     201              :         /** Device usage count */
     202            1 :         uint32_t usage;
     203              : #endif /* CONFIG_PM_DEVICE_RUNTIME */
     204              : #ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
     205              :         /** Power Domain it belongs */
     206              :         const struct device *domain;
     207              : #endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
     208              : };
     209              : 
     210              : /**
     211              :  * @brief Runtime PM info for device with generic PM.
     212              :  *
     213              :  * Generic PM involves suspending and resuming operations which can be blocking,
     214              :  * long lasting or asynchronous. Runtime PM API is limited when used from
     215              :  * interrupt context.
     216              :  */
     217            1 : struct pm_device {
     218              :         /** Base info. */
     219            1 :         struct pm_device_base base;
     220              : #if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
     221              :         /** Pointer to the device */
     222            1 :         const struct device *dev;
     223              :         /** Lock to synchronize the get/put operations */
     224            1 :         struct k_sem lock;
     225              : #if defined(CONFIG_PM_DEVICE_RUNTIME_ASYNC) || defined(__DOXYGEN__)
     226              :         /** Event var to listen to the sync request events */
     227            1 :         struct k_event event;
     228              :         /** Work object for asynchronous calls */
     229            1 :         struct k_work_delayable work;
     230              : #endif /* CONFIG_PM_DEVICE_RUNTIME_ASYNC */
     231              : #endif /* CONFIG_PM_DEVICE_RUNTIME */
     232              : };
     233              : 
     234              : /**
     235              :  * @brief Runtime PM info for device with synchronous PM.
     236              :  *
     237              :  * Synchronous PM can be used with devices which suspend and resume operations can
     238              :  * be performed in the critical section as they are short and non-blocking.
     239              :  * Runtime PM API can be used from any context in that case.
     240              :  */
     241            1 : struct pm_device_isr {
     242              :         /** Base info. */
     243            1 :         struct pm_device_base base;
     244              : #if defined(CONFIG_PM_DEVICE_RUNTIME) || defined(__DOXYGEN__)
     245              :         /** Lock to synchronize the synchronous get/put operations */
     246            1 :         struct k_spinlock lock;
     247              : #endif
     248              : };
     249              : 
     250              : /* Base part must be the first element. */
     251              : BUILD_ASSERT(offsetof(struct pm_device, base) == 0);
     252              : BUILD_ASSERT(offsetof(struct pm_device_isr, base) == 0);
     253              : 
     254              : /** @cond INTERNAL_HIDDEN */
     255              : 
     256              : #ifdef CONFIG_PM_DEVICE_RUNTIME_ASYNC
     257              : #define Z_PM_DEVICE_RUNTIME_INIT(obj)                   \
     258              :         .lock = Z_SEM_INITIALIZER(obj.lock, 1, 1),      \
     259              :         .event = Z_EVENT_INITIALIZER(obj.event),
     260              : #elif CONFIG_PM_DEVICE_RUNTIME
     261              : #define Z_PM_DEVICE_RUNTIME_INIT(obj)                   \
     262              :         .lock = Z_SEM_INITIALIZER(obj.lock, 1, 1),
     263              : #else
     264              : #define Z_PM_DEVICE_RUNTIME_INIT(obj)
     265              : #endif /* CONFIG_PM_DEVICE_RUNTIME */
     266              : 
     267              : #ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
     268              : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(_node_id)                 \
     269              :         .domain = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(_node_id,    \
     270              :                                    power_domains)),
     271              : #else
     272              : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(obj)
     273              : #endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
     274              : 
     275              : /**
     276              :  * @brief Utility macro to initialize #pm_device_base flags
     277              :  *
     278              :  * @param node_id Devicetree node for the initialized device (can be invalid).
     279              :  */
     280              : #define Z_PM_DEVICE_FLAGS(node_id)                                       \
     281              :         (COND_CODE_1(                                                    \
     282              :                  DT_NODE_EXISTS(node_id),                                \
     283              :                  ((DT_PROP_OR(node_id, wakeup_source, 0)                 \
     284              :                          << PM_DEVICE_FLAG_WS_CAPABLE) |           \
     285              :                   (DT_PROP_OR(node_id, zephyr_pm_device_runtime_auto, 0) \
     286              :                          << PM_DEVICE_FLAG_RUNTIME_AUTO) |                 \
     287              :                   (DT_NODE_HAS_COMPAT(node_id, power_domain) <<            \
     288              :                          PM_DEVICE_FLAG_PD)),                            \
     289              :                  (0)))
     290              : 
     291              : /**
     292              :  * @brief Utility macro to initialize #pm_device.
     293              :  *
     294              :  * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
     295              :  * it may not be defined on all devices.
     296              :  *
     297              :  * @param obj Name of the #pm_device_base structure being initialized.
     298              :  * @param node_id Devicetree node for the initialized device (can be invalid).
     299              :  * @param pm_action_cb Device PM control callback function.
     300              :  * @param _flags Additional flags passed to the structure.
     301              :  */
     302              : #define Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, _flags)            \
     303              :         {                                                                    \
     304              :                 .flags = ATOMIC_INIT(Z_PM_DEVICE_FLAGS(node_id) | (_flags)), \
     305              :                 .state = PM_DEVICE_STATE_ACTIVE,                             \
     306              :                 .action_cb = pm_action_cb,                                   \
     307              :                 Z_PM_DEVICE_POWER_DOMAIN_INIT(node_id)                       \
     308              :         }
     309              : 
     310              : /**
     311              :  * @brief Utility macro to initialize #pm_device_rt.
     312              :  *
     313              :  * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
     314              :  * it may not be defined on all devices.
     315              :  *
     316              :  * @param obj Name of the #pm_device_base structure being initialized.
     317              :  * @param node_id Devicetree node for the initialized device (can be invalid).
     318              :  * @param pm_action_cb Device PM control callback function.
     319              :  */
     320              : #define Z_PM_DEVICE_INIT(obj, node_id, pm_action_cb, isr_safe)                  \
     321              :         {                                                                       \
     322              :                 .base = Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb,       \
     323              :                                 isr_safe ? BIT(PM_DEVICE_FLAG_ISR_SAFE) : 0),   \
     324              :                 COND_CODE_1(isr_safe, (), (Z_PM_DEVICE_RUNTIME_INIT(obj)))      \
     325              :         }
     326              : 
     327              : /**
     328              :  * Get the name of device PM resources.
     329              :  *
     330              :  * @param dev_id Device id.
     331              :  */
     332              : #define Z_PM_DEVICE_NAME(dev_id) _CONCAT(__pm_device_, dev_id)
     333              : 
     334              : #ifdef CONFIG_PM
     335              : /**
     336              :  * @brief Define device PM slot.
     337              :  *
     338              :  * This macro defines a pointer to a device in the pm_device_slots region.
     339              :  * When invoked for each device with PM, it will effectively result in a device
     340              :  * pointer array with the same size of the actual devices with PM enabled. This
     341              :  * is used internally by the PM subsystem to keep track of suspended devices
     342              :  * during system power transitions.
     343              :  *
     344              :  * @param dev_id Device id.
     345              :  */
     346              : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id)                                 \
     347              :         static STRUCT_SECTION_ITERABLE_ALTERNATE(pm_device_slots, device, \
     348              :                         _CONCAT(__pm_slot_, dev_id))
     349              : #else
     350              : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id)
     351              : #endif /* CONFIG_PM */
     352              : 
     353              : #ifdef CONFIG_PM_DEVICE
     354              : /**
     355              :  * Define device PM resources for the given node identifier.
     356              :  *
     357              :  * @param node_id Node identifier (DT_INVALID_NODE if not a DT device).
     358              :  * @param dev_id Device id.
     359              :  * @param pm_action_cb PM control callback.
     360              :  */
     361              : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)             \
     362              :         Z_PM_DEVICE_DEFINE_SLOT(dev_id);                                        \
     363              :         static struct COND_CODE_1(isr_safe, (pm_device_isr), (pm_device))       \
     364              :                 Z_PM_DEVICE_NAME(dev_id) =                                      \
     365              :                 Z_PM_DEVICE_INIT(Z_PM_DEVICE_NAME(dev_id), node_id,             \
     366              :                                  pm_action_cb, isr_safe)
     367              : 
     368              : /**
     369              :  * Get a reference to the device PM resources.
     370              :  *
     371              :  * @param dev_id Device id.
     372              :  */
     373              : #define Z_PM_DEVICE_GET(dev_id) ((struct pm_device_base *)&Z_PM_DEVICE_NAME(dev_id))
     374              : 
     375              : #else
     376              : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)
     377              : #define Z_PM_DEVICE_GET(dev_id) NULL
     378              : #endif /* CONFIG_PM_DEVICE */
     379              : 
     380              : /** @endcond */
     381              : 
     382              : /**
     383              :  * Define device PM resources for the given device name.
     384              :  *
     385              :  * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
     386              :  *
     387              :  * @param dev_id Device id.
     388              :  * @param pm_action_cb PM control callback.
     389              :  * @param ... Optional flag to indicate that ISR safe. Use @ref PM_DEVICE_ISR_SAFE or 0.
     390              :  *
     391              :  * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DT_INST_DEFINE
     392              :  */
     393            1 : #define PM_DEVICE_DEFINE(dev_id, pm_action_cb, ...)                     \
     394              :         Z_PM_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, pm_action_cb,       \
     395              :                         COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
     396              : 
     397              : /**
     398              :  * Define device PM resources for the given node identifier.
     399              :  *
     400              :  * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
     401              :  *
     402              :  * @param node_id Node identifier.
     403              :  * @param pm_action_cb PM control callback.
     404              :  * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
     405              :  *
     406              :  * @see #PM_DEVICE_DT_INST_DEFINE, #PM_DEVICE_DEFINE
     407              :  */
     408            1 : #define PM_DEVICE_DT_DEFINE(node_id, pm_action_cb, ...) \
     409              :         Z_PM_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), pm_action_cb, \
     410              :                         COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
     411              : 
     412              : /**
     413              :  * Define device PM resources for the given instance.
     414              :  *
     415              :  * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
     416              :  *
     417              :  * @param idx Instance index.
     418              :  * @param pm_action_cb PM control callback.
     419              :  * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
     420              :  *
     421              :  * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DEFINE
     422              :  */
     423            1 : #define PM_DEVICE_DT_INST_DEFINE(idx, pm_action_cb, ...)                \
     424              :         Z_PM_DEVICE_DEFINE(DT_DRV_INST(idx),                            \
     425              :                            Z_DEVICE_DT_DEV_ID(DT_DRV_INST(idx)),        \
     426              :                            pm_action_cb,                                \
     427              :                            COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
     428              : 
     429              : /**
     430              :  * @brief Obtain a reference to the device PM resources for the given device.
     431              :  *
     432              :  * @param dev_id Device id.
     433              :  *
     434              :  * @return Reference to the device PM resources (NULL if device
     435              :  * @kconfig{CONFIG_PM_DEVICE} is disabled).
     436              :  */
     437            1 : #define PM_DEVICE_GET(dev_id) \
     438              :         Z_PM_DEVICE_GET(dev_id)
     439              : 
     440              : /**
     441              :  * @brief Obtain a reference to the device PM resources for the given node.
     442              :  *
     443              :  * @param node_id Node identifier.
     444              :  *
     445              :  * @return Reference to the device PM resources (NULL if device
     446              :  * @kconfig{CONFIG_PM_DEVICE} is disabled).
     447              :  */
     448            1 : #define PM_DEVICE_DT_GET(node_id) \
     449              :         PM_DEVICE_GET(Z_DEVICE_DT_DEV_ID(node_id))
     450              : 
     451              : /**
     452              :  * @brief Obtain a reference to the device PM resources for the given instance.
     453              :  *
     454              :  * @param idx Instance index.
     455              :  *
     456              :  * @return Reference to the device PM resources (NULL if device
     457              :  * @kconfig{CONFIG_PM_DEVICE} is disabled).
     458              :  */
     459            1 : #define PM_DEVICE_DT_INST_GET(idx) \
     460              :         PM_DEVICE_DT_GET(DT_DRV_INST(idx))
     461              : 
     462              : /**
     463              :  * @brief Get name of device PM state
     464              :  *
     465              :  * @param state State id which name should be returned
     466              :  */
     467            1 : const char *pm_device_state_str(enum pm_device_state state);
     468              : 
     469              : /**
     470              :  * @brief Run a pm action on a device.
     471              :  *
     472              :  * This function calls the device PM control callback so that the device does
     473              :  * the necessary operations to execute the given action.
     474              :  *
     475              :  * @param dev Device instance.
     476              :  * @param action Device pm action.
     477              :  *
     478              :  * @retval 0 If successful.
     479              :  * @retval -ENOTSUP If requested state is not supported.
     480              :  * @retval -EALREADY If device is already at the requested state.
     481              :  * @retval -EBUSY If device is changing its state.
     482              :  * @retval -ENOSYS If device does not support PM.
     483              :  * @retval -EPERM If device has power state locked.
     484              :  * @retval Errno Other negative errno on failure.
     485              :  */
     486            1 : int pm_device_action_run(const struct device *dev,
     487              :                 enum pm_device_action action);
     488              : 
     489              : /**
     490              :  * @brief Run a pm action on all children of a device.
     491              :  *
     492              :  * This function calls all child devices PM control callback so that the device
     493              :  * does the necessary operations to execute the given action.
     494              :  *
     495              :  * @param dev Device instance.
     496              :  * @param action Device pm action.
     497              :  * @param failure_cb Function to call if a child fails the action, can be NULL.
     498              :  */
     499            1 : void pm_device_children_action_run(const struct device *dev,
     500              :                 enum pm_device_action action,
     501              :                 pm_device_action_failed_cb_t failure_cb);
     502              : 
     503              : #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
     504              : /**
     505              :  * @brief Obtain the power state of a device.
     506              :  *
     507              :  * @param dev Device instance.
     508              :  * @param state Pointer where device power state will be stored.
     509              :  *
     510              :  * @retval 0 If successful.
     511              :  * @retval -ENOSYS If device does not implement power management.
     512              :  */
     513            1 : int pm_device_state_get(const struct device *dev,
     514              :                         enum pm_device_state *state);
     515              : 
     516              : /**
     517              :  * @brief Initialize a device state to #PM_DEVICE_STATE_SUSPENDED.
     518              :  *
     519              :  * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. However
     520              :  * in order to save power some drivers may choose to only initialize the device
     521              :  * to the suspended state, or actively put the device into the suspended state.
     522              :  * This function can therefore be used to notify the PM subsystem that the
     523              :  * device is in #PM_DEVICE_STATE_SUSPENDED instead of the default.
     524              :  *
     525              :  * @param dev Device instance.
     526              :  */
     527            1 : static inline void pm_device_init_suspended(const struct device *dev)
     528              : {
     529              :         struct pm_device_base *pm = dev->pm_base;
     530              : 
     531              :         pm->state = PM_DEVICE_STATE_SUSPENDED;
     532              : }
     533              : 
     534              : /**
     535              :  * @brief Initialize a device state to #PM_DEVICE_STATE_OFF.
     536              :  *
     537              :  * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. In
     538              :  * general, this makes sense because the device initialization function will
     539              :  * resume and configure a device, leaving it operational. However, when power
     540              :  * domains are enabled, the device may be connected to a switchable power
     541              :  * source, in which case it won't be powered at boot. This function can
     542              :  * therefore be used to notify the PM subsystem that the device is in
     543              :  * #PM_DEVICE_STATE_OFF instead of the default.
     544              :  *
     545              :  * @param dev Device instance.
     546              :  */
     547            1 : static inline void pm_device_init_off(const struct device *dev)
     548              : {
     549              :         struct pm_device_base *pm = dev->pm_base;
     550              : 
     551              :         pm->state = PM_DEVICE_STATE_OFF;
     552              : }
     553              : 
     554              : /**
     555              :  * @brief Mark a device as busy.
     556              :  *
     557              :  * Devices marked as busy will not be suspended when the system goes into
     558              :  * low-power states. This can be useful if, for example, the device is in the
     559              :  * middle of a transaction.
     560              :  *
     561              :  * @param dev Device instance.
     562              :  *
     563              :  * @see pm_device_busy_clear()
     564              :  */
     565            1 : void pm_device_busy_set(const struct device *dev);
     566              : 
     567              : /**
     568              :  * @brief Clear a device busy status.
     569              :  *
     570              :  * @param dev Device instance.
     571              :  *
     572              :  * @see pm_device_busy_set()
     573              :  */
     574            1 : void pm_device_busy_clear(const struct device *dev);
     575              : 
     576              : /**
     577              :  * @brief Check if any device is busy.
     578              :  *
     579              :  * @retval false If no device is busy
     580              :  * @retval true If one or more devices are busy
     581              :  */
     582            1 : bool pm_device_is_any_busy(void);
     583              : 
     584              : /**
     585              :  * @brief Check if a device is busy.
     586              :  *
     587              :  * @param dev Device instance.
     588              :  *
     589              :  * @retval false If the device is not busy
     590              :  * @retval true If the device is busy
     591              :  */
     592            1 : bool pm_device_is_busy(const struct device *dev);
     593              : 
     594              : /**
     595              :  * @brief Enable or disable a device as a wake up source.
     596              :  *
     597              :  * A device marked as a wake up source will not be suspended when the system
     598              :  * goes into low-power modes, thus allowing to use it as a wake up source for
     599              :  * the system.
     600              :  *
     601              :  * @param dev Device instance.
     602              :  * @param enable @c true to enable or @c false to disable
     603              :  *
     604              :  * @retval true If the wakeup source was successfully enabled.
     605              :  * @retval false If the wakeup source was not successfully enabled.
     606              :  */
     607            1 : bool pm_device_wakeup_enable(const struct device *dev, bool enable);
     608              : 
     609              : /**
     610              :  * @brief Check if a device is enabled as a wake up source.
     611              :  *
     612              :  * @param dev Device instance.
     613              :  *
     614              :  * @retval true if the wakeup source is enabled.
     615              :  * @retval false if the wakeup source is not enabled.
     616              :  */
     617            1 : bool pm_device_wakeup_is_enabled(const struct device *dev);
     618              : 
     619              : /**
     620              :  * @brief Check if a device is wake up capable
     621              :  *
     622              :  * @param dev Device instance.
     623              :  *
     624              :  * @retval true If the device is wake up capable.
     625              :  * @retval false If the device is not wake up capable.
     626              :  */
     627            1 : bool pm_device_wakeup_is_capable(const struct device *dev);
     628              : 
     629              : /**
     630              :  * @brief Check if the device is on a switchable power domain.
     631              :  *
     632              :  * @param dev Device instance.
     633              :  *
     634              :  * @retval true If device is on a switchable power domain.
     635              :  * @retval false If device is not on a switchable power domain.
     636              :  */
     637            1 : bool pm_device_on_power_domain(const struct device *dev);
     638              : 
     639              : /**
     640              :  * @brief Add a device to a power domain.
     641              :  *
     642              :  * This function adds a device to a given power domain.
     643              :  *
     644              :  * @param dev Device to be added to the power domain.
     645              :  * @param domain Power domain.
     646              :  *
     647              :  * @retval 0 If successful.
     648              :  * @retval -EALREADY If device is already part of the power domain.
     649              :  * @retval -ENOSYS If the application was built without power domain support.
     650              :  * @retval -ENOSPC If there is no space available in the power domain to add the device.
     651              :  */
     652            1 : int pm_device_power_domain_add(const struct device *dev,
     653              :                                const struct device *domain);
     654              : 
     655              : /**
     656              :  * @brief Remove a device from a power domain.
     657              :  *
     658              :  * This function removes a device from a given power domain.
     659              :  *
     660              :  * @param dev Device to be removed from the power domain.
     661              :  * @param domain Power domain.
     662              :  *
     663              :  * @retval 0 If successful.
     664              :  * @retval -ENOSYS If the application was built without power domain support.
     665              :  * @retval -ENOENT If device is not in the given domain.
     666              :  */
     667            1 : int pm_device_power_domain_remove(const struct device *dev,
     668              :                                   const struct device *domain);
     669              : 
     670              : /**
     671              :  * @brief Check if the device is currently powered.
     672              :  *
     673              :  * @param dev Device instance.
     674              :  *
     675              :  * @retval true If device is currently powered, or is assumed to be powered
     676              :  * (i.e. it does not support PM or is not under a PM domain)
     677              :  * @retval false If device is not currently powered
     678              :  */
     679            1 : bool pm_device_is_powered(const struct device *dev);
     680              : 
     681              : /**
     682              :  * @brief Move a device driver into its initial device power state.
     683              :  *
     684              :  * @details This function uses the device driver's internal PM hook to
     685              :  * move the device from the OFF state to the initial power state expected
     686              :  * by the system.
     687              :  *
     688              :  * The initial power state expected by the system is:
     689              :  *
     690              :  * - ACTIVE if CONFIG_PM_DEVICE=n or (CONFIG_PM_DEVICE=y and
     691              :  *   CONFIG_PM_DEVICE_RUNTIME=n) or (CONFIG_PM_DEVICE_RUNTIME=y and
     692              :  *   !pm_device_runtime_is_enabled(dev)).
     693              :  * - SUSPENDED if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is ACTIVE.
     694              :  * - OFF if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is SUSPENDED.
     695              :  *
     696              :  * @note This function must be called at the end of a driver's init
     697              :  * function.
     698              :  *
     699              :  * @param dev Device instance.
     700              :  * @param action_cb Device PM control callback function.
     701              :  * @retval 0 On success.
     702              :  * @retval -errno Error code from @a action_cb on failure.
     703              :  */
     704            1 : int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb);
     705              : 
     706              : /**
     707              :  * @brief Prepare PM device for device driver deinit
     708              :  *
     709              :  * @details Ensures device is either SUSPENDED or OFF. If CONFIG_PM_DEVICE=y,
     710              :  * the function checks whether power management has moved the device to
     711              :  * either the SUSPENDED or OFF states. If CONFIG_PM_DEVICE=n, the function
     712              :  * uses the device driver's internal PM hook to move the device to the
     713              :  * SUSPENDED state.
     714              :  *
     715              :  * @note This function must be called at the beginning of a driver's deinit
     716              :  * function.
     717              :  *
     718              :  * @param dev Device instance.
     719              :  * @param action_cb Device PM control callback function.
     720              :  * @retval 0 if success.
     721              :  * @retval -EBUSY Device is not SUSPENDED nor OFF
     722              :  * @retval -errno code if failure.
     723              :  */
     724            1 : int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb);
     725              : #else
     726              : static inline int pm_device_state_get(const struct device *dev,
     727              :                                       enum pm_device_state *state)
     728              : {
     729              :         ARG_UNUSED(dev);
     730              : 
     731              :         *state = PM_DEVICE_STATE_ACTIVE;
     732              : 
     733              :         return 0;
     734              : }
     735              : 
     736              : static inline void pm_device_init_suspended(const struct device *dev)
     737              : {
     738              :         ARG_UNUSED(dev);
     739              : }
     740              : static inline void pm_device_init_off(const struct device *dev)
     741              : {
     742              :         ARG_UNUSED(dev);
     743              : }
     744              : static inline void pm_device_busy_set(const struct device *dev)
     745              : {
     746              :         ARG_UNUSED(dev);
     747              : }
     748              : static inline void pm_device_busy_clear(const struct device *dev)
     749              : {
     750              :         ARG_UNUSED(dev);
     751              : }
     752              : static inline bool pm_device_is_any_busy(void) { return false; }
     753              : static inline bool pm_device_is_busy(const struct device *dev)
     754              : {
     755              :         ARG_UNUSED(dev);
     756              :         return false;
     757              : }
     758              : static inline bool pm_device_wakeup_enable(const struct device *dev,
     759              :                                            bool enable)
     760              : {
     761              :         ARG_UNUSED(dev);
     762              :         ARG_UNUSED(enable);
     763              :         return false;
     764              : }
     765              : static inline bool pm_device_wakeup_is_enabled(const struct device *dev)
     766              : {
     767              :         ARG_UNUSED(dev);
     768              :         return false;
     769              : }
     770              : static inline bool pm_device_wakeup_is_capable(const struct device *dev)
     771              : {
     772              :         ARG_UNUSED(dev);
     773              :         return false;
     774              : }
     775              : static inline bool pm_device_on_power_domain(const struct device *dev)
     776              : {
     777              :         ARG_UNUSED(dev);
     778              :         return false;
     779              : }
     780              : 
     781              : static inline int pm_device_power_domain_add(const struct device *dev,
     782              :                                              const struct device *domain)
     783              : {
     784              :         ARG_UNUSED(dev);
     785              :         ARG_UNUSED(domain);
     786              :         return -ENOSYS;
     787              : }
     788              : 
     789              : static inline int pm_device_power_domain_remove(const struct device *dev,
     790              :                                                 const struct device *domain)
     791              : {
     792              :         ARG_UNUSED(dev);
     793              :         ARG_UNUSED(domain);
     794              :         return -ENOSYS;
     795              : }
     796              : 
     797              : static inline bool pm_device_is_powered(const struct device *dev)
     798              : {
     799              :         ARG_UNUSED(dev);
     800              :         return true;
     801              : }
     802              : 
     803              : static inline int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb)
     804              : {
     805              :         int rc;
     806              : 
     807              :         /* When power management is not enabled, all drivers should initialise to active state */
     808              :         rc = action_cb(dev, PM_DEVICE_ACTION_TURN_ON);
     809              :         if ((rc < 0) && (rc != -ENOTSUP)) {
     810              :                 return rc;
     811              :         }
     812              : 
     813              :         rc = action_cb(dev, PM_DEVICE_ACTION_RESUME);
     814              :         if (rc < 0) {
     815              :                 return rc;
     816              :         }
     817              : 
     818              :         return 0;
     819              : }
     820              : 
     821              : static inline int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb)
     822              : {
     823              :         return action_cb(dev, PM_DEVICE_ACTION_SUSPEND);
     824              : }
     825              : 
     826              : #endif /* CONFIG_PM_DEVICE */
     827              : 
     828              : /** @} */
     829              : 
     830              : #ifdef __cplusplus
     831              : }
     832              : #endif
     833              : 
     834              : #endif
        

Generated by: LCOV version 2.0-1