device: introduce device flags
Introduce a new field to store device flags. Only device deferred init flag has been added, replacing usage of linker hackery to know wether a device requires initialization at boot time or not. This change will be helpful in the near future as devices will become reference counted, so we will need to know wether they have been initialized or not. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
parent
3f6add69da
commit
f44a30109c
10 changed files with 68 additions and 52 deletions
|
@ -8,9 +8,6 @@ zephyr_linker_section_obj_level(SECTION init LEVEL POST_KERNEL)
|
|||
zephyr_linker_section_obj_level(SECTION init LEVEL APPLICATION)
|
||||
zephyr_linker_section_obj_level(SECTION init LEVEL SMP)
|
||||
|
||||
zephyr_linker_section(NAME deferred_init_list KVMA RAM_REGION GROUP RODATA_REGION)
|
||||
zephyr_linker_section_configure(SECTION deferred_init_list INPUT ".z_deferred_init*" KEEP SORT NAME)
|
||||
|
||||
zephyr_iterable_section(NAME device NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
|
||||
|
||||
if(CONFIG_GEN_SW_ISR_TABLE AND NOT CONFIG_DYNAMIC_INTERRUPTS)
|
||||
|
|
|
@ -167,7 +167,7 @@ typedef int16_t device_handle_t;
|
|||
#define DEVICE_DEFINE(dev_id, name, init_fn, pm, data, config, level, prio, \
|
||||
api) \
|
||||
Z_DEVICE_STATE_DEFINE(dev_id); \
|
||||
Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, name, init_fn, pm, data, \
|
||||
Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, name, init_fn, 0U, pm, data, \
|
||||
config, level, prio, api, \
|
||||
&Z_DEVICE_STATE_NAME(dev_id))
|
||||
|
||||
|
@ -185,16 +185,6 @@ typedef int16_t device_handle_t;
|
|||
#define DEVICE_DT_NAME(node_id) \
|
||||
DT_PROP_OR(node_id, label, DT_NODE_FULL_NAME(node_id))
|
||||
|
||||
/**
|
||||
* @brief Determine if a devicetree node initialization should be deferred.
|
||||
*
|
||||
* @param node_id The devicetree node identifier.
|
||||
*
|
||||
* @return Boolean stating if node initialization should be deferred.
|
||||
*/
|
||||
#define DEVICE_DT_DEFER(node_id) \
|
||||
DT_PROP(node_id, zephyr_deferred_init)
|
||||
|
||||
/**
|
||||
* @brief Create a device object from a devicetree node identifier and set it up
|
||||
* for boot time initialization.
|
||||
|
@ -230,8 +220,9 @@ typedef int16_t device_handle_t;
|
|||
...) \
|
||||
Z_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \
|
||||
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
|
||||
DEVICE_DT_NAME(node_id), init_fn, pm, data, config, \
|
||||
level, prio, api, \
|
||||
DEVICE_DT_NAME(node_id), init_fn, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm, data, config, level, \
|
||||
prio, api, \
|
||||
&Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)), \
|
||||
__VA_ARGS__)
|
||||
|
||||
|
@ -447,6 +438,19 @@ struct device_dt_metadata;
|
|||
#define Z_DEVICE_DEPS_CONST const
|
||||
#endif
|
||||
|
||||
/** Device flags */
|
||||
typedef uint8_t device_flags_t;
|
||||
|
||||
/**
|
||||
* @name Device flags
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Device initialization is deferred */
|
||||
#define DEVICE_FLAG_INIT_DEFERRED BIT(0)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Runtime device structure (in ROM) per driver instance
|
||||
*/
|
||||
|
@ -463,6 +467,8 @@ struct device {
|
|||
void *data;
|
||||
/** Initialization function (optional) */
|
||||
int (*init_fn)(const struct device *);
|
||||
/** Device flags */
|
||||
device_flags_t flags;
|
||||
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* Optional pointer to dependencies associated with the device.
|
||||
|
@ -843,6 +849,14 @@ __syscall int device_init(const struct device *dev);
|
|||
static Z_DECL_ALIGN(struct device_state) Z_DEVICE_STATE_NAME(dev_id) \
|
||||
__attribute__((__section__(".z_devstate")))
|
||||
|
||||
/**
|
||||
* @brief Device flags obtained from DT.
|
||||
*
|
||||
* @param node_id Devicetree node identifier.
|
||||
*/
|
||||
#define Z_DEVICE_DT_FLAGS(node_id) \
|
||||
(DT_PROP_OR(node_id, zephyr_deferred_init, 0U) * DEVICE_FLAG_INIT_DEFERRED)
|
||||
|
||||
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
|
||||
|
||||
/**
|
||||
|
@ -1058,6 +1072,7 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
*
|
||||
* @param name_ Name of the device.
|
||||
* @param init_fn_ Init function (optional).
|
||||
* @param flags_ Device flags.
|
||||
* @param pm_ Reference to @ref pm_device_base (optional).
|
||||
* @param data_ Reference to device data.
|
||||
* @param config_ Reference to device config.
|
||||
|
@ -1067,8 +1082,8 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
* @param node_id_ Devicetree node identifier
|
||||
* @param dev_id_ Device identifier token, as passed to Z_DEVICE_BASE_DEFINE
|
||||
*/
|
||||
#define Z_DEVICE_INIT(name_, init_fn_, pm_, data_, config_, api_, state_, deps_, \
|
||||
node_id_, dev_id_) \
|
||||
#define Z_DEVICE_INIT(name_, init_fn_, flags_, pm_, data_, config_, api_, state_, \
|
||||
deps_, node_id_, dev_id_) \
|
||||
{ \
|
||||
.name = name_, \
|
||||
.config = (config_), \
|
||||
|
@ -1076,6 +1091,7 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
.state = (state_), \
|
||||
.data = (data_), \
|
||||
.init_fn = (init_fn_), \
|
||||
.flags = (flags_), \
|
||||
IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \
|
||||
IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \
|
||||
IF_ENABLED(CONFIG_DEVICE_DT_METADATA, \
|
||||
|
@ -1112,6 +1128,7 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
* @param dev_id Device identifier (used to name the defined @ref device).
|
||||
* @param name Name of the device.
|
||||
* @param init_fn Init function.
|
||||
* @param flags Device flags.
|
||||
* @param pm Reference to @ref pm_device_base associated with the device.
|
||||
* (optional).
|
||||
* @param data Reference to device data.
|
||||
|
@ -1121,14 +1138,15 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
* @param api Reference to device API.
|
||||
* @param ... Optional dependencies, manually specified.
|
||||
*/
|
||||
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, level, prio, api, \
|
||||
state, deps) \
|
||||
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, flags, pm, data, config, level, prio, \
|
||||
api, state, deps) \
|
||||
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
|
||||
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \
|
||||
STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \
|
||||
device, COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (device_mutable), (device)), \
|
||||
Z_DEVICE_SECTION_NAME(level, prio), DEVICE_NAME_GET(dev_id)) = \
|
||||
Z_DEVICE_INIT(name, init_fn, pm, data, config, api, state, deps, node_id, dev_id)
|
||||
Z_DEVICE_INIT(name, init_fn, flags, pm, data, config, api, state, deps, node_id, \
|
||||
dev_id)
|
||||
|
||||
/**
|
||||
* @brief Issue an error if the given init level is not supported.
|
||||
|
@ -1159,13 +1177,6 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
.dev = (const struct device *)&DEVICE_NAME_GET(dev_id) \
|
||||
}
|
||||
|
||||
#define Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id) \
|
||||
static const Z_DECL_ALIGN(struct init_entry) __used __noasan \
|
||||
__attribute__((__section__(".z_deferred_init"))) \
|
||||
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
|
||||
.dev = (const struct device *)&DEVICE_NAME_GET(dev_id) \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Define a @ref device and all other required objects.
|
||||
*
|
||||
|
@ -1177,6 +1188,7 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
* @param dev_id Device identifier (used to name the defined @ref device).
|
||||
* @param name Name of the device.
|
||||
* @param init_fn Device init function.
|
||||
* @param flags Device flags.
|
||||
* @param pm Reference to @ref pm_device_base associated with the device.
|
||||
* (optional).
|
||||
* @param data Reference to device data.
|
||||
|
@ -1187,7 +1199,7 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
* @param state Reference to device state.
|
||||
* @param ... Optional dependencies, manually specified.
|
||||
*/
|
||||
#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \
|
||||
#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, flags, pm, data, config,\
|
||||
level, prio, api, state, ...) \
|
||||
Z_DEVICE_NAME_CHECK(name); \
|
||||
\
|
||||
|
@ -1198,11 +1210,12 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
(IF_ENABLED(DT_NODE_EXISTS(node_id), \
|
||||
(Z_DEVICE_DT_METADATA_DEFINE(node_id, dev_id);))))\
|
||||
\
|
||||
Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \
|
||||
level, prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \
|
||||
COND_CODE_1(DEVICE_DT_DEFER(node_id), \
|
||||
(Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id)), \
|
||||
(Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, level, prio)));\
|
||||
Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, flags, pm, data, \
|
||||
config, level, prio, api, state, \
|
||||
Z_DEVICE_DEPS_NAME(dev_id)); \
|
||||
\
|
||||
Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, level, prio); \
|
||||
\
|
||||
IF_ENABLED(CONFIG_LLEXT_EXPORT_DEVICES, \
|
||||
(IF_ENABLED(DT_NODE_EXISTS(node_id), \
|
||||
(Z_DEVICE_EXPORT(node_id);))))
|
||||
|
|
|
@ -761,7 +761,8 @@ struct can_device_state {
|
|||
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
|
||||
DEVICE_DT_NAME(node_id), \
|
||||
&UTIL_CAT(Z_DEVICE_DT_DEV_ID(node_id), _init), \
|
||||
pm, data, config, level, prio, api, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm, data, config, \
|
||||
level, prio, api, \
|
||||
&(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)).devstate), \
|
||||
__VA_ARGS__)
|
||||
|
||||
|
|
|
@ -668,7 +668,8 @@ static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs
|
|||
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
|
||||
DEVICE_DT_NAME(node_id), \
|
||||
&UTIL_CAT(Z_DEVICE_DT_DEV_ID(node_id), _init), \
|
||||
pm, data, config, level, prio, api, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm, data, config, \
|
||||
level, prio, api, \
|
||||
&(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)).devstate), \
|
||||
__VA_ARGS__)
|
||||
|
||||
|
|
|
@ -510,7 +510,7 @@ static inline void smbus_xfer_stats(const struct device *dev, uint8_t sent,
|
|||
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id), \
|
||||
DEVICE_DT_NAME(node_id), \
|
||||
&UTIL_CAT(Z_DEVICE_DT_DEV_NAME(node_id), _init),\
|
||||
pm_device, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm_device, \
|
||||
data_ptr, cfg_ptr, level, prio, \
|
||||
api_ptr, \
|
||||
&(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_NAME \
|
||||
|
|
|
@ -579,7 +579,7 @@ struct spi_device_state {
|
|||
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
|
||||
DEVICE_DT_NAME(node_id), \
|
||||
&UTIL_CAT(Z_DEVICE_DT_DEV_ID(node_id), _init), \
|
||||
pm_device, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm_device, \
|
||||
data_ptr, cfg_ptr, level, prio, \
|
||||
api_ptr, \
|
||||
&(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)).devstate), \
|
||||
|
@ -614,7 +614,8 @@ static inline void spi_transceive_stats(const struct device *dev, int error,
|
|||
api, ...) \
|
||||
Z_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \
|
||||
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
|
||||
DEVICE_DT_NAME(node_id), init_fn, pm, data, config, \
|
||||
DEVICE_DT_NAME(node_id), init_fn, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm, data, config, \
|
||||
level, prio, api, \
|
||||
&Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)), \
|
||||
__VA_ARGS__)
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
CREATE_OBJ_LEVEL(init, APPLICATION)
|
||||
CREATE_OBJ_LEVEL(init, SMP)
|
||||
__init_end = .;
|
||||
__deferred_init_list_start = .;
|
||||
KEEP(*(.z_deferred_init*))
|
||||
__deferred_init_list_end = .;
|
||||
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
|
||||
|
||||
ITERABLE_SECTION_ROM_NUMERIC(device, Z_LINK_ITERABLE_SUBALIGN)
|
||||
|
|
|
@ -1171,7 +1171,8 @@ static inline bool net_eth_is_vlan_interface(struct net_if *iface)
|
|||
init_fn, pm, data, config, prio, \
|
||||
api, mtu) \
|
||||
Z_DEVICE_STATE_DEFINE(dev_id); \
|
||||
Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, \
|
||||
Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm, data, \
|
||||
config, POST_KERNEL, prio, api, \
|
||||
&Z_DEVICE_STATE_NAME(dev_id));
|
||||
|
||||
|
|
|
@ -3378,7 +3378,8 @@ extern int net_stats_prometheus_scrape(struct prometheus_collector *collector,
|
|||
init_fn, pm, data, config, prio, \
|
||||
api, l2, l2_ctx_type, mtu) \
|
||||
Z_DEVICE_STATE_DEFINE(dev_id); \
|
||||
Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, \
|
||||
Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm, data, \
|
||||
config, POST_KERNEL, prio, api, \
|
||||
&Z_DEVICE_STATE_NAME(dev_id)); \
|
||||
NET_L2_DATA_INIT(dev_id, instance, l2_ctx_type); \
|
||||
|
@ -3525,7 +3526,8 @@ extern int net_stats_prometheus_scrape(struct prometheus_collector *collector,
|
|||
#define Z_NET_DEVICE_OFFLOAD_INIT(node_id, dev_id, name, init_fn, pm, \
|
||||
data, config, prio, api, mtu) \
|
||||
Z_DEVICE_STATE_DEFINE(dev_id); \
|
||||
Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, \
|
||||
Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, \
|
||||
Z_DEVICE_DT_FLAGS(node_id), pm, data, \
|
||||
config, POST_KERNEL, prio, api, \
|
||||
&Z_DEVICE_STATE_NAME(dev_id)); \
|
||||
NET_IF_OFFLOAD_INIT(dev_id, 0, mtu)
|
||||
|
|
|
@ -361,11 +361,13 @@ static void z_sys_init_run_level(enum init_level level)
|
|||
|
||||
for (entry = levels[level]; entry < levels[level+1]; entry++) {
|
||||
const struct device *dev = entry->dev;
|
||||
int result;
|
||||
int result = 0;
|
||||
|
||||
sys_trace_sys_init_enter(entry, level);
|
||||
if (dev != NULL) {
|
||||
result = do_device_init(dev);
|
||||
if ((dev->flags & DEVICE_FLAG_INIT_DEFERRED) == 0U) {
|
||||
result = do_device_init(dev);
|
||||
}
|
||||
} else {
|
||||
result = entry->init_fn();
|
||||
}
|
||||
|
@ -376,12 +378,13 @@ static void z_sys_init_run_level(enum init_level level)
|
|||
|
||||
int z_impl_device_init(const struct device *dev)
|
||||
{
|
||||
if (dev == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
const struct device *devs;
|
||||
size_t devc;
|
||||
|
||||
STRUCT_SECTION_FOREACH_ALTERNATE(_deferred_init, init_entry, entry) {
|
||||
if (entry->dev == dev) {
|
||||
devc = z_device_get_all_static(&devs);
|
||||
|
||||
for (const struct device *dev_ = devs; dev_ < (devs + devc); dev_++) {
|
||||
if ((dev_ == dev) && ((dev->flags & DEVICE_FLAG_INIT_DEFERRED) != 0U)) {
|
||||
return do_device_init(dev);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue