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