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