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