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