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
);