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