colibri_imx6: fix video stdout in default environment
[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 <log.h>
11 #include <malloc.h>
12 #include <part.h>
13 #include <dm/device-internal.h>
14 #include <dm/lists.h>
15 #include <dm/uclass-internal.h>
16 #include <linux/err.h>
17
18 static const char *if_typename_str[IF_TYPE_COUNT] = {
19         [IF_TYPE_IDE]           = "ide",
20         [IF_TYPE_SCSI]          = "scsi",
21         [IF_TYPE_ATAPI]         = "atapi",
22         [IF_TYPE_USB]           = "usb",
23         [IF_TYPE_DOC]           = "doc",
24         [IF_TYPE_MMC]           = "mmc",
25         [IF_TYPE_SD]            = "sd",
26         [IF_TYPE_SATA]          = "sata",
27         [IF_TYPE_HOST]          = "host",
28         [IF_TYPE_NVME]          = "nvme",
29         [IF_TYPE_EFI]           = "efi",
30         [IF_TYPE_VIRTIO]        = "virtio",
31 };
32
33 static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
34         [IF_TYPE_IDE]           = UCLASS_IDE,
35         [IF_TYPE_SCSI]          = UCLASS_SCSI,
36         [IF_TYPE_ATAPI]         = UCLASS_INVALID,
37         [IF_TYPE_USB]           = UCLASS_MASS_STORAGE,
38         [IF_TYPE_DOC]           = UCLASS_INVALID,
39         [IF_TYPE_MMC]           = UCLASS_MMC,
40         [IF_TYPE_SD]            = UCLASS_INVALID,
41         [IF_TYPE_SATA]          = UCLASS_AHCI,
42         [IF_TYPE_HOST]          = UCLASS_ROOT,
43         [IF_TYPE_NVME]          = UCLASS_NVME,
44         [IF_TYPE_EFI]           = UCLASS_EFI,
45         [IF_TYPE_VIRTIO]        = UCLASS_VIRTIO,
46 };
47
48 static enum if_type if_typename_to_iftype(const char *if_typename)
49 {
50         int i;
51
52         for (i = 0; i < IF_TYPE_COUNT; i++) {
53                 if (if_typename_str[i] &&
54                     !strcmp(if_typename, if_typename_str[i]))
55                         return i;
56         }
57
58         return IF_TYPE_UNKNOWN;
59 }
60
61 static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
62 {
63         return if_type_uclass_id[if_type];
64 }
65
66 const char *blk_get_if_type_name(enum if_type if_type)
67 {
68         return if_typename_str[if_type];
69 }
70
71 struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
72 {
73         struct blk_desc *desc;
74         struct udevice *dev;
75         int ret;
76
77         ret = blk_get_device(if_type, devnum, &dev);
78         if (ret)
79                 return NULL;
80         desc = dev_get_uclass_platdata(dev);
81
82         return desc;
83 }
84
85 /*
86  * This function is complicated with driver model. We look up the interface
87  * name in a local table. This gives us an interface type which we can match
88  * against the uclass of the block device's parent.
89  */
90 struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
91 {
92         enum uclass_id uclass_id;
93         enum if_type if_type;
94         struct udevice *dev;
95         struct uclass *uc;
96         int ret;
97
98         if_type = if_typename_to_iftype(if_typename);
99         if (if_type == IF_TYPE_UNKNOWN) {
100                 debug("%s: Unknown interface type '%s'\n", __func__,
101                       if_typename);
102                 return NULL;
103         }
104         uclass_id = if_type_to_uclass_id(if_type);
105         if (uclass_id == UCLASS_INVALID) {
106                 debug("%s: Unknown uclass for interface type'\n",
107                       if_typename_str[if_type]);
108                 return NULL;
109         }
110
111         ret = uclass_get(UCLASS_BLK, &uc);
112         if (ret)
113                 return NULL;
114         uclass_foreach_dev(dev, uc) {
115                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
116
117                 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
118                       if_type, devnum, dev->name, desc->if_type, desc->devnum);
119                 if (desc->devnum != devnum)
120                         continue;
121
122                 /* Find out the parent device uclass */
123                 if (device_get_uclass_id(dev->parent) != uclass_id) {
124                         debug("%s: parent uclass %d, this dev %d\n", __func__,
125                               device_get_uclass_id(dev->parent), uclass_id);
126                         continue;
127                 }
128
129                 if (device_probe(dev))
130                         return NULL;
131
132                 debug("%s: Device desc %p\n", __func__, desc);
133                 return desc;
134         }
135         debug("%s: No device found\n", __func__);
136
137         return NULL;
138 }
139
140 /**
141  * blk_get_by_device() - Get the block device descriptor for the given device
142  * @dev:        Instance of a storage device
143  *
144  * Return: With block device descriptor on success , NULL if there is no such
145  *         block device.
146  */
147 struct blk_desc *blk_get_by_device(struct udevice *dev)
148 {
149         struct udevice *child_dev;
150
151         device_foreach_child(child_dev, dev) {
152                 if (device_get_uclass_id(child_dev) != UCLASS_BLK)
153                         continue;
154
155                 return dev_get_uclass_platdata(child_dev);
156         }
157
158         debug("%s: No block device found\n", __func__);
159
160         return NULL;
161 }
162
163 /**
164  * get_desc() - Get the block device descriptor for the given device number
165  *
166  * @if_type:    Interface type
167  * @devnum:     Device number (0 = first)
168  * @descp:      Returns block device descriptor on success
169  * @return 0 on success, -ENODEV if there is no such device and no device
170  * with a higher device number, -ENOENT if there is no such device but there
171  * is one with a higher number, or other -ve on other error.
172  */
173 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp)
174 {
175         bool found_more = false;
176         struct udevice *dev;
177         struct uclass *uc;
178         int ret;
179
180         *descp = NULL;
181         ret = uclass_get(UCLASS_BLK, &uc);
182         if (ret)
183                 return ret;
184         uclass_foreach_dev(dev, uc) {
185                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
186
187                 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
188                       if_type, devnum, dev->name, desc->if_type, desc->devnum);
189                 if (desc->if_type == if_type) {
190                         if (desc->devnum == devnum) {
191                                 ret = device_probe(dev);
192                                 if (ret)
193                                         return ret;
194
195                                 *descp = desc;
196                                 return 0;
197                         } else if (desc->devnum > devnum) {
198                                 found_more = true;
199                         }
200                 }
201         }
202
203         return found_more ? -ENOENT : -ENODEV;
204 }
205
206 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
207 {
208         struct udevice *dev;
209         int ret;
210
211         ret = blk_get_device(if_type, devnum, &dev);
212         if (ret)
213                 return ret;
214
215         return blk_select_hwpart(dev, hwpart);
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         return blk_select_hwpart(desc->bdev, hwpart);
356 }
357
358 int blk_first_device(int if_type, struct udevice **devp)
359 {
360         struct blk_desc *desc;
361         int ret;
362
363         ret = uclass_find_first_device(UCLASS_BLK, devp);
364         if (ret)
365                 return ret;
366         if (!*devp)
367                 return -ENODEV;
368         do {
369                 desc = dev_get_uclass_platdata(*devp);
370                 if (desc->if_type == if_type)
371                         return 0;
372                 ret = uclass_find_next_device(devp);
373                 if (ret)
374                         return ret;
375         } while (*devp);
376
377         return -ENODEV;
378 }
379
380 int blk_next_device(struct udevice **devp)
381 {
382         struct blk_desc *desc;
383         int ret, if_type;
384
385         desc = dev_get_uclass_platdata(*devp);
386         if_type = desc->if_type;
387         do {
388                 ret = uclass_find_next_device(devp);
389                 if (ret)
390                         return ret;
391                 if (!*devp)
392                         return -ENODEV;
393                 desc = dev_get_uclass_platdata(*devp);
394                 if (desc->if_type == if_type)
395                         return 0;
396         } while (1);
397 }
398
399 int blk_find_device(int if_type, int devnum, struct udevice **devp)
400 {
401         struct uclass *uc;
402         struct udevice *dev;
403         int ret;
404
405         ret = uclass_get(UCLASS_BLK, &uc);
406         if (ret)
407                 return ret;
408         uclass_foreach_dev(dev, uc) {
409                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
410
411                 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
412                       if_type, devnum, dev->name, desc->if_type, desc->devnum);
413                 if (desc->if_type == if_type && desc->devnum == devnum) {
414                         *devp = dev;
415                         return 0;
416                 }
417         }
418
419         return -ENODEV;
420 }
421
422 int blk_get_device(int if_type, int devnum, struct udevice **devp)
423 {
424         int ret;
425
426         ret = blk_find_device(if_type, devnum, devp);
427         if (ret)
428                 return ret;
429
430         return device_probe(*devp);
431 }
432
433 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
434                         lbaint_t blkcnt, void *buffer)
435 {
436         struct udevice *dev = block_dev->bdev;
437         const struct blk_ops *ops = blk_get_ops(dev);
438         ulong blks_read;
439
440         if (!ops->read)
441                 return -ENOSYS;
442
443         if (blkcache_read(block_dev->if_type, block_dev->devnum,
444                           start, blkcnt, block_dev->blksz, buffer))
445                 return blkcnt;
446         blks_read = ops->read(dev, start, blkcnt, buffer);
447         if (blks_read == blkcnt)
448                 blkcache_fill(block_dev->if_type, block_dev->devnum,
449                               start, blkcnt, block_dev->blksz, buffer);
450
451         return blks_read;
452 }
453
454 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
455                          lbaint_t blkcnt, const void *buffer)
456 {
457         struct udevice *dev = block_dev->bdev;
458         const struct blk_ops *ops = blk_get_ops(dev);
459
460         if (!ops->write)
461                 return -ENOSYS;
462
463         blkcache_invalidate(block_dev->if_type, block_dev->devnum);
464         return ops->write(dev, start, blkcnt, buffer);
465 }
466
467 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
468                          lbaint_t blkcnt)
469 {
470         struct udevice *dev = block_dev->bdev;
471         const struct blk_ops *ops = blk_get_ops(dev);
472
473         if (!ops->erase)
474                 return -ENOSYS;
475
476         blkcache_invalidate(block_dev->if_type, block_dev->devnum);
477         return ops->erase(dev, start, blkcnt);
478 }
479
480 int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
481 {
482         struct udevice *dev;
483         enum uclass_id id;
484         int ret;
485
486         device_find_first_child(parent, &dev);
487         if (!dev) {
488                 debug("%s: No block device found for parent '%s'\n", __func__,
489                       parent->name);
490                 return -ENODEV;
491         }
492         id = device_get_uclass_id(dev);
493         if (id != UCLASS_BLK) {
494                 debug("%s: Incorrect uclass %s for block device '%s'\n",
495                       __func__, uclass_get_name(id), dev->name);
496                 return -ENOTBLK;
497         }
498         ret = device_probe(dev);
499         if (ret)
500                 return ret;
501         *devp = dev;
502
503         return 0;
504 }
505
506 int blk_find_max_devnum(enum if_type if_type)
507 {
508         struct udevice *dev;
509         int max_devnum = -ENODEV;
510         struct uclass *uc;
511         int ret;
512
513         ret = uclass_get(UCLASS_BLK, &uc);
514         if (ret)
515                 return ret;
516         uclass_foreach_dev(dev, uc) {
517                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
518
519                 if (desc->if_type == if_type && desc->devnum > max_devnum)
520                         max_devnum = desc->devnum;
521         }
522
523         return max_devnum;
524 }
525
526 int blk_next_free_devnum(enum if_type if_type)
527 {
528         int ret;
529
530         ret = blk_find_max_devnum(if_type);
531         if (ret == -ENODEV)
532                 return 0;
533         if (ret < 0)
534                 return ret;
535
536         return ret + 1;
537 }
538
539 static int blk_claim_devnum(enum if_type if_type, int devnum)
540 {
541         struct udevice *dev;
542         struct uclass *uc;
543         int ret;
544
545         ret = uclass_get(UCLASS_BLK, &uc);
546         if (ret)
547                 return ret;
548         uclass_foreach_dev(dev, uc) {
549                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
550
551                 if (desc->if_type == if_type && desc->devnum == devnum) {
552                         int next = blk_next_free_devnum(if_type);
553
554                         if (next < 0)
555                                 return next;
556                         desc->devnum = next;
557                         return 0;
558                 }
559         }
560
561         return -ENOENT;
562 }
563
564 int blk_create_device(struct udevice *parent, const char *drv_name,
565                       const char *name, int if_type, int devnum, int blksz,
566                       lbaint_t lba, struct udevice **devp)
567 {
568         struct blk_desc *desc;
569         struct udevice *dev;
570         int ret;
571
572         if (devnum == -1) {
573                 devnum = blk_next_free_devnum(if_type);
574         } else {
575                 ret = blk_claim_devnum(if_type, devnum);
576                 if (ret < 0 && ret != -ENOENT)
577                         return ret;
578         }
579         if (devnum < 0)
580                 return devnum;
581         ret = device_bind_driver(parent, drv_name, name, &dev);
582         if (ret)
583                 return ret;
584         desc = dev_get_uclass_platdata(dev);
585         desc->if_type = if_type;
586         desc->blksz = blksz;
587         desc->log2blksz = LOG2(desc->blksz);
588         desc->lba = lba;
589         desc->part_type = PART_TYPE_UNKNOWN;
590         desc->bdev = dev;
591         desc->devnum = devnum;
592         *devp = dev;
593
594         return 0;
595 }
596
597 int blk_create_devicef(struct udevice *parent, const char *drv_name,
598                        const char *name, int if_type, int devnum, int blksz,
599                        lbaint_t lba, struct udevice **devp)
600 {
601         char dev_name[30], *str;
602         int ret;
603
604         snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
605         str = strdup(dev_name);
606         if (!str)
607                 return -ENOMEM;
608
609         ret = blk_create_device(parent, drv_name, str, if_type, devnum,
610                                 blksz, lba, devp);
611         if (ret) {
612                 free(str);
613                 return ret;
614         }
615         device_set_name_alloced(*devp);
616
617         return 0;
618 }
619
620 int blk_unbind_all(int if_type)
621 {
622         struct uclass *uc;
623         struct udevice *dev, *next;
624         int ret;
625
626         ret = uclass_get(UCLASS_BLK, &uc);
627         if (ret)
628                 return ret;
629         uclass_foreach_dev_safe(dev, next, uc) {
630                 struct blk_desc *desc = dev_get_uclass_platdata(dev);
631
632                 if (desc->if_type == if_type) {
633                         ret = device_remove(dev, DM_REMOVE_NORMAL);
634                         if (ret)
635                                 return ret;
636                         ret = device_unbind(dev);
637                         if (ret)
638                                 return ret;
639                 }
640         }
641
642         return 0;
643 }
644
645 static int blk_post_probe(struct udevice *dev)
646 {
647 #if defined(CONFIG_PARTITIONS) && defined(CONFIG_HAVE_BLOCK_DEVICE)
648         struct blk_desc *desc = dev_get_uclass_platdata(dev);
649
650         part_init(desc);
651 #endif
652
653         return 0;
654 }
655
656 UCLASS_DRIVER(blk) = {
657         .id             = UCLASS_BLK,
658         .name           = "blk",
659         .post_probe     = blk_post_probe,
660         .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
661 };