1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <ztest.h>
8 #include <devicetree.h>
9 #include <device.h>
10 #include <drivers/gpio.h>
11
12 #define TEST_GPIO DT_NODELABEL(test_gpio_0)
13 #define TEST_I2C DT_NODELABEL(test_i2c)
14 #define TEST_DEVA DT_NODELABEL(test_dev_a)
15 #define TEST_GPIOX DT_NODELABEL(test_gpiox)
16 #define TEST_DEVB DT_NODELABEL(test_dev_b)
17
18 static const struct device *devlist;
19 static const struct device *devlist_end;
20
21 static device_handle_t init_order[10];
22
dev_init(const struct device * dev)23 static int dev_init(const struct device *dev)
24 {
25 static uint8_t init_idx;
26
27 __ASSERT_NO_MSG(init_idx < ARRAY_SIZE(init_order));
28 init_order[init_idx++] = device_handle_get(dev);
29
30 return 0;
31 }
32
33 DEVICE_DT_DEFINE(TEST_GPIO, dev_init, NULL,
34 NULL, NULL, PRE_KERNEL_1, 90, NULL);
35 DEVICE_DT_DEFINE(TEST_I2C, dev_init, NULL,
36 NULL, NULL, POST_KERNEL, 10, NULL);
37 DEVICE_DT_DEFINE(TEST_DEVA, dev_init, NULL,
38 NULL, NULL, POST_KERNEL, 20, NULL);
39 /* NB: Intentional init devb before required gpiox */
40 DEVICE_DT_DEFINE(TEST_DEVB, dev_init, NULL,
41 NULL, NULL, POST_KERNEL, 30, NULL);
42 DEVICE_DT_DEFINE(TEST_GPIOX, dev_init, NULL,
43 NULL, NULL, POST_KERNEL, 40, NULL);
44
45 #define DEV_HDL(node_id) device_handle_get(DEVICE_DT_GET(node_id))
46
test_init_order(void)47 static void test_init_order(void)
48 {
49 zassert_equal(init_order[0], DEV_HDL(TEST_GPIO),
50 NULL);
51 zassert_equal(init_order[1], DEV_HDL(TEST_I2C),
52 NULL);
53 zassert_equal(init_order[2], DEV_HDL(TEST_DEVA),
54 NULL);
55 zassert_equal(init_order[3], DEV_HDL(TEST_DEVB),
56 NULL);
57 zassert_equal(init_order[4], DEV_HDL(TEST_GPIOX),
58 NULL);
59 }
60
check_handle(device_handle_t hdl,const device_handle_t * hdls,size_t nhdls)61 static bool check_handle(device_handle_t hdl,
62 const device_handle_t *hdls,
63 size_t nhdls)
64 {
65 const device_handle_t *hdle = hdls + nhdls;
66
67 while (hdls < hdle) {
68 if (*hdls == hdl) {
69 return true;
70 }
71 ++hdls;
72 }
73
74 return false;
75 }
76
77 struct requires_context {
78 uint8_t ndevs;
79 const struct device *rdevs[2];
80 };
81
requires_visitor(const struct device * dev,void * context)82 static int requires_visitor(const struct device *dev,
83 void *context)
84 {
85 struct requires_context *ctx = context;
86 const struct device **rdp = ctx->rdevs;
87
88 while (rdp < (ctx->rdevs + ctx->ndevs)) {
89 if (*rdp == NULL) {
90 *rdp = dev;
91 return 0;
92 }
93
94 ++rdp;
95 }
96
97 return -ENOSPC;
98 }
99
test_requires(void)100 static void test_requires(void)
101 {
102 size_t nhdls = 0;
103 const device_handle_t *hdls;
104 const struct device *dev;
105 struct requires_context ctx = { 0 };
106
107 /* TEST_GPIO: no req */
108 dev = device_get_binding(DT_LABEL(TEST_GPIO));
109 zassert_equal(dev, DEVICE_DT_GET(TEST_GPIO), NULL);
110 hdls = device_required_handles_get(dev, &nhdls);
111 zassert_equal(nhdls, 0, NULL);
112 zassert_equal(0, device_required_foreach(dev, requires_visitor, &ctx),
113 NULL);
114
115 /* TEST_I2C: no req */
116 dev = device_get_binding(DT_LABEL(TEST_I2C));
117 zassert_equal(dev, DEVICE_DT_GET(TEST_I2C), NULL);
118 hdls = device_required_handles_get(dev, &nhdls);
119 zassert_equal(nhdls, 0, NULL);
120 zassert_equal(0, device_required_foreach(dev, requires_visitor, &ctx),
121 NULL);
122
123 /* TEST_DEVA: TEST_I2C GPIO */
124 dev = device_get_binding(DT_LABEL(TEST_DEVA));
125 zassert_equal(dev, DEVICE_DT_GET(TEST_DEVA), NULL);
126 hdls = device_required_handles_get(dev, &nhdls);
127 zassert_equal(nhdls, 2, NULL);
128 zassert_true(check_handle(DEV_HDL(TEST_I2C), hdls, nhdls), NULL);
129 zassert_true(check_handle(DEV_HDL(TEST_GPIO), hdls, nhdls), NULL);
130
131 /* Visit fails if not enough space */
132 ctx = (struct requires_context){
133 .ndevs = 1,
134 };
135 zassert_equal(-ENOSPC, device_required_foreach(dev, requires_visitor, &ctx),
136 NULL);
137
138 /* Visit succeeds if enough space. */
139 ctx = (struct requires_context){
140 .ndevs = 2,
141 };
142 zassert_equal(2, device_required_foreach(dev, requires_visitor, &ctx),
143 NULL);
144 zassert_true((ctx.rdevs[0] == device_from_handle(DEV_HDL(TEST_I2C)))
145 || (ctx.rdevs[1] == device_from_handle(DEV_HDL(TEST_I2C))),
146 NULL);
147 zassert_true((ctx.rdevs[0] == device_from_handle(DEV_HDL(TEST_GPIO)))
148 || (ctx.rdevs[1] == device_from_handle(DEV_HDL(TEST_GPIO))),
149 NULL);
150
151 /* TEST_GPIOX: TEST_I2C */
152 dev = device_get_binding(DT_LABEL(TEST_GPIOX));
153 zassert_equal(dev, DEVICE_DT_GET(TEST_GPIOX), NULL);
154 hdls = device_required_handles_get(dev, &nhdls);
155 zassert_equal(nhdls, 1, NULL);
156 zassert_true(check_handle(DEV_HDL(TEST_I2C), hdls, nhdls), NULL);
157 ctx = (struct requires_context){
158 .ndevs = 3,
159 };
160 zassert_equal(1, device_required_foreach(dev, requires_visitor, &ctx),
161 NULL);
162 zassert_true(ctx.rdevs[0] == device_from_handle(DEV_HDL(TEST_I2C)),
163 NULL);
164
165 /* TEST_DEVB: TEST_I2C TEST_GPIOX */
166 dev = device_get_binding(DT_LABEL(TEST_DEVB));
167 zassert_equal(dev, DEVICE_DT_GET(TEST_DEVB), NULL);
168 hdls = device_required_handles_get(dev, &nhdls);
169 zassert_equal(nhdls, 2, NULL);
170 zassert_true(check_handle(DEV_HDL(TEST_I2C), hdls, nhdls), NULL);
171 zassert_true(check_handle(DEV_HDL(TEST_GPIOX), hdls, nhdls), NULL);
172 }
173
174
test_main(void)175 void test_main(void)
176 {
177 size_t ndevs;
178
179 ndevs = z_device_get_all_static(&devlist);
180 devlist_end = devlist + ndevs;
181
182 ztest_test_suite(devicetree_driver,
183 ztest_unit_test(test_init_order),
184 ztest_unit_test(test_requires)
185 );
186 ztest_run_test_suite(devicetree_driver);
187 }
188