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