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