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