From 766bfe7b2e28fe07c049e7ab6de6aa993c396142 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Mon, 13 Jan 2025 10:32:04 +0100 Subject: [PATCH] device: introduce struct device_ops Instead of passing a single init function, create struct device_ops with the init function inside. This allows to easily extend device's capabilities in the future without too much breakage, e.g. to add a de-init call. Signed-off-by: Gerard Marull-Paretas --- include/zephyr/device.h | 12 +++++++++--- kernel/init.c | 4 ++-- tests/lib/devicetree/devices/src/main.c | 20 ++++++++++---------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/include/zephyr/device.h b/include/zephyr/device.h index 9c6358c1595..5d764b83b59 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -451,6 +451,12 @@ typedef uint8_t device_flags_t; /** @} */ +/** Device operations */ +struct device_ops { + /** Initialization function */ + int (*init)(const struct device *dev); +}; + /** * @brief Runtime device structure (in ROM) per driver instance */ @@ -465,8 +471,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 *); + /** Device operations */ + struct device_ops ops; /** Device flags */ device_flags_t flags; #if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__) @@ -1090,7 +1096,7 @@ device_get_dt_nodelabels(const struct device *dev) .api = (api_), \ .state = (state_), \ .data = (data_), \ - .init_fn = (init_fn_), \ + .ops = { .init = (init_fn_) }, \ .flags = (flags_), \ IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \ diff --git a/kernel/init.c b/kernel/init.c index e3f0db4d3bc..066b11bbf59 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -306,8 +306,8 @@ static int do_device_init(const struct device *dev) { int rc = 0; - if (dev->init_fn != NULL) { - rc = dev->init_fn(dev); + if (dev->ops.init != NULL) { + rc = dev->ops.init(dev); /* Mark device initialized. If initialization * failed, record the error condition. */ diff --git a/tests/lib/devicetree/devices/src/main.c b/tests/lib/devicetree/devices/src/main.c index 6b4f700f82b..291a4a47850 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_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); + zassert_equal(DEVICE_DT_GET(TEST_GPIO)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_I2C)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_DEVA)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_DEVB)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_GPIOX)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_DEVC)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_PARTITION)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_GPIO_INJECTED)->ops.init, dev_init); + zassert_equal(DEVICE_GET(manual_dev)->ops.init, dev_init); + zassert_equal(DEVICE_DT_GET(TEST_NOLABEL)->ops.init, dev_init); } ZTEST(devicetree_devices, test_init_order)