dm: blk: Add probe in blk_first_device/blk_next_device
[platform/kernel/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 #define LOG_CATEGORY UCLASS_BLK
8
9 #include <common.h>
10 #include <blk.h>
11 #include <dm.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <part.h>
15 #include <dm/device-internal.h>
16 #include <dm/lists.h>
17 #include <dm/uclass-internal.h>
18 #include <linux/err.h>
19
20 static struct {
21         enum uclass_id id;
22         const char *name;
23 } uclass_idname_str[] = {
24         { UCLASS_IDE, "ide" },
25         { UCLASS_SCSI, "scsi" },
26         { UCLASS_USB, "usb" },
27         { UCLASS_MMC,  "mmc" },
28         { UCLASS_AHCI, "sata" },
29         { UCLASS_HOST, "host" },
30         { UCLASS_NVME, "nvme" },
31         { UCLASS_EFI_MEDIA, "efi" },
32         { UCLASS_EFI_LOADER, "efiloader" },
33         { UCLASS_VIRTIO, "virtio" },
34         { UCLASS_PVBLOCK, "pvblock" },
35 };
36
37 static enum uclass_id uclass_name_to_iftype(const char *uclass_idname)
38 {
39         int i;
40
41         for (i = 0; i < ARRAY_SIZE(uclass_idname_str); i++) {
42                 if (!strcmp(uclass_idname, uclass_idname_str[i].name))
43                         return uclass_idname_str[i].id;
44         }
45
46         return UCLASS_INVALID;
47 }
48
49 static enum uclass_id conv_uclass_id(enum uclass_id uclass_id)
50 {
51         /*
52          * This strange adjustment is used because we use UCLASS_MASS_STORAGE
53          * for USB storage devices, so need to return this as the uclass to
54          * use for USB. In fact USB_UCLASS is for USB controllers, not
55          * peripherals.
56          *
57          * The name of the UCLASS_MASS_STORAGE uclass driver is
58          * "usb_mass_storage", but we want to use "usb" in things like the
59          * 'part list' command and when showing interfaces.
60          *
61          * So for now we have this one-way conversion.
62          *
63          * The fix for this is possibly to:
64          *    - rename UCLASS_MASS_STORAGE name to "usb"
65          *    - rename UCLASS_USB name to "usb_ctlr"
66          *    - use UCLASS_MASS_STORAGE instead of UCLASS_USB in if_typename_str
67          */
68         if (uclass_id == UCLASS_USB)
69                 return UCLASS_MASS_STORAGE;
70         return uclass_id;
71 }
72
73 const char *blk_get_uclass_name(enum uclass_id uclass_id)
74 {
75         int i;
76
77         for (i = 0; i < ARRAY_SIZE(uclass_idname_str); i++) {
78                 if (uclass_idname_str[i].id == uclass_id)
79                         return uclass_idname_str[i].name;
80         }
81
82         return "(none)";
83 }
84
85 struct blk_desc *blk_get_devnum_by_uclass_id(enum uclass_id uclass_id, int devnum)
86 {
87         struct blk_desc *desc;
88         struct udevice *dev;
89         int ret;
90
91         ret = blk_get_device(uclass_id, devnum, &dev);
92         if (ret)
93                 return NULL;
94         desc = dev_get_uclass_plat(dev);
95
96         return desc;
97 }
98
99 /*
100  * This function is complicated with driver model. We look up the interface
101  * name in a local table. This gives us an interface type which we can match
102  * against the uclass of the block device's parent.
103  */
104 struct blk_desc *blk_get_devnum_by_uclass_idname(const char *uclass_idname, int devnum)
105 {
106         enum uclass_id uclass_id;
107         enum uclass_id type;
108         struct udevice *dev;
109         struct uclass *uc;
110         int ret;
111
112         type = uclass_name_to_iftype(uclass_idname);
113         if (type == UCLASS_INVALID) {
114                 debug("%s: Unknown interface type '%s'\n", __func__,
115                       uclass_idname);
116                 return NULL;
117         }
118         uclass_id = conv_uclass_id(type);
119         if (uclass_id == UCLASS_INVALID) {
120                 debug("%s: Unknown uclass for interface type'\n",
121                       blk_get_uclass_name(type));
122                 return NULL;
123         }
124
125         ret = uclass_get(UCLASS_BLK, &uc);
126         if (ret)
127                 return NULL;
128         uclass_foreach_dev(dev, uc) {
129                 struct blk_desc *desc = dev_get_uclass_plat(dev);
130
131                 debug("%s: uclass_id=%d, devnum=%d: %s, %d, %d\n", __func__,
132                       type, devnum, dev->name, desc->uclass_id, desc->devnum);
133                 if (desc->devnum != devnum)
134                         continue;
135
136                 /* Find out the parent device uclass */
137                 if (device_get_uclass_id(dev->parent) != uclass_id) {
138                         debug("%s: parent uclass %d, this dev %d\n", __func__,
139                               device_get_uclass_id(dev->parent), uclass_id);
140                         continue;
141                 }
142
143                 if (device_probe(dev))
144                         return NULL;
145
146                 debug("%s: Device desc %p\n", __func__, desc);
147                 return desc;
148         }
149         debug("%s: No device found\n", __func__);
150
151         return NULL;
152 }
153
154 /**
155  * blk_get_by_device() - Get the block device descriptor for the given device
156  * @dev:        Instance of a storage device
157  *
158  * Return: With block device descriptor on success , NULL if there is no such
159  *         block device.
160  */
161 struct blk_desc *blk_get_by_device(struct udevice *dev)
162 {
163         struct udevice *child_dev;
164
165         device_foreach_child(child_dev, dev) {
166                 if (device_get_uclass_id(child_dev) != UCLASS_BLK)
167                         continue;
168
169                 return dev_get_uclass_plat(child_dev);
170         }
171
172         debug("%s: No block device found\n", __func__);
173
174         return NULL;
175 }
176
177 /**
178  * get_desc() - Get the block device descriptor for the given device number
179  *
180  * @uclass_id:  Interface type
181  * @devnum:     Device number (0 = first)
182  * @descp:      Returns block device descriptor on success
183  * Return: 0 on success, -ENODEV if there is no such device and no device
184  * with a higher device number, -ENOENT if there is no such device but there
185  * is one with a higher number, or other -ve on other error.
186  */
187 static int get_desc(enum uclass_id uclass_id, int devnum, struct blk_desc **descp)
188 {
189         bool found_more = false;
190         struct udevice *dev;
191         struct uclass *uc;
192         int ret;
193
194         *descp = NULL;
195         ret = uclass_get(UCLASS_BLK, &uc);
196         if (ret)
197                 return ret;
198         uclass_foreach_dev(dev, uc) {
199                 struct blk_desc *desc = dev_get_uclass_plat(dev);
200
201                 debug("%s: uclass_id=%d, devnum=%d: %s, %d, %d\n", __func__,
202                       uclass_id, devnum, dev->name, desc->uclass_id, desc->devnum);
203                 if (desc->uclass_id == uclass_id) {
204                         if (desc->devnum == devnum) {
205                                 ret = device_probe(dev);
206                                 if (ret)
207                                         return ret;
208
209                                 *descp = desc;
210                                 return 0;
211                         } else if (desc->devnum > devnum) {
212                                 found_more = true;
213                         }
214                 }
215         }
216
217         return found_more ? -ENOENT : -ENODEV;
218 }
219
220 int blk_select_hwpart_devnum(enum uclass_id uclass_id, int devnum, int hwpart)
221 {
222         struct udevice *dev;
223         int ret;
224
225         ret = blk_get_device(uclass_id, devnum, &dev);
226         if (ret)
227                 return ret;
228
229         return blk_select_hwpart(dev, hwpart);
230 }
231
232 int blk_list_part(enum uclass_id uclass_id)
233 {
234         struct blk_desc *desc;
235         int devnum, ok;
236         int ret;
237
238         for (ok = 0, devnum = 0;; ++devnum) {
239                 ret = get_desc(uclass_id, devnum, &desc);
240                 if (ret == -ENODEV)
241                         break;
242                 else if (ret)
243                         continue;
244                 if (desc->part_type != PART_TYPE_UNKNOWN) {
245                         ++ok;
246                         if (devnum)
247                                 putc('\n');
248                         part_print(desc);
249                 }
250         }
251         if (!ok)
252                 return -ENODEV;
253
254         return 0;
255 }
256
257 int blk_print_part_devnum(enum uclass_id uclass_id, int devnum)
258 {
259         struct blk_desc *desc;
260         int ret;
261
262         ret = get_desc(uclass_id, devnum, &desc);
263         if (ret)
264                 return ret;
265         if (desc->type == DEV_TYPE_UNKNOWN)
266                 return -ENOENT;
267         part_print(desc);
268
269         return 0;
270 }
271
272 void blk_list_devices(enum uclass_id uclass_id)
273 {
274         struct blk_desc *desc;
275         int ret;
276         int i;
277
278         for (i = 0;; ++i) {
279                 ret = get_desc(uclass_id, i, &desc);
280                 if (ret == -ENODEV)
281                         break;
282                 else if (ret)
283                         continue;
284                 if (desc->type == DEV_TYPE_UNKNOWN)
285                         continue;  /* list only known devices */
286                 printf("Device %d: ", i);
287                 dev_print(desc);
288         }
289 }
290
291 int blk_print_device_num(enum uclass_id uclass_id, int devnum)
292 {
293         struct blk_desc *desc;
294         int ret;
295
296         ret = get_desc(uclass_id, devnum, &desc);
297         if (ret)
298                 return ret;
299         printf("\nIDE device %d: ", devnum);
300         dev_print(desc);
301
302         return 0;
303 }
304
305 int blk_show_device(enum uclass_id uclass_id, int devnum)
306 {
307         struct blk_desc *desc;
308         int ret;
309
310         printf("\nDevice %d: ", devnum);
311         ret = get_desc(uclass_id, devnum, &desc);
312         if (ret == -ENODEV || ret == -ENOENT) {
313                 printf("unknown device\n");
314                 return -ENODEV;
315         }
316         if (ret)
317                 return ret;
318         dev_print(desc);
319
320         if (desc->type == DEV_TYPE_UNKNOWN)
321                 return -ENOENT;
322
323         return 0;
324 }
325
326 ulong blk_read_devnum(enum uclass_id uclass_id, int devnum, lbaint_t start,
327                       lbaint_t blkcnt, void *buffer)
328 {
329         struct blk_desc *desc;
330         ulong n;
331         int ret;
332
333         ret = get_desc(uclass_id, devnum, &desc);
334         if (ret)
335                 return ret;
336         n = blk_dread(desc, start, blkcnt, buffer);
337         if (IS_ERR_VALUE(n))
338                 return n;
339
340         return n;
341 }
342
343 ulong blk_write_devnum(enum uclass_id uclass_id, int devnum, lbaint_t start,
344                        lbaint_t blkcnt, const void *buffer)
345 {
346         struct blk_desc *desc;
347         int ret;
348
349         ret = get_desc(uclass_id, devnum, &desc);
350         if (ret)
351                 return ret;
352         return blk_dwrite(desc, start, blkcnt, buffer);
353 }
354
355 int blk_select_hwpart(struct udevice *dev, int hwpart)
356 {
357         const struct blk_ops *ops = blk_get_ops(dev);
358
359         if (!ops)
360                 return -ENOSYS;
361         if (!ops->select_hwpart)
362                 return 0;
363
364         return ops->select_hwpart(dev, hwpart);
365 }
366
367 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
368 {
369         return blk_select_hwpart(desc->bdev, hwpart);
370 }
371
372 static int _blk_next_device(int uclass_id, struct udevice **devp)
373 {
374         struct blk_desc *desc;
375         int ret = 0;
376
377         for (; *devp; uclass_find_next_device(devp)) {
378                 desc = dev_get_uclass_plat(*devp);
379                 if (desc->uclass_id == uclass_id) {
380                         ret = device_probe(*devp);
381                         if (!ret)
382                                 return 0;
383                 }
384         }
385
386         if (ret)
387                 return ret;
388
389         return -ENODEV;
390 }
391
392 int blk_first_device(int uclass_id, struct udevice **devp)
393 {
394         uclass_find_first_device(UCLASS_BLK, devp);
395
396         return _blk_next_device(uclass_id, devp);
397 }
398
399 int blk_next_device(struct udevice **devp)
400 {
401         struct blk_desc *desc;
402         int uclass_id;
403
404         desc = dev_get_uclass_plat(*devp);
405         uclass_id = desc->uclass_id;
406         uclass_find_next_device(devp);
407
408         return _blk_next_device(uclass_id, devp);
409 }
410
411 int blk_find_device(int uclass_id, int devnum, struct udevice **devp)
412 {
413         struct uclass *uc;
414         struct udevice *dev;
415         int ret;
416
417         ret = uclass_get(UCLASS_BLK, &uc);
418         if (ret)
419                 return ret;
420         uclass_foreach_dev(dev, uc) {
421                 struct blk_desc *desc = dev_get_uclass_plat(dev);
422
423                 debug("%s: uclass_id=%d, devnum=%d: %s, %d, %d\n", __func__,
424                       uclass_id, devnum, dev->name, desc->uclass_id, desc->devnum);
425                 if (desc->uclass_id == uclass_id && desc->devnum == devnum) {
426                         *devp = dev;
427                         return 0;
428                 }
429         }
430
431         return -ENODEV;
432 }
433
434 int blk_get_device(int uclass_id, int devnum, struct udevice **devp)
435 {
436         int ret;
437
438         ret = blk_find_device(uclass_id, devnum, devp);
439         if (ret)
440                 return ret;
441
442         return device_probe(*devp);
443 }
444
445 long blk_read(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *buf)
446 {
447         struct blk_desc *desc = dev_get_uclass_plat(dev);
448         const struct blk_ops *ops = blk_get_ops(dev);
449         ulong blks_read;
450
451         if (!ops->read)
452                 return -ENOSYS;
453
454         if (blkcache_read(desc->uclass_id, desc->devnum,
455                           start, blkcnt, desc->blksz, buf))
456                 return blkcnt;
457         blks_read = ops->read(dev, start, blkcnt, buf);
458         if (blks_read == blkcnt)
459                 blkcache_fill(desc->uclass_id, desc->devnum, start, blkcnt,
460                               desc->blksz, buf);
461
462         return blks_read;
463 }
464
465 long blk_write(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
466                const void *buf)
467 {
468         struct blk_desc *desc = dev_get_uclass_plat(dev);
469         const struct blk_ops *ops = blk_get_ops(dev);
470
471         if (!ops->write)
472                 return -ENOSYS;
473
474         blkcache_invalidate(desc->uclass_id, desc->devnum);
475
476         return ops->write(dev, start, blkcnt, buf);
477 }
478
479 long blk_erase(struct udevice *dev, lbaint_t start, lbaint_t blkcnt)
480 {
481         struct blk_desc *desc = dev_get_uclass_plat(dev);
482         const struct blk_ops *ops = blk_get_ops(dev);
483
484         if (!ops->erase)
485                 return -ENOSYS;
486
487         blkcache_invalidate(desc->uclass_id, desc->devnum);
488
489         return ops->erase(dev, start, blkcnt);
490 }
491
492 ulong blk_dread(struct blk_desc *desc, lbaint_t start, lbaint_t blkcnt,
493                 void *buffer)
494 {
495         return blk_read(desc->bdev, start, blkcnt, buffer);
496 }
497
498 ulong blk_dwrite(struct blk_desc *desc, lbaint_t start, lbaint_t blkcnt,
499                  const void *buffer)
500 {
501         return blk_write(desc->bdev, start, blkcnt, buffer);
502 }
503
504 ulong blk_derase(struct blk_desc *desc, lbaint_t start, lbaint_t blkcnt)
505 {
506         return blk_erase(desc->bdev, start, blkcnt);
507 }
508
509 int blk_find_from_parent(struct udevice *parent, struct udevice **devp)
510 {
511         struct udevice *dev;
512
513         if (device_find_first_child_by_uclass(parent, UCLASS_BLK, &dev)) {
514                 debug("%s: No block device found for parent '%s'\n", __func__,
515                       parent->name);
516                 return -ENODEV;
517         }
518         *devp = dev;
519
520         return 0;
521 }
522
523 int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
524 {
525         struct udevice *dev;
526         int ret;
527
528         ret = blk_find_from_parent(parent, &dev);
529         if (ret)
530                 return ret;
531         ret = device_probe(dev);
532         if (ret)
533                 return ret;
534         *devp = dev;
535
536         return 0;
537 }
538
539 const char *blk_get_devtype(struct udevice *dev)
540 {
541         struct udevice *parent = dev_get_parent(dev);
542
543         return uclass_get_name(device_get_uclass_id(parent));
544 };
545
546 int blk_find_max_devnum(enum uclass_id uclass_id)
547 {
548         struct udevice *dev;
549         int max_devnum = -ENODEV;
550         struct uclass *uc;
551         int ret;
552
553         ret = uclass_get(UCLASS_BLK, &uc);
554         if (ret)
555                 return ret;
556         uclass_foreach_dev(dev, uc) {
557                 struct blk_desc *desc = dev_get_uclass_plat(dev);
558
559                 if (desc->uclass_id == uclass_id && desc->devnum > max_devnum)
560                         max_devnum = desc->devnum;
561         }
562
563         return max_devnum;
564 }
565
566 int blk_next_free_devnum(enum uclass_id uclass_id)
567 {
568         int ret;
569
570         ret = blk_find_max_devnum(uclass_id);
571         if (ret == -ENODEV)
572                 return 0;
573         if (ret < 0)
574                 return ret;
575
576         return ret + 1;
577 }
578
579 static int blk_flags_check(struct udevice *dev, enum blk_flag_t req_flags)
580 {
581         const struct blk_desc *desc = dev_get_uclass_plat(dev);
582         enum blk_flag_t flags;
583
584         flags = desc->removable ? BLKF_REMOVABLE : BLKF_FIXED;
585
586         return flags & req_flags ? 0 : 1;
587 }
588
589 int blk_find_first(enum blk_flag_t flags, struct udevice **devp)
590 {
591         int ret;
592
593         for (ret = uclass_find_first_device(UCLASS_BLK, devp);
594              *devp && !blk_flags_check(*devp, flags);
595              ret = uclass_find_next_device(devp))
596                 return 0;
597
598         return -ENODEV;
599 }
600
601 int blk_find_next(enum blk_flag_t flags, struct udevice **devp)
602 {
603         int ret;
604
605         for (ret = uclass_find_next_device(devp);
606              *devp && !blk_flags_check(*devp, flags);
607              ret = uclass_find_next_device(devp))
608                 return 0;
609
610         return -ENODEV;
611 }
612
613 int blk_first_device_err(enum blk_flag_t flags, struct udevice **devp)
614 {
615         for (uclass_first_device(UCLASS_BLK, devp);
616              *devp;
617              uclass_next_device(devp)) {
618                 if (!blk_flags_check(*devp, flags))
619                         return 0;
620         }
621
622         return -ENODEV;
623 }
624
625 int blk_next_device_err(enum blk_flag_t flags, struct udevice **devp)
626 {
627         for (uclass_next_device(devp);
628              *devp;
629              uclass_next_device(devp)) {
630                 if (!blk_flags_check(*devp, flags))
631                         return 0;
632         }
633
634         return -ENODEV;
635 }
636
637 int blk_count_devices(enum blk_flag_t flag)
638 {
639         struct udevice *dev;
640         int count = 0;
641
642         blk_foreach_probe(flag, dev)
643                 count++;
644
645         return count;
646 }
647
648 static int blk_claim_devnum(enum uclass_id uclass_id, int devnum)
649 {
650         struct udevice *dev;
651         struct uclass *uc;
652         int ret;
653
654         ret = uclass_get(UCLASS_BLK, &uc);
655         if (ret)
656                 return ret;
657         uclass_foreach_dev(dev, uc) {
658                 struct blk_desc *desc = dev_get_uclass_plat(dev);
659
660                 if (desc->uclass_id == uclass_id && desc->devnum == devnum) {
661                         int next = blk_next_free_devnum(uclass_id);
662
663                         if (next < 0)
664                                 return next;
665                         desc->devnum = next;
666                         return 0;
667                 }
668         }
669
670         return -ENOENT;
671 }
672
673 int blk_create_device(struct udevice *parent, const char *drv_name,
674                       const char *name, int uclass_id, int devnum, int blksz,
675                       lbaint_t lba, struct udevice **devp)
676 {
677         struct blk_desc *desc;
678         struct udevice *dev;
679         int ret;
680
681         if (devnum == -1) {
682                 devnum = blk_next_free_devnum(uclass_id);
683         } else {
684                 ret = blk_claim_devnum(uclass_id, devnum);
685                 if (ret < 0 && ret != -ENOENT)
686                         return ret;
687         }
688         if (devnum < 0)
689                 return devnum;
690         ret = device_bind_driver(parent, drv_name, name, &dev);
691         if (ret)
692                 return ret;
693         desc = dev_get_uclass_plat(dev);
694         desc->uclass_id = uclass_id;
695         desc->blksz = blksz;
696         desc->log2blksz = LOG2(desc->blksz);
697         desc->lba = lba;
698         desc->part_type = PART_TYPE_UNKNOWN;
699         desc->bdev = dev;
700         desc->devnum = devnum;
701         *devp = dev;
702
703         return 0;
704 }
705
706 int blk_create_devicef(struct udevice *parent, const char *drv_name,
707                        const char *name, int uclass_id, int devnum, int blksz,
708                        lbaint_t lba, struct udevice **devp)
709 {
710         char dev_name[30], *str;
711         int ret;
712
713         snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
714         str = strdup(dev_name);
715         if (!str)
716                 return -ENOMEM;
717
718         ret = blk_create_device(parent, drv_name, str, uclass_id, devnum,
719                                 blksz, lba, devp);
720         if (ret) {
721                 free(str);
722                 return ret;
723         }
724         device_set_name_alloced(*devp);
725
726         return 0;
727 }
728
729 int blk_probe_or_unbind(struct udevice *dev)
730 {
731         int ret;
732
733         ret = device_probe(dev);
734         if (ret) {
735                 log_debug("probing %s failed\n", dev->name);
736                 device_unbind(dev);
737         }
738
739         return ret;
740 }
741
742 int blk_unbind_all(int uclass_id)
743 {
744         struct uclass *uc;
745         struct udevice *dev, *next;
746         int ret;
747
748         ret = uclass_get(UCLASS_BLK, &uc);
749         if (ret)
750                 return ret;
751         uclass_foreach_dev_safe(dev, next, uc) {
752                 struct blk_desc *desc = dev_get_uclass_plat(dev);
753
754                 if (desc->uclass_id == uclass_id) {
755                         ret = device_remove(dev, DM_REMOVE_NORMAL);
756                         if (ret)
757                                 return ret;
758                         ret = device_unbind(dev);
759                         if (ret)
760                                 return ret;
761                 }
762         }
763
764         return 0;
765 }
766
767 static int blk_post_probe(struct udevice *dev)
768 {
769         if (CONFIG_IS_ENABLED(PARTITIONS) && blk_enabled()) {
770                 struct blk_desc *desc = dev_get_uclass_plat(dev);
771
772                 part_init(desc);
773
774                 if (desc->part_type != PART_TYPE_UNKNOWN &&
775                     part_create_block_devices(dev))
776                         debug("*** creating partitions failed\n");
777         }
778
779         return 0;
780 }
781
782 UCLASS_DRIVER(blk) = {
783         .id             = UCLASS_BLK,
784         .name           = "blk",
785         .post_probe     = blk_post_probe,
786         .per_device_plat_auto   = sizeof(struct blk_desc),
787 };