2015-10-06 11:00:37 -05:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015 Intel Corporation.
|
2015-06-01 11:11:39 -07:00
|
|
|
*
|
2017-01-18 17:01:01 -08:00
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
2015-06-01 11:11:39 -07:00
|
|
|
*/
|
|
|
|
|
2018-09-14 10:43:44 -07:00
|
|
|
#ifndef ZEPHYR_INCLUDE_DEVICE_H_
|
|
|
|
#define ZEPHYR_INCLUDE_DEVICE_H_
|
2015-06-01 11:11:39 -07:00
|
|
|
|
2016-02-14 11:11:04 -05:00
|
|
|
/**
|
|
|
|
* @brief Device Driver APIs
|
|
|
|
* @defgroup io_interfaces Device Driver APIs
|
|
|
|
* @{
|
|
|
|
* @}
|
|
|
|
*/
|
2021-02-08 21:14:29 +01:00
|
|
|
/**
|
|
|
|
* @brief Miscellaneous Drivers APIs
|
|
|
|
* @defgroup misc_interfaces Miscellaneous Drivers APIs
|
|
|
|
* @ingroup io_interfaces
|
|
|
|
* @{
|
|
|
|
* @}
|
|
|
|
*/
|
2016-02-14 11:11:04 -05:00
|
|
|
/**
|
|
|
|
* @brief Device Model APIs
|
|
|
|
* @defgroup device_model Device Model APIs
|
|
|
|
* @{
|
|
|
|
*/
|
2016-09-01 09:01:10 +03:00
|
|
|
|
2020-03-09 11:02:20 +01:00
|
|
|
#include <init.h>
|
2021-07-19 10:54:39 -07:00
|
|
|
#include <linker/sections.h>
|
2021-04-29 13:32:28 +02:00
|
|
|
#include <pm/device.h>
|
2020-06-23 09:35:03 -07:00
|
|
|
#include <sys/device_mmio.h>
|
2020-06-23 10:44:53 -05:00
|
|
|
#include <sys/util.h>
|
2016-09-01 09:01:10 +03:00
|
|
|
|
2016-01-22 12:38:49 -05:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2020-06-23 10:44:53 -05:00
|
|
|
/** @brief Type used to represent devices and functions.
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* The extreme values and zero have special significance. Negative
|
2020-06-23 10:44:53 -05:00
|
|
|
* values identify functionality that does not correspond to a Zephyr
|
|
|
|
* device, such as the system clock or a SYS_INIT() function.
|
|
|
|
*/
|
|
|
|
typedef int16_t device_handle_t;
|
|
|
|
|
|
|
|
/** @brief Flag value used in lists of device handles to separate
|
|
|
|
* distinct groups.
|
|
|
|
*
|
|
|
|
* This is the minimum value for the device_handle_t type.
|
|
|
|
*/
|
|
|
|
#define DEVICE_HANDLE_SEP INT16_MIN
|
|
|
|
|
|
|
|
/** @brief Flag value used in lists of device handles to indicate the
|
|
|
|
* end of the list.
|
|
|
|
*
|
|
|
|
* This is the maximum value for the device_handle_t type.
|
|
|
|
*/
|
|
|
|
#define DEVICE_HANDLE_ENDS INT16_MAX
|
|
|
|
|
|
|
|
/** @brief Flag value used to identify an unknown device. */
|
|
|
|
#define DEVICE_HANDLE_NULL 0
|
|
|
|
|
2018-11-12 10:25:12 -08:00
|
|
|
#define Z_DEVICE_MAX_NAME_LEN 48
|
2016-11-08 11:06:55 -08:00
|
|
|
|
2020-05-11 10:00:09 -05:00
|
|
|
/**
|
|
|
|
* @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
|
2020-06-09 14:39:26 -05:00
|
|
|
* DEVICE_DEFINE(), using the dev_name provided to DEVICE_DEFINE().
|
2020-05-11 10:00:09 -05:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2020-06-09 14:39:26 -05:00
|
|
|
* @param name The same as dev_name provided to DEVICE_DEFINE()
|
2020-05-11 10:00:09 -05:00
|
|
|
*
|
2020-06-09 14:39:26 -05:00
|
|
|
* @return The expanded name of the device object created by DEVICE_DEFINE()
|
2020-05-11 10:00:09 -05:00
|
|
|
*/
|
2021-01-21 11:16:33 +01:00
|
|
|
#define DEVICE_NAME_GET(name) _CONCAT(__device_, name)
|
2020-03-09 11:02:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @def SYS_DEVICE_DEFINE
|
|
|
|
*
|
2021-11-16 16:37:45 +01:00
|
|
|
* @brief Run an initialization function at boot at specified priority.
|
2020-03-09 11:02:20 +01:00
|
|
|
*
|
2020-06-09 14:39:26 -05:00
|
|
|
* @details Invokes DEVICE_DEFINE() with no power management support
|
2021-10-13 12:11:40 +02:00
|
|
|
* (@p pm_device), no API (@p api_ptr), and a device name derived from
|
2020-06-09 14:39:26 -05:00
|
|
|
* the @p init_fn name (@p dev_name).
|
2020-03-09 11:02:20 +01:00
|
|
|
*/
|
2021-11-16 16:37:45 +01:00
|
|
|
#define SYS_DEVICE_DEFINE(drv_name, init_fn, level, prio) \
|
|
|
|
DEVICE_DEFINE(Z_SYS_NAME(init_fn), drv_name, init_fn, NULL, \
|
2020-03-09 11:02:20 +01:00
|
|
|
NULL, NULL, level, prio, NULL)
|
|
|
|
|
2020-06-09 14:39:26 -05:00
|
|
|
/**
|
|
|
|
* @def DEVICE_DEFINE
|
|
|
|
*
|
2021-11-02 16:30:55 +01:00
|
|
|
* @brief Create device object and set it up for boot time initialization.
|
2016-01-27 15:55:32 -05:00
|
|
|
*
|
|
|
|
* @details This macro defines a device object that is automatically
|
2018-12-03 09:04:21 -08:00
|
|
|
* configured by the kernel during system initialization. Note that
|
|
|
|
* devices set up with this macro will not be accessible from user mode
|
2021-01-05 12:16:23 -06:00
|
|
|
* since the API is not specified;
|
2016-01-27 15:55:32 -05:00
|
|
|
*
|
2018-11-12 10:25:12 -08:00
|
|
|
* @param dev_name Device name. This must be less than Z_DEVICE_MAX_NAME_LEN
|
2021-01-23 07:56:09 -06:00
|
|
|
* characters (including terminating NUL) in order to be looked up from user
|
|
|
|
* mode with device_get_binding().
|
2016-01-27 15:55:32 -05:00
|
|
|
*
|
|
|
|
* @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.
|
|
|
|
*
|
2021-10-13 12:11:40 +02:00
|
|
|
* @param pm_device PM device resources reference (NULL if device does not use PM).
|
2020-06-09 14:39:26 -05:00
|
|
|
*
|
2020-05-28 20:52:59 +02:00
|
|
|
* @param data_ptr Pointer to the device's private data.
|
2016-01-27 15:55:32 -05:00
|
|
|
*
|
2020-05-28 20:36:09 +02:00
|
|
|
* @param cfg_ptr The address to the structure containing the
|
2016-01-27 15:55:32 -05:00
|
|
|
* configuration information for this instance of the driver.
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* @param level The initialization level. See SYS_INIT() for
|
2020-06-09 14:39:26 -05:00
|
|
|
* details.
|
2020-03-09 11:02:20 +01:00
|
|
|
*
|
|
|
|
* @param prio Priority within the selected initialization level. See
|
2020-06-09 14:39:26 -05:00
|
|
|
* SYS_INIT() for details.
|
2016-04-14 09:28:33 -07:00
|
|
|
*
|
2020-05-28 20:52:59 +02:00
|
|
|
* @param api_ptr Provides an initial pointer to the API function struct
|
2016-04-14 09:28:33 -07:00
|
|
|
* used by the driver. Can be NULL.
|
|
|
|
*/
|
2021-10-13 12:11:40 +02:00
|
|
|
#define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_device, \
|
2020-05-28 20:52:59 +02:00
|
|
|
data_ptr, cfg_ptr, level, prio, api_ptr) \
|
2020-06-23 10:28:34 -05:00
|
|
|
Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_name, drv_name, init_fn, \
|
2021-10-13 12:11:40 +02:00
|
|
|
pm_device, \
|
2020-06-23 10:28:34 -05:00
|
|
|
data_ptr, cfg_ptr, level, prio, api_ptr)
|
2020-03-09 11:02:20 +01:00
|
|
|
|
2021-02-24 11:20:29 -06:00
|
|
|
/**
|
|
|
|
* @def DEVICE_DT_NAME
|
|
|
|
*
|
|
|
|
* @brief Return a string name for a devicetree node.
|
|
|
|
*
|
|
|
|
* @details This macro returns a string literal usable as a device name
|
|
|
|
* from a devicetree node. If the node has a "label" property, its value is
|
|
|
|
* returned. Otherwise, the node's full "node-name@@unit-address" name is
|
|
|
|
* returned.
|
|
|
|
*
|
|
|
|
* @param node_id The devicetree node identifier.
|
|
|
|
*/
|
|
|
|
#define DEVICE_DT_NAME(node_id) \
|
|
|
|
DT_PROP_OR(node_id, label, DT_NODE_FULL_NAME(node_id))
|
|
|
|
|
2020-06-10 08:19:39 -05:00
|
|
|
/**
|
|
|
|
* @def DEVICE_DT_DEFINE
|
|
|
|
*
|
2020-11-23 07:38:52 -06:00
|
|
|
* @brief Like DEVICE_DEFINE but taking metadata from a devicetree node.
|
2020-06-10 08:19:39 -05:00
|
|
|
*
|
|
|
|
* @details This macro defines a device object that is automatically
|
2021-08-22 15:35:43 +10:00
|
|
|
* configured by the kernel during system initialization. The device
|
2020-06-10 08:19:39 -05:00
|
|
|
* 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.
|
|
|
|
*
|
2020-11-23 07:38:52 -06:00
|
|
|
* The device is declared with extern visibility, so device objects
|
|
|
|
* defined through this API can be obtained directly through
|
2021-08-22 15:35:43 +10:00
|
|
|
* DEVICE_DT_GET() using @p node_id. Before using the pointer the
|
2020-11-23 07:38:52 -06:00
|
|
|
* referenced object should be checked using device_is_ready().
|
2020-06-10 08:19:39 -05:00
|
|
|
*
|
|
|
|
* @param node_id The devicetree node identifier.
|
|
|
|
*
|
|
|
|
* @param init_fn Address to the init function of the driver.
|
|
|
|
*
|
2021-10-13 12:11:40 +02:00
|
|
|
* @param pm_device PM device resources reference (NULL if device does not use PM).
|
2020-06-10 08:19:39 -05:00
|
|
|
*
|
|
|
|
* @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.
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* @param level The initialization level. See SYS_INIT() for
|
2020-06-10 08:19:39 -05:00
|
|
|
* 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.
|
|
|
|
*/
|
2021-10-13 12:11:40 +02:00
|
|
|
#define DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \
|
2020-06-23 10:44:53 -05:00
|
|
|
data_ptr, cfg_ptr, level, prio, \
|
|
|
|
api_ptr, ...) \
|
2021-01-23 07:56:09 -06:00
|
|
|
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id), \
|
2021-02-24 11:20:29 -06:00
|
|
|
DEVICE_DT_NAME(node_id), init_fn, \
|
2021-10-13 12:11:40 +02:00
|
|
|
pm_device, \
|
2020-06-23 10:44:53 -05:00
|
|
|
data_ptr, cfg_ptr, level, prio, \
|
|
|
|
api_ptr, __VA_ARGS__)
|
2020-06-10 08:19:39 -05:00
|
|
|
|
2020-12-02 11:21:46 -06:00
|
|
|
/**
|
|
|
|
* @def DEVICE_DT_INST_DEFINE
|
|
|
|
*
|
|
|
|
* @brief Like DEVICE_DT_DEFINE for an instance of a DT_DRV_COMPAT compatible
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* @param inst instance number. This is replaced by
|
2020-12-02 11:21:46 -06:00
|
|
|
* <tt>DT_DRV_COMPAT(inst)</tt> in the call to DEVICE_DT_DEFINE.
|
|
|
|
*
|
|
|
|
* @param ... other parameters as expected by DEVICE_DT_DEFINE.
|
|
|
|
*/
|
|
|
|
#define DEVICE_DT_INST_DEFINE(inst, ...) \
|
|
|
|
DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
|
|
|
|
|
2020-06-10 08:19:39 -05:00
|
|
|
/**
|
|
|
|
* @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()
|
|
|
|
*/
|
2021-01-23 07:56:09 -06:00
|
|
|
#define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_NAME(node_id))
|
2020-06-10 08:19:39 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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
|
|
|
|
*
|
|
|
|
* @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))
|
|
|
|
|
2020-12-02 11:21:46 -06:00
|
|
|
/** @def DEVICE_DT_INST_GET
|
|
|
|
*
|
|
|
|
* @brief Obtain a pointer to a device object for an instance of a
|
|
|
|
* DT_DRV_COMPAT compatible
|
|
|
|
*
|
|
|
|
* @param inst instance number
|
|
|
|
*/
|
|
|
|
#define DEVICE_DT_INST_GET(inst) DEVICE_DT_GET(DT_DRV_INST(inst))
|
|
|
|
|
2021-02-05 22:29:20 -08:00
|
|
|
/**
|
|
|
|
* @def DEVICE_DT_GET_ANY
|
|
|
|
*
|
|
|
|
* @brief Obtain a pointer to a device object by devicetree compatible
|
|
|
|
*
|
|
|
|
* If any enabled devicetree node has the given compatible and a
|
|
|
|
* device object was created from it, this returns that device.
|
|
|
|
*
|
|
|
|
* If there no such devices, this returns NULL.
|
|
|
|
*
|
|
|
|
* If there are multiple, this returns an arbitrary one.
|
|
|
|
*
|
|
|
|
* If this returns non-NULL, the device must be checked for readiness
|
|
|
|
* before use, e.g. with device_is_ready().
|
|
|
|
*
|
|
|
|
* @param compat lowercase-and-underscores devicetree compatible
|
|
|
|
* @return a pointer to a device, or NULL
|
|
|
|
*/
|
2021-03-26 10:32:49 -07:00
|
|
|
#define DEVICE_DT_GET_ANY(compat) \
|
|
|
|
COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(compat), \
|
|
|
|
(DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(compat))), \
|
2021-02-05 22:29:20 -08:00
|
|
|
(NULL))
|
|
|
|
|
2021-07-01 22:02:10 +02:00
|
|
|
/**
|
|
|
|
* @def DEVICE_DT_GET_ONE
|
|
|
|
*
|
|
|
|
* @brief Obtain a pointer to a device object by devicetree compatible
|
|
|
|
*
|
|
|
|
* If any enabled devicetree node has the given compatible and a
|
|
|
|
* device object was created from it, this returns that device.
|
|
|
|
*
|
|
|
|
* If there no such devices, this throws a compilation error.
|
|
|
|
*
|
|
|
|
* If there are multiple, this returns an arbitrary one.
|
|
|
|
*
|
|
|
|
* If this returns non-NULL, the device must be checked for readiness
|
|
|
|
* before use, e.g. with device_is_ready().
|
|
|
|
*
|
|
|
|
* @param compat lowercase-and-underscores devicetree compatible
|
|
|
|
* @return a pointer to a device
|
|
|
|
*/
|
|
|
|
#define DEVICE_DT_GET_ONE(compat) \
|
|
|
|
COND_CODE_1(DT_HAS_COMPAT_STATUS_OKAY(compat), \
|
|
|
|
(DEVICE_DT_GET(DT_COMPAT_GET_ANY_STATUS_OKAY(compat))), \
|
|
|
|
(ZERO_OR_COMPILE_ERROR(0)))
|
|
|
|
|
2021-09-06 15:45:34 +02:00
|
|
|
/**
|
|
|
|
* @def DEVICE_DT_GET_OR_NULL
|
|
|
|
*
|
|
|
|
* @brief Utility macro to obtain an optional reference to a device.
|
|
|
|
*
|
|
|
|
* @param node_id Node identifier.
|
|
|
|
*
|
|
|
|
* @return Pointer to a device if it exists, NULL otherwise.
|
|
|
|
*/
|
|
|
|
#define DEVICE_DT_GET_OR_NULL(node_id) \
|
|
|
|
COND_CODE_1(DT_NODE_HAS_STATUS(node_id, okay), \
|
|
|
|
(DEVICE_DT_GET(node_id)), (NULL))
|
|
|
|
|
2016-01-27 14:40:06 -05:00
|
|
|
/**
|
|
|
|
* @def DEVICE_GET
|
|
|
|
*
|
|
|
|
* @brief Obtain a pointer to a device object by name
|
|
|
|
*
|
|
|
|
* @details Return the address of a device object created by
|
2020-11-05 06:09:32 -06:00
|
|
|
* DEVICE_DEFINE(), using the dev_name provided to DEVICE_DEFINE().
|
2016-01-27 14:40:06 -05:00
|
|
|
*
|
2020-11-05 06:09:32 -06:00
|
|
|
* @param name The same as dev_name provided to DEVICE_DEFINE()
|
2016-01-27 14:40:06 -05:00
|
|
|
*
|
2020-11-05 06:09:32 -06:00
|
|
|
* @return A pointer to the device object created by DEVICE_DEFINE()
|
2016-01-27 14:40:06 -05:00
|
|
|
*/
|
|
|
|
#define DEVICE_GET(name) (&DEVICE_NAME_GET(name))
|
|
|
|
|
2018-02-06 22:31:50 -06:00
|
|
|
/** @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
|
2020-11-05 06:09:32 -06:00
|
|
|
* DEVICE_DEFINE().
|
2018-02-06 22:31:50 -06:00
|
|
|
*
|
|
|
|
* This is often useful when configuring interrupts statically in a
|
|
|
|
* device's init or per-instance config function, as the init function
|
2020-11-05 06:09:32 -06:00
|
|
|
* itself is required by DEVICE_DEFINE() and use of DEVICE_GET()
|
2018-02-06 22:31:50 -06:00
|
|
|
* inside it creates a circular dependency.
|
|
|
|
*
|
|
|
|
* @param name Device name
|
|
|
|
*/
|
2020-04-30 21:46:13 +02:00
|
|
|
#define DEVICE_DECLARE(name) static const struct device DEVICE_NAME_GET(name)
|
2016-01-25 16:23:42 -08:00
|
|
|
|
2015-07-10 14:52:53 -04:00
|
|
|
/**
|
2021-02-02 09:19:58 -06:00
|
|
|
* @brief Runtime device dynamic structure (in RAM) per driver instance
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* Fields in this are expected to be default-initialized to zero. The
|
2021-02-02 09:19:58 -06:00
|
|
|
* kernel driver infrastructure and driver access functions are
|
|
|
|
* responsible for ensuring that any non-zero initialization is done
|
|
|
|
* before they are accessed.
|
|
|
|
*/
|
|
|
|
struct device_state {
|
2021-02-02 10:23:55 -06:00
|
|
|
/** Non-negative result of initializing the device.
|
|
|
|
*
|
|
|
|
* The absolute value returned when the device initialization
|
|
|
|
* function was invoked, or `UINT8_MAX` if the value exceeds
|
2021-08-22 15:35:43 +10:00
|
|
|
* an 8-bit integer. If initialized is also set, a zero value
|
2021-02-02 10:23:55 -06:00
|
|
|
* indicates initialization succeeded.
|
|
|
|
*/
|
|
|
|
unsigned int init_res : 8;
|
|
|
|
|
|
|
|
/** Indicates the device initialization function has been
|
|
|
|
* invoked.
|
|
|
|
*/
|
|
|
|
bool initialized : 1;
|
2021-02-02 09:19:58 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Runtime device structure (in ROM) per driver instance
|
2015-07-10 14:52:53 -04:00
|
|
|
*/
|
2015-06-01 11:11:39 -07:00
|
|
|
struct device {
|
2020-06-19 08:05:56 +02:00
|
|
|
/** Name of the device instance */
|
2020-03-09 11:02:20 +01:00
|
|
|
const char *name;
|
2020-06-19 08:05:56 +02:00
|
|
|
/** Address of device instance config information */
|
2020-05-28 20:36:09 +02:00
|
|
|
const void *config;
|
2020-06-19 08:05:56 +02:00
|
|
|
/** Address of the API structure exposed by the device instance */
|
2020-05-28 20:52:59 +02:00
|
|
|
const void *api;
|
2021-02-02 09:19:58 -06:00
|
|
|
/** Address of the common device state */
|
|
|
|
struct device_state * const state;
|
2020-06-19 08:05:56 +02:00
|
|
|
/** Address of the device instance private data */
|
2020-05-28 20:52:59 +02:00
|
|
|
void * const data;
|
2020-06-23 10:44:53 -05:00
|
|
|
/** optional pointer to handles associated with the device.
|
|
|
|
*
|
|
|
|
* This encodes a sequence of sets of device handles that have
|
2021-08-22 15:35:43 +10:00
|
|
|
* some relationship to this node. The individual sets are
|
2020-06-23 10:44:53 -05:00
|
|
|
* extracted with dedicated API, such as
|
|
|
|
* device_required_handles_get().
|
|
|
|
*/
|
|
|
|
const device_handle_t *const handles;
|
2020-09-01 18:31:40 -04:00
|
|
|
#ifdef CONFIG_PM_DEVICE
|
2021-10-13 12:11:40 +02:00
|
|
|
/** Reference to the device PM resources. */
|
2021-05-03 17:42:31 +02:00
|
|
|
struct pm_device * const pm;
|
2020-03-09 11:02:20 +01:00
|
|
|
#endif
|
2015-06-01 11:11:39 -07:00
|
|
|
};
|
|
|
|
|
2020-06-23 10:44:53 -05:00
|
|
|
/**
|
|
|
|
* @brief Get the handle for a given device
|
|
|
|
*
|
|
|
|
* @param dev the device for which a handle is desired.
|
|
|
|
*
|
|
|
|
* @return the handle for the device, or DEVICE_HANDLE_NULL if the
|
|
|
|
* device does not have an associated handle.
|
|
|
|
*/
|
|
|
|
static inline device_handle_t
|
|
|
|
device_handle_get(const struct device *dev)
|
|
|
|
{
|
|
|
|
device_handle_t ret = DEVICE_HANDLE_NULL;
|
|
|
|
extern const struct device __device_start[];
|
|
|
|
|
|
|
|
/* TODO: If/when devices can be constructed that are not part of the
|
|
|
|
* fixed sequence we'll need another solution.
|
|
|
|
*/
|
|
|
|
if (dev != NULL) {
|
|
|
|
ret = 1 + (device_handle_t)(dev - __device_start);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Get the device corresponding to a handle.
|
|
|
|
*
|
|
|
|
* @param dev_handle the device handle
|
|
|
|
*
|
|
|
|
* @return the device that has that handle, or a null pointer if @p
|
|
|
|
* dev_handle does not identify a device.
|
|
|
|
*/
|
|
|
|
static inline const struct device *
|
|
|
|
device_from_handle(device_handle_t dev_handle)
|
|
|
|
{
|
|
|
|
extern const struct device __device_start[];
|
|
|
|
extern const struct device __device_end[];
|
|
|
|
const struct device *dev = NULL;
|
|
|
|
size_t numdev = __device_end - __device_start;
|
|
|
|
|
2021-08-26 17:17:59 -07:00
|
|
|
if ((dev_handle > 0) && ((size_t)dev_handle <= numdev)) {
|
2020-06-23 10:44:53 -05:00
|
|
|
dev = &__device_start[dev_handle - 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
return dev;
|
|
|
|
}
|
|
|
|
|
2021-02-22 11:42:08 -06:00
|
|
|
/**
|
|
|
|
* @brief Prototype for functions used when iterating over a set of devices.
|
|
|
|
*
|
|
|
|
* Such a function may be used in API that identifies a set of devices and
|
|
|
|
* provides a visitor API supporting caller-specific interaction with each
|
|
|
|
* device in the set.
|
|
|
|
*
|
|
|
|
* The visit is said to succeed if the visitor returns a non-negative value.
|
|
|
|
*
|
|
|
|
* @param dev a device in the set being iterated
|
|
|
|
*
|
|
|
|
* @param context state used to support the visitor function
|
|
|
|
*
|
|
|
|
* @return A non-negative number to allow walking to continue, and a negative
|
|
|
|
* error code to case the iteration to stop.
|
|
|
|
*/
|
|
|
|
typedef int (*device_visitor_callback_t)(const struct device *dev, void *context);
|
|
|
|
|
2020-06-23 10:44:53 -05:00
|
|
|
/**
|
|
|
|
* @brief Get the set of handles for devicetree dependencies of this device.
|
|
|
|
*
|
|
|
|
* These are the device dependencies inferred from devicetree.
|
|
|
|
*
|
|
|
|
* @param dev the device for which dependencies are desired.
|
|
|
|
*
|
|
|
|
* @param count pointer to a place to store the number of devices provided at
|
2021-08-22 15:35:43 +10:00
|
|
|
* the returned pointer. The value is not set if the call returns a null
|
|
|
|
* pointer. The value may be set to zero.
|
2020-06-23 10:44:53 -05:00
|
|
|
*
|
|
|
|
* @return a pointer to a sequence of @p *count device handles, or a null
|
|
|
|
* pointer if @p dh does not provide dependency information.
|
|
|
|
*/
|
|
|
|
static inline const device_handle_t *
|
|
|
|
device_required_handles_get(const struct device *dev,
|
|
|
|
size_t *count)
|
|
|
|
{
|
|
|
|
const device_handle_t *rv = dev->handles;
|
|
|
|
|
|
|
|
if (rv != NULL) {
|
|
|
|
size_t i = 0;
|
|
|
|
|
2021-09-24 12:36:56 -07:00
|
|
|
while ((rv[i] != DEVICE_HANDLE_ENDS)
|
|
|
|
&& (rv[i] != DEVICE_HANDLE_SEP)) {
|
2020-06-23 10:44:53 -05:00
|
|
|
++i;
|
|
|
|
}
|
|
|
|
*count = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2021-08-20 19:29:39 +10:00
|
|
|
/**
|
|
|
|
* @brief Get the set of handles that this device supports.
|
|
|
|
*
|
|
|
|
* The set of supported devices is inferred from devicetree, and does not
|
|
|
|
* include any software constructs that may depend on the device.
|
|
|
|
*
|
|
|
|
* @param dev the device for which supports are desired.
|
|
|
|
*
|
|
|
|
* @param count pointer to a place to store the number of devices provided at
|
|
|
|
* the returned pointer. The value is not set if the call returns a null
|
|
|
|
* pointer. The value may be set to zero.
|
|
|
|
*
|
|
|
|
* @return a pointer to a sequence of @p *count device handles, or a null
|
|
|
|
* pointer if @p dh does not provide dependency information.
|
|
|
|
*/
|
|
|
|
static inline const device_handle_t *
|
|
|
|
device_supported_handles_get(const struct device *dev,
|
|
|
|
size_t *count)
|
|
|
|
{
|
|
|
|
const device_handle_t *rv = dev->handles;
|
|
|
|
size_t region = 0;
|
|
|
|
size_t i = 0;
|
|
|
|
|
|
|
|
if (rv != NULL) {
|
|
|
|
/* Fast forward to supporting devices */
|
|
|
|
while (region != 2) {
|
|
|
|
if (*rv == DEVICE_HANDLE_SEP) {
|
|
|
|
region++;
|
|
|
|
}
|
|
|
|
rv++;
|
|
|
|
}
|
|
|
|
/* Count supporting devices */
|
|
|
|
while (rv[i] != DEVICE_HANDLE_ENDS) {
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
*count = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2021-02-22 11:42:08 -06:00
|
|
|
/**
|
|
|
|
* @brief Visit every device that @p dev directly requires.
|
|
|
|
*
|
|
|
|
* Zephyr maintains information about which devices are directly required by
|
|
|
|
* another device; for example an I2C-based sensor driver will require an I2C
|
2021-08-22 15:35:43 +10:00
|
|
|
* controller for communication. Required devices can derive from
|
2021-02-22 11:42:08 -06:00
|
|
|
* statically-defined devicetree relationships or dependencies registered
|
|
|
|
* at runtime.
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* This API supports operating on the set of required devices. Example uses
|
2021-02-22 11:42:08 -06:00
|
|
|
* include making sure required devices are ready before the requiring device
|
|
|
|
* is used, and releasing them when the requiring device is no longer needed.
|
|
|
|
*
|
|
|
|
* There is no guarantee on the order in which required devices are visited.
|
|
|
|
*
|
|
|
|
* If the @p visitor function returns a negative value iteration is halted,
|
|
|
|
* and the returned value from the visitor is returned from this function.
|
|
|
|
*
|
|
|
|
* @note This API is not available to unprivileged threads.
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* @param dev a device of interest. The devices that this device depends on
|
|
|
|
* will be used as the set of devices to visit. This parameter must not be
|
2021-02-22 11:42:08 -06:00
|
|
|
* null.
|
|
|
|
*
|
|
|
|
* @param visitor_cb the function that should be invoked on each device in the
|
2021-08-22 15:35:43 +10:00
|
|
|
* dependency set. This parameter must not be null.
|
2021-02-22 11:42:08 -06:00
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* @param context state that is passed through to the visitor function. This
|
2021-02-22 11:42:08 -06:00
|
|
|
* parameter may be null if @p visitor tolerates a null @p context.
|
|
|
|
*
|
|
|
|
* @return The number of devices that were visited if all visits succeed, or
|
|
|
|
* the negative value returned from the first visit that did not succeed.
|
|
|
|
*/
|
|
|
|
int device_required_foreach(const struct device *dev,
|
|
|
|
device_visitor_callback_t visitor_cb,
|
|
|
|
void *context);
|
|
|
|
|
2021-08-20 19:29:39 +10:00
|
|
|
/**
|
|
|
|
* @brief Visit every device that @p dev directly supports.
|
|
|
|
*
|
|
|
|
* Zephyr maintains information about which devices are directly supported by
|
|
|
|
* another device; for example an I2C controller will support an I2C-based
|
|
|
|
* sensor driver. Supported devices can derive from statically-defined
|
|
|
|
* devicetree relationships.
|
|
|
|
*
|
|
|
|
* This API supports operating on the set of supported devices. Example uses
|
|
|
|
* include iterating over the devices connected to a regulator when it is
|
|
|
|
* powered on.
|
|
|
|
*
|
|
|
|
* There is no guarantee on the order in which required devices are visited.
|
|
|
|
*
|
|
|
|
* If the @p visitor function returns a negative value iteration is halted,
|
|
|
|
* and the returned value from the visitor is returned from this function.
|
|
|
|
*
|
|
|
|
* @note This API is not available to unprivileged threads.
|
|
|
|
*
|
|
|
|
* @param dev a device of interest. The devices that this device supports
|
|
|
|
* will be used as the set of devices to visit. This parameter must not be
|
|
|
|
* null.
|
|
|
|
*
|
|
|
|
* @param visitor_cb the function that should be invoked on each device in the
|
|
|
|
* support set. This parameter must not be null.
|
|
|
|
*
|
|
|
|
* @param context state that is passed through to the visitor function. This
|
|
|
|
* parameter may be null if @p visitor tolerates a null @p context.
|
|
|
|
*
|
|
|
|
* @return The number of devices that were visited if all visits succeed, or
|
|
|
|
* the negative value returned from the first visit that did not succeed.
|
|
|
|
*/
|
|
|
|
int device_supported_foreach(const struct device *dev,
|
|
|
|
device_visitor_callback_t visitor_cb,
|
|
|
|
void *context);
|
|
|
|
|
2016-05-07 23:47:44 -04:00
|
|
|
/**
|
|
|
|
* @brief Retrieve the device structure for a driver by name
|
|
|
|
*
|
2020-11-05 06:09:32 -06:00
|
|
|
* @details Device objects are created via the DEVICE_DEFINE() macro and
|
2016-05-07 23:47:44 -04:00
|
|
|
* 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.
|
|
|
|
*
|
2021-08-22 15:35:43 +10:00
|
|
|
* @param name device name to search for. A null pointer, or a pointer to an
|
2021-02-12 06:19:08 -06:00
|
|
|
* empty string, will cause NULL to be returned.
|
2016-05-07 23:47:44 -04:00
|
|
|
*
|
|
|
|
* @return pointer to device structure; NULL if not found or cannot be used.
|
|
|
|
*/
|
2020-04-30 20:33:38 +02:00
|
|
|
__syscall const struct device *device_get_binding(const char *name);
|
2015-06-01 11:11:39 -07:00
|
|
|
|
2020-06-22 08:55:37 -05:00
|
|
|
/** @brief Get access to the static array of static devices.
|
|
|
|
*
|
|
|
|
* @param devices where to store the pointer to the array of
|
2021-08-22 15:35:43 +10:00
|
|
|
* statically allocated devices. The array must not be mutated
|
2020-06-22 08:55:37 -05:00
|
|
|
* through this pointer.
|
|
|
|
*
|
|
|
|
* @return the number of statically allocated devices.
|
|
|
|
*/
|
2020-04-30 20:33:38 +02:00
|
|
|
size_t z_device_get_all_static(const struct device * *devices);
|
2020-06-22 08:55:37 -05:00
|
|
|
|
2020-06-22 10:01:39 -05:00
|
|
|
/** @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.
|
|
|
|
*/
|
2020-04-30 11:49:39 +02:00
|
|
|
bool z_device_ready(const struct device *dev);
|
2020-06-22 10:01:39 -05:00
|
|
|
|
2021-02-12 09:11:51 -06:00
|
|
|
/** @brief Determine whether a device is ready for use
|
|
|
|
*
|
|
|
|
* This is the implementation underlying `device_usable_check()`, without the
|
|
|
|
* overhead of a syscall wrapper.
|
|
|
|
*
|
|
|
|
* @param dev pointer to the device in question.
|
|
|
|
*
|
|
|
|
* @return a non-positive integer as documented in device_usable_check().
|
|
|
|
*/
|
|
|
|
static inline int z_device_usable_check(const struct device *dev)
|
|
|
|
{
|
|
|
|
return z_device_ready(dev) ? 0 : -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @brief Determine whether a device is ready for use.
|
|
|
|
*
|
|
|
|
* This checks whether a device can be used, returning 0 if it can, and
|
|
|
|
* distinct error values that identify the reason if it cannot.
|
|
|
|
*
|
|
|
|
* @retval 0 if the device is usable.
|
2021-05-13 18:24:25 +02:00
|
|
|
* @retval -ENODEV if the device has not been initialized, the device pointer
|
|
|
|
* is NULL or the initialization failed.
|
2021-02-12 09:11:51 -06:00
|
|
|
* @retval other negative error codes to indicate additional conditions that
|
|
|
|
* make the device unusable.
|
|
|
|
*/
|
|
|
|
__syscall int device_usable_check(const struct device *dev);
|
|
|
|
|
|
|
|
static inline int z_impl_device_usable_check(const struct device *dev)
|
|
|
|
{
|
|
|
|
return z_device_usable_check(dev);
|
|
|
|
}
|
|
|
|
|
2020-11-23 07:38:52 -06:00
|
|
|
/** @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
|
2021-08-22 15:35:43 +10:00
|
|
|
* does not include the readiness checks of device_get_binding(). At minimum
|
2020-11-23 07:38:52 -06:00
|
|
|
* 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.
|
2021-05-13 18:24:25 +02:00
|
|
|
* @retval false if the device is not ready for use or if a NULL device pointer
|
|
|
|
* is passed as argument.
|
2020-11-23 07:38:52 -06:00
|
|
|
*/
|
2021-02-12 09:11:51 -06:00
|
|
|
static inline bool device_is_ready(const struct device *dev)
|
|
|
|
{
|
|
|
|
return device_usable_check(dev) == 0;
|
|
|
|
}
|
2020-11-23 07:38:52 -06:00
|
|
|
|
2016-04-21 12:18:12 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2021-01-23 07:56:09 -06:00
|
|
|
/* Node paths can exceed the maximum size supported by device_get_binding() in user mode,
|
|
|
|
* so synthesize a unique dev_name from the devicetree node.
|
|
|
|
*
|
|
|
|
* The ordinal used in this name can be mapped to the path by
|
2021-08-22 15:35:43 +10:00
|
|
|
* examining zephyr/include/generated/device_extern.h header. If the
|
2021-01-23 07:56:09 -06:00
|
|
|
* format of this conversion changes, gen_defines should be updated to
|
|
|
|
* match it.
|
|
|
|
*/
|
|
|
|
#define Z_DEVICE_DT_DEV_NAME(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id))
|
|
|
|
|
2021-02-02 09:19:58 -06:00
|
|
|
/* Synthesize a unique name for the device state associated with
|
|
|
|
* dev_name.
|
|
|
|
*/
|
|
|
|
#define Z_DEVICE_STATE_NAME(dev_name) _CONCAT(__devstate_, dev_name)
|
|
|
|
|
2020-06-23 10:44:53 -05:00
|
|
|
/** Synthesize the name of the object that holds device ordinal and
|
2021-08-22 15:35:43 +10:00
|
|
|
* dependency data. If the object doesn't come from a devicetree
|
2020-06-23 10:44:53 -05:00
|
|
|
* node, use dev_name.
|
|
|
|
*/
|
|
|
|
#define Z_DEVICE_HANDLE_NAME(node_id, dev_name) \
|
|
|
|
_CONCAT(__devicehdl_, \
|
|
|
|
COND_CODE_1(DT_NODE_EXISTS(node_id), \
|
|
|
|
(node_id), \
|
|
|
|
(dev_name)))
|
|
|
|
|
|
|
|
#define Z_DEVICE_EXTRA_HANDLES(...) \
|
|
|
|
FOR_EACH_NONEMPTY_TERM(IDENTITY, (,), __VA_ARGS__)
|
|
|
|
|
2021-08-26 17:33:45 +02:00
|
|
|
/**
|
|
|
|
* @brief Utility macro to define and initialize the device state.
|
|
|
|
|
|
|
|
* @param node_id Devicetree node id of the device.
|
|
|
|
* @param dev_name Device name.
|
|
|
|
*/
|
2021-10-13 12:11:40 +02:00
|
|
|
#define Z_DEVICE_STATE_DEFINE(node_id, dev_name) \
|
2021-08-26 17:33:45 +02:00
|
|
|
static struct device_state Z_DEVICE_STATE_NAME(dev_name) \
|
2021-10-13 12:11:40 +02:00
|
|
|
__attribute__((__section__(".z_devstate")));
|
2021-08-26 17:33:45 +02:00
|
|
|
|
2021-08-22 15:35:43 +10:00
|
|
|
/* Construct objects that are referenced from struct device. These
|
2020-06-23 10:44:53 -05:00
|
|
|
* include power management and dependency handles.
|
|
|
|
*/
|
2021-10-13 12:11:40 +02:00
|
|
|
#define Z_DEVICE_DEFINE_PRE(node_id, dev_name, ...) \
|
2021-05-27 21:00:22 +02:00
|
|
|
Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) \
|
2021-11-22 19:59:37 +01:00
|
|
|
Z_DEVICE_STATE_DEFINE(node_id, dev_name)
|
2020-06-23 10:44:53 -05:00
|
|
|
|
2020-06-30 10:05:35 -05:00
|
|
|
/* Initial build provides a record that associates the device object
|
|
|
|
* with its devicetree ordinal, and provides the dependency ordinals.
|
|
|
|
* These are provided as weak definitions (to prevent the reference
|
|
|
|
* from being captured when the original object file is compiled), and
|
|
|
|
* in a distinct pass1 section (which will be replaced by
|
|
|
|
* postprocessing).
|
|
|
|
*
|
2021-08-20 18:31:18 +10:00
|
|
|
* Before processing in gen_handles.py, the array format is:
|
|
|
|
* {
|
|
|
|
* DEVICE_ORDINAL (or DEVICE_HANDLE_NULL if not a devicetree node),
|
|
|
|
* List of devicetree dependency ordinals (if any),
|
|
|
|
* DEVICE_HANDLE_SEP,
|
|
|
|
* List of injected dependency ordinals (if any),
|
|
|
|
* DEVICE_HANDLE_SEP,
|
|
|
|
* List of devicetree supporting ordinals (if any),
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* After processing in gen_handles.py, the format is updated to:
|
|
|
|
* {
|
|
|
|
* List of existing devicetree dependency handles (if any),
|
|
|
|
* DEVICE_HANDLE_SEP,
|
|
|
|
* List of injected dependency ordinals (if any),
|
|
|
|
* DEVICE_HANDLE_SEP,
|
|
|
|
* List of existing devicetree support handles (if any),
|
|
|
|
* DEVICE_HANDLE_NULL
|
|
|
|
* }
|
|
|
|
*
|
2020-06-30 10:05:35 -05:00
|
|
|
* It is also (experimentally) necessary to provide explicit alignment
|
2021-08-22 15:35:43 +10:00
|
|
|
* on each object. Otherwise x86-64 builds will introduce padding
|
2020-06-30 10:05:35 -05:00
|
|
|
* between objects in the same input section in individual object
|
|
|
|
* files, which will be retained in subsequent links both wasting
|
|
|
|
* space and resulting in aggregate size changes relative to pass2
|
|
|
|
* when all objects will be in the same input section.
|
|
|
|
*
|
|
|
|
* The build assert will fail if device_handle_t changes size, which
|
|
|
|
* means the alignment directives in the linker scripts and in
|
|
|
|
* `gen_handles.py` must be updated.
|
|
|
|
*/
|
|
|
|
BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts");
|
2020-06-23 10:44:53 -05:00
|
|
|
#define Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, ...) \
|
2020-06-30 10:05:35 -05:00
|
|
|
extern const device_handle_t \
|
|
|
|
Z_DEVICE_HANDLE_NAME(node_id, dev_name)[]; \
|
|
|
|
const device_handle_t \
|
|
|
|
__aligned(sizeof(device_handle_t)) \
|
|
|
|
__attribute__((__weak__, \
|
|
|
|
__section__(".__device_handles_pass1"))) \
|
|
|
|
Z_DEVICE_HANDLE_NAME(node_id, dev_name)[] = { \
|
2020-06-23 10:44:53 -05:00
|
|
|
COND_CODE_1(DT_NODE_EXISTS(node_id), ( \
|
|
|
|
DT_DEP_ORD(node_id), \
|
|
|
|
DT_REQUIRES_DEP_ORDS(node_id) \
|
2020-06-30 10:05:35 -05:00
|
|
|
), ( \
|
2020-06-23 10:44:53 -05:00
|
|
|
DEVICE_HANDLE_NULL, \
|
|
|
|
)) \
|
|
|
|
DEVICE_HANDLE_SEP, \
|
|
|
|
Z_DEVICE_EXTRA_HANDLES(__VA_ARGS__) \
|
2021-08-20 18:31:18 +10:00
|
|
|
DEVICE_HANDLE_SEP, \
|
|
|
|
COND_CODE_1(DT_NODE_EXISTS(node_id), \
|
|
|
|
(DT_SUPPORTS_DEP_ORDS(node_id)), ()) \
|
2020-06-23 10:44:53 -05:00
|
|
|
};
|
|
|
|
|
2021-10-13 16:18:47 +02:00
|
|
|
#define Z_DEVICE_DEFINE_INIT(node_id, dev_name) \
|
2021-10-13 12:11:40 +02:00
|
|
|
.handles = Z_DEVICE_HANDLE_NAME(node_id, dev_name),
|
2020-06-23 10:44:53 -05:00
|
|
|
|
|
|
|
/* Like DEVICE_DEFINE but takes a node_id AND a dev_name, and trailing
|
|
|
|
* dependency handles that come from outside devicetree.
|
|
|
|
*/
|
2021-10-13 12:11:40 +02:00
|
|
|
#define Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, pm_device,\
|
2020-06-23 10:44:53 -05:00
|
|
|
data_ptr, cfg_ptr, level, prio, api_ptr, ...) \
|
2021-10-13 12:11:40 +02:00
|
|
|
Z_DEVICE_DEFINE_PRE(node_id, dev_name, __VA_ARGS__) \
|
2021-01-23 07:56:09 -06:00
|
|
|
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
|
2020-11-23 07:38:52 -06:00
|
|
|
const Z_DECL_ALIGN(struct device) \
|
2020-06-23 10:28:34 -05:00
|
|
|
DEVICE_NAME_GET(dev_name) __used \
|
2021-04-23 15:55:53 +03:00
|
|
|
__attribute__((__section__(".z_device_" #level STRINGIFY(prio)"_"))) = { \
|
2020-06-23 10:28:34 -05:00
|
|
|
.name = drv_name, \
|
|
|
|
.config = (cfg_ptr), \
|
|
|
|
.api = (api_ptr), \
|
2021-02-02 09:19:58 -06:00
|
|
|
.state = &Z_DEVICE_STATE_NAME(dev_name), \
|
2020-06-23 10:28:34 -05:00
|
|
|
.data = (data_ptr), \
|
2021-10-13 12:11:40 +02:00
|
|
|
COND_CODE_1(CONFIG_PM_DEVICE, (.pm = pm_device,), ()) \
|
2021-10-13 16:18:47 +02:00
|
|
|
Z_DEVICE_DEFINE_INIT(node_id, dev_name) \
|
2020-06-23 10:28:34 -05:00
|
|
|
}; \
|
2021-01-23 07:56:09 -06:00
|
|
|
BUILD_ASSERT(sizeof(Z_STRINGIFY(drv_name)) <= Z_DEVICE_MAX_NAME_LEN, \
|
2021-02-24 11:28:13 -06:00
|
|
|
Z_STRINGIFY(DEVICE_NAME_GET(drv_name)) " too long"); \
|
2021-01-23 07:56:09 -06:00
|
|
|
Z_INIT_ENTRY_DEFINE(DEVICE_NAME_GET(dev_name), init_fn, \
|
|
|
|
(&DEVICE_NAME_GET(dev_name)), level, prio)
|
2020-06-23 10:28:34 -05:00
|
|
|
|
2016-01-22 12:38:49 -05:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
2019-08-12 12:54:52 -05:00
|
|
|
|
2021-01-14 17:07:20 -06:00
|
|
|
/* device_extern is generated based on devicetree nodes */
|
2021-01-13 11:06:46 -06:00
|
|
|
#include <device_extern.h>
|
|
|
|
|
2019-08-12 12:54:52 -05:00
|
|
|
#include <syscalls/device.h>
|
|
|
|
|
2018-09-14 10:43:44 -07:00
|
|
|
#endif /* ZEPHYR_INCLUDE_DEVICE_H_ */
|