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