nvme.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Copyright (C) 2017 NXP Semiconductors
  3. * Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <command.h>
  9. #include <dm.h>
  10. #include <nvme.h>
  11. #include <part.h>
  12. #include <linux/math64.h>
  13. static int nvme_curr_device;
  14. static int do_nvme_scan(cmd_tbl_t *cmdtp, int flag,
  15. int argc, char * const argv[])
  16. {
  17. int ret;
  18. ret = nvme_scan_namespace();
  19. if (ret)
  20. return CMD_RET_FAILURE;
  21. return CMD_RET_SUCCESS;
  22. }
  23. static int do_nvme_list(cmd_tbl_t *cmdtp, int flag,
  24. int argc, char * const argv[])
  25. {
  26. blk_list_devices(IF_TYPE_NVME);
  27. return CMD_RET_SUCCESS;
  28. }
  29. static int do_nvme_info(cmd_tbl_t *cmdtp, int flag,
  30. int argc, char * const argv[])
  31. {
  32. int devnum;
  33. struct udevice *udev;
  34. int ret;
  35. if (argc > 1)
  36. devnum = (int)simple_strtoul(argv[1], NULL, 10);
  37. else
  38. devnum = nvme_curr_device;
  39. ret = blk_get_device(IF_TYPE_NVME, devnum, &udev);
  40. if (ret < 0)
  41. return CMD_RET_FAILURE;
  42. nvme_print_info(udev);
  43. return CMD_RET_SUCCESS;
  44. }
  45. static int do_nvme_device(cmd_tbl_t *cmdtp, int flag,
  46. int argc, char * const argv[])
  47. {
  48. if (argc > 1) {
  49. int devnum = (int)simple_strtoul(argv[1], NULL, 10);
  50. if (!blk_show_device(IF_TYPE_NVME, devnum)) {
  51. nvme_curr_device = devnum;
  52. printf("... is now current device\n");
  53. } else {
  54. return CMD_RET_FAILURE;
  55. }
  56. } else {
  57. blk_show_device(IF_TYPE_NVME, nvme_curr_device);
  58. }
  59. return CMD_RET_SUCCESS;
  60. }
  61. static int do_nvme_part(cmd_tbl_t *cmdtp, int flag,
  62. int argc, char * const argv[])
  63. {
  64. if (argc > 1) {
  65. int devnum = (int)simple_strtoul(argv[2], NULL, 10);
  66. if (blk_print_part_devnum(IF_TYPE_NVME, devnum)) {
  67. printf("\nNVMe device %d not available\n", devnum);
  68. return CMD_RET_FAILURE;
  69. }
  70. } else {
  71. blk_print_part_devnum(IF_TYPE_NVME, nvme_curr_device);
  72. }
  73. return CMD_RET_SUCCESS;
  74. }
  75. static int do_nvme_read(cmd_tbl_t *cmdtp, int flag, int argc,
  76. char * const argv[])
  77. {
  78. unsigned long time;
  79. if (argc != 4)
  80. return CMD_RET_USAGE;
  81. ulong addr = simple_strtoul(argv[1], NULL, 16);
  82. ulong cnt = simple_strtoul(argv[3], NULL, 16);
  83. ulong n;
  84. lbaint_t blk = simple_strtoul(argv[2], NULL, 16);
  85. printf("\nNVMe read: device %d block # " LBAFU " count %ld ... ",
  86. nvme_curr_device, blk, cnt);
  87. time = get_timer(0);
  88. n = blk_read_devnum(IF_TYPE_NVME, nvme_curr_device, blk,
  89. cnt, (ulong *)addr);
  90. time = get_timer(time);
  91. printf("read: %s\n", (n == cnt) ? "OK" : "ERROR");
  92. printf("%lu bytes read in %lu ms", cnt * 512, time);
  93. if (time > 0) {
  94. puts(" (");
  95. print_size(div_u64(cnt * 512, time) * 1000, "/s");
  96. puts(")");
  97. }
  98. puts("\n");
  99. return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
  100. }
  101. static int do_nvme_write(cmd_tbl_t *cmdtp, int flag, int argc,
  102. char * const argv[])
  103. {
  104. unsigned long time;
  105. if (argc != 4)
  106. return CMD_RET_USAGE;
  107. ulong addr = simple_strtoul(argv[1], NULL, 16);
  108. ulong cnt = simple_strtoul(argv[3], NULL, 16);
  109. ulong n;
  110. lbaint_t blk = simple_strtoul(argv[2], NULL, 16);
  111. printf("\nNVMe write: device %d block # " LBAFU " count %ld ... ",
  112. nvme_curr_device, blk, cnt);
  113. time = get_timer(0);
  114. n = blk_write_devnum(IF_TYPE_NVME, nvme_curr_device, blk,
  115. cnt, (ulong *)addr);
  116. time = get_timer(time);
  117. printf("write: %s\n", (n == cnt) ? "OK" : "ERROR");
  118. printf("%lu bytes write in %lu ms", cnt * 512, time);
  119. if (time > 0) {
  120. puts(" (");
  121. print_size(div_u64(cnt * 512, time) * 1000, "/s");
  122. puts(")");
  123. }
  124. puts("\n");
  125. return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
  126. }
  127. static cmd_tbl_t cmd_nvme[] = {
  128. U_BOOT_CMD_MKENT(scan, 1, 1, do_nvme_scan, "", ""),
  129. U_BOOT_CMD_MKENT(list, 1, 1, do_nvme_list, "", ""),
  130. U_BOOT_CMD_MKENT(info, 2, 1, do_nvme_info, "", ""),
  131. U_BOOT_CMD_MKENT(device, 2, 1, do_nvme_device, "", ""),
  132. U_BOOT_CMD_MKENT(part, 2, 1, do_nvme_part, "", ""),
  133. U_BOOT_CMD_MKENT(write, 4, 0, do_nvme_write, "", ""),
  134. U_BOOT_CMD_MKENT(read, 4, 0, do_nvme_read, "", "")
  135. };
  136. static int do_nvmecops(cmd_tbl_t *cmdtp, int flag, int argc,
  137. char * const argv[])
  138. {
  139. cmd_tbl_t *cp;
  140. cp = find_cmd_tbl(argv[1], cmd_nvme, ARRAY_SIZE(cmd_nvme));
  141. argc--;
  142. argv++;
  143. if (cp == NULL || argc > cp->maxargs)
  144. return CMD_RET_USAGE;
  145. if (flag == CMD_FLAG_REPEAT && !cp->repeatable)
  146. return CMD_RET_SUCCESS;
  147. return cp->cmd(cmdtp, flag, argc, argv);
  148. }
  149. U_BOOT_CMD(
  150. nvme, 8, 1, do_nvmecops,
  151. "NVM Express sub-system",
  152. "\nnvme scan - scan NVMe blk devices\n"
  153. "nvme list - show all available NVMe blk devices\n"
  154. "nvme info [dev]- show current or a specific NVMe blk device\n"
  155. "nvme device [dev] - show or set current device\n"
  156. "nvme part [dev] - print partition table\n"
  157. "nvme read addr blk# cnt\n"
  158. "nvme write addr blk# cnt"
  159. );