Skip to content

Commit 3af95fb

Browse files
committed
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>
1 parent 57c408f commit 3af95fb

File tree

4 files changed

+51
-33
lines changed

4 files changed

+51
-33
lines changed

cmake/linker_script/common/common-rom.cmake

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ zephyr_linker_section_obj_level(SECTION init LEVEL POST_KERNEL)
88
zephyr_linker_section_obj_level(SECTION init LEVEL APPLICATION)
99
zephyr_linker_section_obj_level(SECTION init LEVEL SMP)
1010

11-
zephyr_linker_section(NAME deferred_init_list KVMA RAM_REGION GROUP RODATA_REGION)
12-
zephyr_linker_section_configure(SECTION deferred_init_list INPUT ".z_deferred_init*" KEEP SORT NAME)
13-
1411
zephyr_iterable_section(NAME device NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN ${CONFIG_LINKER_ITERABLE_SUBALIGN})
1512

1613
if(CONFIG_GEN_SW_ISR_TABLE AND NOT CONFIG_DYNAMIC_INTERRUPTS)

include/zephyr/device.h

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ typedef int16_t device_handle_t;
167167
#define DEVICE_DEFINE(dev_id, name, init_fn, pm, data, config, level, prio, \
168168
api) \
169169
Z_DEVICE_STATE_DEFINE(dev_id); \
170-
Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, name, init_fn, pm, data, \
170+
Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_id, name, init_fn, 0U, pm, data, \
171171
config, level, prio, api, \
172172
&Z_DEVICE_STATE_NAME(dev_id))
173173

@@ -230,8 +230,9 @@ typedef int16_t device_handle_t;
230230
...) \
231231
Z_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \
232232
Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \
233-
DEVICE_DT_NAME(node_id), init_fn, pm, data, config, \
234-
level, prio, api, \
233+
DEVICE_DT_NAME(node_id), init_fn, \
234+
Z_DEVICE_DT_FLAGS(node_id), pm, data, config, level, \
235+
prio, api, \
235236
&Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)), \
236237
__VA_ARGS__)
237238

@@ -447,6 +448,19 @@ struct device_dt_metadata;
447448
#define Z_DEVICE_DEPS_CONST const
448449
#endif
449450

451+
/** Device flags */
452+
typedef uint8_t device_flags_t;
453+
454+
/**
455+
* @name Device flags
456+
* @{
457+
*/
458+
459+
/** Device initialization is deferred */
460+
#define DEVICE_FLAG_INIT_DEFERRED BIT(0)
461+
462+
/** @} */
463+
450464
/**
451465
* @brief Runtime device structure (in ROM) per driver instance
452466
*/
@@ -463,6 +477,8 @@ struct device {
463477
void *data;
464478
/** Initialization function (optional) */
465479
int (*init_fn)(const struct device *);
480+
/** Device flags */
481+
device_flags_t flags;
466482
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
467483
/**
468484
* Optional pointer to dependencies associated with the device.
@@ -843,6 +859,14 @@ __syscall int device_init(const struct device *dev);
843859
static Z_DECL_ALIGN(struct device_state) Z_DEVICE_STATE_NAME(dev_id) \
844860
__attribute__((__section__(".z_devstate")))
845861

862+
/**
863+
* @brief Device flags obtained from DT.
864+
*
865+
* @param node_id Devicetree node identifier.
866+
*/
867+
#define Z_DEVICE_DT_FLAGS(node_id) \
868+
(DT_PROP(node_id, zephyr_deferred_init) * DEVICE_FLAG_INIT_DEFERRED)
869+
846870
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
847871

848872
/**
@@ -1058,6 +1082,7 @@ device_get_dt_nodelabels(const struct device *dev)
10581082
*
10591083
* @param name_ Name of the device.
10601084
* @param init_fn_ Init function (optional).
1085+
* @param flags_ Device flags.
10611086
* @param pm_ Reference to @ref pm_device_base (optional).
10621087
* @param data_ Reference to device data.
10631088
* @param config_ Reference to device config.
@@ -1067,15 +1092,16 @@ device_get_dt_nodelabels(const struct device *dev)
10671092
* @param node_id_ Devicetree node identifier
10681093
* @param dev_id_ Device identifier token, as passed to Z_DEVICE_BASE_DEFINE
10691094
*/
1070-
#define Z_DEVICE_INIT(name_, init_fn_, pm_, data_, config_, api_, state_, deps_, \
1071-
node_id_, dev_id_) \
1095+
#define Z_DEVICE_INIT(name_, init_fn_, flags_, pm_, data_, config_, api_, state_, \
1096+
deps_, node_id_, dev_id_) \
10721097
{ \
10731098
.name = name_, \
10741099
.config = (config_), \
10751100
.api = (api_), \
10761101
.state = (state_), \
10771102
.data = (data_), \
10781103
.init_fn = (init_fn_), \
1104+
.flags = (flags_), \
10791105
IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \
10801106
IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \
10811107
IF_ENABLED(CONFIG_DEVICE_DT_METADATA, \
@@ -1112,6 +1138,7 @@ device_get_dt_nodelabels(const struct device *dev)
11121138
* @param dev_id Device identifier (used to name the defined @ref device).
11131139
* @param name Name of the device.
11141140
* @param init_fn Init function.
1141+
* @param flags Device flags.
11151142
* @param pm Reference to @ref pm_device_base associated with the device.
11161143
* (optional).
11171144
* @param data Reference to device data.
@@ -1121,14 +1148,15 @@ device_get_dt_nodelabels(const struct device *dev)
11211148
* @param api Reference to device API.
11221149
* @param ... Optional dependencies, manually specified.
11231150
*/
1124-
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, level, prio, api, \
1125-
state, deps) \
1151+
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, flags, pm, data, config, level, prio, \
1152+
api, state, deps) \
11261153
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
11271154
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \
11281155
STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \
11291156
device, COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (device_mutable), (device)), \
11301157
Z_DEVICE_SECTION_NAME(level, prio), DEVICE_NAME_GET(dev_id)) = \
1131-
Z_DEVICE_INIT(name, init_fn, pm, data, config, api, state, deps, node_id, dev_id)
1158+
Z_DEVICE_INIT(name, init_fn, flags, pm, data, config, api, state, deps, node_id, \
1159+
dev_id)
11321160

