2 * Copyright (c) 2014 Google, Inc
4 * SPDX-License-Identifier: GPL-2.0+
9 #include <dm/device-internal.h>
12 #include <dm/uclass-internal.h>
16 DECLARE_GLOBAL_DATA_PTR;
18 struct dm_test_parent_platdata {
23 FLAG_CHILD_PROBED = 10,
24 FLAG_CHILD_REMOVED = -7,
27 static struct dm_test_state *test_state;
29 static int testbus_drv_probe(struct udevice *dev)
31 return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
34 static int testbus_child_pre_probe(struct udevice *dev)
36 struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
38 parent_data->flag += FLAG_CHILD_PROBED;
43 static int testbus_child_post_remove(struct udevice *dev)
45 struct dm_test_parent_data *parent_data = dev_get_parentdata(dev);
46 struct dm_test_state *dms = test_state;
48 parent_data->flag += FLAG_CHILD_REMOVED;
55 static const struct udevice_id testbus_ids[] = {
57 .compatible = "denx,u-boot-test-bus",
58 .data = DM_TEST_TYPE_FIRST },
62 U_BOOT_DRIVER(testbus_drv) = {
63 .name = "testbus_drv",
64 .of_match = testbus_ids,
65 .id = UCLASS_TEST_BUS,
66 .probe = testbus_drv_probe,
67 .priv_auto_alloc_size = sizeof(struct dm_test_priv),
68 .platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
69 .per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
70 .per_child_platdata_auto_alloc_size =
71 sizeof(struct dm_test_parent_platdata),
72 .child_pre_probe = testbus_child_pre_probe,
73 .child_post_remove = testbus_child_post_remove,
76 UCLASS_DRIVER(testbus) = {
78 .id = UCLASS_TEST_BUS,
81 /* Test that we can probe for children */
82 static int dm_test_bus_children(struct dm_test_state *dms)
88 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
89 ut_asserteq(num_devices, list_count_items(&uc->dev_head));
91 /* Probe the bus, which should yield 3 more devices */
92 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
95 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
96 ut_asserteq(num_devices, list_count_items(&uc->dev_head));
98 ut_assert(!dm_check_devices(dms, num_devices));
102 DM_TEST(dm_test_bus_children, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
104 /* Test our functions for accessing children */
105 static int dm_test_bus_children_funcs(struct dm_test_state *dms)
107 const void *blob = gd->fdt_blob;
108 struct udevice *bus, *dev;
111 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
113 /* device_get_child() */
114 ut_assertok(device_get_child(bus, 0, &dev));
115 ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev));
116 ut_assertok(device_get_child_by_seq(bus, 5, &dev));
117 ut_assert(dev->flags & DM_FLAG_ACTIVATED);
118 ut_asserteq_str("c-test@5", dev->name);
120 /* Device with sequence number 0 should be accessible */
121 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev));
122 ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
123 ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
124 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev));
125 ut_assertok(device_get_child_by_seq(bus, 0, &dev));
126 ut_assert(dev->flags & DM_FLAG_ACTIVATED);
128 /* There is no device with sequence number 2 */
129 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev));
130 ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev));
131 ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev));
133 /* Looking for something that is not a child */
134 node = fdt_path_offset(blob, "/junk");
135 ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
136 node = fdt_path_offset(blob, "/d-test");
137 ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
139 /* Find a valid child */
140 node = fdt_path_offset(blob, "/some-bus/c-test@1");
141 ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
142 ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
143 ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
144 ut_assert(dev->flags & DM_FLAG_ACTIVATED);
148 DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
150 /* Test that we can iterate through children */
151 static int dm_test_bus_children_iterators(struct dm_test_state *dms)
153 struct udevice *bus, *dev, *child;
155 /* Walk through the children one by one */
156 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
157 ut_assertok(device_find_first_child(bus, &dev));
158 ut_asserteq_str("c-test@5", dev->name);
159 ut_assertok(device_find_next_child(&dev));
160 ut_asserteq_str("c-test@0", dev->name);
161 ut_assertok(device_find_next_child(&dev));
162 ut_asserteq_str("c-test@1", dev->name);
163 ut_assertok(device_find_next_child(&dev));
164 ut_asserteq_ptr(dev, NULL);
166 /* Move to the next child without using device_find_first_child() */
167 ut_assertok(device_find_child_by_seq(bus, 5, true, &dev));
168 ut_asserteq_str("c-test@5", dev->name);
169 ut_assertok(device_find_next_child(&dev));
170 ut_asserteq_str("c-test@0", dev->name);
172 /* Try a device with no children */
173 ut_assertok(device_find_first_child(dev, &child));
174 ut_asserteq_ptr(child, NULL);
178 DM_TEST(dm_test_bus_children_iterators,
179 DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
181 /* Test that the bus can store data about each child */
182 static int dm_test_bus_parent_data(struct dm_test_state *dms)
184 struct dm_test_parent_data *parent_data;
185 struct udevice *bus, *dev;
189 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
191 /* Check that parent data is allocated */
192 ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
193 ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
194 ut_assertok(device_get_child_by_seq(bus, 0, &dev));
195 parent_data = dev_get_parentdata(dev);
196 ut_assert(NULL != parent_data);
198 /* Check that it starts at 0 and goes away when device is removed */
199 parent_data->sum += 5;
200 ut_asserteq(5, parent_data->sum);
202 ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
204 /* Check that we can do this twice */
205 ut_assertok(device_get_child_by_seq(bus, 0, &dev));
206 parent_data = dev_get_parentdata(dev);
207 ut_assert(NULL != parent_data);
208 parent_data->sum += 5;
209 ut_asserteq(5, parent_data->sum);
211 /* Add parent data to all children */
212 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
214 uclass_foreach_dev(dev, uc) {
215 /* Ignore these if they are not on this bus */
216 if (dev->parent != bus) {
217 ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
220 ut_assertok(device_probe(dev));
221 parent_data = dev_get_parentdata(dev);
223 parent_data->sum = value;
227 /* Check it is still there */
229 uclass_foreach_dev(dev, uc) {
230 /* Ignore these if they are not on this bus */
231 if (dev->parent != bus)
233 parent_data = dev_get_parentdata(dev);
235 ut_asserteq(value, parent_data->sum);
242 DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
244 /* Test that the bus ops are called when a child is probed/removed */
245 static int dm_test_bus_parent_ops(struct dm_test_state *dms)
247 struct dm_test_parent_data *parent_data;
248 struct udevice *bus, *dev;
252 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
253 ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
255 uclass_foreach_dev(dev, uc) {
256 /* Ignore these if they are not on this bus */
257 if (dev->parent != bus)
259 ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
261 ut_assertok(device_probe(dev));
262 parent_data = dev_get_parentdata(dev);
263 ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
266 uclass_foreach_dev(dev, uc) {
267 /* Ignore these if they are not on this bus */
268 if (dev->parent != bus)
270 parent_data = dev_get_parentdata(dev);
271 ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
272 ut_assertok(device_remove(dev));
273 ut_asserteq_ptr(NULL, dev_get_parentdata(dev));
274 ut_asserteq_ptr(dms->removed, dev);
280 DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
282 /* Test that the bus can store platform data about each child */
283 static int dm_test_bus_parent_platdata(struct dm_test_state *dms)
285 struct dm_test_parent_platdata *plat;
286 struct udevice *bus, *dev;
289 /* Check that the bus has no children */
290 ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
291 device_find_first_child(bus, &dev);
292 ut_asserteq_ptr(NULL, dev);
294 ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
296 for (device_find_first_child(bus, &dev), child_count = 0;
298 device_find_next_child(&dev)) {
299 /* Check that platform data is allocated */
300 plat = dev_get_parent_platdata(dev);
301 ut_assert(plat != NULL);
304 * Check that it is not affected by the device being
308 ut_asserteq(1, plat->count);
312 ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
313 ut_asserteq(1, plat->count);
314 ut_assertok(device_probe(dev));
317 ut_asserteq(3, child_count);
319 /* Removing the bus should also have no effect (it is still bound) */
321 for (device_find_first_child(bus, &dev), child_count = 0;
323 device_find_next_child(&dev)) {
324 /* Check that platform data is allocated */
325 plat = dev_get_parent_platdata(dev);
326 ut_assert(plat != NULL);
327 ut_asserteq(1, plat->count);
330 ut_asserteq(3, child_count);
332 /* Unbind all the children */
334 device_find_first_child(bus, &dev);
339 /* Now the child platdata should be removed and re-added */
341 for (device_find_first_child(bus, &dev), child_count = 0;
343 device_find_next_child(&dev)) {
344 /* Check that platform data is allocated */
345 plat = dev_get_parent_platdata(dev);
346 ut_assert(plat != NULL);
347 ut_asserteq(0, plat->count);
350 ut_asserteq(3, child_count);
354 DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);