| /* |
| * Copyright (c) 2015 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_DEVICE_H_ |
| #define ZEPHYR_INCLUDE_DEVICE_H_ |
| |
| /** |
| * @brief Device Driver APIs |
| * @defgroup io_interfaces Device Driver APIs |
| * @{ |
| * @} |
| */ |
| /** |
| * @brief Device Model APIs |
| * @defgroup device_model Device Model APIs |
| * @{ |
| */ |
| |
| #include <init.h> |
| #include <sys/device_mmio.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #define Z_DEVICE_MAX_NAME_LEN 48 |
| |
| /** |
| * @def DEVICE_NAME_GET |
| * |
| * @brief Expands to the full name of a global device object |
| * |
| * @details Return the full name of a device object symbol created by |
| * DEVICE_DEFINE(), using the dev_name provided to DEVICE_DEFINE(). |
| * |
| * It is meant to be used for declaring extern symbols pointing on device |
| * objects before using the DEVICE_GET macro to get the device object. |
| * |
| * @param name The same as dev_name provided to DEVICE_DEFINE() |
| * |
| * @return The expanded name of the device object created by DEVICE_DEFINE() |
| */ |
| #define DEVICE_NAME_GET(name) (_CONCAT(__device_, name)) |
| |
| /** |
| * @def SYS_DEVICE_DEFINE |
| * |
| * @brief Run an initialization function at boot at specified priority, |
| * and define device PM control function. |
| * |
| * @details Invokes DEVICE_DEFINE() with no power management support |
| * (@p pm_control_fn), no API (@p api_ptr), and a device name derived from |
| * the @p init_fn name (@p dev_name). |
| */ |
| #define SYS_DEVICE_DEFINE(drv_name, init_fn, pm_control_fn, level, prio) \ |
| DEVICE_DEFINE(Z_SYS_NAME(init_fn), drv_name, init_fn, \ |
| pm_control_fn, \ |
| NULL, NULL, level, prio, NULL) |
| |
| /** |
| * @def DEVICE_INIT |
| * |
| * @brief Invoke DEVICE_DEFINE() with no power management support (@p |
| * pm_control_fn) and no API (@p api_ptr). |
| */ |
| #define DEVICE_INIT(dev_name, drv_name, init_fn, \ |
| data_ptr, cfg_ptr, level, prio) \ |
| __DEPRECATED_MACRO \ |
| DEVICE_DEFINE(dev_name, drv_name, init_fn, NULL, \ |
| data_ptr, cfg_ptr, level, prio, NULL) |
| |
| /** |
| * @def DEVICE_AND_API_INIT |
| * |
| * @brief Invoke DEVICE_DEFINE() with no power management support (@p |
| * pm_control_fn). |
| */ |
| #define DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, \ |
| data_ptr, cfg_ptr, level, prio, api_ptr) \ |
| DEVICE_DEFINE(dev_name, drv_name, init_fn, \ |
| NULL, \ |
| data_ptr, cfg_ptr, level, prio, api_ptr) |
| |
| /** |
| * @def DEVICE_DEFINE |
| * |
| * @brief Create device object and set it up for boot time initialization, |
| * with the option to device_pm_control. In case of Device Idle Power |
| * Management is enabled, make sure the device is in suspended state after |
| * initialization. |
| * |
| * @details This macro defines a device object that is automatically |
| * configured by the kernel during system initialization. Note that |
| * devices set up with this macro will not be accessible from user mode |
| * since the API is not specified; whenever possible, use DEVICE_AND_API_INIT |
| * instead. |
| * |
| * @param dev_name Device name. This must be less than Z_DEVICE_MAX_NAME_LEN |
| * characters in order to be looked up from user mode with device_get_binding(). |
| * |
| * @param drv_name The name this instance of the driver exposes to |
| * the system. |
| * |
| * @param init_fn Address to the init function of the driver. |
| * |
| * @param pm_control_fn Pointer to device_pm_control function. |
| * Can be empty function (device_pm_control_nop) if not implemented. |
| * |
| * @param data_ptr Pointer to the device's private data. |
| * |
| * @param cfg_ptr The address to the structure containing the |
| * configuration information for this instance of the driver. |
| * |
| * @param level The initialization level. See SYS_INIT() for |
| * details. |
| * |
| * @param prio Priority within the selected initialization level. See |
| * SYS_INIT() for details. |
| * |
| * @param api_ptr Provides an initial pointer to the API function struct |
| * used by the driver. Can be NULL. |
| */ |
| #define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, \ |
| data_ptr, cfg_ptr, level, prio, api_ptr) \ |
| Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_name, drv_name, init_fn, \ |
| pm_control_fn, \ |
| data_ptr, cfg_ptr, level, prio, api_ptr) |
| |
| /** |
| * @def DEVICE_DT_DEFINE |
| * |
| * @brief Like DEVICE_DEFINE but taking metadata from a devicetree node. |
| * |
| * @details This macro defines a device object that is automatically |
| * configured by the kernel during system initialization. The device |
| * object name is derived from the node identifier (encoding the |
| * devicetree path to the node), and the driver name is from the @p |
| * label property of the devicetree node. |
| * |
| * The device is declared with extern visibility, so device objects |
| * defined through this API can be obtained directly through |
| * DEVICE_DT_GET() using @p node_id. Before using the pointer the |
| * referenced object should be checked using device_is_ready(). |
| * |
| * @param node_id The devicetree node identifier. |
| * |
| * @param init_fn Address to the init function of the driver. |
| * |
| * @param pm_control_fn Pointer to device_pm_control function. |
| * Can be empty function (device_pm_control_nop) if not implemented. |
| * |
| * @param data_ptr Pointer to the device's private data. |
| * |
| * @param cfg_ptr The address to the structure containing the |
| * configuration information for this instance of the driver. |
| * |
| * @param level The initialization level. See SYS_INIT() for |
| * details. |
| * |
| * @param prio Priority within the selected initialization level. See |
| * SYS_INIT() for details. |
| * |
| * @param api_ptr Provides an initial pointer to the API function struct |
| * used by the driver. Can be NULL. |
| */ |
| #define DEVICE_DT_DEFINE(node_id, init_fn, pm_control_fn, \ |
| data_ptr, cfg_ptr, level, prio, api_ptr) \ |
| Z_DEVICE_DEFINE(node_id, node_id, DT_LABEL(node_id), init_fn, \ |
| pm_control_fn, \ |
| data_ptr, cfg_ptr, level, prio, api_ptr) |
| |
| /** |
| * @def DEVICE_DT_NAME_GET |
| * |
| * @brief The name of the struct device object for @p node_id |
| * |
| * @details Return the full name of a device object symbol created by |
| * DEVICE_DT_DEFINE(), using the dev_name derived from @p node_id |
| * |
| * It is meant to be used for declaring extern symbols pointing on device |
| * objects before using the DEVICE_DT_GET macro to get the device object. |
| * |
| * @param node_id The same as node_id provided to DEVICE_DT_DEFINE() |
| * |
| * @return The expanded name of the device object created by |
| * DEVICE_DT_DEFINE() |
| */ |
| #define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(node_id) |
| |
| /** |
| * @def DEVICE_DT_GET |
| * |
| * @brief Obtain a pointer to a device object by @p node_id |
| * |
| * @details Return the address of a device object created by |
| * DEVICE_DT_INIT(), using the dev_name derived from @p node_id |
| * |
| * @note A declaration for the corresponding device must be in scope; |
| * e.g: |
| * |
| * @code DEVICE_DT_DECLARE(node_id); @endcode |
| * |
| * @param node_id The same as node_id provided to DEVICE_DT_DEFINE() |
| * |
| * @return A pointer to the device object created by DEVICE_DT_DEFINE() |
| */ |
| #define DEVICE_DT_GET(node_id) (&DEVICE_DT_NAME_GET(node_id)) |
| |
| /** @def DEVICE_DT_DECLARE |
| * |
| * @brief Declare a device object associated with @p node_id |
| * |
| * This macro can be used in source files to get a reference to the |
| * device structure corresponding to a devicetree node. |
| * |
| * Within driver implementation files it is used to declare a device so |
| * that DEVICE_DT_GET() may be used before the full declaration in |
| * DEVICE_DT_DEFINE(). |
| * |
| * This is often useful when configuring interrupts statically in a |
| * device's init or per-instance config function, as the init function |
| * itself is required by DEVICE_DT_DEFINE() and use of DEVICE_DT_GET() |
| * inside it creates a circular dependency. |
| * |
| * It can also be used in unrelated modules to store the pointer to a |
| * device without having to look it up at runtime through |
| * device_get_binding(). |
| * |
| * Note that the device declaration has no storage class specifiers. |
| * |
| * @param node_id The same as node_id provided to DEVICE_DT_DEFINE() |
| */ |
| #define DEVICE_DT_DECLARE(node_id) \ |
| extern const struct device DEVICE_DT_NAME_GET(node_id) |
| |
| /** |
| * @def DEVICE_GET |
| * |
| * @brief Obtain a pointer to a device object by name |
| * |
| * @details Return the address of a device object created by |
| * DEVICE_DEFINE(), using the dev_name provided to DEVICE_DEFINE(). |
| * |
| * @param name The same as dev_name provided to DEVICE_DEFINE() |
| * |
| * @return A pointer to the device object created by DEVICE_DEFINE() |
| */ |
| #define DEVICE_GET(name) (&DEVICE_NAME_GET(name)) |
| |
| /** @def DEVICE_DECLARE |
| * |
| * @brief Declare a static device object |
| * |
| * This macro can be used at the top-level to declare a device, such |
| * that DEVICE_GET() may be used before the full declaration in |
| * DEVICE_DEFINE(). |
| * |
| * This is often useful when configuring interrupts statically in a |
| * device's init or per-instance config function, as the init function |
| * itself is required by DEVICE_DEFINE() and use of DEVICE_GET() |
| * inside it creates a circular dependency. |
| * |
| * @param name Device name |
| */ |
| #define DEVICE_DECLARE(name) static const struct device DEVICE_NAME_GET(name) |
| |
| typedef void (*device_pm_cb)(const struct device *dev, |
| int status, void *context, void *arg); |
| |
| /** |
| * @brief Device PM info |
| */ |
| struct device_pm { |
| /** Pointer to the device */ |
| const struct device *dev; |
| /** Lock to synchronize the get/put operations */ |
| struct k_sem lock; |
| /** Device pm enable flag */ |
| bool enable; |
| /** Device usage count */ |
| atomic_t usage; |
| /** Device idle internal power state */ |
| atomic_t fsm_state; |
| /** Work object for asynchronous calls */ |
| struct k_work work; |
| /** Event object to listen to the sync request events */ |
| struct k_poll_event event; |
| /** Signal to notify the Async API callers */ |
| struct k_poll_signal signal; |
| }; |
| |
| /** |
| * @brief Runtime device structure (in memory) per driver instance |
| */ |
| struct device { |
| /** Name of the device instance */ |
| const char *name; |
| /** Address of device instance config information */ |
| const void *config; |
| /** Address of the API structure exposed by the device instance */ |
| const void *api; |
| /** Address of the device instance private data */ |
| void * const data; |
| #ifdef CONFIG_DEVICE_POWER_MANAGEMENT |
| /** Power Management function */ |
| int (*device_pm_control)(const struct device *dev, uint32_t command, |
| void *context, device_pm_cb cb, void *arg); |
| /** Pointer to device instance power management data */ |
| struct device_pm * const pm; |
| #endif |
| }; |
| |
| /** |
| * @brief Retrieve the device structure for a driver by name |
| * |
| * @details Device objects are created via the DEVICE_DEFINE() macro and |
| * placed in memory by the linker. If a driver needs to bind to another driver |
| * it can use this function to retrieve the device structure of the lower level |
| * driver by the name the driver exposes to the system. |
| * |
| * @param name device name to search for. |
| * |
| * @return pointer to device structure; NULL if not found or cannot be used. |
| */ |
| __syscall const struct device *device_get_binding(const char *name); |
| |
| /** @brief Get access to the static array of static devices. |
| * |
| * @param devices where to store the pointer to the array of |
| * statically allocated devices. The array must not be mutated |
| * through this pointer. |
| * |
| * @return the number of statically allocated devices. |
| */ |
| size_t z_device_get_all_static(const struct device * *devices); |
| |
| /** @brief Determine whether a device has been successfully initialized. |
| * |
| * @param dev pointer to the device in question. |
| * |
| * @return true if and only if the device is available for use. |
| */ |
| bool z_device_ready(const struct device *dev); |
| |
| /** @brief Verify that a device is ready for use. |
| * |
| * Indicates whether the provided device pointer is for a device known to be |
| * in a state where it can be used with its standard API. |
| * |
| * This can be used with device pointers captured from DEVICE_DT_GET(), which |
| * does not include the readiness checks of device_get_binding(). At minimum |
| * this means that the device has been successfully initialized, but it may |
| * take on further conditions (e.g. is not powered down). |
| * |
| * @param dev pointer to the device in question. |
| * |
| * @retval true if the device is ready for use. |
| * @retval false if the device is not ready for use. |
| */ |
| __syscall bool device_is_ready(const struct device *dev); |
| |
| static inline bool z_impl_device_is_ready(const struct device *dev) |
| { |
| return z_device_ready(dev); |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * @brief Device Power Management APIs |
| * @defgroup device_power_management_api Device Power Management APIs |
| * @ingroup power_management_api |
| * @{ |
| */ |
| |
| #ifdef CONFIG_DEVICE_POWER_MANAGEMENT |
| |
| /** @def DEVICE_PM_ACTIVE_STATE |
| * |
| * @brief device is in ACTIVE power state |
| * |
| * @details Normal operation of the device. All device context is retained. |
| */ |
| #define DEVICE_PM_ACTIVE_STATE 1 |
| |
| /** @def DEVICE_PM_LOW_POWER_STATE |
| * |
| * @brief device is in LOW power state |
| * |
| * @details Device context is preserved by the HW and need not be |
| * restored by the driver. |
| */ |
| #define DEVICE_PM_LOW_POWER_STATE 2 |
| |
| /** @def DEVICE_PM_SUSPEND_STATE |
| * |
| * @brief device is in SUSPEND power state |
| * |
| * @details Most device context is lost by the hardware. |
| * Device drivers must save and restore or reinitialize any context |
| * lost by the hardware |
| */ |
| #define DEVICE_PM_SUSPEND_STATE 3 |
| |
| /** @def DEVICE_PM_FORCE_SUSPEND_STATE |
| * |
| * @brief device is in force SUSPEND power state |
| * |
| * @details Driver puts the device in suspended state after |
| * completing the ongoing transactions and will not process any |
| * queued work or will not take any new requests for processing. |
| * Most device context is lost by the hardware. Device drivers must |
| * save and restore or reinitialize any context lost by the hardware. |
| */ |
| #define DEVICE_PM_FORCE_SUSPEND_STATE 4 |
| |
| /** @def DEVICE_PM_OFF_STATE |
| * |
| * @brief device is in OFF power state |
| * |
| * @details - Power has been fully removed from the device. |
| * The device context is lost when this state is entered, so the OS |
| * software will reinitialize the device when powering it back on |
| */ |
| #define DEVICE_PM_OFF_STATE 5 |
| |
| /* Constants defining support device power commands */ |
| #define DEVICE_PM_SET_POWER_STATE 1 |
| #define DEVICE_PM_GET_POWER_STATE 2 |
| |
| #endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ |
| |
| /** |
| * @brief Get name of device PM state |
| * |
| * @param state State id which name should be returned |
| */ |
| const char *device_pm_state_str(uint32_t state); |
| |
| /** |
| * @brief Indicate that the device is in the middle of a transaction |
| * |
| * Called by a device driver to indicate that it is in the middle of a |
| * transaction. |
| * |
| * @param busy_dev Pointer to device structure of the driver instance. |
| */ |
| void device_busy_set(const struct device *busy_dev); |
| |
| /** |
| * @brief Indicate that the device has completed its transaction |
| * |
| * Called by a device driver to indicate the end of a transaction. |
| * |
| * @param busy_dev Pointer to device structure of the driver instance. |
| */ |
| void device_busy_clear(const struct device *busy_dev); |
| |
| #ifdef CONFIG_DEVICE_POWER_MANAGEMENT |
| /* |
| * Device PM functions |
| */ |
| |
| /** |
| * @brief No-op function to initialize unimplemented hook |
| * |
| * This function should be used to initialize device hook |
| * for which a device has no PM operations. |
| * |
| * @param unused_device Unused |
| * @param unused_ctrl_command Unused |
| * @param unused_context Unused |
| * @param cb Unused |
| * @param unused_arg Unused |
| * |
| * @retval -ENOTSUP for all operations. |
| */ |
| int device_pm_control_nop(const struct device *unused_device, |
| uint32_t unused_ctrl_command, |
| void *unused_context, |
| device_pm_cb cb, |
| void *unused_arg); |
| /** |
| * @brief Call the set power state function of a device |
| * |
| * Called by the application or power management service to let the device do |
| * required operations when moving to the required power state |
| * Note that devices may support just some of the device power states |
| * @param dev Pointer to device structure of the driver instance. |
| * @param device_power_state Device power state to be set |
| * @param cb Callback function to notify device power status |
| * @param arg Caller passed argument to callback function |
| * |
| * @retval 0 If successful in queuing the request or changing the state. |
| * @retval Errno Negative errno code if failure. Callback will not be called. |
| */ |
| static inline int device_set_power_state(const struct device *dev, |
| uint32_t device_power_state, |
| device_pm_cb cb, void *arg) |
| { |
| if (dev->device_pm_control) { |
| return dev->device_pm_control(dev, |
| DEVICE_PM_SET_POWER_STATE, |
| &device_power_state, cb, arg); |
| } else { |
| return device_pm_control_nop(dev, |
| DEVICE_PM_SET_POWER_STATE, |
| &device_power_state, cb, arg); |
| } |
| } |
| |
| /** |
| * @brief Call the get power state function of a device |
| * |
| * This function lets the caller know the current device |
| * power state at any time. This state will be one of the defined |
| * power states allowed for the devices in that system |
| * |
| * @param dev pointer to device structure of the driver instance. |
| * @param device_power_state Device power state to be filled by the device |
| * |
| * @retval 0 If successful. |
| * @retval Errno Negative errno code if failure. |
| */ |
| static inline int device_get_power_state(const struct device *dev, |
| uint32_t *device_power_state) |
| { |
| if (dev->device_pm_control) { |
| return dev->device_pm_control(dev, |
| DEVICE_PM_GET_POWER_STATE, |
| device_power_state, NULL, NULL); |
| } else { |
| return device_pm_control_nop(dev, |
| DEVICE_PM_GET_POWER_STATE, |
| device_power_state, NULL, NULL); |
| } |
| } |
| |
| /** |
| * @brief Gets the device structure list array and device count |
| * |
| * Called by the Power Manager application to get the list of |
| * device structures associated with the devices in the system. |
| * The PM app would use this list to create its own sorted list |
| * based on the order it wishes to suspend or resume the devices. |
| * |
| * @param device_list Pointer to receive the device list array |
| * @param device_count Pointer to receive the device count |
| * |
| * @deprecated in 2.4 release, replace with z_device_get_all_static() |
| */ |
| __deprecated static inline void device_list_get(const struct device * *device_list, |
| int *device_count) |
| { |
| *device_count = z_device_get_all_static(device_list); |
| } |
| |
| /** |
| * @brief Check if any device is in the middle of a transaction |
| * |
| * Called by an application to see if any device is in the middle |
| * of a critical transaction that cannot be interrupted. |
| * |
| * @retval 0 if no device is busy |
| * @retval -EBUSY if any device is busy |
| */ |
| int device_any_busy_check(void); |
| |
| /** |
| * @brief Check if a specific device is in the middle of a transaction |
| * |
| * Called by an application to see if a particular device is in the |
| * middle of a critical transaction that cannot be interrupted. |
| * |
| * @param chk_dev Pointer to device structure of the specific device driver |
| * the caller is interested in. |
| * @retval 0 if the device is not busy |
| * @retval -EBUSY if the device is busy |
| */ |
| int device_busy_check(const struct device *chk_dev); |
| |
| #ifdef CONFIG_DEVICE_IDLE_PM |
| |
| /* Device PM FSM states */ |
| enum device_pm_fsm_state { |
| DEVICE_PM_FSM_STATE_ACTIVE = 1, |
| DEVICE_PM_FSM_STATE_SUSPENDED, |
| DEVICE_PM_FSM_STATE_SUSPENDING, |
| DEVICE_PM_FSM_STATE_RESUMING, |
| }; |
| |
| /** |
| * @brief Enable device idle PM |
| * |
| * Called by a device driver to enable device idle power management. |
| * The device might be asynchronously suspended if Idle PM is enabled |
| * when the device is not use. |
| * |
| * @param dev Pointer to device structure of the specific device driver |
| * the caller is interested in. |
| */ |
| void device_pm_enable(const struct device *dev); |
| |
| /** |
| * @brief Disable device idle PM |
| * |
| * Called by a device driver to disable device idle power management. |
| * The device might be asynchronously resumed if Idle PM is disabled |
| * |
| * @param dev Pointer to device structure of the specific device driver |
| * the caller is interested in. |
| */ |
| void device_pm_disable(const struct device *dev); |
| |
| /** |
| * @brief Call device resume asynchronously based on usage count |
| * |
| * Called by a device driver to mark the device as being used. |
| * This API will asynchronously bring the device to resume state |
| * if it not already in active state. |
| * |
| * @param dev Pointer to device structure of the specific device driver |
| * the caller is interested in. |
| * @retval 0 If successfully queued the Async request. If queued, |
| * the caller need to wait on the poll event linked to device |
| * pm signal mechanism to know the completion of resume operation. |
| * @retval Errno Negative errno code if failure. |
| */ |
| int device_pm_get(const struct device *dev); |
| |
| /** |
| * @brief Call device resume synchronously based on usage count |
| * |
| * Called by a device driver to mark the device as being used. It |
| * will bring up or resume the device if it is in suspended state |
| * based on the device usage count. This call is blocked until the |
| * device PM state is changed to resume. |
| * |
| * @param dev Pointer to device structure of the specific device driver |
| * the caller is interested in. |
| * @retval 0 If successful. |
| * @retval Errno Negative errno code if failure. |
| */ |
| int device_pm_get_sync(const struct device *dev); |
| |
| /** |
| * @brief Call device suspend asynchronously based on usage count |
| * |
| * Called by a device driver to mark the device as being released. |
| * This API asynchronously put the device to suspend state if |
| * it not already in suspended state. |
| * |
| * @param dev Pointer to device structure of the specific device driver |
| * the caller is interested in. |
| * @retval 0 If successfully queued the Async request. If queued, |
| * the caller need to wait on the poll event linked to device pm |
| * signal mechanism to know the completion of suspend operation. |
| * @retval Errno Negative errno code if failure. |
| */ |
| int device_pm_put(const struct device *dev); |
| |
| /** |
| * @brief Call device suspend synchronously based on usage count |
| * |
| * Called by a device driver to mark the device as being released. It |
| * will put the device to suspended state if is is in active state |
| * based on the device usage count. This call is blocked until the |
| * device PM state is changed to resume. |
| * |
| * @param dev Pointer to device structure of the specific device driver |
| * the caller is interested in. |
| * @retval 0 If successful. |
| * @retval Errno Negative errno code if failure. |
| */ |
| int device_pm_put_sync(const struct device *dev); |
| #else |
| static inline void device_pm_enable(const struct device *dev) { } |
| static inline void device_pm_disable(const struct device *dev) { } |
| static inline int device_pm_get(const struct device *dev) { return -ENOTSUP; } |
| static inline int device_pm_get_sync(const struct device *dev) { return -ENOTSUP; } |
| static inline int device_pm_put(const struct device *dev) { return -ENOTSUP; } |
| static inline int device_pm_put_sync(const struct device *dev) { return -ENOTSUP; } |
| #endif |
| #else |
| #define device_pm_control_nop(...) NULL |
| #endif |
| |
| /** |
| * @} |
| */ |
| |
| #define Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, pm_control_fn, \ |
| data_ptr, cfg_ptr, level, prio, api_ptr) \ |
| Z_DEVICE_DEFINE_PM(dev_name) \ |
| COND_CODE_1(DT_NODE_EXISTS(dev_name), (), (static)) \ |
| const Z_DECL_ALIGN(struct device) \ |
| DEVICE_NAME_GET(dev_name) __used \ |
| __attribute__((__section__(".device_" #level STRINGIFY(prio)))) = { \ |
| .name = drv_name, \ |
| .config = (cfg_ptr), \ |
| .api = (api_ptr), \ |
| .data = (data_ptr), \ |
| Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn) \ |
| }; \ |
| Z_INIT_ENTRY_DEFINE(_CONCAT(__device_, dev_name), init_fn, \ |
| (&_CONCAT(__device_, dev_name)), level, prio) |
| |
| #ifdef CONFIG_DEVICE_POWER_MANAGEMENT |
| #define Z_DEVICE_DEFINE_PM(dev_name) \ |
| static struct device_pm _CONCAT(__pm_, dev_name) __used = { \ |
| .usage = ATOMIC_INIT(0), \ |
| .lock = Z_SEM_INITIALIZER( \ |
| _CONCAT(__pm_, dev_name).lock, 1, 1), \ |
| .signal = K_POLL_SIGNAL_INITIALIZER( \ |
| _CONCAT(__pm_, dev_name).signal), \ |
| .event = K_POLL_EVENT_INITIALIZER( \ |
| K_POLL_TYPE_SIGNAL, \ |
| K_POLL_MODE_NOTIFY_ONLY, \ |
| &_CONCAT(__pm_, dev_name).signal), \ |
| }; |
| #define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn) \ |
| .device_pm_control = (pm_control_fn), \ |
| .pm = &_CONCAT(__pm_, dev_name), |
| #else |
| #define Z_DEVICE_DEFINE_PM(dev_name) |
| #define Z_DEVICE_DEFINE_PM_INIT(dev_name, pm_control_fn) |
| #endif |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #include <syscalls/device.h> |
| |
| #endif /* ZEPHYR_INCLUDE_DEVICE_H_ */ |