1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  */
5 
6 #include <blk.h>
7 #include <dm.h>
8 #include <part.h>
9 #include <sandbox_host.h>
10 #include <usb.h>
11 #include <asm/global_data.h>
12 #include <asm/state.h>
13 #include <dm/test.h>
14 #include <test/test.h>
15 #include <test/ut.h>
16 
17 DECLARE_GLOBAL_DATA_PTR;
18 
19 /* Test that block devices can be created */
dm_test_blk_base(struct unit_test_state * uts)20 static int dm_test_blk_base(struct unit_test_state *uts)
21 {
22 	struct udevice *blk0, *blk1, *dev0, *dev1, *dev, *chk0, *chk1;
23 
24 	/* Create two, one the parent of the other */
25 	ut_assertok(host_create_device("test0", false, DEFAULT_BLKSZ, &dev0));
26 	ut_assertok(host_create_device("test1", false, DEFAULT_BLKSZ, &dev1));
27 
28 	/* Check we can find them */
29 	ut_assertok(blk_get_device(UCLASS_HOST, 0, &blk0));
30 	ut_assertok(blk_get_from_parent(dev0, &chk0));
31 	ut_asserteq_ptr(blk0, chk0);
32 
33 	ut_assertok(blk_get_device(UCLASS_HOST, 1, &blk1));
34 	ut_assertok(blk_get_from_parent(dev1, &chk1));
35 	ut_asserteq_ptr(blk1, chk1);
36 	ut_asserteq(-ENODEV, blk_get_device(UCLASS_HOST, 2, &dev0));
37 
38 	/* Check we can iterate */
39 	ut_assertok(blk_first_device(UCLASS_HOST, &dev));
40 	ut_asserteq_ptr(blk0, dev);
41 	ut_assertok(blk_next_device(&dev));
42 	ut_asserteq_ptr(blk1, dev);
43 
44 	return 0;
45 }
46 DM_TEST(dm_test_blk_base, UTF_SCAN_PDATA | UTF_SCAN_FDT);
47 
count_blk_devices(void)48 static int count_blk_devices(void)
49 {
50 	struct udevice *blk;
51 	struct uclass *uc;
52 	int count = 0;
53 	int ret;
54 
55 	ret = uclass_get(UCLASS_BLK, &uc);
56 	if (ret)
57 		return ret;
58 
59 	uclass_foreach_dev(blk, uc)
60 		count++;
61 
62 	return count;
63 }
64 
65 /* Test that block devices work correctly with USB */
dm_test_blk_usb(struct unit_test_state * uts)66 static int dm_test_blk_usb(struct unit_test_state *uts)
67 {
68 	struct udevice *usb_dev, *dev;
69 	struct blk_desc *dev_desc;
70 
71 	usb_started = false;
72 
73 	/* Get a flash device */
74 	state_set_skip_delays(true);
75 	ut_assertok(usb_stop());
76 	ut_assertok(usb_init());
77 	ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev));
78 	ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
79 
80 	/* The parent should be a block device */
81 	ut_assertok(blk_get_device(UCLASS_USB, 0, &dev));
82 	ut_asserteq_ptr(usb_dev, dev_get_parent(dev));
83 
84 	/* Check we have one block device for each mass storage device */
85 	ut_asserteq(6, count_blk_devices());
86 
87 	/* Now go around again, making sure the old devices were unbound */
88 	ut_assertok(usb_stop());
89 	ut_assertok(usb_init());
90 	ut_asserteq(6, count_blk_devices());
91 	ut_assertok(usb_stop());
92 
93 	return 0;
94 }
95 DM_TEST(dm_test_blk_usb, UTF_SCAN_PDATA | UTF_SCAN_FDT);
96 
97 /* Test that we can find block devices without probing them */
dm_test_blk_find(struct unit_test_state * uts)98 static int dm_test_blk_find(struct unit_test_state *uts)
99 {
100 	struct udevice *blk, *chk, *dev;
101 
102 	ut_assertok(host_create_device("test0", false, DEFAULT_BLKSZ, &dev));
103 
104 	ut_assertok(blk_find_device(UCLASS_HOST, 0, &chk));
105 	ut_assertok(device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk));
106 	ut_asserteq_ptr(chk, blk);
107 	ut_asserteq(false, device_active(dev));
108 	ut_asserteq(-ENODEV, blk_find_device(UCLASS_HOST, 1, &dev));
109 
110 	/* Now activate it */
111 	ut_assertok(blk_get_device(UCLASS_HOST, 0, &blk));
112 	ut_asserteq_ptr(chk, blk);
113 	ut_asserteq(true, device_active(blk));
114 
115 	return 0;
116 }
117 DM_TEST(dm_test_blk_find, UTF_SCAN_PDATA | UTF_SCAN_FDT);
118 
119 /* Test that block device numbering works as expected */
dm_test_blk_devnum(struct unit_test_state * uts)120 static int dm_test_blk_devnum(struct unit_test_state *uts)
121 {
122 	struct udevice *dev, *mmc_dev, *parent;
123 	int i;
124 
125 	/*
126 	 * Probe the devices, with the first one being probed last. This is the
127 	 * one with no alias / sequence number.
128 	 */
129 	ut_assertok(uclass_get_device(UCLASS_MMC, 1, &dev));
130 	ut_assertok(uclass_get_device(UCLASS_MMC, 2, &dev));
131 	ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
132 	for (i = 0; i < 3; i++) {
133 		struct blk_desc *desc;
134 
135 		/* Check that the bblock device is attached */
136 		ut_assertok(uclass_get_device_by_seq(UCLASS_MMC, i, &mmc_dev));
137 		ut_assertok(blk_find_device(UCLASS_MMC, i, &dev));
138 		parent = dev_get_parent(dev);
139 		ut_asserteq_ptr(parent, mmc_dev);
140 		ut_asserteq(trailing_strtol(mmc_dev->name), i);
141 
142 		/*
143 		 * Check that the block device devnum matches its parent's
144 		 * sequence number
145 		 */
146 		desc = dev_get_uclass_plat(dev);
147 		ut_asserteq(desc->devnum, i);
148 	}
149 
150 	return 0;
151 }
152 DM_TEST(dm_test_blk_devnum, UTF_SCAN_PDATA | UTF_SCAN_FDT);
153 
154 /* Test that we can get a block from its parent */
dm_test_blk_get_from_parent(struct unit_test_state * uts)155 static int dm_test_blk_get_from_parent(struct unit_test_state *uts)
156 {
157 	struct udevice *dev, *blk;
158 
159 	ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
160 	ut_assertok(blk_get_from_parent(dev, &blk));
161 
162 	ut_assertok(uclass_get_device(UCLASS_I2C, 0, &dev));
163 	ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk));
164 
165 	ut_assertok(uclass_get_device(UCLASS_GPIO, 0, &dev));
166 	ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk));
167 
168 	return 0;
169 }
170 DM_TEST(dm_test_blk_get_from_parent, UTF_SCAN_PDATA | UTF_SCAN_FDT);
171 
172 /* Test iteration through block devices */
dm_test_blk_iter(struct unit_test_state * uts)173 static int dm_test_blk_iter(struct unit_test_state *uts)
174 {
175 	struct udevice *dev;
176 	int i;
177 
178 	/*
179 	 * See sandbox test.dts - it has:
180 	 *
181 	 *   mmc0 - removable
182 	 *   mmc1 - removable
183 	 *   mmc2 - fixed
184 	 */
185 	ut_assertok(blk_first_device_err(BLKF_FIXED, &dev));
186 	ut_asserteq_str("mmc2.blk", dev->name);
187 	ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
188 
189 	ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev));
190 	ut_asserteq_str("mmc1.blk", dev->name);
191 	ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev));
192 	ut_asserteq_str("mmc0.blk", dev->name);
193 	ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev));
194 
195 	ut_assertok(blk_first_device_err(BLKF_BOTH, &dev));
196 	ut_asserteq_str("mmc2.blk", dev->name);
197 	ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
198 	ut_asserteq_str("mmc1.blk", dev->name);
199 	ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
200 	ut_asserteq_str("mmc0.blk", dev->name);
201 	ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
202 
203 	ut_asserteq(1, blk_count_devices(BLKF_FIXED));
204 	ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE));
205 	ut_asserteq(3, blk_count_devices(BLKF_BOTH));
206 
207 	i = 0;
208 	blk_foreach_probe(BLKF_FIXED, dev)
209 		ut_asserteq_str((i++, "mmc2.blk"), dev->name);
210 	ut_asserteq(1, i);
211 
212 	i = 0;
213 	blk_foreach_probe(BLKF_REMOVABLE, dev)
214 		ut_asserteq_str(i++ ? "mmc0.blk" : "mmc1.blk", dev->name);
215 	ut_asserteq(2, i);
216 
217 	i = 0;
218 	blk_foreach_probe(BLKF_BOTH, dev)
219 		ut_asserteq_str((++i == 1 ? "mmc2.blk" : i == 2 ?
220 			"mmc1.blk" : "mmc0.blk"), dev->name);
221 	ut_asserteq(3, i);
222 
223 	return 0;
224 }
225 DM_TEST(dm_test_blk_iter, UTF_SCAN_PDATA | UTF_SCAN_FDT);
226 
227 /* Test finding fixed/removable block devices */
dm_test_blk_flags(struct unit_test_state * uts)228 static int dm_test_blk_flags(struct unit_test_state *uts)
229 {
230 	struct udevice *dev;
231 
232 	/* Probe and look through block devices */
233 	ut_assertok(blk_first_device_err(BLKF_BOTH, &dev));
234 	ut_assertnonnull(dev);
235 	ut_asserteq_str("mmc2.blk", dev->name);
236 
237 	ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
238 	ut_assertnonnull(dev);
239 	ut_asserteq_str("mmc1.blk", dev->name);
240 
241 	ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
242 	ut_assertnonnull(dev);
243 	ut_asserteq_str("mmc0.blk", dev->name);
244 
245 	ut_asserteq(-ENODEV, blk_next_device_err(BLKF_BOTH, &dev));
246 
247 	/* Look only for fixed devices */
248 	ut_assertok(blk_first_device_err(BLKF_FIXED, &dev));
249 	ut_assertnonnull(dev);
250 	ut_asserteq_str("mmc2.blk", dev->name);
251 
252 	ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
253 
254 	/* Look only for removable devices */
255 	ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev));
256 	ut_assertnonnull(dev);
257 	ut_asserteq_str("mmc1.blk", dev->name);
258 
259 	ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev));
260 	ut_assertnonnull(dev);
261 	ut_asserteq_str("mmc0.blk", dev->name);
262 
263 	ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev));
264 
265 	return 0;
266 }
267 DM_TEST(dm_test_blk_flags, UTF_SCAN_PDATA | UTF_SCAN_FDT);
268 
269 /* Test blk_foreach_probe() */
dm_test_blk_foreach(struct unit_test_state * uts)270 static int dm_test_blk_foreach(struct unit_test_state *uts)
271 {
272 	struct udevice *dev;
273 	int found;
274 
275 	/* The test device tree has two fixed and one removable block device(s) */
276 	found = 0;
277 	blk_foreach_probe(BLKF_BOTH, dev)
278 		found |= 1 << dectoul(&dev->name[3], NULL);
279 	ut_asserteq(7, found);
280 	ut_asserteq(3, blk_count_devices(BLKF_BOTH));
281 
282 	found = 0;
283 	blk_foreach_probe(BLKF_FIXED, dev)
284 		found |= 1 << dectoul(&dev->name[3], NULL);
285 	ut_asserteq(4, found);
286 	ut_asserteq(1, blk_count_devices(BLKF_FIXED));
287 
288 	found = 0;
289 	blk_foreach_probe(BLKF_REMOVABLE, dev)
290 		found |= 1 << dectoul(&dev->name[3], NULL);
291 	ut_asserteq(3, found);
292 	ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE));
293 
294 	return 0;
295 }
296 DM_TEST(dm_test_blk_foreach, UTF_SCAN_PDATA | UTF_SCAN_FDT);
297