blob: 799f1e4dc75b27aacc356b6a7bddb41c8cd2b993 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass89c1dcd2016-03-13 08:22:36 -06002/*
3 * Copyright (C) 2015 Google, Inc
Simon Glass89c1dcd2016-03-13 08:22:36 -06004 */
5
6#include <common.h>
Bin Meng881e4752023-09-26 16:43:33 +08007#include <blk.h>
Simon Glass89c1dcd2016-03-13 08:22:36 -06008#include <dm.h>
Simon Glass655306c2020-05-10 11:39:58 -06009#include <part.h>
Simon Glasse57f8d42022-10-29 19:47:17 -060010#include <sandbox_host.h>
Simon Glass89c1dcd2016-03-13 08:22:36 -060011#include <usb.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060012#include <asm/global_data.h>
Simon Glass89c1dcd2016-03-13 08:22:36 -060013#include <asm/state.h>
14#include <dm/test.h>
Simon Glass75c4d412020-07-19 10:15:37 -060015#include <test/test.h>
Simon Glass89c1dcd2016-03-13 08:22:36 -060016#include <test/ut.h>
17
18DECLARE_GLOBAL_DATA_PTR;
19
20/* Test that block devices can be created */
21static int dm_test_blk_base(struct unit_test_state *uts)
22{
Simon Glasse57f8d42022-10-29 19:47:17 -060023 struct udevice *blk0, *blk1, *dev0, *dev1, *dev, *chk0, *chk1;
Simon Glass89c1dcd2016-03-13 08:22:36 -060024
Simon Glass89c1dcd2016-03-13 08:22:36 -060025 /* Create two, one the parent of the other */
Bin Meng881e4752023-09-26 16:43:33 +080026 ut_assertok(host_create_device("test0", false, DEFAULT_BLKSZ, &dev0));
27 ut_assertok(host_create_device("test1", false, DEFAULT_BLKSZ, &dev1));
Simon Glass89c1dcd2016-03-13 08:22:36 -060028
29 /* Check we can find them */
Simon Glasse57f8d42022-10-29 19:47:17 -060030 ut_assertok(blk_get_device(UCLASS_HOST, 0, &blk0));
31 ut_assertok(blk_get_from_parent(dev0, &chk0));
32 ut_asserteq_ptr(blk0, chk0);
33
34 ut_assertok(blk_get_device(UCLASS_HOST, 1, &blk1));
35 ut_assertok(blk_get_from_parent(dev1, &chk1));
36 ut_asserteq_ptr(blk1, chk1);
37 ut_asserteq(-ENODEV, blk_get_device(UCLASS_HOST, 2, &dev0));
Simon Glass89c1dcd2016-03-13 08:22:36 -060038
39 /* Check we can iterate */
Simon Glasse57f8d42022-10-29 19:47:17 -060040 ut_assertok(blk_first_device(UCLASS_HOST, &dev));
41 ut_asserteq_ptr(blk0, dev);
Bin Meng8122dd12018-10-15 02:21:04 -070042 ut_assertok(blk_next_device(&dev));
Simon Glasse57f8d42022-10-29 19:47:17 -060043 ut_asserteq_ptr(blk1, dev);
Simon Glass89c1dcd2016-03-13 08:22:36 -060044
45 return 0;
46}
Simon Glass974dccd2020-07-28 19:41:12 -060047DM_TEST(dm_test_blk_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glass89c1dcd2016-03-13 08:22:36 -060048
49static int count_blk_devices(void)
50{
51 struct udevice *blk;
52 struct uclass *uc;
53 int count = 0;
54 int ret;
55
56 ret = uclass_get(UCLASS_BLK, &uc);
57 if (ret)
58 return ret;
59
60 uclass_foreach_dev(blk, uc)
61 count++;
62
63 return count;
64}
65
66/* Test that block devices work correctly with USB */
67static int dm_test_blk_usb(struct unit_test_state *uts)
68{
69 struct udevice *usb_dev, *dev;
70 struct blk_desc *dev_desc;
71
Simon Glass6bebdb32022-04-24 23:31:02 -060072 usb_started = false;
73
Simon Glass89c1dcd2016-03-13 08:22:36 -060074 /* Get a flash device */
75 state_set_skip_delays(true);
Simon Glass6bebdb32022-04-24 23:31:02 -060076 ut_assertok(usb_stop());
Simon Glass89c1dcd2016-03-13 08:22:36 -060077 ut_assertok(usb_init());
78 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev));
79 ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
80
81 /* The parent should be a block device */
Simon Glassdbfa32c2022-08-11 19:34:59 -060082 ut_assertok(blk_get_device(UCLASS_USB, 0, &dev));
Simon Glass89c1dcd2016-03-13 08:22:36 -060083 ut_asserteq_ptr(usb_dev, dev_get_parent(dev));
84
85 /* Check we have one block device for each mass storage device */
Simon Glasse4fef742017-04-23 20:02:07 -060086 ut_asserteq(6, count_blk_devices());
Simon Glass89c1dcd2016-03-13 08:22:36 -060087
88 /* Now go around again, making sure the old devices were unbound */
89 ut_assertok(usb_stop());
90 ut_assertok(usb_init());
Simon Glasse4fef742017-04-23 20:02:07 -060091 ut_asserteq(6, count_blk_devices());
Simon Glass89c1dcd2016-03-13 08:22:36 -060092 ut_assertok(usb_stop());
93
94 return 0;
95}
Simon Glass974dccd2020-07-28 19:41:12 -060096DM_TEST(dm_test_blk_usb, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glassd5d4c102017-04-23 20:02:05 -060097
98/* Test that we can find block devices without probing them */
99static int dm_test_blk_find(struct unit_test_state *uts)
100{
Simon Glasse57f8d42022-10-29 19:47:17 -0600101 struct udevice *blk, *chk, *dev;
Simon Glassd5d4c102017-04-23 20:02:05 -0600102
Bin Meng881e4752023-09-26 16:43:33 +0800103 ut_assertok(host_create_device("test0", false, DEFAULT_BLKSZ, &dev));
Simon Glasse57f8d42022-10-29 19:47:17 -0600104
105 ut_assertok(blk_find_device(UCLASS_HOST, 0, &chk));
106 ut_assertok(device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk));
107 ut_asserteq_ptr(chk, blk);
Simon Glassd5d4c102017-04-23 20:02:05 -0600108 ut_asserteq(false, device_active(dev));
Simon Glasse57f8d42022-10-29 19:47:17 -0600109 ut_asserteq(-ENODEV, blk_find_device(UCLASS_HOST, 1, &dev));
Simon Glassd5d4c102017-04-23 20:02:05 -0600110
111 /* Now activate it */
Simon Glasse57f8d42022-10-29 19:47:17 -0600112 ut_assertok(blk_get_device(UCLASS_HOST, 0, &blk));
113 ut_asserteq_ptr(chk, blk);
114 ut_asserteq(true, device_active(blk));
Simon Glassd5d4c102017-04-23 20:02:05 -0600115
116 return 0;
117}
Simon Glass974dccd2020-07-28 19:41:12 -0600118DM_TEST(dm_test_blk_find, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glasse4fef742017-04-23 20:02:07 -0600119
120/* Test that block device numbering works as expected */
121static int dm_test_blk_devnum(struct unit_test_state *uts)
122{
123 struct udevice *dev, *mmc_dev, *parent;
124 int i;
125
126 /*
127 * Probe the devices, with the first one being probed last. This is the
Yuepeng Xing71cc0212022-12-02 14:23:07 +0800128 * one with no alias / sequence number.
Simon Glasse4fef742017-04-23 20:02:07 -0600129 */
130 ut_assertok(uclass_get_device(UCLASS_MMC, 1, &dev));
131 ut_assertok(uclass_get_device(UCLASS_MMC, 2, &dev));
132 ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
133 for (i = 0; i < 3; i++) {
134 struct blk_desc *desc;
135
136 /* Check that the bblock device is attached */
137 ut_assertok(uclass_get_device_by_seq(UCLASS_MMC, i, &mmc_dev));
Simon Glassdbfa32c2022-08-11 19:34:59 -0600138 ut_assertok(blk_find_device(UCLASS_MMC, i, &dev));
Simon Glasse4fef742017-04-23 20:02:07 -0600139 parent = dev_get_parent(dev);
140 ut_asserteq_ptr(parent, mmc_dev);
141 ut_asserteq(trailing_strtol(mmc_dev->name), i);
142
143 /*
144 * Check that the block device devnum matches its parent's
145 * sequence number
146 */
Simon Glass71fa5b42020-12-03 16:55:18 -0700147 desc = dev_get_uclass_plat(dev);
Simon Glasse4fef742017-04-23 20:02:07 -0600148 ut_asserteq(desc->devnum, i);
149 }
150
151 return 0;
152}
Simon Glass974dccd2020-07-28 19:41:12 -0600153DM_TEST(dm_test_blk_devnum, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glass4f269132017-05-27 11:37:17 -0600154
155/* Test that we can get a block from its parent */
156static int dm_test_blk_get_from_parent(struct unit_test_state *uts)
157{
158 struct udevice *dev, *blk;
159
160 ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
161 ut_assertok(blk_get_from_parent(dev, &blk));
162
163 ut_assertok(uclass_get_device(UCLASS_I2C, 0, &dev));
Simon Glassc0bcaaf2022-10-29 19:47:14 -0600164 ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk));
Simon Glass4f269132017-05-27 11:37:17 -0600165
166 ut_assertok(uclass_get_device(UCLASS_GPIO, 0, &dev));
167 ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk));
168
169 return 0;
170}
Simon Glass974dccd2020-07-28 19:41:12 -0600171DM_TEST(dm_test_blk_get_from_parent, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glassfc7a7442021-07-05 16:32:59 -0600172
173/* Test iteration through block devices */
174static int dm_test_blk_iter(struct unit_test_state *uts)
175{
176 struct udevice *dev;
177 int i;
178
179 /*
180 * See sandbox test.dts - it has:
181 *
182 * mmc0 - removable
183 * mmc1 - removable
184 * mmc2 - fixed
185 */
186 ut_assertok(blk_first_device_err(BLKF_FIXED, &dev));
187 ut_asserteq_str("mmc2.blk", dev->name);
188 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
189
190 ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev));
191 ut_asserteq_str("mmc1.blk", dev->name);
192 ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev));
193 ut_asserteq_str("mmc0.blk", dev->name);
194 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev));
195
196 ut_assertok(blk_first_device_err(BLKF_BOTH, &dev));
197 ut_asserteq_str("mmc2.blk", dev->name);
198 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
199 ut_asserteq_str("mmc1.blk", dev->name);
200 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
201 ut_asserteq_str("mmc0.blk", dev->name);
202 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
203
204 ut_asserteq(1, blk_count_devices(BLKF_FIXED));
205 ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE));
206 ut_asserteq(3, blk_count_devices(BLKF_BOTH));
207
208 i = 0;
209 blk_foreach_probe(BLKF_FIXED, dev)
210 ut_asserteq_str((i++, "mmc2.blk"), dev->name);
211 ut_asserteq(1, i);
212
213 i = 0;
214 blk_foreach_probe(BLKF_REMOVABLE, dev)
215 ut_asserteq_str(i++ ? "mmc0.blk" : "mmc1.blk", dev->name);
216 ut_asserteq(2, i);
217
218 i = 0;
219 blk_foreach_probe(BLKF_BOTH, dev)
220 ut_asserteq_str((++i == 1 ? "mmc2.blk" : i == 2 ?
221 "mmc1.blk" : "mmc0.blk"), dev->name);
222 ut_asserteq(3, i);
223
224 return 0;
225}
226DM_TEST(dm_test_blk_iter, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glass8e61f932022-02-28 12:08:35 -0700227
228/* Test finding fixed/removable block devices */
229static int dm_test_blk_flags(struct unit_test_state *uts)
230{
231 struct udevice *dev;
232
233 /* Iterate through devices without probing them */
234 ut_assertok(blk_find_first(BLKF_BOTH, &dev));
235 ut_assertnonnull(dev);
236 ut_asserteq_str("mmc2.blk", dev->name);
237
238 ut_assertok(blk_find_next(BLKF_BOTH, &dev));
239 ut_assertnonnull(dev);
240 ut_asserteq_str("mmc1.blk", dev->name);
241
242 ut_assertok(blk_find_next(BLKF_BOTH, &dev));
243 ut_assertnonnull(dev);
244 ut_asserteq_str("mmc0.blk", dev->name);
245
246 ut_asserteq(-ENODEV, blk_find_next(BLKF_BOTH, &dev));
247 ut_assertnull(dev);
248
249 /* All devices are removable until probed */
250 ut_asserteq(-ENODEV, blk_find_first(BLKF_FIXED, &dev));
251
252 ut_assertok(blk_find_first(BLKF_REMOVABLE, &dev));
253 ut_assertnonnull(dev);
254 ut_asserteq_str("mmc2.blk", dev->name);
255
256 /* Now probe them and iterate again */
257 ut_assertok(blk_first_device_err(BLKF_BOTH, &dev));
258 ut_assertnonnull(dev);
259 ut_asserteq_str("mmc2.blk", dev->name);
260
261 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
262 ut_assertnonnull(dev);
263 ut_asserteq_str("mmc1.blk", dev->name);
264
265 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
266 ut_assertnonnull(dev);
267 ut_asserteq_str("mmc0.blk", dev->name);
268
269 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_BOTH, &dev));
270
271 /* Look only for fixed devices */
272 ut_assertok(blk_first_device_err(BLKF_FIXED, &dev));
273 ut_assertnonnull(dev);
274 ut_asserteq_str("mmc2.blk", dev->name);
275
276 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
277
278 /* Look only for removable devices */
279 ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev));
280 ut_assertnonnull(dev);
281 ut_asserteq_str("mmc1.blk", dev->name);
282
283 ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev));
284 ut_assertnonnull(dev);
285 ut_asserteq_str("mmc0.blk", dev->name);
286
287 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev));
288
289 return 0;
290}
291DM_TEST(dm_test_blk_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
292
293/* Test blk_foreach() and friend */
294static int dm_test_blk_foreach(struct unit_test_state *uts)
295{
296 struct udevice *dev;
297 int found;
298
299 /* Test blk_foreach() - use the 3rd bytes of the name (0/1/2) */
300 found = 0;
301 blk_foreach(BLKF_BOTH, dev)
302 found |= 1 << dectoul(&dev->name[3], NULL);
303 ut_asserteq(7, found);
304
305 /* All devices are removable until probed */
306 found = 0;
307 blk_foreach(BLKF_FIXED, dev)
308 found |= 1 << dectoul(&dev->name[3], NULL);
309 ut_asserteq(0, found);
310
311 found = 0;
312 blk_foreach(BLKF_REMOVABLE, dev)
313 found |= 1 << dectoul(&dev->name[3], NULL);
314 ut_asserteq(7, found);
315
316 /* Now try again with the probing functions */
317 found = 0;
318 blk_foreach_probe(BLKF_BOTH, dev)
319 found |= 1 << dectoul(&dev->name[3], NULL);
320 ut_asserteq(7, found);
321 ut_asserteq(3, blk_count_devices(BLKF_BOTH));
322
323 found = 0;
324 blk_foreach_probe(BLKF_FIXED, dev)
325 found |= 1 << dectoul(&dev->name[3], NULL);
326 ut_asserteq(4, found);
327 ut_asserteq(1, blk_count_devices(BLKF_FIXED));
328
329 found = 0;
330 blk_foreach_probe(BLKF_REMOVABLE, dev)
331 found |= 1 << dectoul(&dev->name[3], NULL);
332 ut_asserteq(3, found);
333 ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE));
334
335 return 0;
336}
337DM_TEST(dm_test_blk_foreach, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);