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