]> git.sur5r.net Git - u-boot/blob - test/dm/bus.c
df8edcb37dd16652aeaa97f6319b1b1ebadc6618
[u-boot] / test / dm / bus.c
1 /*
2  * Copyright (c) 2014 Google, Inc
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <dm/device-internal.h>
10 #include <dm/root.h>
11 #include <dm/test.h>
12 #include <dm/ut.h>
13 #include <dm/util.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 static int testbus_drv_probe(struct udevice *dev)
18 {
19         return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
20 }
21
22 static const struct udevice_id testbus_ids[] = {
23         {
24                 .compatible = "denx,u-boot-test-bus",
25                 .data = DM_TEST_TYPE_FIRST },
26         { }
27 };
28
29 U_BOOT_DRIVER(testbus_drv) = {
30         .name   = "testbus_drv",
31         .of_match       = testbus_ids,
32         .id     = UCLASS_TEST_BUS,
33         .probe  = testbus_drv_probe,
34         .priv_auto_alloc_size = sizeof(struct dm_test_priv),
35         .platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
36         .per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
37 };
38
39 UCLASS_DRIVER(testbus) = {
40         .name           = "testbus",
41         .id             = UCLASS_TEST_BUS,
42 };
43
44 /* Test that we can probe for children */
45 static int dm_test_bus_children(struct dm_test_state *dms)
46 {
47         int num_devices = 4;
48         struct udevice *bus;
49         struct uclass *uc;
50
51         ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
52         ut_asserteq(num_devices, list_count_items(&uc->dev_head));
53
54         /* Probe the bus, which should yield 3 more devices */
55         ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
56         num_devices += 3;
57
58         ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
59         ut_asserteq(num_devices, list_count_items(&uc->dev_head));
60
61         ut_assert(!dm_check_devices(dms, num_devices));
62
63         return 0;
64 }
65 DM_TEST(dm_test_bus_children, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
66
67 /* Test our functions for accessing children */
68 static int dm_test_bus_children_funcs(struct dm_test_state *dms)
69 {
70         const void *blob = gd->fdt_blob;
71         struct udevice *bus, *dev;
72         int node;
73
74         ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
75
76         /* device_get_child() */
77         ut_assertok(device_get_child(bus, 0, &dev));
78         ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev));
79         ut_assertok(device_get_child_by_seq(bus, 5, &dev));
80         ut_assert(dev->flags & DM_FLAG_ACTIVATED);
81         ut_asserteq_str("c-test@5", dev->name);
82
83         /* Device with sequence number 0 should be accessible */
84         ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev));
85         ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
86         ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
87         ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev));
88         ut_assertok(device_get_child_by_seq(bus, 0, &dev));
89         ut_assert(dev->flags & DM_FLAG_ACTIVATED);
90
91         /* There is no device with sequence number 2 */
92         ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev));
93         ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev));
94         ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev));
95
96         /* Looking for something that is not a child */
97         node = fdt_path_offset(blob, "/junk");
98         ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
99         node = fdt_path_offset(blob, "/d-test");
100         ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
101
102         /* Find a valid child */
103         node = fdt_path_offset(blob, "/some-bus/c-test@1");
104         ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
105         ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
106         ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
107         ut_assert(dev->flags & DM_FLAG_ACTIVATED);
108
109         return 0;
110 }
111 DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
112
113 /* Test that the bus can store data about each child */
114 static int dm_test_bus_parent_data(struct dm_test_state *dms)
115 {
116         struct dm_test_parent_data *parent_data;
117         struct udevice *bus, *dev;
118         struct uclass *uc;
119         int value;
120
121         ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
122
123         /* Check that parent data is allocated */
124         ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
125         ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
126         ut_assertok(device_get_child_by_seq(bus, 0, &dev));
127         parent_data = dev_get_parentdata(dev);
128         ut_assert(NULL != parent_data);
129
130         /* Check that it starts at 0 and goes away when device is removed */
131         parent_data->sum += 5;
132         ut_asserteq(5, parent_data->sum);
133         device_remove(dev);
134         ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
135
136         /* Check that we can do this twice */
137         ut_assertok(device_get_child_by_seq(bus, 0, &dev));
138         parent_data = dev_get_parentdata(dev);
139         ut_assert(NULL != parent_data);
140         parent_data->sum += 5;
141         ut_asserteq(5, parent_data->sum);
142
143         /* Add parent data to all children */
144         ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
145         value = 5;
146         uclass_foreach_dev(dev, uc) {
147                 /* Ignore these if they are not on this bus */
148                 if (dev->parent != bus) {
149                         ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
150                         continue;
151                 }
152                 ut_assertok(device_probe(dev));
153                 parent_data = dev_get_parentdata(dev);
154
155                 parent_data->sum = value;
156                 value += 5;
157         }
158
159         /* Check it is still there */
160         value = 5;
161         uclass_foreach_dev(dev, uc) {
162                 /* Ignore these if they are not on this bus */
163                 if (dev->parent != bus)
164                         continue;
165                 parent_data = dev_get_parentdata(dev);
166
167                 ut_asserteq(value, parent_data->sum);
168                 value += 5;
169         }
170
171         return 0;
172 }
173
174 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);