Browse Source

device: store init function in struct device

Preparation work for device init/de-init functionality.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
pull/85182/head
Gerard Marull-Paretas 6 months ago committed by Henrik Brix Andersen
parent
commit
a0a907c90e
  1. 42
      include/zephyr/device.h
  2. 11
      kernel/init.c
  3. 20
      tests/lib/devicetree/devices/src/main.c

42
include/zephyr/device.h

@ -461,6 +461,8 @@ struct device {
struct device_state *state; struct device_state *state;
/** Address of the device instance private data */ /** Address of the device instance private data */
void *data; void *data;
/** Initialization function (optional) */
int (*init_fn)(const struct device *);
#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__) #if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__)
/** /**
* Optional pointer to dependencies associated with the device. * 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. * @brief Initializer for @ref device.
* *
* @param name_ Name of the device. * @param name_ Name of the device.
* @param init_fn_ Init function (optional).
* @param pm_ Reference to @ref pm_device_base (optional). * @param pm_ Reference to @ref pm_device_base (optional).
* @param data_ Reference to device data. * @param data_ Reference to device data.
* @param config_ Reference to device config. * @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 node_id_ Devicetree node identifier
* @param dev_id_ Device identifier token, as passed to Z_DEVICE_BASE_DEFINE * @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_, \ #define Z_DEVICE_INIT(name_, init_fn_, pm_, data_, config_, api_, state_, deps_, \
dev_id_) \ node_id_, dev_id_) \
{ \ { \
.name = name_, \ .name = name_, \
.config = (config_), \ .config = (config_), \
.api = (api_), \ .api = (api_), \
.state = (state_), \ .state = (state_), \
.data = (data_), \ .data = (data_), \
.init_fn = (init_fn_), \
IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \
IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \ IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \
IF_ENABLED(CONFIG_DEVICE_DT_METADATA, \ IF_ENABLED(CONFIG_DEVICE_DT_METADATA, \
@ -1107,6 +1111,7 @@ device_get_dt_nodelabels(const struct device *dev)
* software device). * software device).
* @param dev_id Device identifier (used to name the defined @ref device). * @param dev_id Device identifier (used to name the defined @ref device).
* @param name Name of the device. * @param name Name of the device.
* @param init_fn Init function.
* @param pm Reference to @ref pm_device_base associated with the device. * @param pm Reference to @ref pm_device_base associated with the device.
* (optional). * (optional).
* @param data Reference to device data. * @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 api Reference to device API.
* @param ... Optional dependencies, manually specified. * @param ... Optional dependencies, manually specified.
*/ */
#define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, prio, api, state, \ #define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, level, prio, api, \
deps) \ state, deps) \
COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \ COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \ COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \
STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \ STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \
device, COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (device_mutable), (device)), \ 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_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. * @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 * @param node_id Devicetree node id for the device (DT_INVALID_NODE if a
* software device). * software device).
* @param dev_id Device identifier. * @param dev_id Device identifier.
* @param init_fn_ Device init function.
* @param level Initialization level. * @param level Initialization level.
* @param prio Initialization priority. * @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) \ Z_DEVICE_CHECK_INIT_LEVEL(level) \
\ \
static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \ static const Z_DECL_ALIGN(struct init_entry) __used __noasan Z_INIT_ENTRY_SECTION( \
level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \ level, prio, Z_DEVICE_INIT_SUB_PRIO(node_id)) \
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \ Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), \ COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), \
(.init_fn = { .dev_rw = init_fn_ }, \ (.dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \
.dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \ (.dev = { .dev = &DEVICE_NAME_GET(dev_id)})) \
(.init_fn = { .dev = init_fn_ }, \
.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 \ static const Z_DECL_ALIGN(struct init_entry) __used __noasan \
__attribute__((__section__(".z_deferred_init"))) \ __attribute__((__section__(".z_deferred_init"))) \
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \ Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), \ COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), \
(.init_fn = { .dev_rw = init_fn_ }, \ (.dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \
.dev = { .dev_rw = &DEVICE_NAME_GET(dev_id)}), \ (.dev = { .dev = &DEVICE_NAME_GET(dev_id)})) \
(.init_fn = { .dev = init_fn_ }, \
.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), \ (IF_ENABLED(DT_NODE_EXISTS(node_id), \
(Z_DEVICE_DT_METADATA_DEFINE(node_id, dev_id);))))\ (Z_DEVICE_DT_METADATA_DEFINE(node_id, dev_id);))))\
\ \
Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \
prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \ level, prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \
COND_CODE_1(DEVICE_DT_DEFER(node_id), \ COND_CODE_1(DEVICE_DT_DEFER(node_id), \
(Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, \ (Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id)), \
init_fn)), \ (Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, level, prio)));\
(Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn, \
level, prio))); \
IF_ENABLED(CONFIG_LLEXT_EXPORT_DEVICES, \ IF_ENABLED(CONFIG_LLEXT_EXPORT_DEVICES, \
(IF_ENABLED(DT_NODE_EXISTS(node_id), \ (IF_ENABLED(DT_NODE_EXISTS(node_id), \
(Z_DEVICE_EXPORT(node_id);)))) (Z_DEVICE_EXPORT(node_id);))))

11
kernel/init.c

@ -302,13 +302,12 @@ extern volatile uintptr_t __stack_chk_guard;
__pinned_bss __pinned_bss
bool z_sys_post_kernel; 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; int rc = 0;
if (entry->init_fn.dev != NULL) { if (dev->init_fn != NULL) {
rc = entry->init_fn.dev(dev); rc = dev->init_fn(dev);
/* Mark device initialized. If initialization /* Mark device initialized. If initialization
* failed, record the error condition. * 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); sys_trace_sys_init_enter(entry, level);
if (dev != NULL) { if (dev != NULL) {
result = do_device_init(entry); result = do_device_init(dev);
} else { } else {
result = entry->init_fn.sys(); 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) { STRUCT_SECTION_FOREACH_ALTERNATE(_deferred_init, init_entry, entry) {
if (entry->dev.dev == dev) { if (entry->dev.dev == dev) {
return do_device_init(entry); return do_device_init(dev);
} }
} }

20
tests/lib/devicetree/devices/src/main.c

@ -86,16 +86,16 @@ ZTEST(devicetree_devices, test_init_get)
DEVICE_DT_GET(TEST_NOLABEL), NULL); DEVICE_DT_GET(TEST_NOLABEL), NULL);
/* Check init functions */ /* Check init functions */
zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_GPIO)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_I2C)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_I2C)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVA)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_DEVA)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVB)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_DEVB)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIOX)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_GPIOX)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_DEVC)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_DEVC)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_PARTITION)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_PARTITION)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_GPIO_INJECTED)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_GPIO_INJECTED)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_GET(manual_dev)->init_fn.dev, dev_init); zassert_equal(DEVICE_GET(manual_dev)->init_fn, dev_init);
zassert_equal(DEVICE_INIT_DT_GET(TEST_NOLABEL)->init_fn.dev, dev_init); zassert_equal(DEVICE_DT_GET(TEST_NOLABEL)->init_fn, dev_init);
} }
ZTEST(devicetree_devices, test_init_order) ZTEST(devicetree_devices, test_init_order)

Loading…
Cancel
Save