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 (device_get_uclass_id(dev->parent) == UCLASS_SPI_FLASH && 139 if_type == IF_TYPE_MTD && 140 devnum == BLK_MTD_SPI_NOR) { 141 debug("Fix the spi flash uclass different\n"); 142 } else { 143 debug("%s: parent uclass %d, this dev %d\n", 144 __func__, 145 device_get_uclass_id(dev->parent), 146 uclass_id); 147 continue; 148 } 149 #else 150 debug("%s: parent uclass %d, this dev %d\n", __func__, 151 device_get_uclass_id(dev->parent), uclass_id); 152 continue; 153 #endif 154 } 155 156 if (device_probe(dev)) 157 return NULL; 158 159 debug("%s: Device desc %p\n", __func__, desc); 160 return desc; 161 } 162 debug("%s: No device found\n", __func__); 163 164 return NULL; 165 } 166 167 /** 168 * get_desc() - Get the block device descriptor for the given device number 169 * 170 * @if_type: Interface type 171 * @devnum: Device number (0 = first) 172 * @descp: Returns block device descriptor on success 173 * @return 0 on success, -ENODEV if there is no such device and no device 174 * with a higher device number, -ENOENT if there is no such device but there 175 * is one with a higher number, or other -ve on other error. 176 */ 177 static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) 178 { 179 bool found_more = false; 180 struct udevice *dev; 181 struct uclass *uc; 182 int ret; 183 184 *descp = NULL; 185 ret = uclass_get(UCLASS_BLK, &uc); 186 if (ret) 187 return ret; 188 uclass_foreach_dev(dev, uc) { 189 struct blk_desc *desc = dev_get_uclass_platdata(dev); 190 191 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 192 if_type, devnum, dev->name, desc->if_type, desc->devnum); 193 if (desc->if_type == if_type) { 194 if (desc->devnum == devnum) { 195 ret = device_probe(dev); 196 if (ret) 197 return ret; 198 199 *descp = desc; 200 return 0; 201 } else if (desc->devnum > devnum) { 202 found_more = true; 203 } 204 } 205 } 206 207 return found_more ? -ENOENT : -ENODEV; 208 } 209 210 int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart) 211 { 212 struct udevice *dev; 213 int ret; 214 215 ret = blk_get_device(if_type, devnum, &dev); 216 if (ret) 217 return ret; 218 219 return blk_select_hwpart(dev, hwpart); 220 } 221 222 int blk_list_part(enum if_type if_type) 223 { 224 struct blk_desc *desc; 225 int devnum, ok; 226 int ret; 227 228 for (ok = 0, devnum = 0;; ++devnum) { 229 ret = get_desc(if_type, devnum, &desc); 230 if (ret == -ENODEV) 231 break; 232 else if (ret) 233 continue; 234 if (desc->part_type != PART_TYPE_UNKNOWN) { 235 ++ok; 236 if (devnum) 237 putc('\n'); 238 part_print(desc); 239 } 240 } 241 if (!ok) 242 return -ENODEV; 243 244 return 0; 245 } 246 247 int blk_print_part_devnum(enum if_type if_type, int devnum) 248 { 249 struct blk_desc *desc; 250 int ret; 251 252 ret = get_desc(if_type, devnum, &desc); 253 if (ret) 254 return ret; 255 if (desc->type == DEV_TYPE_UNKNOWN) 256 return -ENOENT; 257 part_print(desc); 258 259 return 0; 260 } 261 262 void blk_list_devices(enum if_type if_type) 263 { 264 struct blk_desc *desc; 265 int ret; 266 int i; 267 268 for (i = 0;; ++i) { 269 ret = get_desc(if_type, i, &desc); 270 if (ret == -ENODEV) 271 break; 272 else if (ret) 273 continue; 274 if (desc->type == DEV_TYPE_UNKNOWN) 275 continue; /* list only known devices */ 276 printf("Device %d: ", i); 277 dev_print(desc); 278 } 279 } 280 281 int blk_print_device_num(enum if_type if_type, int devnum) 282 { 283 struct blk_desc *desc; 284 int ret; 285 286 ret = get_desc(if_type, devnum, &desc); 287 if (ret) 288 return ret; 289 printf("\nIDE device %d: ", devnum); 290 dev_print(desc); 291 292 return 0; 293 } 294 295 int blk_show_device(enum if_type if_type, int devnum) 296 { 297 struct blk_desc *desc; 298 int ret; 299 300 printf("\nDevice %d: ", devnum); 301 ret = get_desc(if_type, devnum, &desc); 302 if (ret == -ENODEV || ret == -ENOENT) { 303 printf("unknown device\n"); 304 return -ENODEV; 305 } 306 if (ret) 307 return ret; 308 dev_print(desc); 309 310 if (desc->type == DEV_TYPE_UNKNOWN) 311 return -ENOENT; 312 313 return 0; 314 } 315 316 ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, 317 lbaint_t blkcnt, void *buffer) 318 { 319 struct blk_desc *desc; 320 ulong n; 321 int ret; 322 323 ret = get_desc(if_type, devnum, &desc); 324 if (ret) 325 return ret; 326 n = blk_dread(desc, start, blkcnt, buffer); 327 if (IS_ERR_VALUE(n)) 328 return n; 329 330 return n; 331 } 332 333 ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, 334 lbaint_t blkcnt, const void *buffer) 335 { 336 struct blk_desc *desc; 337 int ret; 338 339 ret = get_desc(if_type, devnum, &desc); 340 if (ret) 341 return ret; 342 return blk_dwrite(desc, start, blkcnt, buffer); 343 } 344 345 ulong blk_write_zeroes_devnum(enum if_type if_type, int devnum, lbaint_t start, 346 lbaint_t blkcnt) 347 { 348 struct blk_desc *desc; 349 int ret; 350 351 ret = get_desc(if_type, devnum, &desc); 352 if (ret) 353 return ret; 354 return blk_dwrite_zeroes(desc, start, blkcnt); 355 } 356 357 ulong blk_erase_devnum(enum if_type if_type, int devnum, lbaint_t start, 358 lbaint_t blkcnt) 359 { 360 struct blk_desc *desc; 361 int ret; 362 363 ret = get_desc(if_type, devnum, &desc); 364 if (ret) 365 return ret; 366 return blk_derase(desc, start, blkcnt); 367 } 368 369 int blk_select_hwpart(struct udevice *dev, int hwpart) 370 { 371 const struct blk_ops *ops = blk_get_ops(dev); 372 373 if (!ops) 374 return -ENOSYS; 375 if (!ops->select_hwpart) 376 return 0; 377 378 return ops->select_hwpart(dev, hwpart); 379 } 380 381 int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) 382 { 383 return blk_select_hwpart(desc->bdev, hwpart); 384 } 385 386 int blk_first_device(int if_type, struct udevice **devp) 387 { 388 struct blk_desc *desc; 389 int ret; 390 391 ret = uclass_find_first_device(UCLASS_BLK, devp); 392 if (ret) 393 return ret; 394 if (!*devp) 395 return -ENODEV; 396 do { 397 desc = dev_get_uclass_platdata(*devp); 398 if (desc->if_type == if_type) 399 return 0; 400 ret = uclass_find_next_device(devp); 401 if (ret) 402 return ret; 403 } while (*devp); 404 405 return -ENODEV; 406 } 407 408 int blk_next_device(struct udevice **devp) 409 { 410 struct blk_desc *desc; 411 int ret, if_type; 412 413 desc = dev_get_uclass_platdata(*devp); 414 if_type = desc->if_type; 415 do { 416 ret = uclass_find_next_device(devp); 417 if (ret) 418 return ret; 419 if (!*devp) 420 return -ENODEV; 421 desc = dev_get_uclass_platdata(*devp); 422 if (desc->if_type == if_type) 423 return 0; 424 } while (1); 425 } 426 427 int blk_find_device(int if_type, int devnum, struct udevice **devp) 428 { 429 struct uclass *uc; 430 struct udevice *dev; 431 int ret; 432 433 ret = uclass_get(UCLASS_BLK, &uc); 434 if (ret) 435 return ret; 436 uclass_foreach_dev(dev, uc) { 437 struct blk_desc *desc = dev_get_uclass_platdata(dev); 438 439 debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, 440 if_type, devnum, dev->name, desc->if_type, desc->devnum); 441 if (desc->if_type == if_type && desc->devnum == devnum) { 442 *devp = dev; 443 return 0; 444 } 445 } 446 447 return -ENODEV; 448 } 449 450 int blk_get_device(int if_type, int devnum, struct udevice **devp) 451 { 452 int ret; 453 454 ret = blk_find_device(if_type, devnum, devp); 455 if (ret) 456 return ret; 457 458 return device_probe(*devp); 459 } 460 461 unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start, 462 lbaint_t blkcnt, void *buffer) 463 { 464 struct udevice *dev = block_dev->bdev; 465 const struct blk_ops *ops = blk_get_ops(dev); 466 ulong blks_read; 467 468 if (!ops->read) 469 return -ENOSYS; 470 471 if (blkcache_read(block_dev->if_type, block_dev->devnum, 472 start, blkcnt, block_dev->blksz, buffer)) 473 return blkcnt; 474 475 u_spin_lock(&block_dev->blk_lock); 476 blks_read = ops->read(dev, start, blkcnt, buffer); 477 u_spin_unlock(&block_dev->blk_lock); 478 479 if (blks_read == blkcnt) 480 blkcache_fill(block_dev->if_type, block_dev->devnum, 481 start, blkcnt, block_dev->blksz, buffer); 482 483 return blks_read; 484 } 485 486 unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start, 487 lbaint_t blkcnt, const void *buffer) 488 { 489 struct udevice *dev = block_dev->bdev; 490 const struct blk_ops *ops = blk_get_ops(dev); 491 ulong ret; 492 493 if (!ops->write) 494 return -ENOSYS; 495 496 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 497 498 u_spin_lock(&block_dev->blk_lock); 499 ret = ops->write(dev, start, blkcnt, buffer); 500 u_spin_unlock(&block_dev->blk_lock); 501 502 return ret; 503 } 504 505 unsigned long blk_dwrite_zeroes(struct blk_desc *block_dev, lbaint_t start, 506 lbaint_t blkcnt) 507 { 508 struct udevice *dev = block_dev->bdev; 509 const struct blk_ops *ops = blk_get_ops(dev); 510 ulong ret; 511 512 if (!ops->write_zeroes) 513 return -ENOSYS; 514 515 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 516 517 u_spin_lock(&block_dev->blk_lock); 518 ret = ops->write_zeroes(dev, start, blkcnt); 519 u_spin_unlock(&block_dev->blk_lock); 520 521 return ret; 522 } 523 524 unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start, 525 lbaint_t blkcnt) 526 { 527 struct udevice *dev = block_dev->bdev; 528 const struct blk_ops *ops = blk_get_ops(dev); 529 ulong ret; 530 531 if (!ops->erase) 532 return -ENOSYS; 533 534 blkcache_invalidate(block_dev->if_type, block_dev->devnum); 535 536 u_spin_lock(&block_dev->blk_lock); 537 ret = ops->erase(dev, start, blkcnt); 538 u_spin_unlock(&block_dev->blk_lock); 539 540 return ret; 541 } 542 543 int blk_prepare_device(struct udevice *dev) 544 { 545 struct blk_desc *desc = dev_get_uclass_platdata(dev); 546 547 part_init(desc); 548 549 return 0; 550 } 551 552 int blk_get_from_parent(struct udevice *parent, struct udevice **devp) 553 { 554 struct udevice *dev; 555 enum uclass_id id; 556 int ret; 557 558 device_find_first_child(parent, &dev); 559 if (!dev) { 560 debug("%s: No block device found for parent '%s'\n", __func__, 561 parent->name); 562 return -ENODEV; 563 } 564 id = device_get_uclass_id(dev); 565 if (id != UCLASS_BLK) { 566 debug("%s: Incorrect uclass %s for block device '%s'\n", 567 __func__, uclass_get_name(id), dev->name); 568 return -ENOTBLK; 569 } 570 ret = device_probe(dev); 571 if (ret) 572 return ret; 573 *devp = dev; 574 575 return 0; 576 } 577 578 int blk_find_max_devnum(enum if_type if_type) 579 { 580 struct udevice *dev; 581 int max_devnum = -ENODEV; 582 struct uclass *uc; 583 int ret; 584 585 ret = uclass_get(UCLASS_BLK, &uc); 586 if (ret) 587 return ret; 588 uclass_foreach_dev(dev, uc) { 589 struct blk_desc *desc = dev_get_uclass_platdata(dev); 590 591 if (desc->if_type == if_type && desc->devnum > max_devnum) 592 max_devnum = desc->devnum; 593 } 594 595 return max_devnum; 596 } 597 598 static int blk_next_free_devnum(enum if_type if_type) 599 { 600 int ret; 601 602 ret = blk_find_max_devnum(if_type); 603 if (ret == -ENODEV) 604 return 0; 605 if (ret < 0) 606 return ret; 607 608 return ret + 1; 609 } 610 611 static int blk_claim_devnum(enum if_type if_type, int devnum) 612 { 613 struct udevice *dev; 614 struct uclass *uc; 615 int ret; 616 617 ret = uclass_get(UCLASS_BLK, &uc); 618 if (ret) 619 return ret; 620 uclass_foreach_dev(dev, uc) { 621 struct blk_desc *desc = dev_get_uclass_platdata(dev); 622 623 if (desc->if_type == if_type && desc->devnum == devnum) { 624 int next = blk_next_free_devnum(if_type); 625 626 if (next < 0) 627 return next; 628 #ifdef CONFIG_USING_KERNEL_DTB_V2 629 /* 630 * Not allow devnum to be forced distributed. 631 * See commit (e48eeb9ea3 dm: blk: Improve block device claiming). 632 * 633 * fix like: "Device 'dwmmc@fe2b0000': seq 0 is in use by 'sdhci@fe310000'" 634 */ 635 if (!(gd->flags & GD_FLG_KDTB_READY)) 636 #endif 637 desc->devnum = next; 638 639 return 0; 640 } 641 } 642 643 return -ENOENT; 644 } 645 646 int blk_create_device(struct udevice *parent, const char *drv_name, 647 const char *name, int if_type, int devnum, int blksz, 648 lbaint_t size, struct udevice **devp) 649 { 650 struct blk_desc *desc; 651 struct udevice *dev; 652 int ret; 653 654 if (devnum == -1) { 655 devnum = blk_next_free_devnum(if_type); 656 } else { 657 ret = blk_claim_devnum(if_type, devnum); 658 if (ret < 0 && ret != -ENOENT) 659 return ret; 660 } 661 if (devnum < 0) 662 return devnum; 663 ret = device_bind_driver(parent, drv_name, name, &dev); 664 if (ret) 665 return ret; 666 desc = dev_get_uclass_platdata(dev); 667 desc->if_type = if_type; 668 desc->blksz = blksz; 669 desc->rawblksz = blksz; 670 desc->lba = size / blksz; 671 desc->rawlba = size / blksz; 672 desc->part_type = PART_TYPE_UNKNOWN; 673 desc->bdev = dev; 674 desc->devnum = devnum; 675 *devp = dev; 676 677 return 0; 678 } 679 680 int blk_create_devicef(struct udevice *parent, const char *drv_name, 681 const char *name, int if_type, int devnum, int blksz, 682 lbaint_t size, struct udevice **devp) 683 { 684 char dev_name[30], *str; 685 int ret; 686 687 snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); 688 str = strdup(dev_name); 689 if (!str) 690 return -ENOMEM; 691 692 ret = blk_create_device(parent, drv_name, str, if_type, devnum, 693 blksz, size, devp); 694 if (ret) { 695 free(str); 696 return ret; 697 } 698 device_set_name_alloced(*devp); 699 700 return 0; 701 } 702 703 int blk_unbind_all(int if_type) 704 { 705 struct uclass *uc; 706 struct udevice *dev, *next; 707 int ret; 708 709 ret = uclass_get(UCLASS_BLK, &uc); 710 if (ret) 711 return ret; 712 uclass_foreach_dev_safe(dev, next, uc) { 713 struct blk_desc *desc = dev_get_uclass_platdata(dev); 714 715 if (desc->if_type == if_type) { 716 ret = device_remove(dev, DM_REMOVE_NORMAL); 717 if (ret) 718 return ret; 719 ret = device_unbind(dev); 720 if (ret) 721 return ret; 722 } 723 } 724 725 return 0; 726 } 727 728 UCLASS_DRIVER(blk) = { 729 .id = UCLASS_BLK, 730 .name = "blk", 731 .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc), 732 }; 733