blk: Make blk_next_free_devnum() public
[oweals/u-boot.git] / drivers / block / blk-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <blk.h>
9 #include <dm.h>
10 #include <dm/device-internal.h>
11 #include <dm/lists.h>
12 #include <dm/uclass-internal.h>
13
14 static const char *if_typename_str[IF_TYPE_COUNT] = {
15         [IF_TYPE_IDE]           = "ide",
16         [IF_TYPE_SCSI]          = "scsi",
17         [IF_TYPE_ATAPI]         = "atapi",
18         [IF_TYPE_USB]           = "usb",
19         [IF_TYPE_DOC]           = "doc",
20         [IF_TYPE_MMC]           = "mmc",
21         [IF_TYPE_SD]            = "sd",
22         [IF_TYPE_SATA]          = "sata",
23         [IF_TYPE_HOST]          = "host",
24         [IF_TYPE_NVME]          = "nvme",
25         [IF_TYPE_EFI]           = "efi",
26 };
27
28 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
29         [IF_TYPE_IDE]           = UCLASS_IDE,
30         [IF_TYPE_SCSI]          = UCLASS_SCSI,
31         [IF_TYPE_ATAPI]         = UCLASS_INVALID,
32         [IF_TYPE_USB]           = UCLASS_MASS_STORAGE,
33         [IF_TYPE_DOC]           = UCLASS_INVALID,
34         [IF_TYPE_MMC]           = UCLASS_MMC,
35         [IF_TYPE_SD]            = UCLASS_INVALID,
36         [IF_TYPE_SATA]          = UCLASS_AHCI,
37         [IF_TYPE_HOST]          = UCLASS_ROOT,
38         [IF_TYPE_NVME]          = UCLASS_NVME,
39         [IF_TYPE_EFI]           = UCLASS_EFI,
40 };
41
42 static enum if_type if_typename_to_iftype(const char *if_typename)
43 {
44         int i;
45
46         for (i = 0; i < IF_TYPE_COUNT; i++) {
47                 if (if_typename_str[i] &&
48                     !strcmp(if_typename, if_typename_str[i]))
49                         return i;
50         }
51
52         return IF_TYPE_UNKNOWN;
53 }
54
55 static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
56 {
57         return if_type_uclass_id[if_type];
58 }
59
60 const char *blk_get_if_type_name(enum if_type if_type)
61 {
62         return if_typename_str[if_type];
63 }
64
65 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
66 {
67         struct blk_desc *desc;
68         struct udevice *dev;
69         int ret;
70
71         ret = blk_get_device(if_type, devnum, &dev);
72         if (ret)
73                 return NULL;
74         desc = dev_get_uclass_platdata(dev);
75
76         return desc;
77 }
78
79 /*
80  * This function is complicated with driver model. We look up the interface
81  * name in a local table. This gives us an interface type which we can match
82  * against the uclass of the block device's parent.
83  */
84 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
85 {
86         enum uclass_id uclass_id;
87         enum if_type if_type;
88         struct udevice *dev;
89         struct uclass *uc;
90         int ret;
91
92         if_type = if_typename_to_iftype(if_typename);
93         if (if_type == IF_TYPE_UNKNOWN) {
94                 debug("%s: Unknown interface type '%s'\n", __func__,
95                       if_typename);
96                 return NULL;
97         }
98         uclass_id = if_type_to_uclass_id(if_type);
99         if (uclass_id == UCLASS_INVALID) {
100                 debug("%s: Unknown uclass for interface type'\n",
101                       if_typename_str[if_type]);
102                 return NULL;
103         }
104
105         ret = uclass_get(UCLASS_BLK, &uc);
106         if (ret)
107                 return NULL;
108         uclass_foreach_dev(dev, uc) {
109                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
110
111                 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
112                       if_type, devnum, dev->name, desc->if_type, desc->devnum);
113                 if (desc->devnum != devnum)
114                         continue;
115
116                 /* Find out the parent device uclass */
117                 if (device_get_uclass_id(dev->parent) != uclass_id) {
118                         debug("%s: parent uclass %d, this dev %d\n", __func__,
119                               device_get_uclass_id(dev->parent), uclass_id);
120                         continue;
121                 }
122
123                 if (device_probe(dev))
124                         return NULL;
125
126                 debug("%s: Device desc %p\n", __func__, desc);
127                 return desc;
128         }
129         debug("%s: No device found\n", __func__);
130
131         return NULL;
132 }
133
134 /**
135  * blk_get_by_device() - Get the block device descriptor for the given device
136  * @dev:        Instance of a storage device
137  *
138  * Return: With block device descriptor on success , NULL if there is no such
139  *         block device.
140  */
141 struct blk_desc *blk_get_by_device(struct udevice *dev)
142 {
143         struct udevice *child_dev, *next;
144
145         device_foreach_child_safe(child_dev, next, dev) {
146                 if (device_get_uclass_id(child_dev) != UCLASS_BLK)
147                         continue;
148
149                 return dev_get_uclass_platdata(child_dev);
150         }
151
152         debug("%s: No block device found\n", __func__);
153
154         return NULL;
155 }
156
157 /**
158  * get_desc() - Get the block device descriptor for the given device number
159  *
160  * @if_type:    Interface type
161  * @devnum:     Device number (0 = first)
162  * @descp:      Returns block device descriptor on success
163  * @return 0 on success, -ENODEV if there is no such device and no device
164  * with a higher device number, -ENOENT if there is no such device but there
165  * is one with a higher number, or other -ve on other error.
166  */
167 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp)
168 {
169         bool found_more = false;
170         struct udevice *dev;
171         struct uclass *uc;
172         int ret;
173
174         *descp = NULL;
175         ret = uclass_get(UCLASS_BLK, &uc);
176         if (ret)
177                 return ret;
178         uclass_foreach_dev(dev, uc) {
179                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
180
181                 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
182                       if_type, devnum, dev->name, desc->if_type, desc->devnum);
183                 if (desc->if_type == if_type) {
184                         if (desc->devnum == devnum) {
185                                 ret = device_probe(dev);
186                                 if (ret)
187                                         return ret;
188
189                                 *descp = desc;
190                                 return 0;
191                         } else if (desc->devnum > devnum) {
192                                 found_more = true;
193                         }
194                 }
195         }
196
197         return found_more ? -ENOENT : -ENODEV;
198 }
199
200 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
201 {
202         struct udevice *dev;
203         int ret;
204
205         ret = blk_get_device(if_type, devnum, &dev);
206         if (ret)
207                 return ret;
208
209         return blk_select_hwpart(dev, hwpart);
210 }
211
212 int blk_list_part(enum if_type if_type)
213 {
214         struct blk_desc *desc;
215         int devnum, ok;
216         int ret;
217
218         for (ok = 0, devnum = 0;; ++devnum) {
219                 ret = get_desc(if_type, devnum, &desc);
220                 if (ret == -ENODEV)
221                         break;
222                 else if (ret)
223                         continue;
224                 if (desc->part_type != PART_TYPE_UNKNOWN) {
225                         ++ok;
226                         if (devnum)
227                                 putc('\n');
228                         part_print(desc);
229                 }
230         }
231         if (!ok)
232                 return -ENODEV;
233
234         return 0;
235 }
236
237 int blk_print_part_devnum(enum if_type if_type, int devnum)
238 {
239         struct blk_desc *desc;
240         int ret;
241
242         ret = get_desc(if_type, devnum, &desc);
243         if (ret)
244                 return ret;
245         if (desc->type == DEV_TYPE_UNKNOWN)
246                 return -ENOENT;
247         part_print(desc);
248
249         return 0;
250 }
251
252 void blk_list_devices(enum if_type if_type)
253 {
254         struct blk_desc *desc;
255         int ret;
256         int i;
257
258         for (i = 0;; ++i) {
259                 ret = get_desc(if_type, i, &desc);
260                 if (ret == -ENODEV)
261                         break;
262                 else if (ret)
263                         continue;
264                 if (desc->type == DEV_TYPE_UNKNOWN)
265                         continue;  /* list only known devices */
266                 printf("Device %d: ", i);
267                 dev_print(desc);
268         }
269 }
270
271 int blk_print_device_num(enum if_type if_type, int devnum)
272 {
273         struct blk_desc *desc;
274         int ret;
275
276         ret = get_desc(if_type, devnum, &desc);
277         if (ret)
278                 return ret;
279         printf("\nIDE device %d: ", devnum);
280         dev_print(desc);
281
282         return 0;
283 }
284
285 int blk_show_device(enum if_type if_type, int devnum)
286 {
287         struct blk_desc *desc;
288         int ret;
289
290         printf("\nDevice %d: ", devnum);
291         ret = get_desc(if_type, devnum, &desc);
292         if (ret == -ENODEV || ret == -ENOENT) {
293                 printf("unknown device\n");
294                 return -ENODEV;
295         }
296         if (ret)
297                 return ret;
298         dev_print(desc);
299
300         if (desc->type == DEV_TYPE_UNKNOWN)
301                 return -ENOENT;
302
303         return 0;
304 }
305
306 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
307                       lbaint_t blkcnt, void *buffer)
308 {
309         struct blk_desc *desc;
310         ulong n;
311         int ret;
312
313         ret = get_desc(if_type, devnum, &desc);
314         if (ret)
315                 return ret;
316         n = blk_dread(desc, start, blkcnt, buffer);
317         if (IS_ERR_VALUE(n))
318                 return n;
319
320         return n;
321 }
322
323 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
324                        lbaint_t blkcnt, const void *buffer)
325 {
326         struct blk_desc *desc;
327         int ret;
328
329         ret = get_desc(if_type, devnum, &desc);
330         if (ret)
331                 return ret;
332         return blk_dwrite(desc, start, blkcnt, buffer);
333 }
334
335 int blk_select_hwpart(struct udevice *dev, int hwpart)
336 {
337         const struct blk_ops *ops = blk_get_ops(dev);
338
339         if (!ops)
340                 return -ENOSYS;
341         if (!ops->select_hwpart)
342                 return 0;
343
344         return ops->select_hwpart(dev, hwpart);
345 }
346
347 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
348 {
349         return blk_select_hwpart(desc->bdev, hwpart);
350 }
351
352 int blk_first_device(int if_type, struct udevice **devp)
353 {
354         struct blk_desc *desc;
355         int ret;
356
357         ret = uclass_find_first_device(UCLASS_BLK, devp);
358         if (ret)
359                 return ret;
360         if (!*devp)
361                 return -ENODEV;
362         do {
363                 desc = dev_get_uclass_platdata(*devp);
364                 if (desc->if_type == if_type)
365                         return 0;
366                 ret = uclass_find_next_device(devp);
367                 if (ret)
368                         return ret;
369         } while (*devp);
370
371         return -ENODEV;
372 }
373
374 int blk_next_device(struct udevice **devp)
375 {
376         struct blk_desc *desc;
377         int ret, if_type;
378
379         desc = dev_get_uclass_platdata(*devp);
380         if_type = desc->if_type;
381         do {
382                 ret = uclass_find_next_device(devp);
383                 if (ret)
384                         return ret;
385                 if (!*devp)
386                         return -ENODEV;
387                 desc = dev_get_uclass_platdata(*devp);
388                 if (desc->if_type == if_type)
389                         return 0;
390         } while (1);
391 }
392
393 int blk_find_device(int if_type, int devnum, struct udevice **devp)
394 {
395         struct uclass *uc;
396         struct udevice *dev;
397         int ret;
398
399         ret = uclass_get(UCLASS_BLK, &uc);
400         if (ret)
401                 return ret;
402         uclass_foreach_dev(dev, uc) {
403                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
404
405                 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
406                       if_type, devnum, dev->name, desc->if_type, desc->devnum);
407                 if (desc->if_type == if_type && desc->devnum == devnum) {
408                         *devp = dev;
409                         return 0;
410                 }
411         }
412
413         return -ENODEV;
414 }
415
416 int blk_get_device(int if_type, int devnum, struct udevice **devp)
417 {
418         int ret;
419
420         ret = blk_find_device(if_type, devnum, devp);
421         if (ret)
422                 return ret;
423
424         return device_probe(*devp);
425 }
426
427 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
428                         lbaint_t blkcnt, void *buffer)
429 {
430         struct udevice *dev = block_dev->bdev;
431         const struct blk_ops *ops = blk_get_ops(dev);
432         ulong blks_read;
433
434         if (!ops->read)
435                 return -ENOSYS;
436
437         if (blkcache_read(block_dev->if_type, block_dev->devnum,
438                           start, blkcnt, block_dev->blksz, buffer))
439                 return blkcnt;
440         blks_read = ops->read(dev, start, blkcnt, buffer);
441         if (blks_read == blkcnt)
442                 blkcache_fill(block_dev->if_type, block_dev->devnum,
443                               start, blkcnt, block_dev->blksz, buffer);
444
445         return blks_read;
446 }
447
448 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
449                          lbaint_t blkcnt, const void *buffer)
450 {
451         struct udevice *dev = block_dev->bdev;
452         const struct blk_ops *ops = blk_get_ops(dev);
453
454         if (!ops->write)
455                 return -ENOSYS;
456
457         blkcache_invalidate(block_dev->if_type, block_dev->devnum);
458         return ops->write(dev, start, blkcnt, buffer);
459 }
460
461 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
462                          lbaint_t blkcnt)
463 {
464         struct udevice *dev = block_dev->bdev;
465         const struct blk_ops *ops = blk_get_ops(dev);
466
467         if (!ops->erase)
468                 return -ENOSYS;
469
470         blkcache_invalidate(block_dev->if_type, block_dev->devnum);
471         return ops->erase(dev, start, blkcnt);
472 }
473
474 int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
475 {
476         struct udevice *dev;
477         enum uclass_id id;
478         int ret;
479
480         device_find_first_child(parent, &dev);
481         if (!dev) {
482                 debug("%s: No block device found for parent '%s'\n", __func__,
483                       parent->name);
484                 return -ENODEV;
485         }
486         id = device_get_uclass_id(dev);
487         if (id != UCLASS_BLK) {
488                 debug("%s: Incorrect uclass %s for block device '%s'\n",
489                       __func__, uclass_get_name(id), dev->name);
490                 return -ENOTBLK;
491         }
492         ret = device_probe(dev);
493         if (ret)
494                 return ret;
495         *devp = dev;
496
497         return 0;
498 }
499
500 int blk_find_max_devnum(enum if_type if_type)
501 {
502         struct udevice *dev;
503         int max_devnum = -ENODEV;
504         struct uclass *uc;
505         int ret;
506
507         ret = uclass_get(UCLASS_BLK, &uc);
508         if (ret)
509                 return ret;
510         uclass_foreach_dev(dev, uc) {
511                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
512
513                 if (desc->if_type == if_type && desc->devnum > max_devnum)
514                         max_devnum = desc->devnum;
515         }
516
517         return max_devnum;
518 }
519
520 int blk_next_free_devnum(enum if_type if_type)
521 {
522         int ret;
523
524         ret = blk_find_max_devnum(if_type);
525         if (ret == -ENODEV)
526                 return 0;
527         if (ret < 0)
528                 return ret;
529
530         return ret + 1;
531 }
532
533 static int blk_claim_devnum(enum if_type if_type, int devnum)
534 {
535         struct udevice *dev;
536         struct uclass *uc;
537         int ret;
538
539         ret = uclass_get(UCLASS_BLK, &uc);
540         if (ret)
541                 return ret;
542         uclass_foreach_dev(dev, uc) {
543                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
544
545                 if (desc->if_type == if_type && desc->devnum == devnum) {
546                         int next = blk_next_free_devnum(if_type);
547
548                         if (next < 0)
549                                 return next;
550                         desc->devnum = next;
551                         return 0;
552                 }
553         }
554
555         return -ENOENT;
556 }
557
558 int blk_create_device(struct udevice *parent, const char *drv_name,
559                       const char *name, int if_type, int devnum, int blksz,
560                       lbaint_t lba, struct udevice **devp)
561 {
562         struct blk_desc *desc;
563         struct udevice *dev;
564         int ret;
565
566         if (devnum == -1) {
567                 devnum = blk_next_free_devnum(if_type);
568         } else {
569                 ret = blk_claim_devnum(if_type, devnum);
570                 if (ret < 0 && ret != -ENOENT)
571                         return ret;
572         }
573         if (devnum < 0)
574                 return devnum;
575         ret = device_bind_driver(parent, drv_name, name, &dev);
576         if (ret)
577                 return ret;
578         desc = dev_get_uclass_platdata(dev);
579         desc->if_type = if_type;
580         desc->blksz = blksz;
581         desc->lba = lba;
582         desc->part_type = PART_TYPE_UNKNOWN;
583         desc->bdev = dev;
584         desc->devnum = devnum;
585         *devp = dev;
586
587         return 0;
588 }
589
590 int blk_create_devicef(struct udevice *parent, const char *drv_name,
591                        const char *name, int if_type, int devnum, int blksz,
592                        lbaint_t lba, struct udevice **devp)
593 {
594         char dev_name[30], *str;
595         int ret;
596
597         snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
598         str = strdup(dev_name);
599         if (!str)
600                 return -ENOMEM;
601
602         ret = blk_create_device(parent, drv_name, str, if_type, devnum,
603                                 blksz, lba, devp);
604         if (ret) {
605                 free(str);
606                 return ret;
607         }
608         device_set_name_alloced(*devp);
609
610         return 0;
611 }
612
613 int blk_unbind_all(int if_type)
614 {
615         struct uclass *uc;
616         struct udevice *dev, *next;
617         int ret;
618
619         ret = uclass_get(UCLASS_BLK, &uc);
620         if (ret)
621                 return ret;
622         uclass_foreach_dev_safe(dev, next, uc) {
623                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
624
625                 if (desc->if_type == if_type) {
626                         ret = device_remove(dev, DM_REMOVE_NORMAL);
627                         if (ret)
628                                 return ret;
629                         ret = device_unbind(dev);
630                         if (ret)
631                                 return ret;
632                 }
633         }
634
635         return 0;
636 }
637
638 static int blk_post_probe(struct udevice *dev)
639 {
640 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT)
641         struct blk_desc *desc = dev_get_uclass_platdata(dev);
642
643         part_init(desc);
644 #endif
645
646         return 0;
647 }
648
649 UCLASS_DRIVER(blk) = {
650         .id             = UCLASS_BLK,
651         .name           = "blk",
652         .post_probe     = blk_post_probe,
653         .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
654 };