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