blk-uclass.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2016 Google, Inc
  4. * Written by Simon Glass <sjg@chromium.org>
  5. */
  6. #include <common.h>
  7. #include <blk.h>
  8. #include <dm.h>
  9. #include <malloc.h>
  10. #include <dm/device-internal.h>
  11. #include <dm/lists.h>
  12. #include <dm/uclass-internal.h>
  13. #include <linux/err.h>
  14. static const char *if_typename_str[IF_TYPE_COUNT] = {
  15. [IF_TYPE_IDE] = "ide",
  16. [IF_TYPE_SCSI] = "scsi",
  17. [IF_TYPE_ATAPI] = "atapi",
  18. [IF_TYPE_USB] = "usb",
  19. [IF_TYPE_DOC] = "doc",
  20. [IF_TYPE_MMC] = "mmc",
  21. [IF_TYPE_SD] = "sd",
  22. [IF_TYPE_SATA] = "sata",
  23. [IF_TYPE_HOST] = "host",
  24. [IF_TYPE_NVME] = "nvme",
  25. [IF_TYPE_EFI] = "efi",
  26. [IF_TYPE_VIRTIO] = "virtio",
  27. };
  28. static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = {
  29. [IF_TYPE_IDE] = UCLASS_IDE,
  30. [IF_TYPE_SCSI] = UCLASS_SCSI,
  31. [IF_TYPE_ATAPI] = UCLASS_INVALID,
  32. [IF_TYPE_USB] = UCLASS_MASS_STORAGE,
  33. [IF_TYPE_DOC] = UCLASS_INVALID,
  34. [IF_TYPE_MMC] = UCLASS_MMC,
  35. [IF_TYPE_SD] = UCLASS_INVALID,
  36. [IF_TYPE_SATA] = UCLASS_AHCI,
  37. [IF_TYPE_HOST] = UCLASS_ROOT,
  38. [IF_TYPE_NVME] = UCLASS_NVME,
  39. [IF_TYPE_EFI] = UCLASS_EFI,
  40. [IF_TYPE_VIRTIO] = UCLASS_VIRTIO,
  41. };
  42. static enum if_type if_typename_to_iftype(const char *if_typename)
  43. {
  44. int i;
  45. for (i = 0; i < IF_TYPE_COUNT; i++) {
  46. if (if_typename_str[i] &&
  47. !strcmp(if_typename, if_typename_str[i]))
  48. return i;
  49. }
  50. return IF_TYPE_UNKNOWN;
  51. }
  52. static enum uclass_id if_type_to_uclass_id(enum if_type if_type)
  53. {
  54. return if_type_uclass_id[if_type];
  55. }
  56. const char *blk_get_if_type_name(enum if_type if_type)
  57. {
  58. return if_typename_str[if_type];
  59. }
  60. struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum)
  61. {
  62. struct blk_desc *desc;
  63. struct udevice *dev;
  64. int ret;
  65. ret = blk_get_device(if_type, devnum, &dev);
  66. if (ret)
  67. return NULL;
  68. desc = dev_get_uclass_platdata(dev);
  69. return desc;
  70. }
  71. /*
  72. * This function is complicated with driver model. We look up the interface
  73. * name in a local table. This gives us an interface type which we can match
  74. * against the uclass of the block device's parent.
  75. */
  76. struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum)
  77. {
  78. enum uclass_id uclass_id;
  79. enum if_type if_type;
  80. struct udevice *dev;
  81. struct uclass *uc;
  82. int ret;
  83. if_type = if_typename_to_iftype(if_typename);
  84. if (if_type == IF_TYPE_UNKNOWN) {
  85. debug("%s: Unknown interface type '%s'\n", __func__,
  86. if_typename);
  87. return NULL;
  88. }
  89. uclass_id = if_type_to_uclass_id(if_type);
  90. if (uclass_id == UCLASS_INVALID) {
  91. debug("%s: Unknown uclass for interface type'\n",
  92. if_typename_str[if_type]);
  93. return NULL;
  94. }
  95. ret = uclass_get(UCLASS_BLK, &uc);
  96. if (ret)
  97. return NULL;
  98. uclass_foreach_dev(dev, uc) {
  99. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  100. debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
  101. if_type, devnum, dev->name, desc->if_type, desc->devnum);
  102. if (desc->devnum != devnum)
  103. continue;
  104. /* Find out the parent device uclass */
  105. if (device_get_uclass_id(dev->parent) != uclass_id) {
  106. debug("%s: parent uclass %d, this dev %d\n", __func__,
  107. device_get_uclass_id(dev->parent), uclass_id);
  108. continue;
  109. }
  110. if (device_probe(dev))
  111. return NULL;
  112. debug("%s: Device desc %p\n", __func__, desc);
  113. return desc;
  114. }
  115. debug("%s: No device found\n", __func__);
  116. return NULL;
  117. }
  118. /**
  119. * blk_get_by_device() - Get the block device descriptor for the given device
  120. * @dev: Instance of a storage device
  121. *
  122. * Return: With block device descriptor on success , NULL if there is no such
  123. * block device.
  124. */
  125. struct blk_desc *blk_get_by_device(struct udevice *dev)
  126. {
  127. struct udevice *child_dev;
  128. device_foreach_child(child_dev, dev) {
  129. if (device_get_uclass_id(child_dev) != UCLASS_BLK)
  130. continue;
  131. return dev_get_uclass_platdata(child_dev);
  132. }
  133. debug("%s: No block device found\n", __func__);
  134. return NULL;
  135. }
  136. /**
  137. * get_desc() - Get the block device descriptor for the given device number
  138. *
  139. * @if_type: Interface type
  140. * @devnum: Device number (0 = first)
  141. * @descp: Returns block device descriptor on success
  142. * @return 0 on success, -ENODEV if there is no such device and no device
  143. * with a higher device number, -ENOENT if there is no such device but there
  144. * is one with a higher number, or other -ve on other error.
  145. */
  146. static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp)
  147. {
  148. bool found_more = false;
  149. struct udevice *dev;
  150. struct uclass *uc;
  151. int ret;
  152. *descp = NULL;
  153. ret = uclass_get(UCLASS_BLK, &uc);
  154. if (ret)
  155. return ret;
  156. uclass_foreach_dev(dev, uc) {
  157. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  158. debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
  159. if_type, devnum, dev->name, desc->if_type, desc->devnum);
  160. if (desc->if_type == if_type) {
  161. if (desc->devnum == devnum) {
  162. ret = device_probe(dev);
  163. if (ret)
  164. return ret;
  165. *descp = desc;
  166. return 0;
  167. } else if (desc->devnum > devnum) {
  168. found_more = true;
  169. }
  170. }
  171. }
  172. return found_more ? -ENOENT : -ENODEV;
  173. }
  174. int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart)
  175. {
  176. struct udevice *dev;
  177. int ret;
  178. ret = blk_get_device(if_type, devnum, &dev);
  179. if (ret)
  180. return ret;
  181. return blk_select_hwpart(dev, hwpart);
  182. }
  183. int blk_list_part(enum if_type if_type)
  184. {
  185. struct blk_desc *desc;
  186. int devnum, ok;
  187. int ret;
  188. for (ok = 0, devnum = 0;; ++devnum) {
  189. ret = get_desc(if_type, devnum, &desc);
  190. if (ret == -ENODEV)
  191. break;
  192. else if (ret)
  193. continue;
  194. if (desc->part_type != PART_TYPE_UNKNOWN) {
  195. ++ok;
  196. if (devnum)
  197. putc('\n');
  198. part_print(desc);
  199. }
  200. }
  201. if (!ok)
  202. return -ENODEV;
  203. return 0;
  204. }
  205. int blk_print_part_devnum(enum if_type if_type, int devnum)
  206. {
  207. struct blk_desc *desc;
  208. int ret;
  209. ret = get_desc(if_type, devnum, &desc);
  210. if (ret)
  211. return ret;
  212. if (desc->type == DEV_TYPE_UNKNOWN)
  213. return -ENOENT;
  214. part_print(desc);
  215. return 0;
  216. }
  217. void blk_list_devices(enum if_type if_type)
  218. {
  219. struct blk_desc *desc;
  220. int ret;
  221. int i;
  222. for (i = 0;; ++i) {
  223. ret = get_desc(if_type, i, &desc);
  224. if (ret == -ENODEV)
  225. break;
  226. else if (ret)
  227. continue;
  228. if (desc->type == DEV_TYPE_UNKNOWN)
  229. continue; /* list only known devices */
  230. printf("Device %d: ", i);
  231. dev_print(desc);
  232. }
  233. }
  234. int blk_print_device_num(enum if_type if_type, int devnum)
  235. {
  236. struct blk_desc *desc;
  237. int ret;
  238. ret = get_desc(if_type, devnum, &desc);
  239. if (ret)
  240. return ret;
  241. printf("\nIDE device %d: ", devnum);
  242. dev_print(desc);
  243. return 0;
  244. }
  245. int blk_show_device(enum if_type if_type, int devnum)
  246. {
  247. struct blk_desc *desc;
  248. int ret;
  249. printf("\nDevice %d: ", devnum);
  250. ret = get_desc(if_type, devnum, &desc);
  251. if (ret == -ENODEV || ret == -ENOENT) {
  252. printf("unknown device\n");
  253. return -ENODEV;
  254. }
  255. if (ret)
  256. return ret;
  257. dev_print(desc);
  258. if (desc->type == DEV_TYPE_UNKNOWN)
  259. return -ENOENT;
  260. return 0;
  261. }
  262. ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start,
  263. lbaint_t blkcnt, void *buffer)
  264. {
  265. struct blk_desc *desc;
  266. ulong n;
  267. int ret;
  268. ret = get_desc(if_type, devnum, &desc);
  269. if (ret)
  270. return ret;
  271. n = blk_dread(desc, start, blkcnt, buffer);
  272. if (IS_ERR_VALUE(n))
  273. return n;
  274. return n;
  275. }
  276. ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start,
  277. lbaint_t blkcnt, const void *buffer)
  278. {
  279. struct blk_desc *desc;
  280. int ret;
  281. ret = get_desc(if_type, devnum, &desc);
  282. if (ret)
  283. return ret;
  284. return blk_dwrite(desc, start, blkcnt, buffer);
  285. }
  286. int blk_select_hwpart(struct udevice *dev, int hwpart)
  287. {
  288. const struct blk_ops *ops = blk_get_ops(dev);
  289. if (!ops)
  290. return -ENOSYS;
  291. if (!ops->select_hwpart)
  292. return 0;
  293. return ops->select_hwpart(dev, hwpart);
  294. }
  295. int blk_dselect_hwpart(struct blk_desc *desc, int hwpart)
  296. {
  297. return blk_select_hwpart(desc->bdev, hwpart);
  298. }
  299. int blk_first_device(int if_type, struct udevice **devp)
  300. {
  301. struct blk_desc *desc;
  302. int ret;
  303. ret = uclass_find_first_device(UCLASS_BLK, devp);
  304. if (ret)
  305. return ret;
  306. if (!*devp)
  307. return -ENODEV;
  308. do {
  309. desc = dev_get_uclass_platdata(*devp);
  310. if (desc->if_type == if_type)
  311. return 0;
  312. ret = uclass_find_next_device(devp);
  313. if (ret)
  314. return ret;
  315. } while (*devp);
  316. return -ENODEV;
  317. }
  318. int blk_next_device(struct udevice **devp)
  319. {
  320. struct blk_desc *desc;
  321. int ret, if_type;
  322. desc = dev_get_uclass_platdata(*devp);
  323. if_type = desc->if_type;
  324. do {
  325. ret = uclass_find_next_device(devp);
  326. if (ret)
  327. return ret;
  328. if (!*devp)
  329. return -ENODEV;
  330. desc = dev_get_uclass_platdata(*devp);
  331. if (desc->if_type == if_type)
  332. return 0;
  333. } while (1);
  334. }
  335. int blk_find_device(int if_type, int devnum, struct udevice **devp)
  336. {
  337. struct uclass *uc;
  338. struct udevice *dev;
  339. int ret;
  340. ret = uclass_get(UCLASS_BLK, &uc);
  341. if (ret)
  342. return ret;
  343. uclass_foreach_dev(dev, uc) {
  344. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  345. debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__,
  346. if_type, devnum, dev->name, desc->if_type, desc->devnum);
  347. if (desc->if_type == if_type && desc->devnum == devnum) {
  348. *devp = dev;
  349. return 0;
  350. }
  351. }
  352. return -ENODEV;
  353. }
  354. int blk_get_device(int if_type, int devnum, struct udevice **devp)
  355. {
  356. int ret;
  357. ret = blk_find_device(if_type, devnum, devp);
  358. if (ret)
  359. return ret;
  360. return device_probe(*devp);
  361. }
  362. unsigned long blk_dread(struct blk_desc *block_dev, lbaint_t start,
  363. lbaint_t blkcnt, void *buffer)
  364. {
  365. struct udevice *dev = block_dev->bdev;
  366. const struct blk_ops *ops = blk_get_ops(dev);
  367. ulong blks_read;
  368. if (!ops->read)
  369. return -ENOSYS;
  370. if (blkcache_read(block_dev->if_type, block_dev->devnum,
  371. start, blkcnt, block_dev->blksz, buffer))
  372. return blkcnt;
  373. blks_read = ops->read(dev, start, blkcnt, buffer);
  374. if (blks_read == blkcnt)
  375. blkcache_fill(block_dev->if_type, block_dev->devnum,
  376. start, blkcnt, block_dev->blksz, buffer);
  377. return blks_read;
  378. }
  379. unsigned long blk_dwrite(struct blk_desc *block_dev, lbaint_t start,
  380. lbaint_t blkcnt, const void *buffer)
  381. {
  382. struct udevice *dev = block_dev->bdev;
  383. const struct blk_ops *ops = blk_get_ops(dev);
  384. if (!ops->write)
  385. return -ENOSYS;
  386. blkcache_invalidate(block_dev->if_type, block_dev->devnum);
  387. return ops->write(dev, start, blkcnt, buffer);
  388. }
  389. unsigned long blk_derase(struct blk_desc *block_dev, lbaint_t start,
  390. lbaint_t blkcnt)
  391. {
  392. struct udevice *dev = block_dev->bdev;
  393. const struct blk_ops *ops = blk_get_ops(dev);
  394. if (!ops->erase)
  395. return -ENOSYS;
  396. blkcache_invalidate(block_dev->if_type, block_dev->devnum);
  397. return ops->erase(dev, start, blkcnt);
  398. }
  399. int blk_get_from_parent(struct udevice *parent, struct udevice **devp)
  400. {
  401. struct udevice *dev;
  402. enum uclass_id id;
  403. int ret;
  404. device_find_first_child(parent, &dev);
  405. if (!dev) {
  406. debug("%s: No block device found for parent '%s'\n", __func__,
  407. parent->name);
  408. return -ENODEV;
  409. }
  410. id = device_get_uclass_id(dev);
  411. if (id != UCLASS_BLK) {
  412. debug("%s: Incorrect uclass %s for block device '%s'\n",
  413. __func__, uclass_get_name(id), dev->name);
  414. return -ENOTBLK;
  415. }
  416. ret = device_probe(dev);
  417. if (ret)
  418. return ret;
  419. *devp = dev;
  420. return 0;
  421. }
  422. int blk_find_max_devnum(enum if_type if_type)
  423. {
  424. struct udevice *dev;
  425. int max_devnum = -ENODEV;
  426. struct uclass *uc;
  427. int ret;
  428. ret = uclass_get(UCLASS_BLK, &uc);
  429. if (ret)
  430. return ret;
  431. uclass_foreach_dev(dev, uc) {
  432. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  433. if (desc->if_type == if_type && desc->devnum > max_devnum)
  434. max_devnum = desc->devnum;
  435. }
  436. return max_devnum;
  437. }
  438. int blk_next_free_devnum(enum if_type if_type)
  439. {
  440. int ret;
  441. ret = blk_find_max_devnum(if_type);
  442. if (ret == -ENODEV)
  443. return 0;
  444. if (ret < 0)
  445. return ret;
  446. return ret + 1;
  447. }
  448. static int blk_claim_devnum(enum if_type if_type, int devnum)
  449. {
  450. struct udevice *dev;
  451. struct uclass *uc;
  452. int ret;
  453. ret = uclass_get(UCLASS_BLK, &uc);
  454. if (ret)
  455. return ret;
  456. uclass_foreach_dev(dev, uc) {
  457. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  458. if (desc->if_type == if_type && desc->devnum == devnum) {
  459. int next = blk_next_free_devnum(if_type);
  460. if (next < 0)
  461. return next;
  462. desc->devnum = next;
  463. return 0;
  464. }
  465. }
  466. return -ENOENT;
  467. }
  468. int blk_create_device(struct udevice *parent, const char *drv_name,
  469. const char *name, int if_type, int devnum, int blksz,
  470. lbaint_t lba, struct udevice **devp)
  471. {
  472. struct blk_desc *desc;
  473. struct udevice *dev;
  474. int ret;
  475. if (devnum == -1) {
  476. devnum = blk_next_free_devnum(if_type);
  477. } else {
  478. ret = blk_claim_devnum(if_type, devnum);
  479. if (ret < 0 && ret != -ENOENT)
  480. return ret;
  481. }
  482. if (devnum < 0)
  483. return devnum;
  484. ret = device_bind_driver(parent, drv_name, name, &dev);
  485. if (ret)
  486. return ret;
  487. desc = dev_get_uclass_platdata(dev);
  488. desc->if_type = if_type;
  489. desc->blksz = blksz;
  490. desc->log2blksz = LOG2(desc->blksz);
  491. desc->lba = lba;
  492. desc->part_type = PART_TYPE_UNKNOWN;
  493. desc->bdev = dev;
  494. desc->devnum = devnum;
  495. *devp = dev;
  496. return 0;
  497. }
  498. int blk_create_devicef(struct udevice *parent, const char *drv_name,
  499. const char *name, int if_type, int devnum, int blksz,
  500. lbaint_t lba, struct udevice **devp)
  501. {
  502. char dev_name[30], *str;
  503. int ret;
  504. snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name);
  505. str = strdup(dev_name);
  506. if (!str)
  507. return -ENOMEM;
  508. ret = blk_create_device(parent, drv_name, str, if_type, devnum,
  509. blksz, lba, devp);
  510. if (ret) {
  511. free(str);
  512. return ret;
  513. }
  514. device_set_name_alloced(*devp);
  515. return 0;
  516. }
  517. int blk_unbind_all(int if_type)
  518. {
  519. struct uclass *uc;
  520. struct udevice *dev, *next;
  521. int ret;
  522. ret = uclass_get(UCLASS_BLK, &uc);
  523. if (ret)
  524. return ret;
  525. uclass_foreach_dev_safe(dev, next, uc) {
  526. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  527. if (desc->if_type == if_type) {
  528. ret = device_remove(dev, DM_REMOVE_NORMAL);
  529. if (ret)
  530. return ret;
  531. ret = device_unbind(dev);
  532. if (ret)
  533. return ret;
  534. }
  535. }
  536. return 0;
  537. }
  538. static int blk_post_probe(struct udevice *dev)
  539. {
  540. #if defined(CONFIG_PARTITIONS) && defined(CONFIG_HAVE_BLOCK_DEVICE)
  541. struct blk_desc *desc = dev_get_uclass_platdata(dev);
  542. part_init(desc);
  543. #endif
  544. return 0;
  545. }
  546. UCLASS_DRIVER(blk) = {
  547. .id = UCLASS_BLK,
  548. .name = "blk",
  549. .post_probe = blk_post_probe,
  550. .per_device_platdata_auto_alloc_size = sizeof(struct blk_desc),
  551. };