xref: /rk3399_rockchip-uboot/test/dm/core.c (revision 2e7d35d2a60339cfa54e26a07326bc75e1060bb3)
1*2e7d35d2SSimon Glass /*
2*2e7d35d2SSimon Glass  * Tests for the core driver model code
3*2e7d35d2SSimon Glass  *
4*2e7d35d2SSimon Glass  * Copyright (c) 2013 Google, Inc
5*2e7d35d2SSimon Glass  *
6*2e7d35d2SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
7*2e7d35d2SSimon Glass  */
8*2e7d35d2SSimon Glass 
9*2e7d35d2SSimon Glass #include <common.h>
10*2e7d35d2SSimon Glass #include <errno.h>
11*2e7d35d2SSimon Glass #include <dm.h>
12*2e7d35d2SSimon Glass #include <fdtdec.h>
13*2e7d35d2SSimon Glass #include <malloc.h>
14*2e7d35d2SSimon Glass #include <dm/device-internal.h>
15*2e7d35d2SSimon Glass #include <dm/root.h>
16*2e7d35d2SSimon Glass #include <dm/ut.h>
17*2e7d35d2SSimon Glass #include <dm/util.h>
18*2e7d35d2SSimon Glass #include <dm/test.h>
19*2e7d35d2SSimon Glass #include <dm/uclass-internal.h>
20*2e7d35d2SSimon Glass 
21*2e7d35d2SSimon Glass DECLARE_GLOBAL_DATA_PTR;
22*2e7d35d2SSimon Glass 
23*2e7d35d2SSimon Glass enum {
24*2e7d35d2SSimon Glass 	TEST_INTVAL1		= 0,
25*2e7d35d2SSimon Glass 	TEST_INTVAL2		= 3,
26*2e7d35d2SSimon Glass 	TEST_INTVAL3		= 6,
27*2e7d35d2SSimon Glass 	TEST_INTVAL_MANUAL	= 101112,
28*2e7d35d2SSimon Glass };
29*2e7d35d2SSimon Glass 
30*2e7d35d2SSimon Glass static const struct dm_test_pdata test_pdata[] = {
31*2e7d35d2SSimon Glass 	{ .ping_add		= TEST_INTVAL1, },
32*2e7d35d2SSimon Glass 	{ .ping_add		= TEST_INTVAL2, },
33*2e7d35d2SSimon Glass 	{ .ping_add		= TEST_INTVAL3, },
34*2e7d35d2SSimon Glass };
35*2e7d35d2SSimon Glass 
36*2e7d35d2SSimon Glass static const struct dm_test_pdata test_pdata_manual = {
37*2e7d35d2SSimon Glass 	.ping_add		= TEST_INTVAL_MANUAL,
38*2e7d35d2SSimon Glass };
39*2e7d35d2SSimon Glass 
40*2e7d35d2SSimon Glass U_BOOT_DEVICE(dm_test_info1) = {
41*2e7d35d2SSimon Glass 	.name = "test_drv",
42*2e7d35d2SSimon Glass 	.platdata = &test_pdata[0],
43*2e7d35d2SSimon Glass };
44*2e7d35d2SSimon Glass 
45*2e7d35d2SSimon Glass U_BOOT_DEVICE(dm_test_info2) = {
46*2e7d35d2SSimon Glass 	.name = "test_drv",
47*2e7d35d2SSimon Glass 	.platdata = &test_pdata[1],
48*2e7d35d2SSimon Glass };
49*2e7d35d2SSimon Glass 
50*2e7d35d2SSimon Glass U_BOOT_DEVICE(dm_test_info3) = {
51*2e7d35d2SSimon Glass 	.name = "test_drv",
52*2e7d35d2SSimon Glass 	.platdata = &test_pdata[2],
53*2e7d35d2SSimon Glass };
54*2e7d35d2SSimon Glass 
55*2e7d35d2SSimon Glass static struct driver_info driver_info_manual = {
56*2e7d35d2SSimon Glass 	.name = "test_manual_drv",
57*2e7d35d2SSimon Glass 	.platdata = &test_pdata_manual,
58*2e7d35d2SSimon Glass };
59*2e7d35d2SSimon Glass 
60*2e7d35d2SSimon Glass /* Test that binding with platdata occurs correctly */
61*2e7d35d2SSimon Glass static int dm_test_autobind(struct dm_test_state *dms)
62*2e7d35d2SSimon Glass {
63*2e7d35d2SSimon Glass 	struct device *dev;
64*2e7d35d2SSimon Glass 
65*2e7d35d2SSimon Glass 	/*
66*2e7d35d2SSimon Glass 	 * We should have a single class (UCLASS_ROOT) and a single root
67*2e7d35d2SSimon Glass 	 * device with no children.
68*2e7d35d2SSimon Glass 	 */
69*2e7d35d2SSimon Glass 	ut_assert(dms->root);
70*2e7d35d2SSimon Glass 	ut_asserteq(1, list_count_items(&gd->uclass_root));
71*2e7d35d2SSimon Glass 	ut_asserteq(0, list_count_items(&gd->dm_root->child_head));
72*2e7d35d2SSimon Glass 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]);
73*2e7d35d2SSimon Glass 
74*2e7d35d2SSimon Glass 	ut_assertok(dm_scan_platdata());
75*2e7d35d2SSimon Glass 
76*2e7d35d2SSimon Glass 	/* We should have our test class now at least, plus more children */
77*2e7d35d2SSimon Glass 	ut_assert(1 < list_count_items(&gd->uclass_root));
78*2e7d35d2SSimon Glass 	ut_assert(0 < list_count_items(&gd->dm_root->child_head));
79*2e7d35d2SSimon Glass 
80*2e7d35d2SSimon Glass 	/* Our 3 dm_test_infox children should be bound to the test uclass */
81*2e7d35d2SSimon Glass 	ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]);
82*2e7d35d2SSimon Glass 
83*2e7d35d2SSimon Glass 	/* No devices should be probed */
84*2e7d35d2SSimon Glass 	list_for_each_entry(dev, &gd->dm_root->child_head, sibling_node)
85*2e7d35d2SSimon Glass 		ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
86*2e7d35d2SSimon Glass 
87*2e7d35d2SSimon Glass 	/* Our test driver should have been bound 3 times */
88*2e7d35d2SSimon Glass 	ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] == 3);
89*2e7d35d2SSimon Glass 
90*2e7d35d2SSimon Glass 	return 0;
91*2e7d35d2SSimon Glass }
92*2e7d35d2SSimon Glass DM_TEST(dm_test_autobind, 0);
93*2e7d35d2SSimon Glass 
94*2e7d35d2SSimon Glass /* Test that autoprobe finds all the expected devices */
95*2e7d35d2SSimon Glass static int dm_test_autoprobe(struct dm_test_state *dms)
96*2e7d35d2SSimon Glass {
97*2e7d35d2SSimon Glass 	int expected_base_add;
98*2e7d35d2SSimon Glass 	struct device *dev;
99*2e7d35d2SSimon Glass 	struct uclass *uc;
100*2e7d35d2SSimon Glass 	int i;
101*2e7d35d2SSimon Glass 
102*2e7d35d2SSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST, &uc));
103*2e7d35d2SSimon Glass 	ut_assert(uc);
104*2e7d35d2SSimon Glass 
105*2e7d35d2SSimon Glass 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]);
106*2e7d35d2SSimon Glass 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]);
107*2e7d35d2SSimon Glass 
108*2e7d35d2SSimon Glass 	/* The root device should not be activated until needed */
109*2e7d35d2SSimon Glass 	ut_assert(!(dms->root->flags & DM_FLAG_ACTIVATED));
110*2e7d35d2SSimon Glass 
111*2e7d35d2SSimon Glass 	/*
112*2e7d35d2SSimon Glass 	 * We should be able to find the three test devices, and they should
113*2e7d35d2SSimon Glass 	 * all be activated as they are used (lazy activation, required by
114*2e7d35d2SSimon Glass 	 * U-Boot)
115*2e7d35d2SSimon Glass 	 */
116*2e7d35d2SSimon Glass 	for (i = 0; i < 3; i++) {
117*2e7d35d2SSimon Glass 		ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev));
118*2e7d35d2SSimon Glass 		ut_assert(dev);
119*2e7d35d2SSimon Glass 		ut_assertf(!(dev->flags & DM_FLAG_ACTIVATED),
120*2e7d35d2SSimon Glass 			   "Driver %d/%s already activated", i, dev->name);
121*2e7d35d2SSimon Glass 
122*2e7d35d2SSimon Glass 		/* This should activate it */
123*2e7d35d2SSimon Glass 		ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev));
124*2e7d35d2SSimon Glass 		ut_assert(dev);
125*2e7d35d2SSimon Glass 		ut_assert(dev->flags & DM_FLAG_ACTIVATED);
126*2e7d35d2SSimon Glass 
127*2e7d35d2SSimon Glass 		/* Activating a device should activate the root device */
128*2e7d35d2SSimon Glass 		if (!i)
129*2e7d35d2SSimon Glass 			ut_assert(dms->root->flags & DM_FLAG_ACTIVATED);
130*2e7d35d2SSimon Glass 	}
131*2e7d35d2SSimon Glass 
132*2e7d35d2SSimon Glass 	/* Our 3 dm_test_infox children should be passed to post_probe */
133*2e7d35d2SSimon Glass 	ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]);
134*2e7d35d2SSimon Glass 
135*2e7d35d2SSimon Glass 	/* Also we can check the per-device data */
136*2e7d35d2SSimon Glass 	expected_base_add = 0;
137*2e7d35d2SSimon Glass 	for (i = 0; i < 3; i++) {
138*2e7d35d2SSimon Glass 		struct dm_test_uclass_perdev_priv *priv;
139*2e7d35d2SSimon Glass 		struct dm_test_pdata *pdata;
140*2e7d35d2SSimon Glass 
141*2e7d35d2SSimon Glass 		ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev));
142*2e7d35d2SSimon Glass 		ut_assert(dev);
143*2e7d35d2SSimon Glass 
144*2e7d35d2SSimon Glass 		priv = dev->uclass_priv;
145*2e7d35d2SSimon Glass 		ut_assert(priv);
146*2e7d35d2SSimon Glass 		ut_asserteq(expected_base_add, priv->base_add);
147*2e7d35d2SSimon Glass 
148*2e7d35d2SSimon Glass 		pdata = dev->platdata;
149*2e7d35d2SSimon Glass 		expected_base_add += pdata->ping_add;
150*2e7d35d2SSimon Glass 	}
151*2e7d35d2SSimon Glass 
152*2e7d35d2SSimon Glass 	return 0;
153*2e7d35d2SSimon Glass }
154*2e7d35d2SSimon Glass DM_TEST(dm_test_autoprobe, DM_TESTF_SCAN_PDATA);
155*2e7d35d2SSimon Glass 
156*2e7d35d2SSimon Glass /* Check that we see the correct platdata in each device */
157*2e7d35d2SSimon Glass static int dm_test_platdata(struct dm_test_state *dms)
158*2e7d35d2SSimon Glass {
159*2e7d35d2SSimon Glass 	const struct dm_test_pdata *pdata;
160*2e7d35d2SSimon Glass 	struct device *dev;
161*2e7d35d2SSimon Glass 	int i;
162*2e7d35d2SSimon Glass 
163*2e7d35d2SSimon Glass 	for (i = 0; i < 3; i++) {
164*2e7d35d2SSimon Glass 		ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev));
165*2e7d35d2SSimon Glass 		ut_assert(dev);
166*2e7d35d2SSimon Glass 		pdata = dev->platdata;
167*2e7d35d2SSimon Glass 		ut_assert(pdata->ping_add == test_pdata[i].ping_add);
168*2e7d35d2SSimon Glass 	}
169*2e7d35d2SSimon Glass 
170*2e7d35d2SSimon Glass 	return 0;
171*2e7d35d2SSimon Glass }
172*2e7d35d2SSimon Glass DM_TEST(dm_test_platdata, DM_TESTF_SCAN_PDATA);
173*2e7d35d2SSimon Glass 
174*2e7d35d2SSimon Glass /* Test that we can bind, probe, remove, unbind a driver */
175*2e7d35d2SSimon Glass static int dm_test_lifecycle(struct dm_test_state *dms)
176*2e7d35d2SSimon Glass {
177*2e7d35d2SSimon Glass 	int op_count[DM_TEST_OP_COUNT];
178*2e7d35d2SSimon Glass 	struct device *dev, *test_dev;
179*2e7d35d2SSimon Glass 	int pingret;
180*2e7d35d2SSimon Glass 	int ret;
181*2e7d35d2SSimon Glass 
182*2e7d35d2SSimon Glass 	memcpy(op_count, dm_testdrv_op_count, sizeof(op_count));
183*2e7d35d2SSimon Glass 
184*2e7d35d2SSimon Glass 	ut_assertok(device_bind_by_name(dms->root, &driver_info_manual,
185*2e7d35d2SSimon Glass 					&dev));
186*2e7d35d2SSimon Glass 	ut_assert(dev);
187*2e7d35d2SSimon Glass 	ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND]
188*2e7d35d2SSimon Glass 			== op_count[DM_TEST_OP_BIND] + 1);
189*2e7d35d2SSimon Glass 	ut_assert(!dev->priv);
190*2e7d35d2SSimon Glass 
191*2e7d35d2SSimon Glass 	/* Probe the device - it should fail allocating private data */
192*2e7d35d2SSimon Glass 	dms->force_fail_alloc = 1;
193*2e7d35d2SSimon Glass 	ret = device_probe(dev);
194*2e7d35d2SSimon Glass 	ut_assert(ret == -ENOMEM);
195*2e7d35d2SSimon Glass 	ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE]
196*2e7d35d2SSimon Glass 			== op_count[DM_TEST_OP_PROBE] + 1);
197*2e7d35d2SSimon Glass 	ut_assert(!dev->priv);
198*2e7d35d2SSimon Glass 
199*2e7d35d2SSimon Glass 	/* Try again without the alloc failure */
200*2e7d35d2SSimon Glass 	dms->force_fail_alloc = 0;
201*2e7d35d2SSimon Glass 	ut_assertok(device_probe(dev));
202*2e7d35d2SSimon Glass 	ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE]
203*2e7d35d2SSimon Glass 			== op_count[DM_TEST_OP_PROBE] + 2);
204*2e7d35d2SSimon Glass 	ut_assert(dev->priv);
205*2e7d35d2SSimon Glass 
206*2e7d35d2SSimon Glass 	/* This should be device 3 in the uclass */
207*2e7d35d2SSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev));
208*2e7d35d2SSimon Glass 	ut_assert(dev == test_dev);
209*2e7d35d2SSimon Glass 
210*2e7d35d2SSimon Glass 	/* Try ping */
211*2e7d35d2SSimon Glass 	ut_assertok(test_ping(dev, 100, &pingret));
212*2e7d35d2SSimon Glass 	ut_assert(pingret == 102);
213*2e7d35d2SSimon Glass 
214*2e7d35d2SSimon Glass 	/* Now remove device 3 */
215*2e7d35d2SSimon Glass 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]);
216*2e7d35d2SSimon Glass 	ut_assertok(device_remove(dev));
217*2e7d35d2SSimon Glass 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_REMOVE]);
218*2e7d35d2SSimon Glass 
219*2e7d35d2SSimon Glass 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_UNBIND]);
220*2e7d35d2SSimon Glass 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]);
221*2e7d35d2SSimon Glass 	ut_assertok(device_unbind(dev));
222*2e7d35d2SSimon Glass 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]);
223*2e7d35d2SSimon Glass 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_PRE_UNBIND]);
224*2e7d35d2SSimon Glass 
225*2e7d35d2SSimon Glass 	return 0;
226*2e7d35d2SSimon Glass }
227*2e7d35d2SSimon Glass DM_TEST(dm_test_lifecycle, DM_TESTF_SCAN_PDATA | DM_TESTF_PROBE_TEST);
228*2e7d35d2SSimon Glass 
229*2e7d35d2SSimon Glass /* Test that we can bind/unbind and the lists update correctly */
230*2e7d35d2SSimon Glass static int dm_test_ordering(struct dm_test_state *dms)
231*2e7d35d2SSimon Glass {
232*2e7d35d2SSimon Glass 	struct device *dev, *dev_penultimate, *dev_last, *test_dev;
233*2e7d35d2SSimon Glass 	int pingret;
234*2e7d35d2SSimon Glass 
235*2e7d35d2SSimon Glass 	ut_assertok(device_bind_by_name(dms->root, &driver_info_manual,
236*2e7d35d2SSimon Glass 					&dev));
237*2e7d35d2SSimon Glass 	ut_assert(dev);
238*2e7d35d2SSimon Glass 
239*2e7d35d2SSimon Glass 	/* Bind two new devices (numbers 4 and 5) */
240*2e7d35d2SSimon Glass 	ut_assertok(device_bind_by_name(dms->root, &driver_info_manual,
241*2e7d35d2SSimon Glass 					&dev_penultimate));
242*2e7d35d2SSimon Glass 	ut_assert(dev_penultimate);
243*2e7d35d2SSimon Glass 	ut_assertok(device_bind_by_name(dms->root, &driver_info_manual,
244*2e7d35d2SSimon Glass 					&dev_last));
245*2e7d35d2SSimon Glass 	ut_assert(dev_last);
246*2e7d35d2SSimon Glass 
247*2e7d35d2SSimon Glass 	/* Now remove device 3 */
248*2e7d35d2SSimon Glass 	ut_assertok(device_remove(dev));
249*2e7d35d2SSimon Glass 	ut_assertok(device_unbind(dev));
250*2e7d35d2SSimon Glass 
251*2e7d35d2SSimon Glass 	/* The device numbering should have shifted down one */
252*2e7d35d2SSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev));
253*2e7d35d2SSimon Glass 	ut_assert(dev_penultimate == test_dev);
254*2e7d35d2SSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST, 4, &test_dev));
255*2e7d35d2SSimon Glass 	ut_assert(dev_last == test_dev);
256*2e7d35d2SSimon Glass 
257*2e7d35d2SSimon Glass 	/* Add back the original device 3, now in position 5 */
258*2e7d35d2SSimon Glass 	ut_assertok(device_bind_by_name(dms->root, &driver_info_manual, &dev));
259*2e7d35d2SSimon Glass 	ut_assert(dev);
260*2e7d35d2SSimon Glass 
261*2e7d35d2SSimon Glass 	/* Try ping */
262*2e7d35d2SSimon Glass 	ut_assertok(test_ping(dev, 100, &pingret));
263*2e7d35d2SSimon Glass 	ut_assert(pingret == 102);
264*2e7d35d2SSimon Glass 
265*2e7d35d2SSimon Glass 	/* Remove 3 and 4 */
266*2e7d35d2SSimon Glass 	ut_assertok(device_remove(dev_penultimate));
267*2e7d35d2SSimon Glass 	ut_assertok(device_unbind(dev_penultimate));
268*2e7d35d2SSimon Glass 	ut_assertok(device_remove(dev_last));
269*2e7d35d2SSimon Glass 	ut_assertok(device_unbind(dev_last));
270*2e7d35d2SSimon Glass 
271*2e7d35d2SSimon Glass 	/* Our device should now be in position 3 */
272*2e7d35d2SSimon Glass 	ut_assertok(uclass_find_device(UCLASS_TEST, 3, &test_dev));
273*2e7d35d2SSimon Glass 	ut_assert(dev == test_dev);
274*2e7d35d2SSimon Glass 
275*2e7d35d2SSimon Glass 	/* Now remove device 3 */
276*2e7d35d2SSimon Glass 	ut_assertok(device_remove(dev));
277*2e7d35d2SSimon Glass 	ut_assertok(device_unbind(dev));
278*2e7d35d2SSimon Glass 
279*2e7d35d2SSimon Glass 	return 0;
280*2e7d35d2SSimon Glass }
281*2e7d35d2SSimon Glass DM_TEST(dm_test_ordering, DM_TESTF_SCAN_PDATA);
282*2e7d35d2SSimon Glass 
283*2e7d35d2SSimon Glass /* Check that we can perform operations on a device (do a ping) */
284*2e7d35d2SSimon Glass int dm_check_operations(struct dm_test_state *dms, struct device *dev,
285*2e7d35d2SSimon Glass 			uint32_t base, struct dm_test_priv *priv)
286*2e7d35d2SSimon Glass {
287*2e7d35d2SSimon Glass 	int expected;
288*2e7d35d2SSimon Glass 	int pingret;
289*2e7d35d2SSimon Glass 
290*2e7d35d2SSimon Glass 	/* Getting the child device should allocate platdata / priv */
291*2e7d35d2SSimon Glass 	ut_assertok(testfdt_ping(dev, 10, &pingret));
292*2e7d35d2SSimon Glass 	ut_assert(dev->priv);
293*2e7d35d2SSimon Glass 	ut_assert(dev->platdata);
294*2e7d35d2SSimon Glass 
295*2e7d35d2SSimon Glass 	expected = 10 + base;
296*2e7d35d2SSimon Glass 	ut_asserteq(expected, pingret);
297*2e7d35d2SSimon Glass 
298*2e7d35d2SSimon Glass 	/* Do another ping */
299*2e7d35d2SSimon Glass 	ut_assertok(testfdt_ping(dev, 20, &pingret));
300*2e7d35d2SSimon Glass 	expected = 20 + base;
301*2e7d35d2SSimon Glass 	ut_asserteq(expected, pingret);
302*2e7d35d2SSimon Glass 
303*2e7d35d2SSimon Glass 	/* Now check the ping_total */
304*2e7d35d2SSimon Glass 	priv = dev->priv;
305*2e7d35d2SSimon Glass 	ut_asserteq(DM_TEST_START_TOTAL + 10 + 20 + base * 2,
306*2e7d35d2SSimon Glass 		    priv->ping_total);
307*2e7d35d2SSimon Glass 
308*2e7d35d2SSimon Glass 	return 0;
309*2e7d35d2SSimon Glass }
310*2e7d35d2SSimon Glass 
311*2e7d35d2SSimon Glass /* Check that we can perform operations on devices */
312*2e7d35d2SSimon Glass static int dm_test_operations(struct dm_test_state *dms)
313*2e7d35d2SSimon Glass {
314*2e7d35d2SSimon Glass 	struct device *dev;
315*2e7d35d2SSimon Glass 	int i;
316*2e7d35d2SSimon Glass 
317*2e7d35d2SSimon Glass 	/*
318*2e7d35d2SSimon Glass 	 * Now check that the ping adds are what we expect. This is using the
319*2e7d35d2SSimon Glass 	 * ping-add property in each node.
320*2e7d35d2SSimon Glass 	 */
321*2e7d35d2SSimon Glass 	for (i = 0; i < ARRAY_SIZE(test_pdata); i++) {
322*2e7d35d2SSimon Glass 		uint32_t base;
323*2e7d35d2SSimon Glass 
324*2e7d35d2SSimon Glass 		ut_assertok(uclass_get_device(UCLASS_TEST, i, &dev));
325*2e7d35d2SSimon Glass 
326*2e7d35d2SSimon Glass 		/*
327*2e7d35d2SSimon Glass 		 * Get the 'reg' property, which tells us what the ping add
328*2e7d35d2SSimon Glass 		 * should be. We don't use the platdata because we want
329*2e7d35d2SSimon Glass 		 * to test the code that sets that up (testfdt_drv_probe()).
330*2e7d35d2SSimon Glass 		 */
331*2e7d35d2SSimon Glass 		base = test_pdata[i].ping_add;
332*2e7d35d2SSimon Glass 		debug("dev=%d, base=%d\n", i, base);
333*2e7d35d2SSimon Glass 
334*2e7d35d2SSimon Glass 		ut_assert(!dm_check_operations(dms, dev, base, dev->priv));
335*2e7d35d2SSimon Glass 	}
336*2e7d35d2SSimon Glass 
337*2e7d35d2SSimon Glass 	return 0;
338*2e7d35d2SSimon Glass }
339*2e7d35d2SSimon Glass DM_TEST(dm_test_operations, DM_TESTF_SCAN_PDATA);
340*2e7d35d2SSimon Glass 
341*2e7d35d2SSimon Glass /* Remove all drivers and check that things work */
342*2e7d35d2SSimon Glass static int dm_test_remove(struct dm_test_state *dms)
343*2e7d35d2SSimon Glass {
344*2e7d35d2SSimon Glass 	struct device *dev;
345*2e7d35d2SSimon Glass 	int i;
346*2e7d35d2SSimon Glass 
347*2e7d35d2SSimon Glass 	for (i = 0; i < 3; i++) {
348*2e7d35d2SSimon Glass 		ut_assertok(uclass_find_device(UCLASS_TEST, i, &dev));
349*2e7d35d2SSimon Glass 		ut_assert(dev);
350*2e7d35d2SSimon Glass 		ut_assertf(dev->flags & DM_FLAG_ACTIVATED,
351*2e7d35d2SSimon Glass 			   "Driver %d/%s not activated", i, dev->name);
352*2e7d35d2SSimon Glass 		ut_assertok(device_remove(dev));
353*2e7d35d2SSimon Glass 		ut_assertf(!(dev->flags & DM_FLAG_ACTIVATED),
354*2e7d35d2SSimon Glass 			   "Driver %d/%s should have deactivated", i,
355*2e7d35d2SSimon Glass 			   dev->name);
356*2e7d35d2SSimon Glass 		ut_assert(!dev->priv);
357*2e7d35d2SSimon Glass 	}
358*2e7d35d2SSimon Glass 
359*2e7d35d2SSimon Glass 	return 0;
360*2e7d35d2SSimon Glass }
361*2e7d35d2SSimon Glass DM_TEST(dm_test_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_PROBE_TEST);
362*2e7d35d2SSimon Glass 
363*2e7d35d2SSimon Glass /* Remove and recreate everything, check for memory leaks */
364*2e7d35d2SSimon Glass static int dm_test_leak(struct dm_test_state *dms)
365*2e7d35d2SSimon Glass {
366*2e7d35d2SSimon Glass 	int i;
367*2e7d35d2SSimon Glass 
368*2e7d35d2SSimon Glass 	for (i = 0; i < 2; i++) {
369*2e7d35d2SSimon Glass 		struct mallinfo start, end;
370*2e7d35d2SSimon Glass 		struct device *dev;
371*2e7d35d2SSimon Glass 		int ret;
372*2e7d35d2SSimon Glass 		int id;
373*2e7d35d2SSimon Glass 
374*2e7d35d2SSimon Glass 		start = mallinfo();
375*2e7d35d2SSimon Glass 		if (!start.uordblks)
376*2e7d35d2SSimon Glass 			puts("Warning: Please add '#define DEBUG' to the top of common/dlmalloc.c\n");
377*2e7d35d2SSimon Glass 
378*2e7d35d2SSimon Glass 		ut_assertok(dm_scan_platdata());
379*2e7d35d2SSimon Glass 		ut_assertok(dm_scan_fdt(gd->fdt_blob));
380*2e7d35d2SSimon Glass 
381*2e7d35d2SSimon Glass 		/* Scanning the uclass is enough to probe all the devices */
382*2e7d35d2SSimon Glass 		for (id = UCLASS_ROOT; id < UCLASS_COUNT; id++) {
383*2e7d35d2SSimon Glass 			for (ret = uclass_first_device(UCLASS_TEST, &dev);
384*2e7d35d2SSimon Glass 			     dev;
385*2e7d35d2SSimon Glass 			     ret = uclass_next_device(&dev))
386*2e7d35d2SSimon Glass 				;
387*2e7d35d2SSimon Glass 			ut_assertok(ret);
388*2e7d35d2SSimon Glass 		}
389*2e7d35d2SSimon Glass 
390*2e7d35d2SSimon Glass 		/* Don't delete the root class, since we started with that */
391*2e7d35d2SSimon Glass 		for (id = UCLASS_ROOT + 1; id < UCLASS_COUNT; id++) {
392*2e7d35d2SSimon Glass 			struct uclass *uc;
393*2e7d35d2SSimon Glass 
394*2e7d35d2SSimon Glass 			uc = uclass_find(id);
395*2e7d35d2SSimon Glass 			if (!uc)
396*2e7d35d2SSimon Glass 				continue;
397*2e7d35d2SSimon Glass 			ut_assertok(uclass_destroy(uc));
398*2e7d35d2SSimon Glass 		}
399*2e7d35d2SSimon Glass 
400*2e7d35d2SSimon Glass 		end = mallinfo();
401*2e7d35d2SSimon Glass 		ut_asserteq(start.uordblks, end.uordblks);
402*2e7d35d2SSimon Glass 	}
403*2e7d35d2SSimon Glass 
404*2e7d35d2SSimon Glass 	return 0;
405*2e7d35d2SSimon Glass }
406*2e7d35d2SSimon Glass DM_TEST(dm_test_leak, 0);
407*2e7d35d2SSimon Glass 
408*2e7d35d2SSimon Glass /* Test uclass init/destroy methods */
409*2e7d35d2SSimon Glass static int dm_test_uclass(struct dm_test_state *dms)
410*2e7d35d2SSimon Glass {
411*2e7d35d2SSimon Glass 	struct uclass *uc;
412*2e7d35d2SSimon Glass 
413*2e7d35d2SSimon Glass 	ut_assertok(uclass_get(UCLASS_TEST, &uc));
414*2e7d35d2SSimon Glass 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]);
415*2e7d35d2SSimon Glass 	ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_DESTROY]);
416*2e7d35d2SSimon Glass 	ut_assert(uc->priv);
417*2e7d35d2SSimon Glass 
418*2e7d35d2SSimon Glass 	ut_assertok(uclass_destroy(uc));
419*2e7d35d2SSimon Glass 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_INIT]);
420*2e7d35d2SSimon Glass 	ut_asserteq(1, dm_testdrv_op_count[DM_TEST_OP_DESTROY]);
421*2e7d35d2SSimon Glass 
422*2e7d35d2SSimon Glass 	return 0;
423*2e7d35d2SSimon Glass }
424*2e7d35d2SSimon Glass DM_TEST(dm_test_uclass, 0);
425*2e7d35d2SSimon Glass 
426*2e7d35d2SSimon Glass /**
427*2e7d35d2SSimon Glass  * create_children() - Create children of a parent node
428*2e7d35d2SSimon Glass  *
429*2e7d35d2SSimon Glass  * @dms:	Test system state
430*2e7d35d2SSimon Glass  * @parent:	Parent device
431*2e7d35d2SSimon Glass  * @count:	Number of children to create
432*2e7d35d2SSimon Glass  * @key:	Key value to put in first child. Subsequence children
433*2e7d35d2SSimon Glass  *		receive an incrementing value
434*2e7d35d2SSimon Glass  * @child:	If not NULL, then the child device pointers are written into
435*2e7d35d2SSimon Glass  *		this array.
436*2e7d35d2SSimon Glass  * @return 0 if OK, -ve on error
437*2e7d35d2SSimon Glass  */
438*2e7d35d2SSimon Glass static int create_children(struct dm_test_state *dms, struct device *parent,
439*2e7d35d2SSimon Glass 			   int count, int key, struct device *child[])
440*2e7d35d2SSimon Glass {
441*2e7d35d2SSimon Glass 	struct device *dev;
442*2e7d35d2SSimon Glass 	int i;
443*2e7d35d2SSimon Glass 
444*2e7d35d2SSimon Glass 	for (i = 0; i < count; i++) {
445*2e7d35d2SSimon Glass 		struct dm_test_pdata *pdata;
446*2e7d35d2SSimon Glass 
447*2e7d35d2SSimon Glass 		ut_assertok(device_bind_by_name(parent, &driver_info_manual,
448*2e7d35d2SSimon Glass 						&dev));
449*2e7d35d2SSimon Glass 		pdata = calloc(1, sizeof(*pdata));
450*2e7d35d2SSimon Glass 		pdata->ping_add = key + i;
451*2e7d35d2SSimon Glass 		dev->platdata = pdata;
452*2e7d35d2SSimon Glass 		if (child)
453*2e7d35d2SSimon Glass 			child[i] = dev;
454*2e7d35d2SSimon Glass 	}
455*2e7d35d2SSimon Glass 
456*2e7d35d2SSimon Glass 	return 0;
457*2e7d35d2SSimon Glass }
458*2e7d35d2SSimon Glass 
459*2e7d35d2SSimon Glass #define NODE_COUNT	10
460*2e7d35d2SSimon Glass 
461*2e7d35d2SSimon Glass static int dm_test_children(struct dm_test_state *dms)
462*2e7d35d2SSimon Glass {
463*2e7d35d2SSimon Glass 	struct device *top[NODE_COUNT];
464*2e7d35d2SSimon Glass 	struct device *child[NODE_COUNT];
465*2e7d35d2SSimon Glass 	struct device *grandchild[NODE_COUNT];
466*2e7d35d2SSimon Glass 	struct device *dev;
467*2e7d35d2SSimon Glass 	int total;
468*2e7d35d2SSimon Glass 	int ret;
469*2e7d35d2SSimon Glass 	int i;
470*2e7d35d2SSimon Glass 
471*2e7d35d2SSimon Glass 	/* We don't care about the numbering for this test */
472*2e7d35d2SSimon Glass 	dms->skip_post_probe = 1;
473*2e7d35d2SSimon Glass 
474*2e7d35d2SSimon Glass 	ut_assert(NODE_COUNT > 5);
475*2e7d35d2SSimon Glass 
476*2e7d35d2SSimon Glass 	/* First create 10 top-level children */
477*2e7d35d2SSimon Glass 	ut_assertok(create_children(dms, dms->root, NODE_COUNT, 0, top));
478*2e7d35d2SSimon Glass 
479*2e7d35d2SSimon Glass 	/* Now a few have their own children */
480*2e7d35d2SSimon Glass 	ut_assertok(create_children(dms, top[2], NODE_COUNT, 2, NULL));
481*2e7d35d2SSimon Glass 	ut_assertok(create_children(dms, top[5], NODE_COUNT, 5, child));
482*2e7d35d2SSimon Glass 
483*2e7d35d2SSimon Glass 	/* And grandchildren */
484*2e7d35d2SSimon Glass 	for (i = 0; i < NODE_COUNT; i++)
485*2e7d35d2SSimon Glass 		ut_assertok(create_children(dms, child[i], NODE_COUNT, 50 * i,
486*2e7d35d2SSimon Glass 					    i == 2 ? grandchild : NULL));
487*2e7d35d2SSimon Glass 
488*2e7d35d2SSimon Glass 	/* Check total number of devices */
489*2e7d35d2SSimon Glass 	total = NODE_COUNT * (3 + NODE_COUNT);
490*2e7d35d2SSimon Glass 	ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_BIND]);
491*2e7d35d2SSimon Glass 
492*2e7d35d2SSimon Glass 	/* Try probing one of the grandchildren */
493*2e7d35d2SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST,
494*2e7d35d2SSimon Glass 				      NODE_COUNT * 3 + 2 * NODE_COUNT, &dev));
495*2e7d35d2SSimon Glass 	ut_asserteq_ptr(grandchild[0], dev);
496*2e7d35d2SSimon Glass 
497*2e7d35d2SSimon Glass 	/*
498*2e7d35d2SSimon Glass 	 * This should have probed the child and top node also, for a total
499*2e7d35d2SSimon Glass 	 * of 3 nodes.
500*2e7d35d2SSimon Glass 	 */
501*2e7d35d2SSimon Glass 	ut_asserteq(3, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
502*2e7d35d2SSimon Glass 
503*2e7d35d2SSimon Glass 	/* Probe the other grandchildren */
504*2e7d35d2SSimon Glass 	for (i = 1; i < NODE_COUNT; i++)
505*2e7d35d2SSimon Glass 		ut_assertok(device_probe(grandchild[i]));
506*2e7d35d2SSimon Glass 
507*2e7d35d2SSimon Glass 	ut_asserteq(2 + NODE_COUNT, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
508*2e7d35d2SSimon Glass 
509*2e7d35d2SSimon Glass 	/* Probe everything */
510*2e7d35d2SSimon Glass 	for (ret = uclass_first_device(UCLASS_TEST, &dev);
511*2e7d35d2SSimon Glass 	     dev;
512*2e7d35d2SSimon Glass 	     ret = uclass_next_device(&dev))
513*2e7d35d2SSimon Glass 		;
514*2e7d35d2SSimon Glass 	ut_assertok(ret);
515*2e7d35d2SSimon Glass 
516*2e7d35d2SSimon Glass 	ut_asserteq(total, dm_testdrv_op_count[DM_TEST_OP_PROBE]);
517*2e7d35d2SSimon Glass 
518*2e7d35d2SSimon Glass 	/* Remove a top-level child and check that the children are removed */
519*2e7d35d2SSimon Glass 	ut_assertok(device_remove(top[2]));
520*2e7d35d2SSimon Glass 	ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_REMOVE]);
521*2e7d35d2SSimon Glass 	dm_testdrv_op_count[DM_TEST_OP_REMOVE] = 0;
522*2e7d35d2SSimon Glass 
523*2e7d35d2SSimon Glass 	/* Try one with grandchildren */
524*2e7d35d2SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev));
525*2e7d35d2SSimon Glass 	ut_asserteq_ptr(dev, top[5]);
526*2e7d35d2SSimon Glass 	ut_assertok(device_remove(dev));
527*2e7d35d2SSimon Glass 	ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT),
528*2e7d35d2SSimon Glass 		    dm_testdrv_op_count[DM_TEST_OP_REMOVE]);
529*2e7d35d2SSimon Glass 
530*2e7d35d2SSimon Glass 	/* Try the same with unbind */
531*2e7d35d2SSimon Glass 	ut_assertok(device_unbind(top[2]));
532*2e7d35d2SSimon Glass 	ut_asserteq(NODE_COUNT + 1, dm_testdrv_op_count[DM_TEST_OP_UNBIND]);
533*2e7d35d2SSimon Glass 	dm_testdrv_op_count[DM_TEST_OP_UNBIND] = 0;
534*2e7d35d2SSimon Glass 
535*2e7d35d2SSimon Glass 	/* Try one with grandchildren */
536*2e7d35d2SSimon Glass 	ut_assertok(uclass_get_device(UCLASS_TEST, 5, &dev));
537*2e7d35d2SSimon Glass 	ut_asserteq_ptr(dev, top[6]);
538*2e7d35d2SSimon Glass 	ut_assertok(device_unbind(top[5]));
539*2e7d35d2SSimon Glass 	ut_asserteq(1 + NODE_COUNT * (1 + NODE_COUNT),
540*2e7d35d2SSimon Glass 		    dm_testdrv_op_count[DM_TEST_OP_UNBIND]);
541*2e7d35d2SSimon Glass 
542*2e7d35d2SSimon Glass 	return 0;
543*2e7d35d2SSimon Glass }
544*2e7d35d2SSimon Glass DM_TEST(dm_test_children, 0);
545