1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2013 Google, Inc
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <fdtdec.h>
11*4882a593Smuzhiyun #include <malloc.h>
12*4882a593Smuzhiyun #include <asm/io.h>
13*4882a593Smuzhiyun #include <dm/test.h>
14*4882a593Smuzhiyun #include <dm/root.h>
15*4882a593Smuzhiyun #include <dm/device-internal.h>
16*4882a593Smuzhiyun #include <dm/uclass-internal.h>
17*4882a593Smuzhiyun #include <dm/util.h>
18*4882a593Smuzhiyun #include <test/ut.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
21*4882a593Smuzhiyun
testfdt_drv_ping(struct udevice * dev,int pingval,int * pingret)22*4882a593Smuzhiyun static int testfdt_drv_ping(struct udevice *dev, int pingval, int *pingret)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun const struct dm_test_pdata *pdata = dev->platdata;
25*4882a593Smuzhiyun struct dm_test_priv *priv = dev_get_priv(dev);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun *pingret = pingval + pdata->ping_add;
28*4882a593Smuzhiyun priv->ping_total += *pingret;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun return 0;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun static const struct test_ops test_ops = {
34*4882a593Smuzhiyun .ping = testfdt_drv_ping,
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
testfdt_ofdata_to_platdata(struct udevice * dev)37*4882a593Smuzhiyun static int testfdt_ofdata_to_platdata(struct udevice *dev)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun struct dm_test_pdata *pdata = dev_get_platdata(dev);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun pdata->ping_add = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
42*4882a593Smuzhiyun "ping-add", -1);
43*4882a593Smuzhiyun pdata->base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
44*4882a593Smuzhiyun "ping-expect");
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun return 0;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
testfdt_drv_probe(struct udevice * dev)49*4882a593Smuzhiyun static int testfdt_drv_probe(struct udevice *dev)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun struct dm_test_priv *priv = dev_get_priv(dev);
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun priv->ping_total += DM_TEST_START_TOTAL;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /*
56*4882a593Smuzhiyun * If this device is on a bus, the uclass_flag will be set before
57*4882a593Smuzhiyun * calling this function. This is used by
58*4882a593Smuzhiyun * dm_test_bus_child_pre_probe_uclass().
59*4882a593Smuzhiyun */
60*4882a593Smuzhiyun priv->uclass_total += priv->uclass_flag;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun return 0;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun static const struct udevice_id testfdt_ids[] = {
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun .compatible = "denx,u-boot-fdt-test",
68*4882a593Smuzhiyun .data = DM_TEST_TYPE_FIRST },
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun .compatible = "google,another-fdt-test",
71*4882a593Smuzhiyun .data = DM_TEST_TYPE_SECOND },
72*4882a593Smuzhiyun { }
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun U_BOOT_DRIVER(testfdt_drv) = {
76*4882a593Smuzhiyun .name = "testfdt_drv",
77*4882a593Smuzhiyun .of_match = testfdt_ids,
78*4882a593Smuzhiyun .id = UCLASS_TEST_FDT,
79*4882a593Smuzhiyun .ofdata_to_platdata = testfdt_ofdata_to_platdata,
80*4882a593Smuzhiyun .probe = testfdt_drv_probe,
81*4882a593Smuzhiyun .ops = &test_ops,
82*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct dm_test_priv),
83*4882a593Smuzhiyun .platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /* From here is the testfdt uclass code */
testfdt_ping(struct udevice * dev,int pingval,int * pingret)87*4882a593Smuzhiyun int testfdt_ping(struct udevice *dev, int pingval, int *pingret)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun const struct test_ops *ops = device_get_ops(dev);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun if (!ops->ping)
92*4882a593Smuzhiyun return -ENOSYS;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return ops->ping(dev, pingval, pingret);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun UCLASS_DRIVER(testfdt) = {
98*4882a593Smuzhiyun .name = "testfdt",
99*4882a593Smuzhiyun .id = UCLASS_TEST_FDT,
100*4882a593Smuzhiyun .flags = DM_UC_FLAG_SEQ_ALIAS,
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun struct dm_testprobe_pdata {
104*4882a593Smuzhiyun int probe_err;
105*4882a593Smuzhiyun };
106*4882a593Smuzhiyun
testprobe_drv_probe(struct udevice * dev)107*4882a593Smuzhiyun static int testprobe_drv_probe(struct udevice *dev)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct dm_testprobe_pdata *pdata = dev_get_platdata(dev);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun return pdata->probe_err;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun static const struct udevice_id testprobe_ids[] = {
115*4882a593Smuzhiyun { .compatible = "denx,u-boot-probe-test" },
116*4882a593Smuzhiyun { }
117*4882a593Smuzhiyun };
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun U_BOOT_DRIVER(testprobe_drv) = {
120*4882a593Smuzhiyun .name = "testprobe_drv",
121*4882a593Smuzhiyun .of_match = testprobe_ids,
122*4882a593Smuzhiyun .id = UCLASS_TEST_PROBE,
123*4882a593Smuzhiyun .probe = testprobe_drv_probe,
124*4882a593Smuzhiyun .platdata_auto_alloc_size = sizeof(struct dm_testprobe_pdata),
125*4882a593Smuzhiyun };
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun UCLASS_DRIVER(testprobe) = {
128*4882a593Smuzhiyun .name = "testprobe",
129*4882a593Smuzhiyun .id = UCLASS_TEST_PROBE,
130*4882a593Smuzhiyun .flags = DM_UC_FLAG_SEQ_ALIAS,
131*4882a593Smuzhiyun };
132*4882a593Smuzhiyun
dm_check_devices(struct unit_test_state * uts,int num_devices)133*4882a593Smuzhiyun int dm_check_devices(struct unit_test_state *uts, int num_devices)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun struct udevice *dev;
136*4882a593Smuzhiyun int ret;
137*4882a593Smuzhiyun int i;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /*
140*4882a593Smuzhiyun * Now check that the ping adds are what we expect. This is using the
141*4882a593Smuzhiyun * ping-add property in each node.
142*4882a593Smuzhiyun */
143*4882a593Smuzhiyun for (i = 0; i < num_devices; i++) {
144*4882a593Smuzhiyun uint32_t base;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun ret = uclass_get_device(UCLASS_TEST_FDT, i, &dev);
147*4882a593Smuzhiyun ut_assert(!ret);
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun /*
150*4882a593Smuzhiyun * Get the 'ping-expect' property, which tells us what the
151*4882a593Smuzhiyun * ping add should be. We don't use the platdata because we
152*4882a593Smuzhiyun * want to test the code that sets that up
153*4882a593Smuzhiyun * (testfdt_drv_probe()).
154*4882a593Smuzhiyun */
155*4882a593Smuzhiyun base = fdtdec_get_addr(gd->fdt_blob, dev_of_offset(dev),
156*4882a593Smuzhiyun "ping-expect");
157*4882a593Smuzhiyun debug("dev=%d, base=%d: %s\n", i, base,
158*4882a593Smuzhiyun fdt_get_name(gd->fdt_blob, dev_of_offset(dev), NULL));
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun ut_assert(!dm_check_operations(uts, dev, base,
161*4882a593Smuzhiyun dev_get_priv(dev)));
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun return 0;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /* Test that FDT-based binding works correctly */
dm_test_fdt(struct unit_test_state * uts)168*4882a593Smuzhiyun static int dm_test_fdt(struct unit_test_state *uts)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun const int num_devices = 6;
171*4882a593Smuzhiyun struct udevice *dev;
172*4882a593Smuzhiyun struct uclass *uc;
173*4882a593Smuzhiyun int ret;
174*4882a593Smuzhiyun int i;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun ret = dm_scan_fdt(gd->fdt_blob, false);
177*4882a593Smuzhiyun ut_assert(!ret);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun ret = uclass_get(UCLASS_TEST_FDT, &uc);
180*4882a593Smuzhiyun ut_assert(!ret);
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* These are num_devices compatible root-level device tree nodes */
183*4882a593Smuzhiyun ut_asserteq(num_devices, list_count_items(&uc->dev_head));
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* Each should have platform data but no private data */
186*4882a593Smuzhiyun for (i = 0; i < num_devices; i++) {
187*4882a593Smuzhiyun ret = uclass_find_device(UCLASS_TEST_FDT, i, &dev);
188*4882a593Smuzhiyun ut_assert(!ret);
189*4882a593Smuzhiyun ut_assert(!dev_get_priv(dev));
190*4882a593Smuzhiyun ut_assert(dev->platdata);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun ut_assertok(dm_check_devices(uts, num_devices));
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun return 0;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun DM_TEST(dm_test_fdt, 0);
198*4882a593Smuzhiyun
dm_test_fdt_pre_reloc(struct unit_test_state * uts)199*4882a593Smuzhiyun static int dm_test_fdt_pre_reloc(struct unit_test_state *uts)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun struct uclass *uc;
202*4882a593Smuzhiyun int ret;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun ret = dm_scan_fdt(gd->fdt_blob, true);
205*4882a593Smuzhiyun ut_assert(!ret);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun ret = uclass_get(UCLASS_TEST_FDT, &uc);
208*4882a593Smuzhiyun ut_assert(!ret);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* These is only one pre-reloc device */
211*4882a593Smuzhiyun ut_asserteq(1, list_count_items(&uc->dev_head));
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun return 0;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun DM_TEST(dm_test_fdt_pre_reloc, 0);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* Test that sequence numbers are allocated properly */
dm_test_fdt_uclass_seq(struct unit_test_state * uts)218*4882a593Smuzhiyun static int dm_test_fdt_uclass_seq(struct unit_test_state *uts)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun struct udevice *dev;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /* A few basic santiy tests */
223*4882a593Smuzhiyun ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 3, true, &dev));
224*4882a593Smuzhiyun ut_asserteq_str("b-test", dev->name);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_FDT, 8, true, &dev));
227*4882a593Smuzhiyun ut_asserteq_str("a-test", dev->name);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 5,
230*4882a593Smuzhiyun true, &dev));
231*4882a593Smuzhiyun ut_asserteq_ptr(NULL, dev);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /* Test aliases */
234*4882a593Smuzhiyun ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 6, &dev));
235*4882a593Smuzhiyun ut_asserteq_str("e-test", dev->name);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_find_device_by_seq(UCLASS_TEST_FDT, 7,
238*4882a593Smuzhiyun true, &dev));
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun /*
241*4882a593Smuzhiyun * Note that c-test nodes are not probed since it is not a top-level
242*4882a593Smuzhiyun * node
243*4882a593Smuzhiyun */
244*4882a593Smuzhiyun ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 3, &dev));
245*4882a593Smuzhiyun ut_asserteq_str("b-test", dev->name);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /*
248*4882a593Smuzhiyun * d-test wants sequence number 3 also, but it can't have it because
249*4882a593Smuzhiyun * b-test gets it first.
250*4882a593Smuzhiyun */
251*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 2, &dev));
252*4882a593Smuzhiyun ut_asserteq_str("d-test", dev->name);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun /* d-test actually gets 0 */
255*4882a593Smuzhiyun ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 0, &dev));
256*4882a593Smuzhiyun ut_asserteq_str("d-test", dev->name);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun /* initially no one wants seq 1 */
259*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_TEST_FDT, 1,
260*4882a593Smuzhiyun &dev));
261*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev));
262*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 4, &dev));
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /* But now that it is probed, we can find it */
265*4882a593Smuzhiyun ut_assertok(uclass_get_device_by_seq(UCLASS_TEST_FDT, 1, &dev));
266*4882a593Smuzhiyun ut_asserteq_str("f-test", dev->name);
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun return 0;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun DM_TEST(dm_test_fdt_uclass_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /* Test that we can find a device by device tree offset */
dm_test_fdt_offset(struct unit_test_state * uts)273*4882a593Smuzhiyun static int dm_test_fdt_offset(struct unit_test_state *uts)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun const void *blob = gd->fdt_blob;
276*4882a593Smuzhiyun struct udevice *dev;
277*4882a593Smuzhiyun int node;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun node = fdt_path_offset(blob, "/e-test");
280*4882a593Smuzhiyun ut_assert(node > 0);
281*4882a593Smuzhiyun ut_assertok(uclass_get_device_by_of_offset(UCLASS_TEST_FDT, node,
282*4882a593Smuzhiyun &dev));
283*4882a593Smuzhiyun ut_asserteq_str("e-test", dev->name);
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* This node should not be bound */
286*4882a593Smuzhiyun node = fdt_path_offset(blob, "/junk");
287*4882a593Smuzhiyun ut_assert(node > 0);
288*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT,
289*4882a593Smuzhiyun node, &dev));
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun /* This is not a top level node so should not be probed */
292*4882a593Smuzhiyun node = fdt_path_offset(blob, "/some-bus/c-test@5");
293*4882a593Smuzhiyun ut_assert(node > 0);
294*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_get_device_by_of_offset(UCLASS_TEST_FDT,
295*4882a593Smuzhiyun node, &dev));
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun return 0;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun DM_TEST(dm_test_fdt_offset,
300*4882a593Smuzhiyun DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /**
303*4882a593Smuzhiyun * Test various error conditions with uclass_first_device() and
304*4882a593Smuzhiyun * uclass_next_device()
305*4882a593Smuzhiyun */
dm_test_first_next_device(struct unit_test_state * uts)306*4882a593Smuzhiyun static int dm_test_first_next_device(struct unit_test_state *uts)
307*4882a593Smuzhiyun {
308*4882a593Smuzhiyun struct dm_testprobe_pdata *pdata;
309*4882a593Smuzhiyun struct udevice *dev, *parent = NULL;
310*4882a593Smuzhiyun int count;
311*4882a593Smuzhiyun int ret;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun /* There should be 4 devices */
314*4882a593Smuzhiyun for (ret = uclass_first_device(UCLASS_TEST_PROBE, &dev), count = 0;
315*4882a593Smuzhiyun dev;
316*4882a593Smuzhiyun ret = uclass_next_device(&dev)) {
317*4882a593Smuzhiyun count++;
318*4882a593Smuzhiyun parent = dev_get_parent(dev);
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun ut_assertok(ret);
321*4882a593Smuzhiyun ut_asserteq(4, count);
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun /* Remove them and try again, with an error on the second one */
324*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 1, &dev));
325*4882a593Smuzhiyun pdata = dev_get_platdata(dev);
326*4882a593Smuzhiyun pdata->probe_err = -ENOMEM;
327*4882a593Smuzhiyun device_remove(parent, DM_REMOVE_NORMAL);
328*4882a593Smuzhiyun ut_assertok(uclass_first_device(UCLASS_TEST_PROBE, &dev));
329*4882a593Smuzhiyun ut_asserteq(-ENOMEM, uclass_next_device(&dev));
330*4882a593Smuzhiyun ut_asserteq_ptr(dev, NULL);
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /* Now an error on the first one */
333*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_TEST_PROBE, 0, &dev));
334*4882a593Smuzhiyun pdata = dev_get_platdata(dev);
335*4882a593Smuzhiyun pdata->probe_err = -ENOENT;
336*4882a593Smuzhiyun device_remove(parent, DM_REMOVE_NORMAL);
337*4882a593Smuzhiyun ut_asserteq(-ENOENT, uclass_first_device(UCLASS_TEST_PROBE, &dev));
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun return 0;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun DM_TEST(dm_test_first_next_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun /**
344*4882a593Smuzhiyun * check_devices() - Check return values and pointers
345*4882a593Smuzhiyun *
346*4882a593Smuzhiyun * This runs through a full sequence of uclass_first_device_check()...
347*4882a593Smuzhiyun * uclass_next_device_check() checking that the return values and devices
348*4882a593Smuzhiyun * are correct.
349*4882a593Smuzhiyun *
350*4882a593Smuzhiyun * @uts: Test state
351*4882a593Smuzhiyun * @devlist: List of expected devices
352*4882a593Smuzhiyun * @mask: Indicates which devices should return an error. Device n should
353*4882a593Smuzhiyun * return error (-NOENT - n) if bit n is set, or no error (i.e. 0) if
354*4882a593Smuzhiyun * bit n is clear.
355*4882a593Smuzhiyun */
check_devices(struct unit_test_state * uts,struct udevice * devlist[],int mask)356*4882a593Smuzhiyun static int check_devices(struct unit_test_state *uts,
357*4882a593Smuzhiyun struct udevice *devlist[], int mask)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun int expected_ret;
360*4882a593Smuzhiyun struct udevice *dev;
361*4882a593Smuzhiyun int i;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun expected_ret = (mask & 1) ? -ENOENT : 0;
364*4882a593Smuzhiyun mask >>= 1;
365*4882a593Smuzhiyun ut_asserteq(expected_ret,
366*4882a593Smuzhiyun uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
367*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
368*4882a593Smuzhiyun ut_asserteq_ptr(devlist[i], dev);
369*4882a593Smuzhiyun expected_ret = (mask & 1) ? -ENOENT - (i + 1) : 0;
370*4882a593Smuzhiyun mask >>= 1;
371*4882a593Smuzhiyun ut_asserteq(expected_ret, uclass_next_device_check(&dev));
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun ut_asserteq_ptr(NULL, dev);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun return 0;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun /* Test uclass_first_device_check() and uclass_next_device_check() */
dm_test_first_next_ok_device(struct unit_test_state * uts)379*4882a593Smuzhiyun static int dm_test_first_next_ok_device(struct unit_test_state *uts)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun struct dm_testprobe_pdata *pdata;
382*4882a593Smuzhiyun struct udevice *dev, *parent = NULL, *devlist[4];
383*4882a593Smuzhiyun int count;
384*4882a593Smuzhiyun int ret;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /* There should be 4 devices */
387*4882a593Smuzhiyun count = 0;
388*4882a593Smuzhiyun for (ret = uclass_first_device_check(UCLASS_TEST_PROBE, &dev);
389*4882a593Smuzhiyun dev;
390*4882a593Smuzhiyun ret = uclass_next_device_check(&dev)) {
391*4882a593Smuzhiyun ut_assertok(ret);
392*4882a593Smuzhiyun devlist[count++] = dev;
393*4882a593Smuzhiyun parent = dev_get_parent(dev);
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun ut_asserteq(4, count);
396*4882a593Smuzhiyun ut_assertok(uclass_first_device_check(UCLASS_TEST_PROBE, &dev));
397*4882a593Smuzhiyun ut_assertok(check_devices(uts, devlist, 0));
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* Remove them and try again, with an error on the second one */
400*4882a593Smuzhiyun pdata = dev_get_platdata(devlist[1]);
401*4882a593Smuzhiyun pdata->probe_err = -ENOENT - 1;
402*4882a593Smuzhiyun device_remove(parent, DM_REMOVE_NORMAL);
403*4882a593Smuzhiyun ut_assertok(check_devices(uts, devlist, 1 << 1));
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun /* Now an error on the first one */
406*4882a593Smuzhiyun pdata = dev_get_platdata(devlist[0]);
407*4882a593Smuzhiyun pdata->probe_err = -ENOENT - 0;
408*4882a593Smuzhiyun device_remove(parent, DM_REMOVE_NORMAL);
409*4882a593Smuzhiyun ut_assertok(check_devices(uts, devlist, 3 << 0));
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun /* Now errors on all */
412*4882a593Smuzhiyun pdata = dev_get_platdata(devlist[2]);
413*4882a593Smuzhiyun pdata->probe_err = -ENOENT - 2;
414*4882a593Smuzhiyun pdata = dev_get_platdata(devlist[3]);
415*4882a593Smuzhiyun pdata->probe_err = -ENOENT - 3;
416*4882a593Smuzhiyun device_remove(parent, DM_REMOVE_NORMAL);
417*4882a593Smuzhiyun ut_assertok(check_devices(uts, devlist, 0xf << 0));
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun return 0;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
422