]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
1ca7e206 SG |
2 | /* |
3 | * Copyright (c) 2014 Google, Inc | |
1ca7e206 SG |
4 | */ |
5 | ||
6 | #include <common.h> | |
9f8037ea | 7 | #ifdef CONFIG_SANDBOX |
f7ae49fc | 8 | #include <log.h> |
9f8037ea SG |
9 | #include <os.h> |
10 | #endif | |
1ca7e206 | 11 | #include <dm.h> |
240b9320 | 12 | #include <dm/device.h> |
e59f458d | 13 | #include <dm/device-internal.h> |
1ca7e206 | 14 | #include <dm/test.h> |
cdc133bd | 15 | #include <dm/uclass-internal.h> |
1ca7e206 | 16 | #include <dm/util.h> |
0e1fad43 | 17 | #include <test/test.h> |
e721b882 | 18 | #include <test/ut.h> |
1ca7e206 SG |
19 | |
20 | DECLARE_GLOBAL_DATA_PTR; | |
21 | ||
caa4daa2 | 22 | struct dm_test_parent_plat { |
cdc133bd | 23 | int count; |
0118ce79 | 24 | int bind_flag; |
081f2fcb | 25 | int uclass_bind_flag; |
cdc133bd SG |
26 | }; |
27 | ||
a327dee0 SG |
28 | enum { |
29 | FLAG_CHILD_PROBED = 10, | |
30 | FLAG_CHILD_REMOVED = -7, | |
31 | }; | |
32 | ||
33 | static struct dm_test_state *test_state; | |
34 | ||
1ca7e206 SG |
35 | static int testbus_drv_probe(struct udevice *dev) |
36 | { | |
2e3f1ff6 | 37 | return dm_scan_fdt_dev(dev); |
1ca7e206 SG |
38 | } |
39 | ||
0118ce79 SG |
40 | static int testbus_child_post_bind(struct udevice *dev) |
41 | { | |
caa4daa2 | 42 | struct dm_test_parent_plat *plat; |
0118ce79 | 43 | |
caa4daa2 | 44 | plat = dev_get_parent_plat(dev); |
0118ce79 | 45 | plat->bind_flag = 1; |
081f2fcb | 46 | plat->uclass_bind_flag = 2; |
0118ce79 SG |
47 | |
48 | return 0; | |
49 | } | |
50 | ||
a327dee0 SG |
51 | static int testbus_child_pre_probe(struct udevice *dev) |
52 | { | |
bcbe3d15 | 53 | struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); |
a327dee0 SG |
54 | |
55 | parent_data->flag += FLAG_CHILD_PROBED; | |
56 | ||
57 | return 0; | |
58 | } | |
59 | ||
83c7e434 SG |
60 | static int testbus_child_pre_probe_uclass(struct udevice *dev) |
61 | { | |
62 | struct dm_test_priv *priv = dev_get_priv(dev); | |
63 | ||
64 | priv->uclass_flag++; | |
65 | ||
66 | return 0; | |
67 | } | |
68 | ||
d92878aa BM |
69 | static int testbus_child_post_probe_uclass(struct udevice *dev) |
70 | { | |
71 | struct dm_test_priv *priv = dev_get_priv(dev); | |
72 | ||
73 | priv->uclass_postp++; | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
a327dee0 SG |
78 | static int testbus_child_post_remove(struct udevice *dev) |
79 | { | |
bcbe3d15 | 80 | struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev); |
a327dee0 SG |
81 | struct dm_test_state *dms = test_state; |
82 | ||
83 | parent_data->flag += FLAG_CHILD_REMOVED; | |
84 | if (dms) | |
85 | dms->removed = dev; | |
86 | ||
87 | return 0; | |
88 | } | |
89 | ||
1ca7e206 SG |
90 | static const struct udevice_id testbus_ids[] = { |
91 | { | |
92 | .compatible = "denx,u-boot-test-bus", | |
93 | .data = DM_TEST_TYPE_FIRST }, | |
94 | { } | |
95 | }; | |
96 | ||
97 | U_BOOT_DRIVER(testbus_drv) = { | |
98 | .name = "testbus_drv", | |
99 | .of_match = testbus_ids, | |
100 | .id = UCLASS_TEST_BUS, | |
101 | .probe = testbus_drv_probe, | |
0118ce79 | 102 | .child_post_bind = testbus_child_post_bind, |
41575d8e | 103 | .priv_auto = sizeof(struct dm_test_priv), |
caa4daa2 | 104 | .plat_auto = sizeof(struct dm_test_pdata), |
41575d8e | 105 | .per_child_auto = sizeof(struct dm_test_parent_data), |
caa4daa2 SG |
106 | .per_child_plat_auto = |
107 | sizeof(struct dm_test_parent_plat), | |
a327dee0 SG |
108 | .child_pre_probe = testbus_child_pre_probe, |
109 | .child_post_remove = testbus_child_post_remove, | |
1ca7e206 SG |
110 | }; |
111 | ||
112 | UCLASS_DRIVER(testbus) = { | |
113 | .name = "testbus", | |
114 | .id = UCLASS_TEST_BUS, | |
9cc36a2b | 115 | .flags = DM_UC_FLAG_SEQ_ALIAS, |
83c7e434 | 116 | .child_pre_probe = testbus_child_pre_probe_uclass, |
d92878aa | 117 | .child_post_probe = testbus_child_post_probe_uclass, |
1ca7e206 SG |
118 | }; |
119 | ||
120 | /* Test that we can probe for children */ | |
e721b882 | 121 | static int dm_test_bus_children(struct unit_test_state *uts) |
1ca7e206 | 122 | { |
88e6a60e | 123 | int num_devices = 9; |
1ca7e206 SG |
124 | struct udevice *bus; |
125 | struct uclass *uc; | |
126 | ||
127 | ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); | |
128 | ut_asserteq(num_devices, list_count_items(&uc->dev_head)); | |
129 | ||
130 | /* Probe the bus, which should yield 3 more devices */ | |
131 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
132 | num_devices += 3; | |
133 | ||
134 | ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); | |
135 | ut_asserteq(num_devices, list_count_items(&uc->dev_head)); | |
136 | ||
e721b882 | 137 | ut_assert(!dm_check_devices(uts, num_devices)); |
1ca7e206 SG |
138 | |
139 | return 0; | |
140 | } | |
e180c2b1 | 141 | DM_TEST(dm_test_bus_children, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
997c87bb SG |
142 | |
143 | /* Test our functions for accessing children */ | |
e721b882 | 144 | static int dm_test_bus_children_funcs(struct unit_test_state *uts) |
997c87bb SG |
145 | { |
146 | const void *blob = gd->fdt_blob; | |
147 | struct udevice *bus, *dev; | |
148 | int node; | |
149 | ||
150 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
151 | ||
152 | /* device_get_child() */ | |
153 | ut_assertok(device_get_child(bus, 0, &dev)); | |
154 | ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev)); | |
155 | ut_assertok(device_get_child_by_seq(bus, 5, &dev)); | |
156 | ut_assert(dev->flags & DM_FLAG_ACTIVATED); | |
157 | ut_asserteq_str("c-test@5", dev->name); | |
158 | ||
159 | /* Device with sequence number 0 should be accessible */ | |
160 | ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev)); | |
161 | ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); | |
162 | ut_assert(!(dev->flags & DM_FLAG_ACTIVATED)); | |
163 | ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev)); | |
164 | ut_assertok(device_get_child_by_seq(bus, 0, &dev)); | |
165 | ut_assert(dev->flags & DM_FLAG_ACTIVATED); | |
166 | ||
167 | /* There is no device with sequence number 2 */ | |
168 | ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev)); | |
169 | ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev)); | |
170 | ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev)); | |
171 | ||
172 | /* Looking for something that is not a child */ | |
173 | node = fdt_path_offset(blob, "/junk"); | |
174 | ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev)); | |
175 | node = fdt_path_offset(blob, "/d-test"); | |
176 | ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev)); | |
177 | ||
298afb52 SG |
178 | return 0; |
179 | } | |
e180c2b1 | 180 | DM_TEST(dm_test_bus_children_funcs, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
298afb52 SG |
181 | |
182 | static int dm_test_bus_children_of_offset(struct unit_test_state *uts) | |
183 | { | |
184 | const void *blob = gd->fdt_blob; | |
185 | struct udevice *bus, *dev; | |
186 | int node; | |
187 | ||
188 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
4f414d39 | 189 | ut_assertnonnull(bus); |
298afb52 | 190 | |
997c87bb SG |
191 | /* Find a valid child */ |
192 | node = fdt_path_offset(blob, "/some-bus/c-test@1"); | |
298afb52 | 193 | ut_assert(node > 0); |
997c87bb | 194 | ut_assertok(device_find_child_by_of_offset(bus, node, &dev)); |
4f414d39 | 195 | ut_assertnonnull(dev); |
997c87bb SG |
196 | ut_assert(!(dev->flags & DM_FLAG_ACTIVATED)); |
197 | ut_assertok(device_get_child_by_of_offset(bus, node, &dev)); | |
4f414d39 | 198 | ut_assertnonnull(dev); |
997c87bb SG |
199 | ut_assert(dev->flags & DM_FLAG_ACTIVATED); |
200 | ||
201 | return 0; | |
202 | } | |
298afb52 | 203 | DM_TEST(dm_test_bus_children_of_offset, |
e180c2b1 | 204 | UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_FLAT_TREE); |
e59f458d | 205 | |
a8981d4f | 206 | /* Test that we can iterate through children */ |
e721b882 | 207 | static int dm_test_bus_children_iterators(struct unit_test_state *uts) |
a8981d4f SG |
208 | { |
209 | struct udevice *bus, *dev, *child; | |
210 | ||
211 | /* Walk through the children one by one */ | |
212 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
213 | ut_assertok(device_find_first_child(bus, &dev)); | |
214 | ut_asserteq_str("c-test@5", dev->name); | |
215 | ut_assertok(device_find_next_child(&dev)); | |
216 | ut_asserteq_str("c-test@0", dev->name); | |
217 | ut_assertok(device_find_next_child(&dev)); | |
218 | ut_asserteq_str("c-test@1", dev->name); | |
219 | ut_assertok(device_find_next_child(&dev)); | |
220 | ut_asserteq_ptr(dev, NULL); | |
221 | ||
222 | /* Move to the next child without using device_find_first_child() */ | |
223 | ut_assertok(device_find_child_by_seq(bus, 5, true, &dev)); | |
224 | ut_asserteq_str("c-test@5", dev->name); | |
225 | ut_assertok(device_find_next_child(&dev)); | |
226 | ut_asserteq_str("c-test@0", dev->name); | |
227 | ||
228 | /* Try a device with no children */ | |
229 | ut_assertok(device_find_first_child(dev, &child)); | |
230 | ut_asserteq_ptr(child, NULL); | |
231 | ||
232 | return 0; | |
233 | } | |
234 | DM_TEST(dm_test_bus_children_iterators, | |
e180c2b1 | 235 | UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
a8981d4f | 236 | |
e59f458d | 237 | /* Test that the bus can store data about each child */ |
e721b882 | 238 | static int test_bus_parent_data(struct unit_test_state *uts) |
e59f458d SG |
239 | { |
240 | struct dm_test_parent_data *parent_data; | |
241 | struct udevice *bus, *dev; | |
242 | struct uclass *uc; | |
243 | int value; | |
244 | ||
245 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
246 | ||
247 | /* Check that parent data is allocated */ | |
248 | ut_assertok(device_find_child_by_seq(bus, 0, true, &dev)); | |
bcbe3d15 | 249 | ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); |
e59f458d | 250 | ut_assertok(device_get_child_by_seq(bus, 0, &dev)); |
bcbe3d15 | 251 | parent_data = dev_get_parent_priv(dev); |
e59f458d SG |
252 | ut_assert(NULL != parent_data); |
253 | ||
254 | /* Check that it starts at 0 and goes away when device is removed */ | |
255 | parent_data->sum += 5; | |
256 | ut_asserteq(5, parent_data->sum); | |
706865af | 257 | device_remove(dev, DM_REMOVE_NORMAL); |
bcbe3d15 | 258 | ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); |
e59f458d SG |
259 | |
260 | /* Check that we can do this twice */ | |
261 | ut_assertok(device_get_child_by_seq(bus, 0, &dev)); | |
bcbe3d15 | 262 | parent_data = dev_get_parent_priv(dev); |
e59f458d SG |
263 | ut_assert(NULL != parent_data); |
264 | parent_data->sum += 5; | |
265 | ut_asserteq(5, parent_data->sum); | |
266 | ||
267 | /* Add parent data to all children */ | |
268 | ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); | |
269 | value = 5; | |
270 | uclass_foreach_dev(dev, uc) { | |
271 | /* Ignore these if they are not on this bus */ | |
272 | if (dev->parent != bus) { | |
bcbe3d15 | 273 | ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); |
e59f458d SG |
274 | continue; |
275 | } | |
276 | ut_assertok(device_probe(dev)); | |
bcbe3d15 | 277 | parent_data = dev_get_parent_priv(dev); |
e59f458d SG |
278 | |
279 | parent_data->sum = value; | |
280 | value += 5; | |
281 | } | |
282 | ||
283 | /* Check it is still there */ | |
284 | value = 5; | |
285 | uclass_foreach_dev(dev, uc) { | |
286 | /* Ignore these if they are not on this bus */ | |
287 | if (dev->parent != bus) | |
288 | continue; | |
bcbe3d15 | 289 | parent_data = dev_get_parent_priv(dev); |
e59f458d SG |
290 | |
291 | ut_asserteq(value, parent_data->sum); | |
292 | value += 5; | |
293 | } | |
294 | ||
295 | return 0; | |
296 | } | |
dac8db2c | 297 | /* Test that the bus can store data about each child */ |
e721b882 | 298 | static int dm_test_bus_parent_data(struct unit_test_state *uts) |
dac8db2c | 299 | { |
e721b882 | 300 | return test_bus_parent_data(uts); |
dac8db2c | 301 | } |
e180c2b1 | 302 | DM_TEST(dm_test_bus_parent_data, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
a327dee0 | 303 | |
dac8db2c | 304 | /* As above but the size is controlled by the uclass */ |
e721b882 | 305 | static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts) |
dac8db2c | 306 | { |
e23eb614 | 307 | struct driver *drv; |
dac8db2c SG |
308 | struct udevice *bus; |
309 | int size; | |
310 | int ret; | |
311 | ||
312 | /* Set the driver size to 0 so that the uclass size is used */ | |
313 | ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); | |
e23eb614 | 314 | drv = (struct driver *)bus->driver; |
41575d8e | 315 | size = drv->per_child_auto; |
9f8037ea SG |
316 | |
317 | #ifdef CONFIG_SANDBOX | |
318 | os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); | |
319 | os_mprotect_allow(drv, sizeof(*drv)); | |
320 | #endif | |
41575d8e SG |
321 | bus->uclass->uc_drv->per_child_auto = size; |
322 | drv->per_child_auto = 0; | |
e721b882 | 323 | ret = test_bus_parent_data(uts); |
dac8db2c SG |
324 | if (ret) |
325 | return ret; | |
41575d8e SG |
326 | bus->uclass->uc_drv->per_child_auto = 0; |
327 | drv->per_child_auto = size; | |
dac8db2c SG |
328 | |
329 | return 0; | |
330 | } | |
331 | DM_TEST(dm_test_bus_parent_data_uclass, | |
e180c2b1 | 332 | UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
dac8db2c | 333 | |
a327dee0 | 334 | /* Test that the bus ops are called when a child is probed/removed */ |
e721b882 | 335 | static int dm_test_bus_parent_ops(struct unit_test_state *uts) |
a327dee0 SG |
336 | { |
337 | struct dm_test_parent_data *parent_data; | |
e721b882 | 338 | struct dm_test_state *dms = uts->priv; |
a327dee0 SG |
339 | struct udevice *bus, *dev; |
340 | struct uclass *uc; | |
341 | ||
342 | test_state = dms; | |
343 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
344 | ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc)); | |
345 | ||
346 | uclass_foreach_dev(dev, uc) { | |
347 | /* Ignore these if they are not on this bus */ | |
348 | if (dev->parent != bus) | |
349 | continue; | |
bcbe3d15 | 350 | ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); |
a327dee0 SG |
351 | |
352 | ut_assertok(device_probe(dev)); | |
bcbe3d15 | 353 | parent_data = dev_get_parent_priv(dev); |
a327dee0 SG |
354 | ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); |
355 | } | |
356 | ||
357 | uclass_foreach_dev(dev, uc) { | |
358 | /* Ignore these if they are not on this bus */ | |
359 | if (dev->parent != bus) | |
360 | continue; | |
bcbe3d15 | 361 | parent_data = dev_get_parent_priv(dev); |
a327dee0 | 362 | ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag); |
706865af | 363 | ut_assertok(device_remove(dev, DM_REMOVE_NORMAL)); |
bcbe3d15 | 364 | ut_asserteq_ptr(NULL, dev_get_parent_priv(dev)); |
a327dee0 SG |
365 | ut_asserteq_ptr(dms->removed, dev); |
366 | } | |
367 | test_state = NULL; | |
368 | ||
369 | return 0; | |
370 | } | |
e180c2b1 | 371 | DM_TEST(dm_test_bus_parent_ops, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
cdc133bd | 372 | |
caa4daa2 | 373 | static int test_bus_parent_plat(struct unit_test_state *uts) |
cdc133bd | 374 | { |
caa4daa2 | 375 | struct dm_test_parent_plat *plat; |
cdc133bd | 376 | struct udevice *bus, *dev; |
cdc133bd SG |
377 | |
378 | /* Check that the bus has no children */ | |
379 | ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); | |
380 | device_find_first_child(bus, &dev); | |
381 | ut_asserteq_ptr(NULL, dev); | |
382 | ||
383 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
384 | ||
240b9320 | 385 | for (device_find_first_child(bus, &dev); |
cdc133bd SG |
386 | dev; |
387 | device_find_next_child(&dev)) { | |
388 | /* Check that platform data is allocated */ | |
caa4daa2 | 389 | plat = dev_get_parent_plat(dev); |
cdc133bd SG |
390 | ut_assert(plat != NULL); |
391 | ||
392 | /* | |
393 | * Check that it is not affected by the device being | |
394 | * probed/removed | |
395 | */ | |
396 | plat->count++; | |
397 | ut_asserteq(1, plat->count); | |
398 | device_probe(dev); | |
706865af | 399 | device_remove(dev, DM_REMOVE_NORMAL); |
cdc133bd | 400 | |
caa4daa2 | 401 | ut_asserteq_ptr(plat, dev_get_parent_plat(dev)); |
cdc133bd SG |
402 | ut_asserteq(1, plat->count); |
403 | ut_assertok(device_probe(dev)); | |
cdc133bd | 404 | } |
240b9320 | 405 | ut_asserteq(3, device_get_child_count(bus)); |
cdc133bd SG |
406 | |
407 | /* Removing the bus should also have no effect (it is still bound) */ | |
706865af | 408 | device_remove(bus, DM_REMOVE_NORMAL); |
240b9320 | 409 | for (device_find_first_child(bus, &dev); |
cdc133bd SG |
410 | dev; |
411 | device_find_next_child(&dev)) { | |
412 | /* Check that platform data is allocated */ | |
caa4daa2 | 413 | plat = dev_get_parent_plat(dev); |
cdc133bd SG |
414 | ut_assert(plat != NULL); |
415 | ut_asserteq(1, plat->count); | |
cdc133bd | 416 | } |
240b9320 | 417 | ut_asserteq(3, device_get_child_count(bus)); |
cdc133bd SG |
418 | |
419 | /* Unbind all the children */ | |
420 | do { | |
421 | device_find_first_child(bus, &dev); | |
422 | if (dev) | |
423 | device_unbind(dev); | |
424 | } while (dev); | |
425 | ||
caa4daa2 | 426 | /* Now the child plat should be removed and re-added */ |
cdc133bd | 427 | device_probe(bus); |
240b9320 | 428 | for (device_find_first_child(bus, &dev); |
cdc133bd SG |
429 | dev; |
430 | device_find_next_child(&dev)) { | |
431 | /* Check that platform data is allocated */ | |
caa4daa2 | 432 | plat = dev_get_parent_plat(dev); |
cdc133bd SG |
433 | ut_assert(plat != NULL); |
434 | ut_asserteq(0, plat->count); | |
cdc133bd | 435 | } |
240b9320 | 436 | ut_asserteq(3, device_get_child_count(bus)); |
cdc133bd SG |
437 | |
438 | return 0; | |
439 | } | |
ba8da9dc SG |
440 | |
441 | /* Test that the bus can store platform data about each child */ | |
caa4daa2 | 442 | static int dm_test_bus_parent_plat(struct unit_test_state *uts) |
ba8da9dc | 443 | { |
caa4daa2 | 444 | return test_bus_parent_plat(uts); |
ba8da9dc | 445 | } |
caa4daa2 | 446 | DM_TEST(dm_test_bus_parent_plat, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
ba8da9dc SG |
447 | |
448 | /* As above but the size is controlled by the uclass */ | |
caa4daa2 | 449 | static int dm_test_bus_parent_plat_uclass(struct unit_test_state *uts) |
ba8da9dc SG |
450 | { |
451 | struct udevice *bus; | |
e23eb614 | 452 | struct driver *drv; |
ba8da9dc SG |
453 | int size; |
454 | int ret; | |
455 | ||
456 | /* Set the driver size to 0 so that the uclass size is used */ | |
457 | ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus)); | |
e23eb614 | 458 | drv = (struct driver *)bus->driver; |
caa4daa2 | 459 | size = drv->per_child_plat_auto; |
9f8037ea SG |
460 | #ifdef CONFIG_SANDBOX |
461 | os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv)); | |
462 | os_mprotect_allow(drv, sizeof(*drv)); | |
463 | #endif | |
caa4daa2 SG |
464 | bus->uclass->uc_drv->per_child_plat_auto = size; |
465 | drv->per_child_plat_auto = 0; | |
466 | ret = test_bus_parent_plat(uts); | |
ba8da9dc SG |
467 | if (ret) |
468 | return ret; | |
caa4daa2 SG |
469 | bus->uclass->uc_drv->per_child_plat_auto = 0; |
470 | drv->per_child_plat_auto = size; | |
ba8da9dc SG |
471 | |
472 | return 0; | |
473 | } | |
caa4daa2 | 474 | DM_TEST(dm_test_bus_parent_plat_uclass, |
e180c2b1 | 475 | UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
0118ce79 SG |
476 | |
477 | /* Test that the child post_bind method is called */ | |
e721b882 | 478 | static int dm_test_bus_child_post_bind(struct unit_test_state *uts) |
0118ce79 | 479 | { |
caa4daa2 | 480 | struct dm_test_parent_plat *plat; |
0118ce79 | 481 | struct udevice *bus, *dev; |
0118ce79 SG |
482 | |
483 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
240b9320 | 484 | for (device_find_first_child(bus, &dev); |
0118ce79 SG |
485 | dev; |
486 | device_find_next_child(&dev)) { | |
487 | /* Check that platform data is allocated */ | |
caa4daa2 | 488 | plat = dev_get_parent_plat(dev); |
0118ce79 SG |
489 | ut_assert(plat != NULL); |
490 | ut_asserteq(1, plat->bind_flag); | |
0118ce79 | 491 | } |
240b9320 | 492 | ut_asserteq(3, device_get_child_count(bus)); |
0118ce79 SG |
493 | |
494 | return 0; | |
495 | } | |
e180c2b1 | 496 | DM_TEST(dm_test_bus_child_post_bind, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
081f2fcb SG |
497 | |
498 | /* Test that the child post_bind method is called */ | |
e721b882 | 499 | static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts) |
081f2fcb | 500 | { |
caa4daa2 | 501 | struct dm_test_parent_plat *plat; |
081f2fcb | 502 | struct udevice *bus, *dev; |
081f2fcb SG |
503 | |
504 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
240b9320 | 505 | for (device_find_first_child(bus, &dev); |
081f2fcb SG |
506 | dev; |
507 | device_find_next_child(&dev)) { | |
508 | /* Check that platform data is allocated */ | |
caa4daa2 | 509 | plat = dev_get_parent_plat(dev); |
081f2fcb SG |
510 | ut_assert(plat != NULL); |
511 | ut_asserteq(2, plat->uclass_bind_flag); | |
081f2fcb | 512 | } |
240b9320 | 513 | ut_asserteq(3, device_get_child_count(bus)); |
081f2fcb SG |
514 | |
515 | return 0; | |
516 | } | |
517 | DM_TEST(dm_test_bus_child_post_bind_uclass, | |
e180c2b1 | 518 | UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
83c7e434 SG |
519 | |
520 | /* | |
521 | * Test that the bus' uclass' child_pre_probe() is called before the | |
522 | * device's probe() method | |
523 | */ | |
e721b882 | 524 | static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts) |
83c7e434 SG |
525 | { |
526 | struct udevice *bus, *dev; | |
83c7e434 SG |
527 | |
528 | /* | |
529 | * See testfdt_drv_probe() which effectively checks that the uclass | |
530 | * flag is set before that method is called | |
531 | */ | |
532 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
240b9320 | 533 | for (device_find_first_child(bus, &dev); |
83c7e434 SG |
534 | dev; |
535 | device_find_next_child(&dev)) { | |
536 | struct dm_test_priv *priv = dev_get_priv(dev); | |
537 | ||
538 | /* Check that things happened in the right order */ | |
539 | ut_asserteq_ptr(NULL, priv); | |
540 | ut_assertok(device_probe(dev)); | |
541 | ||
542 | priv = dev_get_priv(dev); | |
543 | ut_assert(priv != NULL); | |
544 | ut_asserteq(1, priv->uclass_flag); | |
545 | ut_asserteq(1, priv->uclass_total); | |
83c7e434 | 546 | } |
240b9320 | 547 | ut_asserteq(3, device_get_child_count(bus)); |
83c7e434 SG |
548 | |
549 | return 0; | |
550 | } | |
551 | DM_TEST(dm_test_bus_child_pre_probe_uclass, | |
e180c2b1 | 552 | UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |
d92878aa BM |
553 | |
554 | /* | |
555 | * Test that the bus' uclass' child_post_probe() is called after the | |
556 | * device's probe() method | |
557 | */ | |
558 | static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts) | |
559 | { | |
560 | struct udevice *bus, *dev; | |
d92878aa BM |
561 | |
562 | /* | |
563 | * See testfdt_drv_probe() which effectively initializes that | |
564 | * the uclass postp flag is set to a value | |
565 | */ | |
566 | ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus)); | |
240b9320 | 567 | for (device_find_first_child(bus, &dev); |
d92878aa BM |
568 | dev; |
569 | device_find_next_child(&dev)) { | |
570 | struct dm_test_priv *priv = dev_get_priv(dev); | |
571 | ||
572 | /* Check that things happened in the right order */ | |
573 | ut_asserteq_ptr(NULL, priv); | |
574 | ut_assertok(device_probe(dev)); | |
575 | ||
576 | priv = dev_get_priv(dev); | |
577 | ut_assert(priv != NULL); | |
578 | ut_asserteq(0, priv->uclass_postp); | |
d92878aa | 579 | } |
240b9320 | 580 | ut_asserteq(3, device_get_child_count(bus)); |
d92878aa BM |
581 | |
582 | return 0; | |
583 | } | |
584 | DM_TEST(dm_test_bus_child_post_probe_uclass, | |
e180c2b1 | 585 | UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |