blob: 612f3ffb32dbf6f45af90edf5eec5a63619e082b [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>
7#include <dm.h>
Simon Glass655306c2020-05-10 11:39:58 -06008#include <part.h>
Simon Glasse57f8d42022-10-29 19:47:17 -06009#include <sandbox_host.h>
Simon Glass89c1dcd2016-03-13 08:22:36 -060010#include <usb.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Simon Glass89c1dcd2016-03-13 08:22:36 -060012#include <asm/state.h>
13#include <dm/test.h>
Simon Glass75c4d412020-07-19 10:15:37 -060014#include <test/test.h>
Simon Glass89c1dcd2016-03-13 08:22:36 -060015#include <test/ut.h>
16
17DECLARE_GLOBAL_DATA_PTR;
18
Simon Glass6bebdb32022-04-24 23:31:02 -060019/* Allow resetting the USB-started flag */
20extern char usb_started;
21
Simon Glass89c1dcd2016-03-13 08:22:36 -060022/* Test that block devices can be created */
23static int dm_test_blk_base(struct unit_test_state *uts)
24{
Simon Glasse57f8d42022-10-29 19:47:17 -060025 struct udevice *blk0, *blk1, *dev0, *dev1, *dev, *chk0, *chk1;
Simon Glass89c1dcd2016-03-13 08:22:36 -060026
Simon Glass89c1dcd2016-03-13 08:22:36 -060027 /* Create two, one the parent of the other */
Simon Glasse57f8d42022-10-29 19:47:17 -060028 ut_assertok(host_create_device("test0", false, &dev0));
29 ut_assertok(host_create_device("test1", false, &dev1));
Simon Glass89c1dcd2016-03-13 08:22:36 -060030
31 /* Check we can find them */
Simon Glasse57f8d42022-10-29 19:47:17 -060032 ut_assertok(blk_get_device(UCLASS_HOST, 0, &blk0));
33 ut_assertok(blk_get_from_parent(dev0, &chk0));
34 ut_asserteq_ptr(blk0, chk0);
35
36 ut_assertok(blk_get_device(UCLASS_HOST, 1, &blk1));
37 ut_assertok(blk_get_from_parent(dev1, &chk1));
38 ut_asserteq_ptr(blk1, chk1);
39 ut_asserteq(-ENODEV, blk_get_device(UCLASS_HOST, 2, &dev0));
Simon Glass89c1dcd2016-03-13 08:22:36 -060040
41 /* Check we can iterate */
Simon Glasse57f8d42022-10-29 19:47:17 -060042 ut_assertok(blk_first_device(UCLASS_HOST, &dev));
43 ut_asserteq_ptr(blk0, dev);
Bin Meng8122dd12018-10-15 02:21:04 -070044 ut_assertok(blk_next_device(&dev));
Simon Glasse57f8d42022-10-29 19:47:17 -060045 ut_asserteq_ptr(blk1, dev);
Simon Glass89c1dcd2016-03-13 08:22:36 -060046
47 return 0;
48}
Simon Glass974dccd2020-07-28 19:41:12 -060049DM_TEST(dm_test_blk_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glass89c1dcd2016-03-13 08:22:36 -060050
51static int count_blk_devices(void)
52{
53 struct udevice *blk;
54 struct uclass *uc;
55 int count = 0;
56 int ret;
57
58 ret = uclass_get(UCLASS_BLK, &uc);
59 if (ret)
60 return ret;
61
62 uclass_foreach_dev(blk, uc)
63 count++;
64
65 return count;
66}
67
68/* Test that block devices work correctly with USB */
69static int dm_test_blk_usb(struct unit_test_state *uts)
70{
71 struct udevice *usb_dev, *dev;
72 struct blk_desc *dev_desc;
73
Simon Glass6bebdb32022-04-24 23:31:02 -060074 usb_started = false;
75
Simon Glass89c1dcd2016-03-13 08:22:36 -060076 /* Get a flash device */
77 state_set_skip_delays(true);
Simon Glass6bebdb32022-04-24 23:31:02 -060078 ut_assertok(usb_stop());
Simon Glass89c1dcd2016-03-13 08:22:36 -060079 ut_assertok(usb_init());
80 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev));
81 ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
82
83 /* The parent should be a block device */
Simon Glassdbfa32c2022-08-11 19:34:59 -060084 ut_assertok(blk_get_device(UCLASS_USB, 0, &dev));
Simon Glass89c1dcd2016-03-13 08:22:36 -060085 ut_asserteq_ptr(usb_dev, dev_get_parent(dev));
86
87 /* Check we have one block device for each mass storage device */
Simon Glasse4fef742017-04-23 20:02:07 -060088 ut_asserteq(6, count_blk_devices());
Simon Glass89c1dcd2016-03-13 08:22:36 -060089
90 /* Now go around again, making sure the old devices were unbound */
91 ut_assertok(usb_stop());
92 ut_assertok(usb_init());
Simon Glasse4fef742017-04-23 20:02:07 -060093 ut_asserteq(6, count_blk_devices());
Simon Glass89c1dcd2016-03-13 08:22:36 -060094 ut_assertok(usb_stop());
95
96 return 0;
97}
Simon Glass974dccd2020-07-28 19:41:12 -060098DM_TEST(dm_test_blk_usb, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glassd5d4c102017-04-23 20:02:05 -060099
100/* Test that we can find block devices without probing them */
101static int dm_test_blk_find(struct unit_test_state *uts)
102{
Simon Glasse57f8d42022-10-29 19:47:17 -0600103 struct udevice *blk, *chk, *dev;
Simon Glassd5d4c102017-04-23 20:02:05 -0600104
Simon Glasse57f8d42022-10-29 19:47:17 -0600105 ut_assertok(host_create_device("test0", false, &dev));
106
107 ut_assertok(blk_find_device(UCLASS_HOST, 0, &chk));
108 ut_assertok(device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk));
109 ut_asserteq_ptr(chk, blk);
Simon Glassd5d4c102017-04-23 20:02:05 -0600110 ut_asserteq(false, device_active(dev));
Simon Glasse57f8d42022-10-29 19:47:17 -0600111 ut_asserteq(-ENODEV, blk_find_device(UCLASS_HOST, 1, &dev));
Simon Glassd5d4c102017-04-23 20:02:05 -0600112
113 /* Now activate it */
Simon Glasse57f8d42022-10-29 19:47:17 -0600114 ut_assertok(blk_get_device(UCLASS_HOST, 0, &blk));
115 ut_asserteq_ptr(chk, blk);
116 ut_asserteq(true, device_active(blk));
Simon Glassd5d4c102017-04-23 20:02:05 -0600117
118 return 0;
119}
Simon Glass974dccd2020-07-28 19:41:12 -0600120DM_TEST(dm_test_blk_find, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glasse4fef742017-04-23 20:02:07 -0600121
122/* Test that block device numbering works as expected */
123static int dm_test_blk_devnum(struct unit_test_state *uts)
124{
125 struct udevice *dev, *mmc_dev, *parent;
126 int i;
127
128 /*
129 * Probe the devices, with the first one being probed last. This is the
130 * one with no alias / sequence numnber.
131 */
132 ut_assertok(uclass_get_device(UCLASS_MMC, 1, &dev));
133 ut_assertok(uclass_get_device(UCLASS_MMC, 2, &dev));
134 ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
135 for (i = 0; i < 3; i++) {
136 struct blk_desc *desc;
137
138 /* Check that the bblock device is attached */
139 ut_assertok(uclass_get_device_by_seq(UCLASS_MMC, i, &mmc_dev));
Simon Glassdbfa32c2022-08-11 19:34:59 -0600140 ut_assertok(blk_find_device(UCLASS_MMC, i, &dev));
Simon Glasse4fef742017-04-23 20:02:07 -0600141 parent = dev_get_parent(dev);
142 ut_asserteq_ptr(parent, mmc_dev);
143 ut_asserteq(trailing_strtol(mmc_dev->name), i);
144
145 /*
146 * Check that the block device devnum matches its parent's
147 * sequence number
148 */
Simon Glass71fa5b42020-12-03 16:55:18 -0700149 desc = dev_get_uclass_plat(dev);
Simon Glasse4fef742017-04-23 20:02:07 -0600150 ut_asserteq(desc->devnum, i);
151 }
152
153 return 0;
154}
Simon Glass974dccd2020-07-28 19:41:12 -0600155DM_TEST(dm_test_blk_devnum, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glass4f269132017-05-27 11:37:17 -0600156
157/* Test that we can get a block from its parent */
158static int dm_test_blk_get_from_parent(struct unit_test_state *uts)
159{
160 struct udevice *dev, *blk;
161
162 ut_assertok(uclass_get_device(UCLASS_MMC, 0, &dev));
163 ut_assertok(blk_get_from_parent(dev, &blk));
164
165 ut_assertok(uclass_get_device(UCLASS_I2C, 0, &dev));
Simon Glassc0bcaaf2022-10-29 19:47:14 -0600166 ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk));
Simon Glass4f269132017-05-27 11:37:17 -0600167
168 ut_assertok(uclass_get_device(UCLASS_GPIO, 0, &dev));
169 ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk));
170
171 return 0;
172}
Simon Glass974dccd2020-07-28 19:41:12 -0600173DM_TEST(dm_test_blk_get_from_parent, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glassfc7a7442021-07-05 16:32:59 -0600174
175/* Test iteration through block devices */
176static int dm_test_blk_iter(struct unit_test_state *uts)
177{
178 struct udevice *dev;
179 int i;
180
181 /*
182 * See sandbox test.dts - it has:
183 *
184 * mmc0 - removable
185 * mmc1 - removable
186 * mmc2 - fixed
187 */
188 ut_assertok(blk_first_device_err(BLKF_FIXED, &dev));
189 ut_asserteq_str("mmc2.blk", dev->name);
190 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
191
192 ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev));
193 ut_asserteq_str("mmc1.blk", dev->name);
194 ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev));
195 ut_asserteq_str("mmc0.blk", dev->name);
196 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev));
197
198 ut_assertok(blk_first_device_err(BLKF_BOTH, &dev));
199 ut_asserteq_str("mmc2.blk", dev->name);
200 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
201 ut_asserteq_str("mmc1.blk", dev->name);
202 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
203 ut_asserteq_str("mmc0.blk", dev->name);
204 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
205
206 ut_asserteq(1, blk_count_devices(BLKF_FIXED));
207 ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE));
208 ut_asserteq(3, blk_count_devices(BLKF_BOTH));
209
210 i = 0;
211 blk_foreach_probe(BLKF_FIXED, dev)
212 ut_asserteq_str((i++, "mmc2.blk"), dev->name);
213 ut_asserteq(1, i);
214
215 i = 0;
216 blk_foreach_probe(BLKF_REMOVABLE, dev)
217 ut_asserteq_str(i++ ? "mmc0.blk" : "mmc1.blk", dev->name);
218 ut_asserteq(2, i);
219
220 i = 0;
221 blk_foreach_probe(BLKF_BOTH, dev)
222 ut_asserteq_str((++i == 1 ? "mmc2.blk" : i == 2 ?
223 "mmc1.blk" : "mmc0.blk"), dev->name);
224 ut_asserteq(3, i);
225
226 return 0;
227}
228DM_TEST(dm_test_blk_iter, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
Simon Glass8e61f932022-02-28 12:08:35 -0700229
230/* Test finding fixed/removable block devices */
231static int dm_test_blk_flags(struct unit_test_state *uts)
232{
233 struct udevice *dev;
234
235 /* Iterate through devices without probing them */
236 ut_assertok(blk_find_first(BLKF_BOTH, &dev));
237 ut_assertnonnull(dev);
238 ut_asserteq_str("mmc2.blk", dev->name);
239
240 ut_assertok(blk_find_next(BLKF_BOTH, &dev));
241 ut_assertnonnull(dev);
242 ut_asserteq_str("mmc1.blk", dev->name);
243
244 ut_assertok(blk_find_next(BLKF_BOTH, &dev));
245 ut_assertnonnull(dev);
246 ut_asserteq_str("mmc0.blk", dev->name);
247
248 ut_asserteq(-ENODEV, blk_find_next(BLKF_BOTH, &dev));
249 ut_assertnull(dev);
250
251 /* All devices are removable until probed */
252 ut_asserteq(-ENODEV, blk_find_first(BLKF_FIXED, &dev));
253
254 ut_assertok(blk_find_first(BLKF_REMOVABLE, &dev));
255 ut_assertnonnull(dev);
256 ut_asserteq_str("mmc2.blk", dev->name);
257
258 /* Now probe them and iterate again */
259 ut_assertok(blk_first_device_err(BLKF_BOTH, &dev));
260 ut_assertnonnull(dev);
261 ut_asserteq_str("mmc2.blk", dev->name);
262
263 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
264 ut_assertnonnull(dev);
265 ut_asserteq_str("mmc1.blk", dev->name);
266
267 ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
268 ut_assertnonnull(dev);
269 ut_asserteq_str("mmc0.blk", dev->name);
270
271 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_BOTH, &dev));
272
273 /* Look only for fixed devices */
274 ut_assertok(blk_first_device_err(BLKF_FIXED, &dev));
275 ut_assertnonnull(dev);
276 ut_asserteq_str("mmc2.blk", dev->name);
277
278 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
279
280 /* Look only for removable devices */
281 ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev));
282 ut_assertnonnull(dev);
283 ut_asserteq_str("mmc1.blk", dev->name);
284
285 ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev));
286 ut_assertnonnull(dev);
287 ut_asserteq_str("mmc0.blk", dev->name);
288
289 ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev));
290
291 return 0;
292}
293DM_TEST(dm_test_blk_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
294
295/* Test blk_foreach() and friend */
296static int dm_test_blk_foreach(struct unit_test_state *uts)
297{
298 struct udevice *dev;
299 int found;
300
301 /* Test blk_foreach() - use the 3rd bytes of the name (0/1/2) */
302 found = 0;
303 blk_foreach(BLKF_BOTH, dev)
304 found |= 1 << dectoul(&dev->name[3], NULL);
305 ut_asserteq(7, found);
306
307 /* All devices are removable until probed */
308 found = 0;
309 blk_foreach(BLKF_FIXED, dev)
310 found |= 1 << dectoul(&dev->name[3], NULL);
311 ut_asserteq(0, found);
312
313 found = 0;
314 blk_foreach(BLKF_REMOVABLE, dev)
315 found |= 1 << dectoul(&dev->name[3], NULL);
316 ut_asserteq(7, found);
317
318 /* Now try again with the probing functions */
319 found = 0;
320 blk_foreach_probe(BLKF_BOTH, dev)
321 found |= 1 << dectoul(&dev->name[3], NULL);
322 ut_asserteq(7, found);
323 ut_asserteq(3, blk_count_devices(BLKF_BOTH));
324
325 found = 0;
326 blk_foreach_probe(BLKF_FIXED, dev)
327 found |= 1 << dectoul(&dev->name[3], NULL);
328 ut_asserteq(4, found);
329 ut_asserteq(1, blk_count_devices(BLKF_FIXED));
330
331 found = 0;
332 blk_foreach_probe(BLKF_REMOVABLE, dev)
333 found |= 1 << dectoul(&dev->name[3], NULL);
334 ut_asserteq(3, found);
335 ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE));
336
337 return 0;
338}
339DM_TEST(dm_test_blk_foreach, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);