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>
diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake
index 9807a44..7e9f173 100644
--- a/cmake/linker_script/common/common-rom.cmake
+++ b/cmake/linker_script/common/common-rom.cmake
@@ -8,9 +8,6 @@
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)
diff --git a/include/zephyr/device.h b/include/zephyr/device.h
index e0ba141..9c6358c 100644
--- a/include/zephyr/device.h
+++ b/include/zephyr/device.h
@@ -167,7 +167,7 @@
#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))
@@ -186,16 +186,6 @@
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 @@
...) \
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 @@
#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 @@
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 @@
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 @@
*
* @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 @@
* @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 @@
.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 @@
* @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 @@
* @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 @@
.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 @@
* @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 @@
* @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 @@
(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);))))
diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h
index 5f32b8c..7938440 100644
--- a/include/zephyr/drivers/can.h
+++ b/include/zephyr/drivers/can.h
@@ -761,7 +761,8 @@
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__)
diff --git a/include/zephyr/drivers/i2c.h b/include/zephyr/drivers/i2c.h
index d8eaee8..7e2e620 100644
--- a/include/zephyr/drivers/i2c.h
+++ b/include/zephyr/drivers/i2c.h
@@ -668,7 +668,8 @@
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__)
diff --git a/include/zephyr/drivers/smbus.h b/include/zephyr/drivers/smbus.h
index f0642d6..47369aa 100644
--- a/include/zephyr/drivers/smbus.h
+++ b/include/zephyr/drivers/smbus.h
@@ -510,7 +510,7 @@
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 \
diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h
index c9aaf38..f6e3985 100644
--- a/include/zephyr/drivers/spi.h
+++ b/include/zephyr/drivers/spi.h
@@ -579,7 +579,7 @@
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 @@
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__)
diff --git a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld
index c6920b5..72a1605 100644
--- a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld
+++ b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld
@@ -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)
diff --git a/include/zephyr/net/ethernet.h b/include/zephyr/net/ethernet.h
index 85856ea..517f717 100644
--- a/include/zephyr/net/ethernet.h
+++ b/include/zephyr/net/ethernet.h
@@ -1171,7 +1171,8 @@
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));
diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h
index 7384adc..879b565 100644
--- a/include/zephyr/net/net_if.h
+++ b/include/zephyr/net/net_if.h
@@ -3378,7 +3378,8 @@
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 @@
#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)
diff --git a/kernel/init.c b/kernel/init.c
index 2c3b13d..e3f0db4 100644
--- a/kernel/init.c
+++ b/kernel/init.c
@@ -361,11 +361,13 @@
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 @@
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);
}
}