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-05 20:47:19

            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              :         /** Event var to listen to the sync request events */
     226            1 :         struct k_event event;
     227              : #if defined(CONFIG_PM_DEVICE_RUNTIME_ASYNC) || defined(__DOXYGEN__)
     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
     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              : #else
     261              : #define Z_PM_DEVICE_RUNTIME_INIT(obj)
     262              : #endif /* CONFIG_PM_DEVICE_RUNTIME */
     263              : 
     264              : #ifdef CONFIG_PM_DEVICE_POWER_DOMAIN
     265              : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(_node_id)                 \
     266              :         .domain = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(_node_id,    \
     267              :                                    power_domains)),
     268              : #else
     269              : #define Z_PM_DEVICE_POWER_DOMAIN_INIT(obj)
     270              : #endif /* CONFIG_PM_DEVICE_POWER_DOMAIN */
     271              : 
     272              : /**
     273              :  * @brief Utility macro to initialize #pm_device_base flags
     274              :  *
     275              :  * @param node_id Devicetree node for the initialized device (can be invalid).
     276              :  */
     277              : #define Z_PM_DEVICE_FLAGS(node_id)                                       \
     278              :         (COND_CODE_1(                                                    \
     279              :                  DT_NODE_EXISTS(node_id),                                \
     280              :                  ((DT_PROP_OR(node_id, wakeup_source, 0)                 \
     281              :                          << PM_DEVICE_FLAG_WS_CAPABLE) |           \
     282              :                   (DT_PROP_OR(node_id, zephyr_pm_device_runtime_auto, 0) \
     283              :                          << PM_DEVICE_FLAG_RUNTIME_AUTO) |                 \
     284              :                   (DT_NODE_HAS_COMPAT(node_id, power_domain) <<            \
     285              :                          PM_DEVICE_FLAG_PD)),                            \
     286              :                  (0)))
     287              : 
     288              : /**
     289              :  * @brief Utility macro to initialize #pm_device.
     290              :  *
     291              :  * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
     292              :  * it may not be defined on all devices.
     293              :  *
     294              :  * @param obj Name of the #pm_device_base structure being initialized.
     295              :  * @param node_id Devicetree node for the initialized device (can be invalid).
     296              :  * @param pm_action_cb Device PM control callback function.
     297              :  * @param _flags Additional flags passed to the structure.
     298              :  */
     299              : #define Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb, _flags)            \
     300              :         {                                                                    \
     301              :                 .flags = ATOMIC_INIT(Z_PM_DEVICE_FLAGS(node_id) | (_flags)), \
     302              :                 .state = PM_DEVICE_STATE_ACTIVE,                             \
     303              :                 .action_cb = pm_action_cb,                                   \
     304              :                 Z_PM_DEVICE_POWER_DOMAIN_INIT(node_id)                       \
     305              :         }
     306              : 
     307              : /**
     308              :  * @brief Utility macro to initialize #pm_device_rt.
     309              :  *
     310              :  * @note #DT_PROP_OR is used to retrieve the wakeup_source property because
     311              :  * it may not be defined on all devices.
     312              :  *
     313              :  * @param obj Name of the #pm_device_base structure being initialized.
     314              :  * @param node_id Devicetree node for the initialized device (can be invalid).
     315              :  * @param pm_action_cb Device PM control callback function.
     316              :  */
     317              : #define Z_PM_DEVICE_INIT(obj, node_id, pm_action_cb, isr_safe)                  \
     318              :         {                                                                       \
     319              :                 .base = Z_PM_DEVICE_BASE_INIT(obj, node_id, pm_action_cb,       \
     320              :                                 isr_safe ? BIT(PM_DEVICE_FLAG_ISR_SAFE) : 0),   \
     321              :                 COND_CODE_1(isr_safe, (), (Z_PM_DEVICE_RUNTIME_INIT(obj)))      \
     322              :         }
     323              : 
     324              : /**
     325              :  * Get the name of device PM resources.
     326              :  *
     327              :  * @param dev_id Device id.
     328              :  */
     329              : #define Z_PM_DEVICE_NAME(dev_id) _CONCAT(__pm_device_, dev_id)
     330              : 
     331              : #ifdef CONFIG_PM
     332              : /**
     333              :  * @brief Define device PM slot.
     334              :  *
     335              :  * This macro defines a pointer to a device in the pm_device_slots region.
     336              :  * When invoked for each device with PM, it will effectively result in a device
     337              :  * pointer array with the same size of the actual devices with PM enabled. This
     338              :  * is used internally by the PM subsystem to keep track of suspended devices
     339              :  * during system power transitions.
     340              :  *
     341              :  * @param dev_id Device id.
     342              :  */
     343              : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id)                                 \
     344              :         static STRUCT_SECTION_ITERABLE_ALTERNATE(pm_device_slots, device, \
     345              :                         _CONCAT(__pm_slot_, dev_id))
     346              : #else
     347              : #define Z_PM_DEVICE_DEFINE_SLOT(dev_id)
     348              : #endif /* CONFIG_PM */
     349              : 
     350              : #ifdef CONFIG_PM_DEVICE
     351              : /**
     352              :  * Define device PM resources for the given node identifier.
     353              :  *
     354              :  * @param node_id Node identifier (DT_INVALID_NODE if not a DT device).
     355              :  * @param dev_id Device id.
     356              :  * @param pm_action_cb PM control callback.
     357              :  */
     358              : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)             \
     359              :         Z_PM_DEVICE_DEFINE_SLOT(dev_id);                                        \
     360              :         static struct COND_CODE_1(isr_safe, (pm_device_isr), (pm_device))       \
     361              :                 Z_PM_DEVICE_NAME(dev_id) =                                      \
     362              :                 Z_PM_DEVICE_INIT(Z_PM_DEVICE_NAME(dev_id), node_id,             \
     363              :                                  pm_action_cb, isr_safe)
     364              : 
     365              : /**
     366              :  * Get a reference to the device PM resources.
     367              :  *
     368              :  * @param dev_id Device id.
     369              :  */
     370              : #define Z_PM_DEVICE_GET(dev_id) ((struct pm_device_base *)&Z_PM_DEVICE_NAME(dev_id))
     371              : 
     372              : #else
     373              : #define Z_PM_DEVICE_DEFINE(node_id, dev_id, pm_action_cb, isr_safe)
     374              : #define Z_PM_DEVICE_GET(dev_id) NULL
     375              : #endif /* CONFIG_PM_DEVICE */
     376              : 
     377              : /** @endcond */
     378              : 
     379              : /**
     380              :  * Define device PM resources for the given device name.
     381              :  *
     382              :  * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
     383              :  *
     384              :  * @param dev_id Device id.
     385              :  * @param pm_action_cb PM control callback.
     386              :  * @param ... Optional flag to indicate that ISR safe. Use @ref PM_DEVICE_ISR_SAFE or 0.
     387              :  *
     388              :  * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DT_INST_DEFINE
     389              :  */
     390            1 : #define PM_DEVICE_DEFINE(dev_id, pm_action_cb, ...)                     \
     391              :         Z_PM_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, pm_action_cb,       \
     392              :                         COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
     393              : 
     394              : /**
     395              :  * Define device PM resources for the given node identifier.
     396              :  *
     397              :  * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
     398              :  *
     399              :  * @param node_id Node identifier.
     400              :  * @param pm_action_cb PM control callback.
     401              :  * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
     402              :  *
     403              :  * @see #PM_DEVICE_DT_INST_DEFINE, #PM_DEVICE_DEFINE
     404              :  */
     405            1 : #define PM_DEVICE_DT_DEFINE(node_id, pm_action_cb, ...) \
     406              :         Z_PM_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), pm_action_cb, \
     407              :                         COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
     408              : 
     409              : /**
     410              :  * Define device PM resources for the given instance.
     411              :  *
     412              :  * @note This macro is a no-op if @kconfig{CONFIG_PM_DEVICE} is not enabled.
     413              :  *
     414              :  * @param idx Instance index.
     415              :  * @param pm_action_cb PM control callback.
     416              :  * @param ... Optional flag to indicate that device is isr_ok. Use @ref PM_DEVICE_ISR_SAFE or 0.
     417              :  *
     418              :  * @see #PM_DEVICE_DT_DEFINE, #PM_DEVICE_DEFINE
     419              :  */
     420            1 : #define PM_DEVICE_DT_INST_DEFINE(idx, pm_action_cb, ...)                \
     421              :         Z_PM_DEVICE_DEFINE(DT_DRV_INST(idx),                            \
     422              :                            Z_DEVICE_DT_DEV_ID(DT_DRV_INST(idx)),        \
     423              :                            pm_action_cb,                                \
     424              :                            COND_CODE_1(IS_EMPTY(__VA_ARGS__), (0), (__VA_ARGS__)))
     425              : 
     426              : /**
     427              :  * @brief Obtain a reference to the device PM resources for the given device.
     428              :  *
     429              :  * @param dev_id Device id.
     430              :  *
     431              :  * @return Reference to the device PM resources (NULL if device
     432              :  * @kconfig{CONFIG_PM_DEVICE} is disabled).
     433              :  */
     434            1 : #define PM_DEVICE_GET(dev_id) \
     435              :         Z_PM_DEVICE_GET(dev_id)
     436              : 
     437              : /**
     438              :  * @brief Obtain a reference to the device PM resources for the given node.
     439              :  *
     440              :  * @param node_id Node identifier.
     441              :  *
     442              :  * @return Reference to the device PM resources (NULL if device
     443              :  * @kconfig{CONFIG_PM_DEVICE} is disabled).
     444              :  */
     445            1 : #define PM_DEVICE_DT_GET(node_id) \
     446              :         PM_DEVICE_GET(Z_DEVICE_DT_DEV_ID(node_id))
     447              : 
     448              : /**
     449              :  * @brief Obtain a reference to the device PM resources for the given instance.
     450              :  *
     451              :  * @param idx Instance index.
     452              :  *
     453              :  * @return Reference to the device PM resources (NULL if device
     454              :  * @kconfig{CONFIG_PM_DEVICE} is disabled).
     455              :  */
     456            1 : #define PM_DEVICE_DT_INST_GET(idx) \
     457              :         PM_DEVICE_DT_GET(DT_DRV_INST(idx))
     458              : 
     459              : /**
     460              :  * @brief Get name of device PM state
     461              :  *
     462              :  * @param state State id which name should be returned
     463              :  */
     464            1 : const char *pm_device_state_str(enum pm_device_state state);
     465              : 
     466              : /**
     467              :  * @brief Run a pm action on a device.
     468              :  *
     469              :  * This function calls the device PM control callback so that the device does
     470              :  * the necessary operations to execute the given action.
     471              :  *
     472              :  * @param dev Device instance.
     473              :  * @param action Device pm action.
     474              :  *
     475              :  * @retval 0 If successful.
     476              :  * @retval -ENOTSUP If requested state is not supported.
     477              :  * @retval -EALREADY If device is already at the requested state.
     478              :  * @retval -EBUSY If device is changing its state.
     479              :  * @retval -ENOSYS If device does not support PM.
     480              :  * @retval -EPERM If device has power state locked.
     481              :  * @retval Errno Other negative errno on failure.
     482              :  */
     483            1 : int pm_device_action_run(const struct device *dev,
     484              :                 enum pm_device_action action);
     485              : 
     486              : /**
     487              :  * @brief Run a pm action on all children of a device.
     488              :  *
     489              :  * This function calls all child devices PM control callback so that the device
     490              :  * does the necessary operations to execute the given action.
     491              :  *
     492              :  * @param dev Device instance.
     493              :  * @param action Device pm action.
     494              :  * @param failure_cb Function to call if a child fails the action, can be NULL.
     495              :  */
     496            1 : void pm_device_children_action_run(const struct device *dev,
     497              :                 enum pm_device_action action,
     498              :                 pm_device_action_failed_cb_t failure_cb);
     499              : 
     500              : #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__)
     501              : /**
     502              :  * @brief Obtain the power state of a device.
     503              :  *
     504              :  * @param dev Device instance.
     505              :  * @param state Pointer where device power state will be stored.
     506              :  *
     507              :  * @retval 0 If successful.
     508              :  * @retval -ENOSYS If device does not implement power management.
     509              :  */
     510            1 : int pm_device_state_get(const struct device *dev,
     511              :                         enum pm_device_state *state);
     512              : 
     513              : /**
     514              :  * @brief Initialize a device state to #PM_DEVICE_STATE_SUSPENDED.
     515              :  *
     516              :  * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. However
     517              :  * in order to save power some drivers may choose to only initialize the device
     518              :  * to the suspended state, or actively put the device into the suspended state.
     519              :  * This function can therefore be used to notify the PM subsystem that the
     520              :  * device is in #PM_DEVICE_STATE_SUSPENDED instead of the default.
     521              :  *
     522              :  * @param dev Device instance.
     523              :  */
     524            1 : static inline void pm_device_init_suspended(const struct device *dev)
     525              : {
     526              :         struct pm_device_base *pm = dev->pm_base;
     527              : 
     528              :         pm->state = PM_DEVICE_STATE_SUSPENDED;
     529              : }
     530              : 
     531              : /**
     532              :  * @brief Initialize a device state to #PM_DEVICE_STATE_OFF.
     533              :  *
     534              :  * By default device state is initialized to #PM_DEVICE_STATE_ACTIVE. In
     535              :  * general, this makes sense because the device initialization function will
     536              :  * resume and configure a device, leaving it operational. However, when power
     537              :  * domains are enabled, the device may be connected to a switchable power
     538              :  * source, in which case it won't be powered at boot. This function can
     539              :  * therefore be used to notify the PM subsystem that the device is in
     540              :  * #PM_DEVICE_STATE_OFF instead of the default.
     541              :  *
     542              :  * @param dev Device instance.
     543              :  */
     544            1 : static inline void pm_device_init_off(const struct device *dev)
     545              : {
     546              :         struct pm_device_base *pm = dev->pm_base;
     547              : 
     548              :         pm->state = PM_DEVICE_STATE_OFF;
     549              : }
     550              : 
     551              : /**
     552              :  * @brief Mark a device as busy.
     553              :  *
     554              :  * Devices marked as busy will not be suspended when the system goes into
     555              :  * low-power states. This can be useful if, for example, the device is in the
     556              :  * middle of a transaction.
     557              :  *
     558              :  * @param dev Device instance.
     559              :  *
     560              :  * @see pm_device_busy_clear()
     561              :  */
     562            1 : void pm_device_busy_set(const struct device *dev);
     563              : 
     564              : /**
     565              :  * @brief Clear a device busy status.
     566              :  *
     567              :  * @param dev Device instance.
     568              :  *
     569              :  * @see pm_device_busy_set()
     570              :  */
     571            1 : void pm_device_busy_clear(const struct device *dev);
     572              : 
     573              : /**
     574              :  * @brief Check if any device is busy.
     575              :  *
     576              :  * @retval false If no device is busy
     577              :  * @retval true If one or more devices are busy
     578              :  */
     579            1 : bool pm_device_is_any_busy(void);
     580              : 
     581              : /**
     582              :  * @brief Check if a device is busy.
     583              :  *
     584              :  * @param dev Device instance.
     585              :  *
     586              :  * @retval false If the device is not busy
     587              :  * @retval true If the device is busy
     588              :  */
     589            1 : bool pm_device_is_busy(const struct device *dev);
     590              : 
     591              : /**
     592              :  * @brief Enable or disable a device as a wake up source.
     593              :  *
     594              :  * A device marked as a wake up source will not be suspended when the system
     595              :  * goes into low-power modes, thus allowing to use it as a wake up source for
     596              :  * the system.
     597              :  *
     598              :  * @param dev Device instance.
     599              :  * @param enable @c true to enable or @c false to disable
     600              :  *
     601              :  * @retval true If the wakeup source was successfully enabled.
     602              :  * @retval false If the wakeup source was not successfully enabled.
     603              :  */
     604            1 : bool pm_device_wakeup_enable(const struct device *dev, bool enable);
     605              : 
     606              : /**
     607              :  * @brief Check if a device is enabled as a wake up source.
     608              :  *
     609              :  * @param dev Device instance.
     610              :  *
     611              :  * @retval true if the wakeup source is enabled.
     612              :  * @retval false if the wakeup source is not enabled.
     613              :  */
     614            1 : bool pm_device_wakeup_is_enabled(const struct device *dev);
     615              : 
     616              : /**
     617              :  * @brief Check if a device is wake up capable
     618              :  *
     619              :  * @param dev Device instance.
     620              :  *
     621              :  * @retval true If the device is wake up capable.
     622              :  * @retval false If the device is not wake up capable.
     623              :  */
     624            1 : bool pm_device_wakeup_is_capable(const struct device *dev);
     625              : 
     626              : /**
     627              :  * @brief Check if the device is on a switchable power domain.
     628              :  *
     629              :  * @param dev Device instance.
     630              :  *
     631              :  * @retval true If device is on a switchable power domain.
     632              :  * @retval false If device is not on a switchable power domain.
     633              :  */
     634            1 : bool pm_device_on_power_domain(const struct device *dev);
     635              : 
     636              : /**
     637              :  * @brief Add a device to a power domain.
     638              :  *
     639              :  * This function adds a device to a given power domain.
     640              :  *
     641              :  * @param dev Device to be added to the power domain.
     642              :  * @param domain Power domain.
     643              :  *
     644              :  * @retval 0 If successful.
     645              :  * @retval -EALREADY If device is already part of the power domain.
     646              :  * @retval -ENOSYS If the application was built without power domain support.
     647              :  * @retval -ENOSPC If there is no space available in the power domain to add the device.
     648              :  */
     649            1 : int pm_device_power_domain_add(const struct device *dev,
     650              :                                const struct device *domain);
     651              : 
     652              : /**
     653              :  * @brief Remove a device from a power domain.
     654              :  *
     655              :  * This function removes a device from a given power domain.
     656              :  *
     657              :  * @param dev Device to be removed from the power domain.
     658              :  * @param domain Power domain.
     659              :  *
     660              :  * @retval 0 If successful.
     661              :  * @retval -ENOSYS If the application was built without power domain support.
     662              :  * @retval -ENOENT If device is not in the given domain.
     663              :  */
     664            1 : int pm_device_power_domain_remove(const struct device *dev,
     665              :                                   const struct device *domain);
     666              : 
     667              : /**
     668              :  * @brief Check if the device is currently powered.
     669              :  *
     670              :  * @param dev Device instance.
     671              :  *
     672              :  * @retval true If device is currently powered, or is assumed to be powered
     673              :  * (i.e. it does not support PM or is not under a PM domain)
     674              :  * @retval false If device is not currently powered
     675              :  */
     676            1 : bool pm_device_is_powered(const struct device *dev);
     677              : 
     678              : /**
     679              :  * @brief Move a device driver into its initial device power state.
     680              :  *
     681              :  * @details This function uses the device driver's internal PM hook to
     682              :  * move the device from the OFF state to the initial power state expected
     683              :  * by the system.
     684              :  *
     685              :  * The initial power state expected by the system is:
     686              :  *
     687              :  * - ACTIVE if CONFIG_PM_DEVICE=n or (CONFIG_PM_DEVICE=y and
     688              :  *   CONFIG_PM_DEVICE_RUNTIME=n) or (CONFIG_PM_DEVICE_RUNTIME=y and
     689              :  *   !pm_device_runtime_is_enabled(dev)).
     690              :  * - SUSPENDED if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is ACTIVE.
     691              :  * - OFF if CONFIG_PM_DEVICE_RUNTIME=y and device's parent power domain is SUSPENDED.
     692              :  *
     693              :  * @note This function must be called at the end of a driver's init
     694              :  * function.
     695              :  *
     696              :  * @param dev Device instance.
     697              :  * @param action_cb Device PM control callback function.
     698              :  * @retval 0 On success.
     699              :  * @retval -errno Error code from @a action_cb on failure.
     700              :  */
     701            1 : int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb);
     702              : 
     703              : /**
     704              :  * @brief Prepare PM device for device driver deinit
     705              :  *
     706              :  * @details Ensures device is either SUSPENDED or OFF. If CONFIG_PM_DEVICE=y,
     707              :  * the function checks whether power management has moved the device to
     708              :  * either the SUSPENDED or OFF states. If CONFIG_PM_DEVICE=n, the function
     709              :  * uses the device driver's internal PM hook to move the device to the
     710              :  * SUSPENDED state.
     711              :  *
     712              :  * @note This function must be called at the beginning of a driver's deinit
     713              :  * function.
     714              :  *
     715              :  * @param dev Device instance.
     716              :  * @param action_cb Device PM control callback function.
     717              :  * @retval 0 if success.
     718              :  * @retval -EBUSY Device is not SUSPENDED nor OFF
     719              :  * @retval -errno code if failure.
     720              :  */
     721            1 : int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb);
     722              : #else
     723              : static inline int pm_device_state_get(const struct device *dev,
     724              :                                       enum pm_device_state *state)
     725              : {
     726              :         ARG_UNUSED(dev);
     727              : 
     728              :         *state = PM_DEVICE_STATE_ACTIVE;
     729              : 
     730              :         return 0;
     731              : }
     732              : 
     733              : static inline void pm_device_init_suspended(const struct device *dev)
     734              : {
     735              :         ARG_UNUSED(dev);
     736              : }
     737              : static inline void pm_device_init_off(const struct device *dev)
     738              : {
     739              :         ARG_UNUSED(dev);
     740              : }
     741              : static inline void pm_device_busy_set(const struct device *dev)
     742              : {
     743              :         ARG_UNUSED(dev);
     744              : }
     745              : static inline void pm_device_busy_clear(const struct device *dev)
     746              : {
     747              :         ARG_UNUSED(dev);
     748              : }
     749              : static inline bool pm_device_is_any_busy(void) { return false; }
     750              : static inline bool pm_device_is_busy(const struct device *dev)
     751              : {
     752              :         ARG_UNUSED(dev);
     753              :         return false;
     754              : }
     755              : static inline bool pm_device_wakeup_enable(const struct device *dev,
     756              :                                            bool enable)
     757              : {
     758              :         ARG_UNUSED(dev);
     759              :         ARG_UNUSED(enable);
     760              :         return false;
     761              : }
     762              : static inline bool pm_device_wakeup_is_enabled(const struct device *dev)
     763              : {
     764              :         ARG_UNUSED(dev);
     765              :         return false;
     766              : }
     767              : static inline bool pm_device_wakeup_is_capable(const struct device *dev)
     768              : {
     769              :         ARG_UNUSED(dev);
     770              :         return false;
     771              : }
     772              : static inline bool pm_device_on_power_domain(const struct device *dev)
     773              : {
     774              :         ARG_UNUSED(dev);
     775              :         return false;
     776              : }
     777              : 
     778              : static inline int pm_device_power_domain_add(const struct device *dev,
     779              :                                              const struct device *domain)
     780              : {
     781              :         ARG_UNUSED(dev);
     782              :         ARG_UNUSED(domain);
     783              :         return -ENOSYS;
     784              : }
     785              : 
     786              : static inline int pm_device_power_domain_remove(const struct device *dev,
     787              :                                                 const struct device *domain)
     788              : {
     789              :         ARG_UNUSED(dev);
     790              :         ARG_UNUSED(domain);
     791              :         return -ENOSYS;
     792              : }
     793              : 
     794              : static inline bool pm_device_is_powered(const struct device *dev)
     795              : {
     796              :         ARG_UNUSED(dev);
     797              :         return true;
     798              : }
     799              : 
     800              : static inline int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb)
     801              : {
     802              :         int rc;
     803              : 
     804              :         /* When power management is not enabled, all drivers should initialise to active state */
     805              :         rc = action_cb(dev, PM_DEVICE_ACTION_TURN_ON);
     806              :         if ((rc < 0) && (rc != -ENOTSUP)) {
     807              :                 return rc;
     808              :         }
     809              : 
     810              :         rc = action_cb(dev, PM_DEVICE_ACTION_RESUME);
     811              :         if (rc < 0) {
     812              :                 return rc;
     813              :         }
     814              : 
     815              :         return 0;
     816              : }
     817              : 
     818              : static inline int pm_device_driver_deinit(const struct device *dev, pm_device_action_cb_t action_cb)
     819              : {
     820              :         return action_cb(dev, PM_DEVICE_ACTION_SUSPEND);
     821              : }
     822              : 
     823              : #endif /* CONFIG_PM_DEVICE */
     824              : 
     825              : /** @} */
     826              : 
     827              : #ifdef __cplusplus
     828              : }
     829              : #endif
     830              : 
     831              : #endif
        

Generated by: LCOV version 2.0-1