Commit 6139281a6473334351c8776643478c0b0e208342

Authored by Simon Glass
1 parent e7017a3c7d

dm: blk: Allow finding block devices without probing

Sometimes it is useful to be able to find a block device without also
probing it. Add a function for this as well as the associated test.

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 3 changed files with 48 additions and 3 deletions Inline Diff

drivers/block/blk-uclass.c
1 /* 1 /*
2 * Copyright (C) 2016 Google, Inc 2 * Copyright (C) 2016 Google, Inc
3 * Written by Simon Glass <sjg@chromium.org> 3 * Written by Simon Glass <sjg@chromium.org>
4 * 4 *
5 * SPDX-License-Identifier: GPL-2.0+ 5 * SPDX-License-Identifier: GPL-2.0+
6 */ 6 */
7 7
8 #include <common.h> 8 #include <common.h>
9 #include <blk.h> 9 #include <blk.h>
10 #include <dm.h> 10 #include <dm.h>
11 #include <dm/device-internal.h> 11 #include <dm/device-internal.h>
12 #include <dm/lists.h> 12 #include <dm/lists.h>
13 13
14 static const char *if_typename_str[IF_TYPE_COUNT] = { 14 static const char *if_typename_str[IF_TYPE_COUNT] = {
15 [IF_TYPE_IDE] = "ide", 15 [IF_TYPE_IDE] = "ide",
16 [IF_TYPE_SCSI] = "scsi", 16 [IF_TYPE_SCSI] = "scsi",
17 [IF_TYPE_ATAPI] = "atapi", 17 [IF_TYPE_ATAPI] = "atapi",
18 [IF_TYPE_USB] = "usb", 18 [IF_TYPE_USB] = "usb",
19 [IF_TYPE_DOC] = "doc", 19 [IF_TYPE_DOC] = "doc",
20 [IF_TYPE_MMC] = "mmc", 20 [IF_TYPE_MMC] = "mmc",
21 [IF_TYPE_SD] = "sd", 21 [IF_TYPE_SD] = "sd",
22 [IF_TYPE_SATA] = "sata", 22 [IF_TYPE_SATA] = "sata",
23 [IF_TYPE_HOST] = "host", 23 [IF_TYPE_HOST] = "host",
24 [IF_TYPE_SYSTEMACE] = "ace", 24 [IF_TYPE_SYSTEMACE] = "ace",
25 }; 25 };
26 26
27 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { 27 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
28 [IF_TYPE_IDE] = UCLASS_INVALID, 28 [IF_TYPE_IDE] = UCLASS_INVALID,
29 [IF_TYPE_SCSI] = UCLASS_SCSI, 29 [IF_TYPE_SCSI] = UCLASS_SCSI,
30 [IF_TYPE_ATAPI] = UCLASS_INVALID, 30 [IF_TYPE_ATAPI] = UCLASS_INVALID,
31 [IF_TYPE_USB] = UCLASS_MASS_STORAGE, 31 [IF_TYPE_USB] = UCLASS_MASS_STORAGE,
32 [IF_TYPE_DOC] = UCLASS_INVALID, 32 [IF_TYPE_DOC] = UCLASS_INVALID,
33 [IF_TYPE_MMC] = UCLASS_MMC, 33 [IF_TYPE_MMC] = UCLASS_MMC,
34 [IF_TYPE_SD] = UCLASS_INVALID, 34 [IF_TYPE_SD] = UCLASS_INVALID,
35 [IF_TYPE_SATA] = UCLASS_AHCI, 35 [IF_TYPE_SATA] = UCLASS_AHCI,
36 [IF_TYPE_HOST] = UCLASS_ROOT, 36 [IF_TYPE_HOST] = UCLASS_ROOT,
37 [IF_TYPE_SYSTEMACE] = UCLASS_INVALID, 37 [IF_TYPE_SYSTEMACE] = UCLASS_INVALID,
38 }; 38 };
39 39
40 static enum if_type if_typename_to_iftype(const char *if_typename) 40 static enum if_type if_typename_to_iftype(const char *if_typename)
41 { 41 {
42 int i; 42 int i;
43 43
44 for (i = 0; i < IF_TYPE_COUNT; i++) { 44 for (i = 0; i < IF_TYPE_COUNT; i++) {
45 if (if_typename_str[i] && 45 if (if_typename_str[i] &&
46 !strcmp(if_typename, if_typename_str[i])) 46 !strcmp(if_typename, if_typename_str[i]))
47 return i; 47 return i;
48 } 48 }
49 49
50 return IF_TYPE_UNKNOWN; 50 return IF_TYPE_UNKNOWN;
51 } 51 }
52 52
53 static enum uclass_id if_type_to_uclass_id(enum if_type if_type) 53 static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
54 { 54 {
55 return if_type_uclass_id[if_type]; 55 return if_type_uclass_id[if_type];
56 } 56 }
57 57
58 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) 58 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
59 { 59 {
60 struct blk_desc *desc; 60 struct blk_desc *desc;
61 struct udevice *dev; 61 struct udevice *dev;
62 int ret; 62 int ret;
63 63
64 ret = blk_get_device(if_type, devnum, &dev); 64 ret = blk_get_device(if_type, devnum, &dev);
65 if (ret) 65 if (ret)
66 return NULL; 66 return NULL;
67 desc = dev_get_uclass_platdata(dev); 67 desc = dev_get_uclass_platdata(dev);
68 68
69 return desc; 69 return desc;
70 } 70 }
71 71
72 /* 72 /*
73 * This function is complicated with driver model. We look up the interface 73 * This function is complicated with driver model. We look up the interface
74 * name in a local table. This gives us an interface type which we can match 74 * name in a local table. This gives us an interface type which we can match
75 * against the uclass of the block device's parent. 75 * against the uclass of the block device's parent.
76 */ 76 */
77 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) 77 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
78 { 78 {
79 enum uclass_id uclass_id; 79 enum uclass_id uclass_id;
80 enum if_type if_type; 80 enum if_type if_type;
81 struct udevice *dev; 81 struct udevice *dev;
82 struct uclass *uc; 82 struct uclass *uc;
83 int ret; 83 int ret;
84 84
85 if_type = if_typename_to_iftype(if_typename); 85 if_type = if_typename_to_iftype(if_typename);
86 if (if_type == IF_TYPE_UNKNOWN) { 86 if (if_type == IF_TYPE_UNKNOWN) {
87 debug("%s: Unknown interface type '%s'\n", __func__, 87 debug("%s: Unknown interface type '%s'\n", __func__,
88 if_typename); 88 if_typename);
89 return NULL; 89 return NULL;
90 } 90 }
91 uclass_id = if_type_to_uclass_id(if_type); 91 uclass_id = if_type_to_uclass_id(if_type);
92 if (uclass_id == UCLASS_INVALID) { 92 if (uclass_id == UCLASS_INVALID) {
93 debug("%s: Unknown uclass for interface type'\n", 93 debug("%s: Unknown uclass for interface type'\n",
94 if_typename_str[if_type]); 94 if_typename_str[if_type]);
95 return NULL; 95 return NULL;
96 } 96 }
97 97
98 ret = uclass_get(UCLASS_BLK, &uc); 98 ret = uclass_get(UCLASS_BLK, &uc);
99 if (ret) 99 if (ret)
100 return NULL; 100 return NULL;
101 uclass_foreach_dev(dev, uc) { 101 uclass_foreach_dev(dev, uc) {
102 struct blk_desc *desc = dev_get_uclass_platdata(dev); 102 struct blk_desc *desc = dev_get_uclass_platdata(dev);
103 103
104 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 104 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
105 if_type, devnum, dev->name, desc->if_type, desc->devnum); 105 if_type, devnum, dev->name, desc->if_type, desc->devnum);
106 if (desc->devnum != devnum) 106 if (desc->devnum != devnum)
107 continue; 107 continue;
108 108
109 /* Find out the parent device uclass */ 109 /* Find out the parent device uclass */
110 if (device_get_uclass_id(dev->parent) != uclass_id) { 110 if (device_get_uclass_id(dev->parent) != uclass_id) {
111 debug("%s: parent uclass %d, this dev %d\n", __func__, 111 debug("%s: parent uclass %d, this dev %d\n", __func__,
112 device_get_uclass_id(dev->parent), uclass_id); 112 device_get_uclass_id(dev->parent), uclass_id);
113 continue; 113 continue;
114 } 114 }
115 115
116 if (device_probe(dev)) 116 if (device_probe(dev))
117 return NULL; 117 return NULL;
118 118
119 debug("%s: Device desc %p\n", __func__, desc); 119 debug("%s: Device desc %p\n", __func__, desc);
120 return desc; 120 return desc;
121 } 121 }
122 debug("%s: No device found\n", __func__); 122 debug("%s: No device found\n", __func__);
123 123
124 return NULL; 124 return NULL;
125 } 125 }
126 126
127 /** 127 /**
128 * get_desc() - Get the block device descriptor for the given device number 128 * get_desc() - Get the block device descriptor for the given device number
129 * 129 *
130 * @if_type: Interface type 130 * @if_type: Interface type
131 * @devnum: Device number (0 = first) 131 * @devnum: Device number (0 = first)
132 * @descp: Returns block device descriptor on success 132 * @descp: Returns block device descriptor on success
133 * @return 0 on success, -ENODEV if there is no such device and no device 133 * @return 0 on success, -ENODEV if there is no such device and no device
134 * with a higher device number, -ENOENT if there is no such device but there 134 * with a higher device number, -ENOENT if there is no such device but there
135 * is one with a higher number, or other -ve on other error. 135 * is one with a higher number, or other -ve on other error.
136 */ 136 */
137 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) 137 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp)
138 { 138 {
139 bool found_more = false; 139 bool found_more = false;
140 struct udevice *dev; 140 struct udevice *dev;
141 struct uclass *uc; 141 struct uclass *uc;
142 int ret; 142 int ret;
143 143
144 *descp = NULL; 144 *descp = NULL;
145 ret = uclass_get(UCLASS_BLK, &uc); 145 ret = uclass_get(UCLASS_BLK, &uc);
146 if (ret) 146 if (ret)
147 return ret; 147 return ret;
148 uclass_foreach_dev(dev, uc) { 148 uclass_foreach_dev(dev, uc) {
149 struct blk_desc *desc = dev_get_uclass_platdata(dev); 149 struct blk_desc *desc = dev_get_uclass_platdata(dev);
150 150
151 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 151 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
152 if_type, devnum, dev->name, desc->if_type, desc->devnum); 152 if_type, devnum, dev->name, desc->if_type, desc->devnum);
153 if (desc->if_type == if_type) { 153 if (desc->if_type == if_type) {
154 if (desc->devnum == devnum) { 154 if (desc->devnum == devnum) {
155 ret = device_probe(dev); 155 ret = device_probe(dev);
156 if (ret) 156 if (ret)
157 return ret; 157 return ret;
158 158
159 *descp = desc; 159 *descp = desc;
160 return 0; 160 return 0;
161 } else if (desc->devnum > devnum) { 161 } else if (desc->devnum > devnum) {
162 found_more = true; 162 found_more = true;
163 } 163 }
164 } 164 }
165 } 165 }
166 166
167 return found_more ? -ENOENT : -ENODEV; 167 return found_more ? -ENOENT : -ENODEV;
168 } 168 }
169 169
170 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart) 170 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
171 { 171 {
172 struct udevice *dev; 172 struct udevice *dev;
173 int ret; 173 int ret;
174 174
175 ret = blk_get_device(if_type, devnum, &dev); 175 ret = blk_get_device(if_type, devnum, &dev);
176 if (ret) 176 if (ret)
177 return ret; 177 return ret;
178 178
179 return blk_select_hwpart(dev, hwpart); 179 return blk_select_hwpart(dev, hwpart);
180 } 180 }
181 181
182 int blk_list_part(enum if_type if_type) 182 int blk_list_part(enum if_type if_type)
183 { 183 {
184 struct blk_desc *desc; 184 struct blk_desc *desc;
185 int devnum, ok; 185 int devnum, ok;
186 int ret; 186 int ret;
187 187
188 for (ok = 0, devnum = 0;; ++devnum) { 188 for (ok = 0, devnum = 0;; ++devnum) {
189 ret = get_desc(if_type, devnum, &desc); 189 ret = get_desc(if_type, devnum, &desc);
190 if (ret == -ENODEV) 190 if (ret == -ENODEV)
191 break; 191 break;
192 else if (ret) 192 else if (ret)
193 continue; 193 continue;
194 if (desc->part_type != PART_TYPE_UNKNOWN) { 194 if (desc->part_type != PART_TYPE_UNKNOWN) {
195 ++ok; 195 ++ok;
196 if (devnum) 196 if (devnum)
197 putc('\n'); 197 putc('\n');
198 part_print(desc); 198 part_print(desc);
199 } 199 }
200 } 200 }
201 if (!ok) 201 if (!ok)
202 return -ENODEV; 202 return -ENODEV;
203 203
204 return 0; 204 return 0;
205 } 205 }
206 206
207 int blk_print_part_devnum(enum if_type if_type, int devnum) 207 int blk_print_part_devnum(enum if_type if_type, int devnum)
208 { 208 {
209 struct blk_desc *desc; 209 struct blk_desc *desc;
210 int ret; 210 int ret;
211 211
212 ret = get_desc(if_type, devnum, &desc); 212 ret = get_desc(if_type, devnum, &desc);
213 if (ret) 213 if (ret)
214 return ret; 214 return ret;
215 if (desc->type == DEV_TYPE_UNKNOWN) 215 if (desc->type == DEV_TYPE_UNKNOWN)
216 return -ENOENT; 216 return -ENOENT;
217 part_print(desc); 217 part_print(desc);
218 218
219 return 0; 219 return 0;
220 } 220 }
221 221
222 void blk_list_devices(enum if_type if_type) 222 void blk_list_devices(enum if_type if_type)
223 { 223 {
224 struct blk_desc *desc; 224 struct blk_desc *desc;
225 int ret; 225 int ret;
226 int i; 226 int i;
227 227
228 for (i = 0;; ++i) { 228 for (i = 0;; ++i) {
229 ret = get_desc(if_type, i, &desc); 229 ret = get_desc(if_type, i, &desc);
230 if (ret == -ENODEV) 230 if (ret == -ENODEV)
231 break; 231 break;
232 else if (ret) 232 else if (ret)
233 continue; 233 continue;
234 if (desc->type == DEV_TYPE_UNKNOWN) 234 if (desc->type == DEV_TYPE_UNKNOWN)
235 continue; /* list only known devices */ 235 continue; /* list only known devices */
236 printf("Device %d: ", i); 236 printf("Device %d: ", i);
237 dev_print(desc); 237 dev_print(desc);
238 } 238 }
239 } 239 }
240 240
241 int blk_print_device_num(enum if_type if_type, int devnum) 241 int blk_print_device_num(enum if_type if_type, int devnum)
242 { 242 {
243 struct blk_desc *desc; 243 struct blk_desc *desc;
244 int ret; 244 int ret;
245 245
246 ret = get_desc(if_type, devnum, &desc); 246 ret = get_desc(if_type, devnum, &desc);
247 if (ret) 247 if (ret)
248 return ret; 248 return ret;
249 printf("\nIDE device %d: ", devnum); 249 printf("\nIDE device %d: ", devnum);
250 dev_print(desc); 250 dev_print(desc);
251 251
252 return 0; 252 return 0;
253 } 253 }
254 254
255 int blk_show_device(enum if_type if_type, int devnum) 255 int blk_show_device(enum if_type if_type, int devnum)
256 { 256 {
257 struct blk_desc *desc; 257 struct blk_desc *desc;
258 int ret; 258 int ret;
259 259
260 printf("\nDevice %d: ", devnum); 260 printf("\nDevice %d: ", devnum);
261 ret = get_desc(if_type, devnum, &desc); 261 ret = get_desc(if_type, devnum, &desc);
262 if (ret == -ENODEV || ret == -ENOENT) { 262 if (ret == -ENODEV || ret == -ENOENT) {
263 printf("unknown device\n"); 263 printf("unknown device\n");
264 return -ENODEV; 264 return -ENODEV;
265 } 265 }
266 if (ret) 266 if (ret)
267 return ret; 267 return ret;
268 dev_print(desc); 268 dev_print(desc);
269 269
270 if (desc->type == DEV_TYPE_UNKNOWN) 270 if (desc->type == DEV_TYPE_UNKNOWN)
271 return -ENOENT; 271 return -ENOENT;
272 272
273 return 0; 273 return 0;
274 } 274 }
275 275
276 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, 276 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
277 lbaint_t blkcnt, void *buffer) 277 lbaint_t blkcnt, void *buffer)
278 { 278 {
279 struct blk_desc *desc; 279 struct blk_desc *desc;
280 ulong n; 280 ulong n;
281 int ret; 281 int ret;
282 282
283 ret = get_desc(if_type, devnum, &desc); 283 ret = get_desc(if_type, devnum, &desc);
284 if (ret) 284 if (ret)
285 return ret; 285 return ret;
286 n = blk_dread(desc, start, blkcnt, buffer); 286 n = blk_dread(desc, start, blkcnt, buffer);
287 if (IS_ERR_VALUE(n)) 287 if (IS_ERR_VALUE(n))
288 return n; 288 return n;
289 289
290 /* flush cache after read */ 290 /* flush cache after read */
291 flush_cache((ulong)buffer, blkcnt * desc->blksz); 291 flush_cache((ulong)buffer, blkcnt * desc->blksz);
292 292
293 return n; 293 return n;
294 } 294 }
295 295
296 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, 296 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
297 lbaint_t blkcnt, const void *buffer) 297 lbaint_t blkcnt, const void *buffer)
298 { 298 {
299 struct blk_desc *desc; 299 struct blk_desc *desc;
300 int ret; 300 int ret;
301 301
302 ret = get_desc(if_type, devnum, &desc); 302 ret = get_desc(if_type, devnum, &desc);
303 if (ret) 303 if (ret)
304 return ret; 304 return ret;
305 return blk_dwrite(desc, start, blkcnt, buffer); 305 return blk_dwrite(desc, start, blkcnt, buffer);
306 } 306 }
307 307
308 int blk_select_hwpart(struct udevice *dev, int hwpart) 308 int blk_select_hwpart(struct udevice *dev, int hwpart)
309 { 309 {
310 const struct blk_ops *ops = blk_get_ops(dev); 310 const struct blk_ops *ops = blk_get_ops(dev);
311 311
312 if (!ops) 312 if (!ops)
313 return -ENOSYS; 313 return -ENOSYS;
314 if (!ops->select_hwpart) 314 if (!ops->select_hwpart)
315 return 0; 315 return 0;
316 316
317 return ops->select_hwpart(dev, hwpart); 317 return ops->select_hwpart(dev, hwpart);
318 } 318 }
319 319
320 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) 320 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
321 { 321 {
322 return blk_select_hwpart(desc->bdev, hwpart); 322 return blk_select_hwpart(desc->bdev, hwpart);
323 } 323 }
324 324
325 int blk_first_device(int if_type, struct udevice **devp) 325 int blk_first_device(int if_type, struct udevice **devp)
326 { 326 {
327 struct blk_desc *desc; 327 struct blk_desc *desc;
328 int ret; 328 int ret;
329 329
330 ret = uclass_first_device(UCLASS_BLK, devp); 330 ret = uclass_first_device(UCLASS_BLK, devp);
331 if (ret) 331 if (ret)
332 return ret; 332 return ret;
333 if (!*devp) 333 if (!*devp)
334 return -ENODEV; 334 return -ENODEV;
335 do { 335 do {
336 desc = dev_get_uclass_platdata(*devp); 336 desc = dev_get_uclass_platdata(*devp);
337 if (desc->if_type == if_type) 337 if (desc->if_type == if_type)
338 return 0; 338 return 0;
339 ret = uclass_next_device(devp); 339 ret = uclass_next_device(devp);
340 if (ret) 340 if (ret)
341 return ret; 341 return ret;
342 } while (*devp); 342 } while (*devp);
343 343
344 return -ENODEV; 344 return -ENODEV;
345 } 345 }
346 346
347 int blk_next_device(struct udevice **devp) 347 int blk_next_device(struct udevice **devp)
348 { 348 {
349 struct blk_desc *desc; 349 struct blk_desc *desc;
350 int ret, if_type; 350 int ret, if_type;
351 351
352 desc = dev_get_uclass_platdata(*devp); 352 desc = dev_get_uclass_platdata(*devp);
353 if_type = desc->if_type; 353 if_type = desc->if_type;
354 do { 354 do {
355 ret = uclass_next_device(devp); 355 ret = uclass_next_device(devp);
356 if (ret) 356 if (ret)
357 return ret; 357 return ret;
358 if (!*devp) 358 if (!*devp)
359 return -ENODEV; 359 return -ENODEV;
360 desc = dev_get_uclass_platdata(*devp); 360 desc = dev_get_uclass_platdata(*devp);
361 if (desc->if_type == if_type) 361 if (desc->if_type == if_type)
362 return 0; 362 return 0;
363 } while (1); 363 } while (1);
364 } 364 }
365 365
366 int blk_get_device(int if_type, int devnum, struct udevice **devp) 366 int blk_find_device(int if_type, int devnum, struct udevice **devp)
367 { 367 {
368 struct uclass *uc; 368 struct uclass *uc;
369 struct udevice *dev; 369 struct udevice *dev;
370 int ret; 370 int ret;
371 371
372 ret = uclass_get(UCLASS_BLK, &uc); 372 ret = uclass_get(UCLASS_BLK, &uc);
373 if (ret) 373 if (ret)
374 return ret; 374 return ret;
375 uclass_foreach_dev(dev, uc) { 375 uclass_foreach_dev(dev, uc) {
376 struct blk_desc *desc = dev_get_uclass_platdata(dev); 376 struct blk_desc *desc = dev_get_uclass_platdata(dev);
377 377
378 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 378 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
379 if_type, devnum, dev->name, desc->if_type, desc->devnum); 379 if_type, devnum, dev->name, desc->if_type, desc->devnum);
380 if (desc->if_type == if_type && desc->devnum == devnum) { 380 if (desc->if_type == if_type && desc->devnum == devnum) {
381 *devp = dev; 381 *devp = dev;
382 return device_probe(dev); 382 return 0;
383 } 383 }
384 } 384 }
385 385
386 return -ENODEV; 386 return -ENODEV;
387 }
388
389 int blk_get_device(int if_type, int devnum, struct udevice **devp)
390 {
391 int ret;
392
393 ret = blk_find_device(if_type, devnum, devp);
394 if (ret)
395 return ret;
396
397 return device_probe(*devp);
387 } 398 }
388 399
389 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, 400 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
390 lbaint_t blkcnt, void *buffer) 401 lbaint_t blkcnt, void *buffer)
391 { 402 {
392 struct udevice *dev = block_dev->bdev; 403 struct udevice *dev = block_dev->bdev;
393 const struct blk_ops *ops = blk_get_ops(dev); 404 const struct blk_ops *ops = blk_get_ops(dev);
394 ulong blks_read; 405 ulong blks_read;
395 406
396 if (!ops->read) 407 if (!ops->read)
397 return -ENOSYS; 408 return -ENOSYS;
398 409
399 if (blkcache_read(block_dev->if_type, block_dev->devnum, 410 if (blkcache_read(block_dev->if_type, block_dev->devnum,
400 start, blkcnt, block_dev->blksz, buffer)) 411 start, blkcnt, block_dev->blksz, buffer))
401 return blkcnt; 412 return blkcnt;
402 blks_read = ops->read(dev, start, blkcnt, buffer); 413 blks_read = ops->read(dev, start, blkcnt, buffer);
403 if (blks_read == blkcnt) 414 if (blks_read == blkcnt)
404 blkcache_fill(block_dev->if_type, block_dev->devnum, 415 blkcache_fill(block_dev->if_type, block_dev->devnum,
405 start, blkcnt, block_dev->blksz, buffer); 416 start, blkcnt, block_dev->blksz, buffer);
406 417
407 return blks_read; 418 return blks_read;
408 } 419 }
409 420
410 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, 421 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
411 lbaint_t blkcnt, const void *buffer) 422 lbaint_t blkcnt, const void *buffer)
412 { 423 {
413 struct udevice *dev = block_dev->bdev; 424 struct udevice *dev = block_dev->bdev;
414 const struct blk_ops *ops = blk_get_ops(dev); 425 const struct blk_ops *ops = blk_get_ops(dev);
415 426
416 if (!ops->write) 427 if (!ops->write)
417 return -ENOSYS; 428 return -ENOSYS;
418 429
419 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 430 blkcache_invalidate(block_dev->if_type, block_dev->devnum);
420 return ops->write(dev, start, blkcnt, buffer); 431 return ops->write(dev, start, blkcnt, buffer);
421 } 432 }
422 433
423 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, 434 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
424 lbaint_t blkcnt) 435 lbaint_t blkcnt)
425 { 436 {
426 struct udevice *dev = block_dev->bdev; 437 struct udevice *dev = block_dev->bdev;
427 const struct blk_ops *ops = blk_get_ops(dev); 438 const struct blk_ops *ops = blk_get_ops(dev);
428 439
429 if (!ops->erase) 440 if (!ops->erase)
430 return -ENOSYS; 441 return -ENOSYS;
431 442
432 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 443 blkcache_invalidate(block_dev->if_type, block_dev->devnum);
433 return ops->erase(dev, start, blkcnt); 444 return ops->erase(dev, start, blkcnt);
434 } 445 }
435 446
436 int blk_prepare_device(struct udevice *dev) 447 int blk_prepare_device(struct udevice *dev)
437 { 448 {
438 struct blk_desc *desc = dev_get_uclass_platdata(dev); 449 struct blk_desc *desc = dev_get_uclass_platdata(dev);
439 450
440 part_init(desc); 451 part_init(desc);
441 452
442 return 0; 453 return 0;
443 } 454 }
444 455
445 int blk_find_max_devnum(enum if_type if_type) 456 int blk_find_max_devnum(enum if_type if_type)
446 { 457 {
447 struct udevice *dev; 458 struct udevice *dev;
448 int max_devnum = -ENODEV; 459 int max_devnum = -ENODEV;
449 struct uclass *uc; 460 struct uclass *uc;
450 int ret; 461 int ret;
451 462
452 ret = uclass_get(UCLASS_BLK, &uc); 463 ret = uclass_get(UCLASS_BLK, &uc);
453 if (ret) 464 if (ret)
454 return ret; 465 return ret;
455 uclass_foreach_dev(dev, uc) { 466 uclass_foreach_dev(dev, uc) {
456 struct blk_desc *desc = dev_get_uclass_platdata(dev); 467 struct blk_desc *desc = dev_get_uclass_platdata(dev);
457 468
458 if (desc->if_type == if_type && desc->devnum > max_devnum) 469 if (desc->if_type == if_type && desc->devnum > max_devnum)
459 max_devnum = desc->devnum; 470 max_devnum = desc->devnum;
460 } 471 }
461 472
462 return max_devnum; 473 return max_devnum;
463 } 474 }
464 475
465 int blk_create_device(struct udevice *parent, const char *drv_name, 476 int blk_create_device(struct udevice *parent, const char *drv_name,
466 const char *name, int if_type, int devnum, int blksz, 477 const char *name, int if_type, int devnum, int blksz,
467 lbaint_t size, struct udevice **devp) 478 lbaint_t size, struct udevice **devp)
468 { 479 {
469 struct blk_desc *desc; 480 struct blk_desc *desc;
470 struct udevice *dev; 481 struct udevice *dev;
471 int ret; 482 int ret;
472 483
473 if (devnum == -1) { 484 if (devnum == -1) {
474 ret = blk_find_max_devnum(if_type); 485 ret = blk_find_max_devnum(if_type);
475 if (ret == -ENODEV) 486 if (ret == -ENODEV)
476 devnum = 0; 487 devnum = 0;
477 else if (ret < 0) 488 else if (ret < 0)
478 return ret; 489 return ret;
479 else 490 else
480 devnum = ret + 1; 491 devnum = ret + 1;
481 } 492 }
482 ret = device_bind_driver(parent, drv_name, name, &dev); 493 ret = device_bind_driver(parent, drv_name, name, &dev);
483 if (ret) 494 if (ret)
484 return ret; 495 return ret;
485 desc = dev_get_uclass_platdata(dev); 496 desc = dev_get_uclass_platdata(dev);
486 desc->if_type = if_type; 497 desc->if_type = if_type;
487 desc->blksz = blksz; 498 desc->blksz = blksz;
488 desc->lba = size / blksz; 499 desc->lba = size / blksz;
489 desc->part_type = PART_TYPE_UNKNOWN; 500 desc->part_type = PART_TYPE_UNKNOWN;
490 desc->bdev = dev; 501 desc->bdev = dev;
491 desc->devnum = devnum; 502 desc->devnum = devnum;
492 *devp = dev; 503 *devp = dev;
493 504
494 return 0; 505 return 0;
495 } 506 }
496 507
497 int blk_create_devicef(struct udevice *parent, const char *drv_name, 508 int blk_create_devicef(struct udevice *parent, const char *drv_name,
498 const char *name, int if_type, int devnum, int blksz, 509 const char *name, int if_type, int devnum, int blksz,
499 lbaint_t size, struct udevice **devp) 510 lbaint_t size, struct udevice **devp)
500 { 511 {
501 char dev_name[30], *str; 512 char dev_name[30], *str;
502 int ret; 513 int ret;
503 514
504 snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); 515 snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
505 str = strdup(dev_name); 516 str = strdup(dev_name);
506 if (!str) 517 if (!str)
507 return -ENOMEM; 518 return -ENOMEM;
508 519
509 ret = blk_create_device(parent, drv_name, str, if_type, devnum, 520 ret = blk_create_device(parent, drv_name, str, if_type, devnum,
510 blksz, size, devp); 521 blksz, size, devp);
511 if (ret) { 522 if (ret) {
512 free(str); 523 free(str);
513 return ret; 524 return ret;
514 } 525 }
515 device_set_name_alloced(*devp); 526 device_set_name_alloced(*devp);
516 527
517 return ret; 528 return ret;
518 } 529 }
519 530
520 int blk_unbind_all(int if_type) 531 int blk_unbind_all(int if_type)
521 { 532 {
522 struct uclass *uc; 533 struct uclass *uc;
523 struct udevice *dev, *next; 534 struct udevice *dev, *next;
524 int ret; 535 int ret;
525 536
526 ret = uclass_get(UCLASS_BLK, &uc); 537 ret = uclass_get(UCLASS_BLK, &uc);
527 if (ret) 538 if (ret)
528 return ret; 539 return ret;
529 uclass_foreach_dev_safe(dev, next, uc) { 540 uclass_foreach_dev_safe(dev, next, uc) {
530 struct blk_desc *desc = dev_get_uclass_platdata(dev); 541 struct blk_desc *desc = dev_get_uclass_platdata(dev);
531 542
532 if (desc->if_type == if_type) { 543 if (desc->if_type == if_type) {
533 ret = device_remove(dev, DM_REMOVE_NORMAL); 544 ret = device_remove(dev, DM_REMOVE_NORMAL);
534 if (ret) 545 if (ret)
535 return ret; 546 return ret;
536 ret = device_unbind(dev); 547 ret = device_unbind(dev);
537 if (ret) 548 if (ret)
538 return ret; 549 return ret;
539 } 550 }
540 } 551 }
541 552
542 return 0; 553 return 0;
543 } 554 }
544 555
545 UCLASS_DRIVER(blk) = { 556 UCLASS_DRIVER(blk) = {
546 .id = UCLASS_BLK, 557 .id = UCLASS_BLK,
547 .name = "blk", 558 .name = "blk",
548 .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), 559 .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
549 }; 560 };
550 561
1 /* 1 /*
2 * (C) Copyright 2000-2004 2 * (C) Copyright 2000-2004
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * 4 *
5 * SPDX-License-Identifier: GPL-2.0+ 5 * SPDX-License-Identifier: GPL-2.0+
6 */ 6 */
7 7
8 #ifndef BLK_H 8 #ifndef BLK_H
9 #define BLK_H 9 #define BLK_H
10 10
11 #ifdef CONFIG_SYS_64BIT_LBA 11 #ifdef CONFIG_SYS_64BIT_LBA
12 typedef uint64_t lbaint_t; 12 typedef uint64_t lbaint_t;
13 #define LBAFlength "ll" 13 #define LBAFlength "ll"
14 #else 14 #else
15 typedef ulong lbaint_t; 15 typedef ulong lbaint_t;
16 #define LBAFlength "l" 16 #define LBAFlength "l"
17 #endif 17 #endif
18 #define LBAF "%" LBAFlength "x" 18 #define LBAF "%" LBAFlength "x"
19 #define LBAFU "%" LBAFlength "u" 19 #define LBAFU "%" LBAFlength "u"
20 20
21 /* Interface types: */ 21 /* Interface types: */
22 enum if_type { 22 enum if_type {
23 IF_TYPE_UNKNOWN = 0, 23 IF_TYPE_UNKNOWN = 0,
24 IF_TYPE_IDE, 24 IF_TYPE_IDE,
25 IF_TYPE_SCSI, 25 IF_TYPE_SCSI,
26 IF_TYPE_ATAPI, 26 IF_TYPE_ATAPI,
27 IF_TYPE_USB, 27 IF_TYPE_USB,
28 IF_TYPE_DOC, 28 IF_TYPE_DOC,
29 IF_TYPE_MMC, 29 IF_TYPE_MMC,
30 IF_TYPE_SD, 30 IF_TYPE_SD,
31 IF_TYPE_SATA, 31 IF_TYPE_SATA,
32 IF_TYPE_HOST, 32 IF_TYPE_HOST,
33 IF_TYPE_SYSTEMACE, 33 IF_TYPE_SYSTEMACE,
34 34
35 IF_TYPE_COUNT, /* Number of interface types */ 35 IF_TYPE_COUNT, /* Number of interface types */
36 }; 36 };
37 37
38 /* 38 /*
39 * With driver model (CONFIG_BLK) this is uclass platform data, accessible 39 * With driver model (CONFIG_BLK) this is uclass platform data, accessible
40 * with dev_get_uclass_platdata(dev) 40 * with dev_get_uclass_platdata(dev)
41 */ 41 */
42 struct blk_desc { 42 struct blk_desc {
43 /* 43 /*
44 * TODO: With driver model we should be able to use the parent 44 * TODO: With driver model we should be able to use the parent
45 * device's uclass instead. 45 * device's uclass instead.
46 */ 46 */
47 enum if_type if_type; /* type of the interface */ 47 enum if_type if_type; /* type of the interface */
48 int devnum; /* device number */ 48 int devnum; /* device number */
49 unsigned char part_type; /* partition type */ 49 unsigned char part_type; /* partition type */
50 unsigned char target; /* target SCSI ID */ 50 unsigned char target; /* target SCSI ID */
51 unsigned char lun; /* target LUN */ 51 unsigned char lun; /* target LUN */
52 unsigned char hwpart; /* HW partition, e.g. for eMMC */ 52 unsigned char hwpart; /* HW partition, e.g. for eMMC */
53 unsigned char type; /* device type */ 53 unsigned char type; /* device type */
54 unsigned char removable; /* removable device */ 54 unsigned char removable; /* removable device */
55 #ifdef CONFIG_LBA48 55 #ifdef CONFIG_LBA48
56 /* device can use 48bit addr (ATA/ATAPI v7) */ 56 /* device can use 48bit addr (ATA/ATAPI v7) */
57 unsigned char lba48; 57 unsigned char lba48;
58 #endif 58 #endif
59 lbaint_t lba; /* number of blocks */ 59 lbaint_t lba; /* number of blocks */
60 unsigned long blksz; /* block size */ 60 unsigned long blksz; /* block size */
61 int log2blksz; /* for convenience: log2(blksz) */ 61 int log2blksz; /* for convenience: log2(blksz) */
62 char vendor[40+1]; /* IDE model, SCSI Vendor */ 62 char vendor[40+1]; /* IDE model, SCSI Vendor */
63 char product[20+1]; /* IDE Serial no, SCSI product */ 63 char product[20+1]; /* IDE Serial no, SCSI product */
64 char revision[8+1]; /* firmware revision */ 64 char revision[8+1]; /* firmware revision */
65 #ifdef CONFIG_BLK 65 #ifdef CONFIG_BLK
66 /* 66 /*
67 * For now we have a few functions which take struct blk_desc as a 67 * For now we have a few functions which take struct blk_desc as a
68 * parameter. This field allows them to look up the associated 68 * parameter. This field allows them to look up the associated
69 * device. Once these functions are removed we can drop this field. 69 * device. Once these functions are removed we can drop this field.
70 */ 70 */
71 struct udevice *bdev; 71 struct udevice *bdev;
72 #else 72 #else
73 unsigned long (*block_read)(struct blk_desc *block_dev, 73 unsigned long (*block_read)(struct blk_desc *block_dev,
74 lbaint_t start, 74 lbaint_t start,
75 lbaint_t blkcnt, 75 lbaint_t blkcnt,
76 void *buffer); 76 void *buffer);
77 unsigned long (*block_write)(struct blk_desc *block_dev, 77 unsigned long (*block_write)(struct blk_desc *block_dev,
78 lbaint_t start, 78 lbaint_t start,
79 lbaint_t blkcnt, 79 lbaint_t blkcnt,
80 const void *buffer); 80 const void *buffer);
81 unsigned long (*block_erase)(struct blk_desc *block_dev, 81 unsigned long (*block_erase)(struct blk_desc *block_dev,
82 lbaint_t start, 82 lbaint_t start,
83 lbaint_t blkcnt); 83 lbaint_t blkcnt);
84 void *priv; /* driver private struct pointer */ 84 void *priv; /* driver private struct pointer */
85 #endif 85 #endif
86 }; 86 };
87 87
88 #define BLOCK_CNT(size, blk_desc) (PAD_COUNT(size, blk_desc->blksz)) 88 #define BLOCK_CNT(size, blk_desc) (PAD_COUNT(size, blk_desc->blksz))
89 #define PAD_TO_BLOCKSIZE(size, blk_desc) \ 89 #define PAD_TO_BLOCKSIZE(size, blk_desc) \
90 (PAD_SIZE(size, blk_desc->blksz)) 90 (PAD_SIZE(size, blk_desc->blksz))
91 91
92 #ifdef CONFIG_BLOCK_CACHE 92 #ifdef CONFIG_BLOCK_CACHE
93 /** 93 /**
94 * blkcache_read() - attempt to read a set of blocks from cache 94 * blkcache_read() - attempt to read a set of blocks from cache
95 * 95 *
96 * @param iftype - IF_TYPE_x for type of device 96 * @param iftype - IF_TYPE_x for type of device
97 * @param dev - device index of particular type 97 * @param dev - device index of particular type
98 * @param start - starting block number 98 * @param start - starting block number
99 * @param blkcnt - number of blocks to read 99 * @param blkcnt - number of blocks to read
100 * @param blksz - size in bytes of each block 100 * @param blksz - size in bytes of each block
101 * @param buf - buffer to contain cached data 101 * @param buf - buffer to contain cached data
102 * 102 *
103 * @return - '1' if block returned from cache, '0' otherwise. 103 * @return - '1' if block returned from cache, '0' otherwise.
104 */ 104 */
105 int blkcache_read(int iftype, int dev, 105 int blkcache_read(int iftype, int dev,
106 lbaint_t start, lbaint_t blkcnt, 106 lbaint_t start, lbaint_t blkcnt,
107 unsigned long blksz, void *buffer); 107 unsigned long blksz, void *buffer);
108 108
109 /** 109 /**
110 * blkcache_fill() - make data read from a block device available 110 * blkcache_fill() - make data read from a block device available
111 * to the block cache 111 * to the block cache
112 * 112 *
113 * @param iftype - IF_TYPE_x for type of device 113 * @param iftype - IF_TYPE_x for type of device
114 * @param dev - device index of particular type 114 * @param dev - device index of particular type
115 * @param start - starting block number 115 * @param start - starting block number
116 * @param blkcnt - number of blocks available 116 * @param blkcnt - number of blocks available
117 * @param blksz - size in bytes of each block 117 * @param blksz - size in bytes of each block
118 * @param buf - buffer containing data to cache 118 * @param buf - buffer containing data to cache
119 * 119 *
120 */ 120 */
121 void blkcache_fill(int iftype, int dev, 121 void blkcache_fill(int iftype, int dev,
122 lbaint_t start, lbaint_t blkcnt, 122 lbaint_t start, lbaint_t blkcnt,
123 unsigned long blksz, void const *buffer); 123 unsigned long blksz, void const *buffer);
124 124
125 /** 125 /**
126 * blkcache_invalidate() - discard the cache for a set of blocks 126 * blkcache_invalidate() - discard the cache for a set of blocks
127 * because of a write or device (re)initialization. 127 * because of a write or device (re)initialization.
128 * 128 *
129 * @param iftype - IF_TYPE_x for type of device 129 * @param iftype - IF_TYPE_x for type of device
130 * @param dev - device index of particular type 130 * @param dev - device index of particular type
131 */ 131 */
132 void blkcache_invalidate(int iftype, int dev); 132 void blkcache_invalidate(int iftype, int dev);
133 133
134 /** 134 /**
135 * blkcache_configure() - configure block cache 135 * blkcache_configure() - configure block cache
136 * 136 *
137 * @param blocks - maximum blocks per entry 137 * @param blocks - maximum blocks per entry
138 * @param entries - maximum entries in cache 138 * @param entries - maximum entries in cache
139 */ 139 */
140 void blkcache_configure(unsigned blocks, unsigned entries); 140 void blkcache_configure(unsigned blocks, unsigned entries);
141 141
142 /* 142 /*
143 * statistics of the block cache 143 * statistics of the block cache
144 */ 144 */
145 struct block_cache_stats { 145 struct block_cache_stats {
146 unsigned hits; 146 unsigned hits;
147 unsigned misses; 147 unsigned misses;
148 unsigned entries; /* current entry count */ 148 unsigned entries; /* current entry count */
149 unsigned max_blocks_per_entry; 149 unsigned max_blocks_per_entry;
150 unsigned max_entries; 150 unsigned max_entries;
151 }; 151 };
152 152
153 /** 153 /**
154 * get_blkcache_stats() - return statistics and reset 154 * get_blkcache_stats() - return statistics and reset
155 * 155 *
156 * @param stats - statistics are copied here 156 * @param stats - statistics are copied here
157 */ 157 */
158 void blkcache_stats(struct block_cache_stats *stats); 158 void blkcache_stats(struct block_cache_stats *stats);
159 159
160 #else 160 #else
161 161
162 static inline int blkcache_read(int iftype, int dev, 162 static inline int blkcache_read(int iftype, int dev,
163 lbaint_t start, lbaint_t blkcnt, 163 lbaint_t start, lbaint_t blkcnt,
164 unsigned long blksz, void *buffer) 164 unsigned long blksz, void *buffer)
165 { 165 {
166 return 0; 166 return 0;
167 } 167 }
168 168
169 static inline void blkcache_fill(int iftype, int dev, 169 static inline void blkcache_fill(int iftype, int dev,
170 lbaint_t start, lbaint_t blkcnt, 170 lbaint_t start, lbaint_t blkcnt,
171 unsigned long blksz, void const *buffer) {} 171 unsigned long blksz, void const *buffer) {}
172 172
173 static inline void blkcache_invalidate(int iftype, int dev) {} 173 static inline void blkcache_invalidate(int iftype, int dev) {}
174 174
175 #endif 175 #endif
176 176
177 #ifdef CONFIG_BLK 177 #ifdef CONFIG_BLK
178 struct udevice; 178 struct udevice;
179 179
180 /* Operations on block devices */ 180 /* Operations on block devices */
181 struct blk_ops { 181 struct blk_ops {
182 /** 182 /**
183 * read() - read from a block device 183 * read() - read from a block device
184 * 184 *
185 * @dev: Device to read from 185 * @dev: Device to read from
186 * @start: Start block number to read (0=first) 186 * @start: Start block number to read (0=first)
187 * @blkcnt: Number of blocks to read 187 * @blkcnt: Number of blocks to read
188 * @buffer: Destination buffer for data read 188 * @buffer: Destination buffer for data read
189 * @return number of blocks read, or -ve error number (see the 189 * @return number of blocks read, or -ve error number (see the
190 * IS_ERR_VALUE() macro 190 * IS_ERR_VALUE() macro
191 */ 191 */
192 unsigned long (*read)(struct udevice *dev, lbaint_t start, 192 unsigned long (*read)(struct udevice *dev, lbaint_t start,
193 lbaint_t blkcnt, void *buffer); 193 lbaint_t blkcnt, void *buffer);
194 194
195 /** 195 /**
196 * write() - write to a block device 196 * write() - write to a block device
197 * 197 *
198 * @dev: Device to write to 198 * @dev: Device to write to
199 * @start: Start block number to write (0=first) 199 * @start: Start block number to write (0=first)
200 * @blkcnt: Number of blocks to write 200 * @blkcnt: Number of blocks to write
201 * @buffer: Source buffer for data to write 201 * @buffer: Source buffer for data to write
202 * @return number of blocks written, or -ve error number (see the 202 * @return number of blocks written, or -ve error number (see the
203 * IS_ERR_VALUE() macro 203 * IS_ERR_VALUE() macro
204 */ 204 */
205 unsigned long (*write)(struct udevice *dev, lbaint_t start, 205 unsigned long (*write)(struct udevice *dev, lbaint_t start,
206 lbaint_t blkcnt, const void *buffer); 206 lbaint_t blkcnt, const void *buffer);
207 207
208 /** 208 /**
209 * erase() - erase a section of a block device 209 * erase() - erase a section of a block device
210 * 210 *
211 * @dev: Device to (partially) erase 211 * @dev: Device to (partially) erase
212 * @start: Start block number to erase (0=first) 212 * @start: Start block number to erase (0=first)
213 * @blkcnt: Number of blocks to erase 213 * @blkcnt: Number of blocks to erase
214 * @return number of blocks erased, or -ve error number (see the 214 * @return number of blocks erased, or -ve error number (see the
215 * IS_ERR_VALUE() macro 215 * IS_ERR_VALUE() macro
216 */ 216 */
217 unsigned long (*erase)(struct udevice *dev, lbaint_t start, 217 unsigned long (*erase)(struct udevice *dev, lbaint_t start,
218 lbaint_t blkcnt); 218 lbaint_t blkcnt);
219 219
220 /** 220 /**
221 * select_hwpart() - select a particular hardware partition 221 * select_hwpart() - select a particular hardware partition
222 * 222 *
223 * Some devices (e.g. MMC) can support partitioning at the hardware 223 * Some devices (e.g. MMC) can support partitioning at the hardware
224 * level. This is quite separate from the normal idea of 224 * level. This is quite separate from the normal idea of
225 * software-based partitions. MMC hardware partitions must be 225 * software-based partitions. MMC hardware partitions must be
226 * explicitly selected. Once selected only the region of the device 226 * explicitly selected. Once selected only the region of the device
227 * covered by that partition is accessible. 227 * covered by that partition is accessible.
228 * 228 *
229 * The MMC standard provides for two boot partitions (numbered 1 and 2), 229 * The MMC standard provides for two boot partitions (numbered 1 and 2),
230 * rpmb (3), and up to 4 addition general-purpose partitions (4-7). 230 * rpmb (3), and up to 4 addition general-purpose partitions (4-7).
231 * 231 *
232 * @desc: Block device to update 232 * @desc: Block device to update
233 * @hwpart: Hardware partition number to select. 0 means the raw 233 * @hwpart: Hardware partition number to select. 0 means the raw
234 * device, 1 is the first partition, 2 is the second, etc. 234 * device, 1 is the first partition, 2 is the second, etc.
235 * @return 0 if OK, -ve on error 235 * @return 0 if OK, -ve on error
236 */ 236 */
237 int (*select_hwpart)(struct udevice *dev, int hwpart); 237 int (*select_hwpart)(struct udevice *dev, int hwpart);
238 }; 238 };
239 239
240 #define blk_get_ops(dev) ((struct blk_ops *)(dev)->driver->ops) 240 #define blk_get_ops(dev) ((struct blk_ops *)(dev)->driver->ops)
241 241
242 /* 242 /*
243 * These functions should take struct udevice instead of struct blk_desc, 243 * These functions should take struct udevice instead of struct blk_desc,
244 * but this is convenient for migration to driver model. Add a 'd' prefix 244 * but this is convenient for migration to driver model. Add a 'd' prefix
245 * to the function operations, so that blk_read(), etc. can be reserved for 245 * to the function operations, so that blk_read(), etc. can be reserved for
246 * functions with the correct arguments. 246 * functions with the correct arguments.
247 */ 247 */
248 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, 248 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
249 lbaint_t blkcnt, void *buffer); 249 lbaint_t blkcnt, void *buffer);
250 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, 250 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
251 lbaint_t blkcnt, const void *buffer); 251 lbaint_t blkcnt, const void *buffer);
252 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, 252 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
253 lbaint_t blkcnt); 253 lbaint_t blkcnt);
254 254
255 /** 255 /**
256 * blk_find_device() - Find a block device
257 *
258 * This function does not activate the device. The device will be returned
259 * whether or not it is activated.
260 *
261 * @if_type: Interface type (enum if_type_t)
262 * @devnum: Device number (specific to each interface type)
263 * @devp: the device, if found
264 * @return 0 if found, -ENODEV if no device found, or other -ve error value
265 */
266 int blk_find_device(int if_type, int devnum, struct udevice **devp);
267
268 /**
256 * blk_get_device() - Find and probe a block device ready for use 269 * blk_get_device() - Find and probe a block device ready for use
257 * 270 *
258 * @if_type: Interface type (enum if_type_t) 271 * @if_type: Interface type (enum if_type_t)
259 * @devnum: Device number (specific to each interface type) 272 * @devnum: Device number (specific to each interface type)
260 * @devp: the device, if found 273 * @devp: the device, if found
261 * @return - if found, -ENODEV if no device found, or other -ve error value 274 * @return 0 if found, -ENODEV if no device found, or other -ve error value
262 */ 275 */
263 int blk_get_device(int if_type, int devnum, struct udevice **devp); 276 int blk_get_device(int if_type, int devnum, struct udevice **devp);
264 277
265 /** 278 /**
266 * blk_first_device() - Find the first device for a given interface 279 * blk_first_device() - Find the first device for a given interface
267 * 280 *
268 * The device is probed ready for use 281 * The device is probed ready for use
269 * 282 *
270 * @devnum: Device number (specific to each interface type) 283 * @devnum: Device number (specific to each interface type)
271 * @devp: the device, if found 284 * @devp: the device, if found
272 * @return 0 if found, -ENODEV if no device, or other -ve error value 285 * @return 0 if found, -ENODEV if no device, or other -ve error value
273 */ 286 */
274 int blk_first_device(int if_type, struct udevice **devp); 287 int blk_first_device(int if_type, struct udevice **devp);
275 288
276 /** 289 /**
277 * blk_next_device() - Find the next device for a given interface 290 * blk_next_device() - Find the next device for a given interface
278 * 291 *
279 * This can be called repeatedly after blk_first_device() to iterate through 292 * This can be called repeatedly after blk_first_device() to iterate through
280 * all devices of the given interface type. 293 * all devices of the given interface type.
281 * 294 *
282 * The device is probed ready for use 295 * The device is probed ready for use
283 * 296 *
284 * @devp: On entry, the previous device returned. On exit, the next 297 * @devp: On entry, the previous device returned. On exit, the next
285 * device, if found 298 * device, if found
286 * @return 0 if found, -ENODEV if no device, or other -ve error value 299 * @return 0 if found, -ENODEV if no device, or other -ve error value
287 */ 300 */
288 int blk_next_device(struct udevice **devp); 301 int blk_next_device(struct udevice **devp);
289 302
290 /** 303 /**
291 * blk_create_device() - Create a new block device 304 * blk_create_device() - Create a new block device
292 * 305 *
293 * @parent: Parent of the new device 306 * @parent: Parent of the new device
294 * @drv_name: Driver name to use for the block device 307 * @drv_name: Driver name to use for the block device
295 * @name: Name for the device 308 * @name: Name for the device
296 * @if_type: Interface type (enum if_type_t) 309 * @if_type: Interface type (enum if_type_t)
297 * @devnum: Device number, specific to the interface type, or -1 to 310 * @devnum: Device number, specific to the interface type, or -1 to
298 * allocate the next available number 311 * allocate the next available number
299 * @blksz: Block size of the device in bytes (typically 512) 312 * @blksz: Block size of the device in bytes (typically 512)
300 * @size: Total size of the device in bytes 313 * @size: Total size of the device in bytes
301 * @devp: the new device (which has not been probed) 314 * @devp: the new device (which has not been probed)
302 */ 315 */
303 int blk_create_device(struct udevice *parent, const char *drv_name, 316 int blk_create_device(struct udevice *parent, const char *drv_name,
304 const char *name, int if_type, int devnum, int blksz, 317 const char *name, int if_type, int devnum, int blksz,
305 lbaint_t size, struct udevice **devp); 318 lbaint_t size, struct udevice **devp);
306 319
307 /** 320 /**
308 * blk_create_devicef() - Create a new named block device 321 * blk_create_devicef() - Create a new named block device
309 * 322 *
310 * @parent: Parent of the new device 323 * @parent: Parent of the new device
311 * @drv_name: Driver name to use for the block device 324 * @drv_name: Driver name to use for the block device
312 * @name: Name for the device (parent name is prepended) 325 * @name: Name for the device (parent name is prepended)
313 * @if_type: Interface type (enum if_type_t) 326 * @if_type: Interface type (enum if_type_t)
314 * @devnum: Device number, specific to the interface type, or -1 to 327 * @devnum: Device number, specific to the interface type, or -1 to
315 * allocate the next available number 328 * allocate the next available number
316 * @blksz: Block size of the device in bytes (typically 512) 329 * @blksz: Block size of the device in bytes (typically 512)
317 * @size: Total size of the device in bytes 330 * @size: Total size of the device in bytes
318 * @devp: the new device (which has not been probed) 331 * @devp: the new device (which has not been probed)
319 */ 332 */
320 int blk_create_devicef(struct udevice *parent, const char *drv_name, 333 int blk_create_devicef(struct udevice *parent, const char *drv_name,
321 const char *name, int if_type, int devnum, int blksz, 334 const char *name, int if_type, int devnum, int blksz,
322 lbaint_t size, struct udevice **devp); 335 lbaint_t size, struct udevice **devp);
323 336
324 /** 337 /**
325 * blk_prepare_device() - Prepare a block device for use 338 * blk_prepare_device() - Prepare a block device for use
326 * 339 *
327 * This reads partition information from the device if supported. 340 * This reads partition information from the device if supported.
328 * 341 *
329 * @dev: Device to prepare 342 * @dev: Device to prepare
330 * @return 0 if ok, -ve on error 343 * @return 0 if ok, -ve on error
331 */ 344 */
332 int blk_prepare_device(struct udevice *dev); 345 int blk_prepare_device(struct udevice *dev);
333 346
334 /** 347 /**
335 * blk_unbind_all() - Unbind all device of the given interface type 348 * blk_unbind_all() - Unbind all device of the given interface type
336 * 349 *
337 * The devices are removed and then unbound. 350 * The devices are removed and then unbound.
338 * 351 *
339 * @if_type: Interface type to unbind 352 * @if_type: Interface type to unbind
340 * @return 0 if OK, -ve on error 353 * @return 0 if OK, -ve on error
341 */ 354 */
342 int blk_unbind_all(int if_type); 355 int blk_unbind_all(int if_type);
343 356
344 /** 357 /**
345 * blk_find_max_devnum() - find the maximum device number for an interface type 358 * blk_find_max_devnum() - find the maximum device number for an interface type
346 * 359 *
347 * Finds the last allocated device number for an interface type @if_type. The 360 * Finds the last allocated device number for an interface type @if_type. The
348 * next number is safe to use for a newly allocated device. 361 * next number is safe to use for a newly allocated device.
349 * 362 *
350 * @if_type: Interface type to scan 363 * @if_type: Interface type to scan
351 * @return maximum device number found, or -ENODEV if none, or other -ve on 364 * @return maximum device number found, or -ENODEV if none, or other -ve on
352 * error 365 * error
353 */ 366 */
354 int blk_find_max_devnum(enum if_type if_type); 367 int blk_find_max_devnum(enum if_type if_type);
355 368
356 /** 369 /**
357 * blk_select_hwpart() - select a hardware partition 370 * blk_select_hwpart() - select a hardware partition
358 * 371 *
359 * Select a hardware partition if the device supports it (typically MMC does) 372 * Select a hardware partition if the device supports it (typically MMC does)
360 * 373 *
361 * @dev: Device to update 374 * @dev: Device to update
362 * @hwpart: Partition number to select 375 * @hwpart: Partition number to select
363 * @return 0 if OK, -ve on error 376 * @return 0 if OK, -ve on error
364 */ 377 */
365 int blk_select_hwpart(struct udevice *dev, int hwpart); 378 int blk_select_hwpart(struct udevice *dev, int hwpart);
366 379
367 #else 380 #else
368 #include <errno.h> 381 #include <errno.h>
369 /* 382 /*
370 * These functions should take struct udevice instead of struct blk_desc, 383 * These functions should take struct udevice instead of struct blk_desc,
371 * but this is convenient for migration to driver model. Add a 'd' prefix 384 * but this is convenient for migration to driver model. Add a 'd' prefix
372 * to the function operations, so that blk_read(), etc. can be reserved for 385 * to the function operations, so that blk_read(), etc. can be reserved for
373 * functions with the correct arguments. 386 * functions with the correct arguments.
374 */ 387 */
375 static inline ulong blk_dread(struct blk_desc *block_dev, lbaint_t start, 388 static inline ulong blk_dread(struct blk_desc *block_dev, lbaint_t start,
376 lbaint_t blkcnt, void *buffer) 389 lbaint_t blkcnt, void *buffer)
377 { 390 {
378 ulong blks_read; 391 ulong blks_read;
379 if (blkcache_read(block_dev->if_type, block_dev->devnum, 392 if (blkcache_read(block_dev->if_type, block_dev->devnum,
380 start, blkcnt, block_dev->blksz, buffer)) 393 start, blkcnt, block_dev->blksz, buffer))
381 return blkcnt; 394 return blkcnt;
382 395
383 /* 396 /*
384 * We could check if block_read is NULL and return -ENOSYS. But this 397 * We could check if block_read is NULL and return -ENOSYS. But this
385 * bloats the code slightly (cause some board to fail to build), and 398 * bloats the code slightly (cause some board to fail to build), and
386 * it would be an error to try an operation that does not exist. 399 * it would be an error to try an operation that does not exist.
387 */ 400 */
388 blks_read = block_dev->block_read(block_dev, start, blkcnt, buffer); 401 blks_read = block_dev->block_read(block_dev, start, blkcnt, buffer);
389 if (blks_read == blkcnt) 402 if (blks_read == blkcnt)
390 blkcache_fill(block_dev->if_type, block_dev->devnum, 403 blkcache_fill(block_dev->if_type, block_dev->devnum,
391 start, blkcnt, block_dev->blksz, buffer); 404 start, blkcnt, block_dev->blksz, buffer);
392 405
393 return blks_read; 406 return blks_read;
394 } 407 }
395 408
396 static inline ulong blk_dwrite(struct blk_desc *block_dev, lbaint_t start, 409 static inline ulong blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
397 lbaint_t blkcnt, const void *buffer) 410 lbaint_t blkcnt, const void *buffer)
398 { 411 {
399 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 412 blkcache_invalidate(block_dev->if_type, block_dev->devnum);
400 return block_dev->block_write(block_dev, start, blkcnt, buffer); 413 return block_dev->block_write(block_dev, start, blkcnt, buffer);
401 } 414 }
402 415
403 static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start, 416 static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start,
404 lbaint_t blkcnt) 417 lbaint_t blkcnt)
405 { 418 {
406 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 419 blkcache_invalidate(block_dev->if_type, block_dev->devnum);
407 return block_dev->block_erase(block_dev, start, blkcnt); 420 return block_dev->block_erase(block_dev, start, blkcnt);
408 } 421 }
409 422
410 /** 423 /**
411 * struct blk_driver - Driver for block interface types 424 * struct blk_driver - Driver for block interface types
412 * 425 *
413 * This provides access to the block devices for each interface type. One 426 * This provides access to the block devices for each interface type. One
414 * driver should be provided using U_BOOT_LEGACY_BLK() for each interface 427 * driver should be provided using U_BOOT_LEGACY_BLK() for each interface
415 * type that is to be supported. 428 * type that is to be supported.
416 * 429 *
417 * @if_typename: Interface type name 430 * @if_typename: Interface type name
418 * @if_type: Interface type 431 * @if_type: Interface type
419 * @max_devs: Maximum number of devices supported 432 * @max_devs: Maximum number of devices supported
420 * @desc: Pointer to list of devices for this interface type, 433 * @desc: Pointer to list of devices for this interface type,
421 * or NULL to use @get_dev() instead 434 * or NULL to use @get_dev() instead
422 */ 435 */
423 struct blk_driver { 436 struct blk_driver {
424 const char *if_typename; 437 const char *if_typename;
425 enum if_type if_type; 438 enum if_type if_type;
426 int max_devs; 439 int max_devs;
427 struct blk_desc *desc; 440 struct blk_desc *desc;
428 /** 441 /**
429 * get_dev() - get a pointer to a block device given its number 442 * get_dev() - get a pointer to a block device given its number
430 * 443 *
431 * Each interface allocates its own devices and typically 444 * Each interface allocates its own devices and typically
432 * struct blk_desc is contained with the interface's data structure. 445 * struct blk_desc is contained with the interface's data structure.
433 * There is no global numbering for block devices. This method allows 446 * There is no global numbering for block devices. This method allows
434 * the device for an interface type to be obtained when @desc is NULL. 447 * the device for an interface type to be obtained when @desc is NULL.
435 * 448 *
436 * @devnum: Device number (0 for first device on that interface, 449 * @devnum: Device number (0 for first device on that interface,
437 * 1 for second, etc. 450 * 1 for second, etc.
438 * @descp: Returns pointer to the block device on success 451 * @descp: Returns pointer to the block device on success
439 * @return 0 if OK, -ve on error 452 * @return 0 if OK, -ve on error
440 */ 453 */
441 int (*get_dev)(int devnum, struct blk_desc **descp); 454 int (*get_dev)(int devnum, struct blk_desc **descp);
442 455
443 /** 456 /**
444 * select_hwpart() - Select a hardware partition 457 * select_hwpart() - Select a hardware partition
445 * 458 *
446 * Some devices (e.g. MMC) can support partitioning at the hardware 459 * Some devices (e.g. MMC) can support partitioning at the hardware
447 * level. This is quite separate from the normal idea of 460 * level. This is quite separate from the normal idea of
448 * software-based partitions. MMC hardware partitions must be 461 * software-based partitions. MMC hardware partitions must be
449 * explicitly selected. Once selected only the region of the device 462 * explicitly selected. Once selected only the region of the device
450 * covered by that partition is accessible. 463 * covered by that partition is accessible.
451 * 464 *
452 * The MMC standard provides for two boot partitions (numbered 1 and 2), 465 * The MMC standard provides for two boot partitions (numbered 1 and 2),
453 * rpmb (3), and up to 4 addition general-purpose partitions (4-7). 466 * rpmb (3), and up to 4 addition general-purpose partitions (4-7).
454 * Partition 0 is the main user-data partition. 467 * Partition 0 is the main user-data partition.
455 * 468 *
456 * @desc: Block device descriptor 469 * @desc: Block device descriptor
457 * @hwpart: Hardware partition number to select. 0 means the main 470 * @hwpart: Hardware partition number to select. 0 means the main
458 * user-data partition, 1 is the first partition, 2 is 471 * user-data partition, 1 is the first partition, 2 is
459 * the second, etc. 472 * the second, etc.
460 * @return 0 if OK, other value for an error 473 * @return 0 if OK, other value for an error
461 */ 474 */
462 int (*select_hwpart)(struct blk_desc *desc, int hwpart); 475 int (*select_hwpart)(struct blk_desc *desc, int hwpart);
463 }; 476 };
464 477
465 /* 478 /*
466 * Declare a new U-Boot legacy block driver. New drivers should use driver 479 * Declare a new U-Boot legacy block driver. New drivers should use driver
467 * model (UCLASS_BLK). 480 * model (UCLASS_BLK).
468 */ 481 */
469 #define U_BOOT_LEGACY_BLK(__name) \ 482 #define U_BOOT_LEGACY_BLK(__name) \
470 ll_entry_declare(struct blk_driver, __name, blk_driver) 483 ll_entry_declare(struct blk_driver, __name, blk_driver)
471 484
472 struct blk_driver *blk_driver_lookup_type(int if_type); 485 struct blk_driver *blk_driver_lookup_type(int if_type);
473 486
474 #endif /* !CONFIG_BLK */ 487 #endif /* !CONFIG_BLK */
475 488
476 /** 489 /**
477 * blk_get_devnum_by_typename() - Get a block device by type and number 490 * blk_get_devnum_by_typename() - Get a block device by type and number
478 * 491 *
479 * This looks through the available block devices of the given type, returning 492 * This looks through the available block devices of the given type, returning
480 * the one with the given @devnum. 493 * the one with the given @devnum.
481 * 494 *
482 * @if_type: Block device type 495 * @if_type: Block device type
483 * @devnum: Device number 496 * @devnum: Device number
484 * @return point to block device descriptor, or NULL if not found 497 * @return point to block device descriptor, or NULL if not found
485 */ 498 */
486 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum); 499 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum);
487 500
488 /** 501 /**
489 * blk_get_devnum_by_type() - Get a block device by type name, and number 502 * blk_get_devnum_by_type() - Get a block device by type name, and number
490 * 503 *
491 * This looks up the block device type based on @if_typename, then calls 504 * This looks up the block device type based on @if_typename, then calls
492 * blk_get_devnum_by_type(). 505 * blk_get_devnum_by_type().
493 * 506 *
494 * @if_typename: Block device type name 507 * @if_typename: Block device type name
495 * @devnum: Device number 508 * @devnum: Device number
496 * @return point to block device descriptor, or NULL if not found 509 * @return point to block device descriptor, or NULL if not found
497 */ 510 */
498 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, 511 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename,
499 int devnum); 512 int devnum);
500 513
501 /** 514 /**
502 * blk_dselect_hwpart() - select a hardware partition 515 * blk_dselect_hwpart() - select a hardware partition
503 * 516 *
504 * This selects a hardware partition (such as is supported by MMC). The block 517 * This selects a hardware partition (such as is supported by MMC). The block
505 * device size may change as this effectively points the block device to a 518 * device size may change as this effectively points the block device to a
506 * partition at the hardware level. See the select_hwpart() method above. 519 * partition at the hardware level. See the select_hwpart() method above.
507 * 520 *
508 * @desc: Block device descriptor for the device to select 521 * @desc: Block device descriptor for the device to select
509 * @hwpart: Partition number to select 522 * @hwpart: Partition number to select
510 * @return 0 if OK, -ve on error 523 * @return 0 if OK, -ve on error
511 */ 524 */
512 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart); 525 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart);
513 526
514 /** 527 /**
515 * blk_list_part() - list the partitions for block devices of a given type 528 * blk_list_part() - list the partitions for block devices of a given type
516 * 529 *
517 * This looks up the partition type for each block device of type @if_type, 530 * This looks up the partition type for each block device of type @if_type,
518 * then displays a list of partitions. 531 * then displays a list of partitions.
519 * 532 *
520 * @if_type: Block device type 533 * @if_type: Block device type
521 * @return 0 if OK, -ENODEV if there is none of that type 534 * @return 0 if OK, -ENODEV if there is none of that type
522 */ 535 */
523 int blk_list_part(enum if_type if_type); 536 int blk_list_part(enum if_type if_type);
524 537
525 /** 538 /**
526 * blk_list_devices() - list the block devices of a given type 539 * blk_list_devices() - list the block devices of a given type
527 * 540 *
528 * This lists each block device of the type @if_type, showing the capacity 541 * This lists each block device of the type @if_type, showing the capacity
529 * as well as type-specific information. 542 * as well as type-specific information.
530 * 543 *
531 * @if_type: Block device type 544 * @if_type: Block device type
532 */ 545 */
533 void blk_list_devices(enum if_type if_type); 546 void blk_list_devices(enum if_type if_type);
534 547
535 /** 548 /**
536 * blk_show_device() - show information about a given block device 549 * blk_show_device() - show information about a given block device
537 * 550 *
538 * This shows the block device capacity as well as type-specific information. 551 * This shows the block device capacity as well as type-specific information.
539 * 552 *
540 * @if_type: Block device type 553 * @if_type: Block device type
541 * @devnum: Device number 554 * @devnum: Device number
542 * @return 0 if OK, -ENODEV for invalid device number 555 * @return 0 if OK, -ENODEV for invalid device number
543 */ 556 */
544 int blk_show_device(enum if_type if_type, int devnum); 557 int blk_show_device(enum if_type if_type, int devnum);
545 558
546 /** 559 /**
547 * blk_print_device_num() - show information about a given block device 560 * blk_print_device_num() - show information about a given block device
548 * 561 *
549 * This is similar to blk_show_device() but returns an error if the block 562 * This is similar to blk_show_device() but returns an error if the block
550 * device type is unknown. 563 * device type is unknown.
551 * 564 *
552 * @if_type: Block device type 565 * @if_type: Block device type
553 * @devnum: Device number 566 * @devnum: Device number
554 * @return 0 if OK, -ENODEV for invalid device number, -ENOENT if the block 567 * @return 0 if OK, -ENODEV for invalid device number, -ENOENT if the block
555 * device is not connected 568 * device is not connected
556 */ 569 */
557 int blk_print_device_num(enum if_type if_type, int devnum); 570 int blk_print_device_num(enum if_type if_type, int devnum);
558 571
559 /** 572 /**
560 * blk_print_part_devnum() - print the partition information for a device 573 * blk_print_part_devnum() - print the partition information for a device
561 * 574 *
562 * @if_type: Block device type 575 * @if_type: Block device type
563 * @devnum: Device number 576 * @devnum: Device number
564 * @return 0 if OK, -ENOENT if the block device is not connected, -ENOSYS if 577 * @return 0 if OK, -ENOENT if the block device is not connected, -ENOSYS if
565 * the interface type is not supported, other -ve on other error 578 * the interface type is not supported, other -ve on other error
566 */ 579 */
567 int blk_print_part_devnum(enum if_type if_type, int devnum); 580 int blk_print_part_devnum(enum if_type if_type, int devnum);
568 581
569 /** 582 /**
570 * blk_read_devnum() - read blocks from a device 583 * blk_read_devnum() - read blocks from a device
571 * 584 *
572 * @if_type: Block device type 585 * @if_type: Block device type
573 * @devnum: Device number 586 * @devnum: Device number
574 * @blkcnt: Number of blocks to read 587 * @blkcnt: Number of blocks to read
575 * @buffer: Address to write data to 588 * @buffer: Address to write data to
576 * @return number of blocks read, or -ve error number on error 589 * @return number of blocks read, or -ve error number on error
577 */ 590 */
578 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, 591 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
579 lbaint_t blkcnt, void *buffer); 592 lbaint_t blkcnt, void *buffer);
580 593
581 /** 594 /**
582 * blk_write_devnum() - write blocks to a device 595 * blk_write_devnum() - write blocks to a device
583 * 596 *
584 * @if_type: Block device type 597 * @if_type: Block device type
585 * @devnum: Device number 598 * @devnum: Device number
586 * @blkcnt: Number of blocks to write 599 * @blkcnt: Number of blocks to write
587 * @buffer: Address to read data from 600 * @buffer: Address to read data from
588 * @return number of blocks written, or -ve error number on error 601 * @return number of blocks written, or -ve error number on error
589 */ 602 */
590 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, 603 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
591 lbaint_t blkcnt, const void *buffer); 604 lbaint_t blkcnt, const void *buffer);
592 605
593 /** 606 /**
594 * blk_select_hwpart_devnum() - select a hardware partition 607 * blk_select_hwpart_devnum() - select a hardware partition
595 * 608 *
596 * This is similar to blk_dselect_hwpart() but it looks up the interface and 609 * This is similar to blk_dselect_hwpart() but it looks up the interface and
597 * device number. 610 * device number.
598 * 611 *
599 * @if_type: Block device type 612 * @if_type: Block device type
600 * @devnum: Device number 613 * @devnum: Device number
601 * @hwpart: Partition number to select 614 * @hwpart: Partition number to select
602 * @return 0 if OK, -ve on error 615 * @return 0 if OK, -ve on error
603 */ 616 */
604 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart); 617 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart);
605 618
606 #endif 619 #endif
607 620
1 /* 1 /*
2 * Copyright (C) 2015 Google, Inc 2 * Copyright (C) 2015 Google, Inc
3 * 3 *
4 * SPDX-License-Identifier: GPL-2.0+ 4 * SPDX-License-Identifier: GPL-2.0+
5 */ 5 */
6 6
7 #include <common.h> 7 #include <common.h>
8 #include <dm.h> 8 #include <dm.h>
9 #include <usb.h> 9 #include <usb.h>
10 #include <asm/state.h> 10 #include <asm/state.h>
11 #include <dm/test.h> 11 #include <dm/test.h>
12 #include <test/ut.h> 12 #include <test/ut.h>
13 13
14 DECLARE_GLOBAL_DATA_PTR; 14 DECLARE_GLOBAL_DATA_PTR;
15 15
16 /* Test that block devices can be created */ 16 /* Test that block devices can be created */
17 static int dm_test_blk_base(struct unit_test_state *uts) 17 static int dm_test_blk_base(struct unit_test_state *uts)
18 { 18 {
19 struct udevice *blk, *usb_blk, *dev; 19 struct udevice *blk, *usb_blk, *dev;
20 20
21 /* Make sure there are no block devices */ 21 /* Make sure there are no block devices */
22 ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_BLK, 0, &blk)); 22 ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_BLK, 0, &blk));
23 23
24 /* Create two, one the parent of the other */ 24 /* Create two, one the parent of the other */
25 ut_assertok(blk_create_device(gd->dm_root, "sandbox_host_blk", "test", 25 ut_assertok(blk_create_device(gd->dm_root, "sandbox_host_blk", "test",
26 IF_TYPE_HOST, 1, 512, 1024, &blk)); 26 IF_TYPE_HOST, 1, 512, 1024, &blk));
27 ut_assertok(blk_create_device(blk, "usb_storage_blk", "test", 27 ut_assertok(blk_create_device(blk, "usb_storage_blk", "test",
28 IF_TYPE_USB, 3, 512, 1024, &usb_blk)); 28 IF_TYPE_USB, 3, 512, 1024, &usb_blk));
29 29
30 /* Check we can find them */ 30 /* Check we can find them */
31 ut_asserteq(-ENODEV, blk_get_device(IF_TYPE_HOST, 0, &dev)); 31 ut_asserteq(-ENODEV, blk_get_device(IF_TYPE_HOST, 0, &dev));
32 ut_assertok(blk_get_device(IF_TYPE_HOST, 1, &dev)); 32 ut_assertok(blk_get_device(IF_TYPE_HOST, 1, &dev));
33 ut_asserteq_ptr(blk, dev); 33 ut_asserteq_ptr(blk, dev);
34 34
35 ut_asserteq(-ENODEV, blk_get_device(IF_TYPE_USB, 0, &dev)); 35 ut_asserteq(-ENODEV, blk_get_device(IF_TYPE_USB, 0, &dev));
36 ut_assertok(blk_get_device(IF_TYPE_USB, 3, &dev)); 36 ut_assertok(blk_get_device(IF_TYPE_USB, 3, &dev));
37 ut_asserteq_ptr(usb_blk, dev); 37 ut_asserteq_ptr(usb_blk, dev);
38 38
39 /* Check we can iterate */ 39 /* Check we can iterate */
40 ut_assertok(blk_first_device(IF_TYPE_HOST, &dev)); 40 ut_assertok(blk_first_device(IF_TYPE_HOST, &dev));
41 ut_asserteq_ptr(blk, dev); 41 ut_asserteq_ptr(blk, dev);
42 ut_asserteq(-ENODEV, blk_next_device(&dev)); 42 ut_asserteq(-ENODEV, blk_next_device(&dev));
43 43
44 ut_assertok(blk_first_device(IF_TYPE_USB, &dev)); 44 ut_assertok(blk_first_device(IF_TYPE_USB, &dev));
45 ut_asserteq_ptr(usb_blk, dev); 45 ut_asserteq_ptr(usb_blk, dev);
46 ut_asserteq(-ENODEV, blk_next_device(&dev)); 46 ut_asserteq(-ENODEV, blk_next_device(&dev));
47 47
48 return 0; 48 return 0;
49 } 49 }
50 DM_TEST(dm_test_blk_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 50 DM_TEST(dm_test_blk_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
51 51
52 static int count_blk_devices(void) 52 static int count_blk_devices(void)
53 { 53 {
54 struct udevice *blk; 54 struct udevice *blk;
55 struct uclass *uc; 55 struct uclass *uc;
56 int count = 0; 56 int count = 0;
57 int ret; 57 int ret;
58 58
59 ret = uclass_get(UCLASS_BLK, &uc); 59 ret = uclass_get(UCLASS_BLK, &uc);
60 if (ret) 60 if (ret)
61 return ret; 61 return ret;
62 62
63 uclass_foreach_dev(blk, uc) 63 uclass_foreach_dev(blk, uc)
64 count++; 64 count++;
65 65
66 return count; 66 return count;
67 } 67 }
68 68
69 /* Test that block devices work correctly with USB */ 69 /* Test that block devices work correctly with USB */
70 static int dm_test_blk_usb(struct unit_test_state *uts) 70 static int dm_test_blk_usb(struct unit_test_state *uts)
71 { 71 {
72 struct udevice *usb_dev, *dev; 72 struct udevice *usb_dev, *dev;
73 struct blk_desc *dev_desc; 73 struct blk_desc *dev_desc;
74 74
75 /* Get a flash device */ 75 /* Get a flash device */
76 state_set_skip_delays(true); 76 state_set_skip_delays(true);
77 ut_assertok(usb_init()); 77 ut_assertok(usb_init());
78 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev)); 78 ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev));
79 ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); 79 ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
80 80
81 /* The parent should be a block device */ 81 /* The parent should be a block device */
82 ut_assertok(blk_get_device(IF_TYPE_USB, 0, &dev)); 82 ut_assertok(blk_get_device(IF_TYPE_USB, 0, &dev));
83 ut_asserteq_ptr(usb_dev, dev_get_parent(dev)); 83 ut_asserteq_ptr(usb_dev, dev_get_parent(dev));
84 84
85 /* Check we have one block device for each mass storage device */ 85 /* Check we have one block device for each mass storage device */
86 ut_asserteq(4, count_blk_devices()); 86 ut_asserteq(4, count_blk_devices());
87 87
88 /* Now go around again, making sure the old devices were unbound */ 88 /* Now go around again, making sure the old devices were unbound */
89 ut_assertok(usb_stop()); 89 ut_assertok(usb_stop());
90 ut_assertok(usb_init()); 90 ut_assertok(usb_init());
91 ut_asserteq(4, count_blk_devices()); 91 ut_asserteq(4, count_blk_devices());
92 ut_assertok(usb_stop()); 92 ut_assertok(usb_stop());
93 93
94 return 0; 94 return 0;
95 } 95 }
96 DM_TEST(dm_test_blk_usb, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); 96 DM_TEST(dm_test_blk_usb, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
97
98 /* Test that we can find block devices without probing them */
99 static int dm_test_blk_find(struct unit_test_state *uts)
100 {
101 struct udevice *blk, *dev;
102
103 ut_assertok(blk_create_device(gd->dm_root, "sandbox_host_blk", "test",
104 IF_TYPE_HOST, 1, 512, 1024, &blk));
105 ut_asserteq(-ENODEV, blk_find_device(IF_TYPE_HOST, 0, &dev));
106 ut_assertok(blk_find_device(IF_TYPE_HOST, 1, &dev));
107 ut_asserteq_ptr(blk, dev);
108 ut_asserteq(false, device_active(dev));
109
110 /* Now activate it */
111 ut_assertok(blk_get_device(IF_TYPE_HOST, 1, &dev));
112 ut_asserteq_ptr(blk, dev);
113 ut_asserteq(true, device_active(dev));
114
115 return 0;
116 }
117 DM_TEST(dm_test_blk_find, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
97 118