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