11331161
/**
11341162
* @brief Issue an error if the given init level is not supported.
@@ -1159,13 +1187,6 @@ device_get_dt_nodelabels(const struct device *dev)
11591187
.dev = (const struct device *)&DEVICE_NAME_GET(dev_id) \
11601188
}
11611189

1162-
#define Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id) \
1163-
static const Z_DECL_ALIGN(struct init_entry) __used __noasan \
1164-
__attribute__((__section__(".z_deferred_init"))) \
1165-
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
1166-
.dev = (const struct device *)&DEVICE_NAME_GET(dev_id) \
1167-
}
1168-
11691190
/**
11701191
* @brief Define a @ref device and all other required objects.
11711192
*
@@ -1177,6 +1198,7 @@ device_get_dt_nodelabels(const struct device *dev)
11771198
* @param dev_id Device identifier (used to name the defined @ref device).
11781199
* @param name Name of the device.
11791200
* @param init_fn Device init function.
1201+
* @param flags Device flags.
11801202
* @param pm Reference to @ref pm_device_base associated with the device.
11811203
* (optional).
11821204
* @param data Reference to device data.
@@ -1187,7 +1209,7 @@ device_get_dt_nodelabels(const struct device *dev)
11871209
* @param state Reference to device state.
11881210
* @param ... Optional dependencies, manually specified.
11891211
*/
1190-
#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \
1212+
#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, flags, pm, data, config,\
11911213
level, prio, api, state, ...) \
11921214
Z_DEVICE_NAME_CHECK(name); \
11931215
\
@@ -1198,11 +1220,12 @@ device_get_dt_nodelabels(const struct device *dev)
11981220
(IF_ENABLED(DT_NODE_EXISTS(node_id), \
11991221
(Z_DEVICE_DT_METADATA_DEFINE(node_id, dev_id);))))\
12001222
\
1201-
Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \
1202-
level, prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \
1203-
COND_CODE_1(DEVICE_DT_DEFER(node_id), \
1204-
(Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id)), \
1205-
(Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, level, prio)));\
1223+
Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, flags, pm, data, \
1224+
config, level, prio, api, state, \
1225+
Z_DEVICE_DEPS_NAME(dev_id)); \
1226+
\
1227+
Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, level, prio); \
1228+
\
12061229
IF_ENABLED(CONFIG_LLEXT_EXPORT_DEVICES, \
12071230
(IF_ENABLED(DT_NODE_EXISTS(node_id), \
12081231
(Z_DEVICE_EXPORT(node_id);))))

include/zephyr/linker/common-rom/common-rom-kernel-devices.ld

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@
1818
CREATE_OBJ_LEVEL(init, APPLICATION)
1919
CREATE_OBJ_LEVEL(init, SMP)
2020
__init_end = .;
21-
__deferred_init_list_start = .;
22-
KEEP(*(.z_deferred_init*))
23-
__deferred_init_list_end = .;
2421
} GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
2522

2623
ITERABLE_SECTION_ROM_NUMERIC(device, Z_LINK_ITERABLE_SUBALIGN)

kernel/init.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ static void z_sys_init_run_level(enum init_level level)
364364
int result;
365365

366366
sys_trace_sys_init_enter(entry, level);
367-
if (dev != NULL) {
367+
if (dev != NULL && ((dev->flags & DEVICE_FLAG_INIT_DEFERRED) == 0U)) {
368368
result = do_device_init(dev);
369369
} else {
370370
result = entry->init_fn();
@@ -376,12 +376,13 @@ static void z_sys_init_run_level(enum init_level level)
376376

377377
int z_impl_device_init(const struct device *dev)
378378
{
379-
if (dev == NULL) {
380-
return -ENOENT;
381-
}
379+
const struct device *devs;
380+
size_t devc;
381+
382+
devc = z_device_get_all_static(&devs);
382383

383-
STRUCT_SECTION_FOREACH_ALTERNATE(_deferred_init, init_entry, entry) {
384-
if (entry->dev == dev) {
384+
for (const struct device *dev_ = devs; dev_ < (devs + devc); dev_++) {
385+
if ((dev_ == dev) && ((dev->flags & DEVICE_FLAG_INIT_DEFERRED) != 0U)) {
385386
return do_device_init(dev);
386387
}
387388
}

0 commit comments

Comments
 (0)