From a0a907c90e47f088571542ef6fa068ba440aeb69 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 9 Jan 2025 17:32:34 +0100 Subject: [PATCH] device: store init function in struct device Preparation work for device init/de-init functionality. Signed-off-by: Gerard Marull-Paretas --- include/zephyr/device.h | 42 ++++++++++++------------- kernel/init.c | 11 +++---- tests/lib/devicetree/devices/src/main.c | 20 ++++++------ 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/include/zephyr/device.h b/include/zephyr/device.h index c7536a45a3d..d8394ef75a6 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -461,6 +461,8 @@ struct device { struct device_state *state; /** Address of the device instance private data */ void *data; + /** Initialization function (optional) */ + int (*init_fn)(const struct device *); #if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__) /** * Optional pointer to dependencies associated with the device. @@ -1055,6 +1057,7 @@ device_get_dt_nodelabels(const struct device *dev) * @brief Initializer for @ref device. * * @param name_ Name of the device. + * @param init_fn_ Init function (optional). * @param pm_ Reference to @ref pm_device_base (optional). * @param data_ Reference to device data. * @param config_ Reference to device config. @@ -1064,14 +1067,15 @@ 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_, pm_, data_, config_, api_, state_, deps_, node_id_, \ - dev_id_) \ +#define Z_DEVICE_INIT(name_, init_fn_, pm_, data_, config_, api_, state_, deps_, \ + node_id_, dev_id_) \ { \ .name = name_, \ .config = (config_), \ .api = (api_), \ .state = (state_), \ .data = (data_), \ + .init_fn = (init_fn_), \ IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \ IF_ENABLED(CONFIG_DEVICE_DT_METADATA, \ @@ -1107,6 +1111,7 @@ device_get_dt_nodelabels(const struct device *dev) * software device). * @param dev_id Device identifier (used to name the defined @ref device). * @param name Name of the device. + * @param init_fn Init function. * @param pm Reference to @ref pm_device_base associated with the device. * (optional). * @param data Reference to device data. @@ -1116,14 +1121,14 @@ 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, pm, data, config, level, prio, api, state, \ - deps) \ +#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, 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, pm, data, config, api, state, deps, node_id, dev_id) + Z_DEVICE_INIT(name, init_fn, pm, data, config, api, state, deps, node_id, dev_id) /** * @brief Issue an error if the given init level is not supported. @@ -1142,32 +1147,27 @@ device_get_dt_nodelabels(const struct device *dev) * @param node_id Devicetree node id for the device (DT_INVALID_NODE if a * software device). * @param dev_id Device identifier. - * @param init_fn_ Device init function. * @param level Initialization level. * @param prio Initialization priority. */ -#define Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_, level, prio) \ +#define Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, level, prio) \ Z_DEVICE_CHECK_INIT_LEVEL(level) \ \ static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \ level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \ Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \ COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), \ - (.init_fn = { .dev_rw = init_fn_ }, \ - .dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \ - (.init_fn = { .dev = init_fn_ }, \ - .dev = { .dev = &DEVICE_NAME_GET(dev_id)})) \ + (.dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \ + (.dev = { .dev = &DEVICE_NAME_GET(dev_id)})) \ } -#define Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_) \ +#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)) = { \ COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), \ - (.init_fn = { .dev_rw = init_fn_ }, \ - .dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \ - (.init_fn = { .dev = init_fn_ }, \ - .dev = { .dev = &DEVICE_NAME_GET(dev_id)})) \ + (.dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \ + (.dev = { .dev = &DEVICE_NAME_GET(dev_id)})) \ } /** @@ -1202,13 +1202,11 @@ 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, pm, data, config, level, \ - prio, api, state, Z_DEVICE_DEPS_NAME(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, \ - init_fn)), \ - (Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn, \ - level, prio))); \ + (Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, 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/kernel/init.c b/kernel/init.c index 1cae55555d8..222b6ff021c 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -302,13 +302,12 @@ extern volatile uintptr_t __stack_chk_guard; __pinned_bss bool z_sys_post_kernel; -static int do_device_init(const struct init_entry *entry) +static int do_device_init(const struct device *dev) { - const struct device *dev = entry->dev.dev; int rc = 0; - if (entry->init_fn.dev != NULL) { - rc = entry->init_fn.dev(dev); + if (dev->init_fn != NULL) { + rc = dev->init_fn(dev); /* Mark device initialized. If initialization * failed, record the error condition. */ @@ -366,7 +365,7 @@ static void z_sys_init_run_level(enum init_level level) sys_trace_sys_init_enter(entry, level); if (dev != NULL) { - result = do_device_init(entry); + result = do_device_init(dev); } else { result = entry->init_fn.sys(); } @@ -383,7 +382,7 @@ int z_impl_device_init(const struct device *dev) STRUCT_SECTION_FOREACH_ALTERNATE(_deferred_init, init_entry, entry) { if (entry->dev.dev == dev) { - return do_device_init(entry); + return do_device_init(dev); } } diff --git a/tests/lib/devicetree/devices/src/main.c b/tests/lib/devicetree/devices/src/main.c index 4aaf02fded2..d40917077c6 100644 --- a/tests/lib/devicetree/devices/src/main.c +++ b/tests/lib/devicetree/devices/src/main.c @@ -86,16 +86,16 @@ ZTEST(devicetree_devices, test_init_get) DEVICE_DT_GET(TEST_NOLABEL), NULL); /* Check init functions */ - zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_I2C)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVA)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVB)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIOX)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVC)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_PARTITION)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO_INJECTED)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_GET(manual_dev)->init_fn.dev, dev_init); - zassert_equal(DEVICE_INIT_DT_GET(TEST_NOLABEL)->init_fn.dev, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_GPIO)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_I2C)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_DEVA)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_DEVB)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_GPIOX)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_DEVC)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_PARTITION)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_GPIO_INJECTED)->init_fn, dev_init); + zassert_equal(DEVICE_GET(manual_dev)->init_fn, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_NOLABEL)->init_fn, dev_init); } ZTEST(devicetree_devices, test_init_order)