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