Prepare v2023.10
[platform/kernel/u-boot.git] / test / dm / blk.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  */
5
6 #include <common.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 */
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, &dev0));
26         ut_assertok(host_create_device("test1", false, &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, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
47
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 */
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, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
96
97 /* Test that we can find block devices without probing them */
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, &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, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
118
119 /* Test that block device numbering works as expected */
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, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
153
154 /* Test that we can get a block from its parent */
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, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
171
172 /* Test iteration through block devices */
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, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
226
227 /* Test finding fixed/removable block devices */
228 static int dm_test_blk_flags(struct unit_test_state *uts)
229 {
230         struct udevice *dev;
231
232         /* Iterate through devices without probing them */
233         ut_assertok(blk_find_first(BLKF_BOTH, &dev));
234         ut_assertnonnull(dev);
235         ut_asserteq_str("mmc2.blk", dev->name);
236
237         ut_assertok(blk_find_next(BLKF_BOTH, &dev));
238         ut_assertnonnull(dev);
239         ut_asserteq_str("mmc1.blk", dev->name);
240
241         ut_assertok(blk_find_next(BLKF_BOTH, &dev));
242         ut_assertnonnull(dev);
243         ut_asserteq_str("mmc0.blk", dev->name);
244
245         ut_asserteq(-ENODEV, blk_find_next(BLKF_BOTH, &dev));
246         ut_assertnull(dev);
247
248         /* All devices are removable until probed */
249         ut_asserteq(-ENODEV, blk_find_first(BLKF_FIXED, &dev));
250
251         ut_assertok(blk_find_first(BLKF_REMOVABLE, &dev));
252         ut_assertnonnull(dev);
253         ut_asserteq_str("mmc2.blk", dev->name);
254
255         /* Now probe them and iterate again */
256         ut_assertok(blk_first_device_err(BLKF_BOTH, &dev));
257         ut_assertnonnull(dev);
258         ut_asserteq_str("mmc2.blk", dev->name);
259
260         ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
261         ut_assertnonnull(dev);
262         ut_asserteq_str("mmc1.blk", dev->name);
263
264         ut_assertok(blk_next_device_err(BLKF_BOTH, &dev));
265         ut_assertnonnull(dev);
266         ut_asserteq_str("mmc0.blk", dev->name);
267
268         ut_asserteq(-ENODEV, blk_next_device_err(BLKF_BOTH, &dev));
269
270         /* Look only for fixed devices */
271         ut_assertok(blk_first_device_err(BLKF_FIXED, &dev));
272         ut_assertnonnull(dev);
273         ut_asserteq_str("mmc2.blk", dev->name);
274
275         ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev));
276
277         /* Look only for removable devices */
278         ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev));
279         ut_assertnonnull(dev);
280         ut_asserteq_str("mmc1.blk", dev->name);
281
282         ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev));
283         ut_assertnonnull(dev);
284         ut_asserteq_str("mmc0.blk", dev->name);
285
286         ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev));
287
288         return 0;
289 }
290 DM_TEST(dm_test_blk_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
291
292 /* Test blk_foreach() and friend */
293 static int dm_test_blk_foreach(struct unit_test_state *uts)
294 {
295         struct udevice *dev;
296         int found;
297
298         /* Test blk_foreach() - use the 3rd bytes of the name (0/1/2) */
299         found = 0;
300         blk_foreach(BLKF_BOTH, dev)
301                 found |= 1 << dectoul(&dev->name[3], NULL);
302         ut_asserteq(7, found);
303
304         /* All devices are removable until probed */
305         found = 0;
306         blk_foreach(BLKF_FIXED, dev)
307                 found |= 1 << dectoul(&dev->name[3], NULL);
308         ut_asserteq(0, found);
309
310         found = 0;
311         blk_foreach(BLKF_REMOVABLE, dev)
312                 found |= 1 << dectoul(&dev->name[3], NULL);
313         ut_asserteq(7, found);
314
315         /* Now try again with the probing functions */
316         found = 0;
317         blk_foreach_probe(BLKF_BOTH, dev)
318                 found |= 1 << dectoul(&dev->name[3], NULL);
319         ut_asserteq(7, found);
320         ut_asserteq(3, blk_count_devices(BLKF_BOTH));
321
322         found = 0;
323         blk_foreach_probe(BLKF_FIXED, dev)
324                 found |= 1 << dectoul(&dev->name[3], NULL);
325         ut_asserteq(4, found);
326         ut_asserteq(1, blk_count_devices(BLKF_FIXED));
327
328         found = 0;
329         blk_foreach_probe(BLKF_REMOVABLE, dev)
330                 found |= 1 << dectoul(&dev->name[3], NULL);
331         ut_asserteq(3, found);
332         ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE));
333
334         return 0;
335 }
336 DM_TEST(dm_test_blk_foreach, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);