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 <gerard.marull@nordicsemi.no>
This commit is contained in:
Gerard Marull-Paretas 2025-01-13 10:32:04 +01:00 committed by Henrik Brix Andersen
parent f44a30109c
commit 766bfe7b2e
3 changed files with 21 additions and 15 deletions

View File

@ -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_)) /**/ \

View File

@ -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.
*/

View File

@ -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)