mmc.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2003
  4. * Kyle Harris, kharris@nexus-tech.net
  5. */
  6. #include <common.h>
  7. #include <command.h>
  8. #include <console.h>
  9. #include <mmc.h>
  10. #include <sparse_format.h>
  11. #include <image-sparse.h>
  12. #include <stdlib.h>
  13. static int curr_device = -1;
  14. static void print_mmcinfo(struct mmc *mmc)
  15. {
  16. int i;
  17. printf("Device: %s\n", mmc->cfg->name);
  18. printf("Manufacturer ID: %x\n", mmc->cid[0] >> 24);
  19. printf("OEM: %x\n", (mmc->cid[0] >> 8) & 0xffff);
  20. printf("Name: %c%c%c%c%c \n", mmc->cid[0] & 0xff,
  21. (mmc->cid[1] >> 24), (mmc->cid[1] >> 16) & 0xff,
  22. (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
  23. printf("Bus Speed: %d\n", mmc->clock);
  24. #if CONFIG_IS_ENABLED(MMC_VERBOSE)
  25. printf("Mode: %s\n", mmc_mode_name(mmc->selected_mode));
  26. mmc_dump_capabilities("card capabilities", mmc->card_caps);
  27. mmc_dump_capabilities("host capabilities", mmc->host_caps);
  28. #endif
  29. printf("Rd Block Len: %d\n", mmc->read_bl_len);
  30. printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC",
  31. EXTRACT_SDMMC_MAJOR_VERSION(mmc->version),
  32. EXTRACT_SDMMC_MINOR_VERSION(mmc->version));
  33. if (EXTRACT_SDMMC_CHANGE_VERSION(mmc->version) != 0)
  34. printf(".%d", EXTRACT_SDMMC_CHANGE_VERSION(mmc->version));
  35. printf("\n");
  36. printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
  37. puts("Capacity: ");
  38. print_size(mmc->capacity, "\n");
  39. printf("Bus Width: %d-bit%s\n", mmc->bus_width,
  40. mmc->ddr_mode ? " DDR" : "");
  41. #if CONFIG_IS_ENABLED(MMC_WRITE)
  42. puts("Erase Group Size: ");
  43. print_size(((u64)mmc->erase_grp_size) << 9, "\n");
  44. #endif
  45. if (!IS_SD(mmc) && mmc->version >= MMC_VERSION_4_41) {
  46. bool has_enh = (mmc->part_support & ENHNCD_SUPPORT) != 0;
  47. bool usr_enh = has_enh && (mmc->part_attr & EXT_CSD_ENH_USR);
  48. #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
  49. puts("HC WP Group Size: ");
  50. print_size(((u64)mmc->hc_wp_grp_size) << 9, "\n");
  51. #endif
  52. puts("User Capacity: ");
  53. print_size(mmc->capacity_user, usr_enh ? " ENH" : "");
  54. if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_USR)
  55. puts(" WRREL\n");
  56. else
  57. putc('\n');
  58. if (usr_enh) {
  59. puts("User Enhanced Start: ");
  60. print_size(mmc->enh_user_start, "\n");
  61. puts("User Enhanced Size: ");
  62. print_size(mmc->enh_user_size, "\n");
  63. }
  64. puts("Boot Capacity: ");
  65. print_size(mmc->capacity_boot, has_enh ? " ENH\n" : "\n");
  66. puts("RPMB Capacity: ");
  67. print_size(mmc->capacity_rpmb, has_enh ? " ENH\n" : "\n");
  68. for (i = 0; i < ARRAY_SIZE(mmc->capacity_gp); i++) {
  69. bool is_enh = has_enh &&
  70. (mmc->part_attr & EXT_CSD_ENH_GP(i));
  71. if (mmc->capacity_gp[i]) {
  72. printf("GP%i Capacity: ", i+1);
  73. print_size(mmc->capacity_gp[i],
  74. is_enh ? " ENH" : "");
  75. if (mmc->wr_rel_set & EXT_CSD_WR_DATA_REL_GP(i))
  76. puts(" WRREL\n");
  77. else
  78. putc('\n');
  79. }
  80. }
  81. }
  82. }
  83. static struct mmc *init_mmc_device(int dev, bool force_init)
  84. {
  85. struct mmc *mmc;
  86. mmc = find_mmc_device(dev);
  87. if (!mmc) {
  88. printf("no mmc device at slot %x\n", dev);
  89. return NULL;
  90. }
  91. #if !defined(CONFIG_MMC_BROKEN_CD)
  92. if (!mmc_getcd(mmc))
  93. force_init = true;
  94. #endif
  95. if (force_init)
  96. mmc->has_init = 0;
  97. if (mmc_init(mmc))
  98. return NULL;
  99. #ifdef CONFIG_BLOCK_CACHE
  100. struct blk_desc *bd = mmc_get_blk_desc(mmc);
  101. blkcache_invalidate(bd->if_type, bd->devnum);
  102. #endif
  103. return mmc;
  104. }
  105. static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  106. {
  107. struct mmc *mmc;
  108. if (curr_device < 0) {
  109. if (get_mmc_num() > 0)
  110. curr_device = 0;
  111. else {
  112. puts("No MMC device available\n");
  113. return 1;
  114. }
  115. }
  116. mmc = init_mmc_device(curr_device, false);
  117. if (!mmc)
  118. return CMD_RET_FAILURE;
  119. print_mmcinfo(mmc);
  120. return CMD_RET_SUCCESS;
  121. }
  122. #if CONFIG_IS_ENABLED(CMD_MMC_RPMB)
  123. static int confirm_key_prog(void)
  124. {
  125. puts("Warning: Programming authentication key can be done only once !\n"
  126. " Use this command only if you are sure of what you are doing,\n"
  127. "Really perform the key programming? <y/N> ");
  128. if (confirm_yesno())
  129. return 1;
  130. puts("Authentication key programming aborted\n");
  131. return 0;
  132. }
  133. static int do_mmcrpmb_key(cmd_tbl_t *cmdtp, int flag,
  134. int argc, char * const argv[])
  135. {
  136. void *key_addr;
  137. struct mmc *mmc = find_mmc_device(curr_device);
  138. if (argc != 2)
  139. return CMD_RET_USAGE;
  140. key_addr = (void *)simple_strtoul(argv[1], NULL, 16);
  141. if (!confirm_key_prog())
  142. return CMD_RET_FAILURE;
  143. if (mmc_rpmb_set_key(mmc, key_addr)) {
  144. printf("ERROR - Key already programmed ?\n");
  145. return CMD_RET_FAILURE;
  146. }
  147. return CMD_RET_SUCCESS;
  148. }
  149. static int do_mmcrpmb_read(cmd_tbl_t *cmdtp, int flag,
  150. int argc, char * const argv[])
  151. {
  152. u16 blk, cnt;
  153. void *addr;
  154. int n;
  155. void *key_addr = NULL;
  156. struct mmc *mmc = find_mmc_device(curr_device);
  157. if (argc < 4)
  158. return CMD_RET_USAGE;
  159. addr = (void *)simple_strtoul(argv[1], NULL, 16);
  160. blk = simple_strtoul(argv[2], NULL, 16);
  161. cnt = simple_strtoul(argv[3], NULL, 16);
  162. if (argc == 5)
  163. key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
  164. printf("\nMMC RPMB read: dev # %d, block # %d, count %d ... ",
  165. curr_device, blk, cnt);
  166. n = mmc_rpmb_read(mmc, addr, blk, cnt, key_addr);
  167. printf("%d RPMB blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
  168. if (n != cnt)
  169. return CMD_RET_FAILURE;
  170. return CMD_RET_SUCCESS;
  171. }
  172. static int do_mmcrpmb_write(cmd_tbl_t *cmdtp, int flag,
  173. int argc, char * const argv[])
  174. {
  175. u16 blk, cnt;
  176. void *addr;
  177. int n;
  178. void *key_addr;
  179. struct mmc *mmc = find_mmc_device(curr_device);
  180. if (argc != 5)
  181. return CMD_RET_USAGE;
  182. addr = (void *)simple_strtoul(argv[1], NULL, 16);
  183. blk = simple_strtoul(argv[2], NULL, 16);
  184. cnt = simple_strtoul(argv[3], NULL, 16);
  185. key_addr = (void *)simple_strtoul(argv[4], NULL, 16);
  186. printf("\nMMC RPMB write: dev # %d, block # %d, count %d ... ",
  187. curr_device, blk, cnt);
  188. n = mmc_rpmb_write(mmc, addr, blk, cnt, key_addr);
  189. printf("%d RPMB blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
  190. if (n != cnt)
  191. return CMD_RET_FAILURE;
  192. return CMD_RET_SUCCESS;
  193. }
  194. static int do_mmcrpmb_counter(cmd_tbl_t *cmdtp, int flag,
  195. int argc, char * const argv[])
  196. {
  197. unsigned long counter;
  198. struct mmc *mmc = find_mmc_device(curr_device);
  199. if (mmc_rpmb_get_counter(mmc, &counter))
  200. return CMD_RET_FAILURE;
  201. printf("RPMB Write counter= %lx\n", counter);
  202. return CMD_RET_SUCCESS;
  203. }
  204. static cmd_tbl_t cmd_rpmb[] = {
  205. U_BOOT_CMD_MKENT(key, 2, 0, do_mmcrpmb_key, "", ""),
  206. U_BOOT_CMD_MKENT(read, 5, 1, do_mmcrpmb_read, "", ""),
  207. U_BOOT_CMD_MKENT(write, 5, 0, do_mmcrpmb_write, "", ""),
  208. U_BOOT_CMD_MKENT(counter, 1, 1, do_mmcrpmb_counter, "", ""),
  209. };
  210. static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag,
  211. int argc, char * const argv[])
  212. {
  213. cmd_tbl_t *cp;
  214. struct mmc *mmc;
  215. char original_part;
  216. int ret;
  217. cp = find_cmd_tbl(argv[1], cmd_rpmb, ARRAY_SIZE(cmd_rpmb));
  218. /* Drop the rpmb subcommand */
  219. argc--;
  220. argv++;
  221. if (cp == NULL || argc > cp->maxargs)
  222. return CMD_RET_USAGE;
  223. if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
  224. return CMD_RET_SUCCESS;
  225. mmc = init_mmc_device(curr_device, false);
  226. if (!mmc)
  227. return CMD_RET_FAILURE;
  228. if (!(mmc->version & MMC_VERSION_MMC)) {
  229. printf("It is not a EMMC device\n");
  230. return CMD_RET_FAILURE;
  231. }
  232. if (mmc->version < MMC_VERSION_4_41) {
  233. printf("RPMB not supported before version 4.41\n");
  234. return CMD_RET_FAILURE;
  235. }
  236. /* Switch to the RPMB partition */
  237. #ifndef CONFIG_BLK
  238. original_part = mmc->block_dev.hwpart;
  239. #else
  240. original_part = mmc_get_blk_desc(mmc)->hwpart;
  241. #endif
  242. if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, MMC_PART_RPMB) !=
  243. 0)
  244. return CMD_RET_FAILURE;
  245. ret = cp->cmd(cmdtp, flag, argc, argv);
  246. /* Return to original partition */
  247. if (blk_select_hwpart_devnum(IF_TYPE_MMC, curr_device, original_part) !=
  248. 0)
  249. return CMD_RET_FAILURE;
  250. return ret;
  251. }
  252. #endif
  253. static int do_mmc_read(cmd_tbl_t *cmdtp, int flag,
  254. int argc, char * const argv[])
  255. {
  256. struct mmc *mmc;
  257. u32 blk, cnt, n;
  258. void *addr;
  259. if (argc != 4)
  260. return CMD_RET_USAGE;
  261. addr = (void *)simple_strtoul(argv[1], NULL, 16);
  262. blk = simple_strtoul(argv[2], NULL, 16);
  263. cnt = simple_strtoul(argv[3], NULL, 16);
  264. mmc = init_mmc_device(curr_device, false);
  265. if (!mmc)
  266. return CMD_RET_FAILURE;
  267. printf("\nMMC read: dev # %d, block # %d, count %d ... ",
  268. curr_device, blk, cnt);
  269. n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
  270. printf("%d blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR");
  271. return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
  272. }
  273. static int do_mmc_memset(cmd_tbl_t *cmdtp, int flag,
  274. int argc, char * const argv[])
  275. {
  276. u32 cnt;
  277. void *addr;
  278. addr = (void *)simple_strtoul(argv[1], NULL, 16);
  279. cnt = simple_strtoul(argv[2], NULL, 10);
  280. memset(addr, 0xff, cnt);
  281. printf("\nMMC memset addr:%p cnt: %d\n", addr, cnt);
  282. return CMD_RET_SUCCESS;
  283. }
  284. static int do_mmc_cmp(cmd_tbl_t *cmdtp, int flag,
  285. int argc, char * const argv[])
  286. {
  287. int ret = CMD_RET_SUCCESS, i = 0;
  288. uint8_t *buf1 = malloc(512);
  289. uint8_t *buf2 = malloc(512);
  290. struct mmc *mmc;
  291. u32 blk1, blk2, cnt, n;
  292. if (argc != 4)
  293. return CMD_RET_USAGE;
  294. blk1 = simple_strtoul(argv[1], NULL, 16);
  295. blk2 = simple_strtoul(argv[2], NULL, 16);
  296. cnt = simple_strtoul(argv[3], NULL, 10);
  297. mmc = init_mmc_device(curr_device, false);
  298. if (!mmc)
  299. return CMD_RET_FAILURE;
  300. printf("\nMMC cmp: dev # %d, block1 # %d, block2 # %d, count %d ... ",
  301. curr_device, blk1, blk2, cnt);
  302. while(i < cnt) {
  303. n = blk_dread(mmc_get_blk_desc(mmc), blk1 + i, 1, buf1);
  304. if (n != 1) {
  305. ret = CMD_RET_FAILURE;
  306. break;
  307. }
  308. n = blk_dread(mmc_get_blk_desc(mmc), blk2 + i, 1, buf2);
  309. if (n != 1) {
  310. ret = CMD_RET_FAILURE;
  311. break;
  312. }
  313. if (memcmp(buf1, buf2, 512) != 0) {
  314. ret = CMD_RET_FAILURE;
  315. break;
  316. }
  317. i++;
  318. }
  319. printf("blocks cmp : %s\n", (ret == CMD_RET_SUCCESS) ? "OK" : "ERROR");
  320. return ret;
  321. }
  322. static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag,
  323. int argc, char * const argv[])
  324. {
  325. u32 size;
  326. int ret = CMD_RET_SUCCESS;
  327. void *addr1, *addr2;
  328. if (argc != 4)
  329. return CMD_RET_USAGE;
  330. addr1 = (void *)simple_strtoul(argv[1], NULL, 16);
  331. addr2 = (void *)simple_strtoul(argv[2], NULL, 16);
  332. size = simple_strtoul(argv[3], NULL, 10);
  333. printf("\nmemcmp addr1 0x%p, addr2 0x%p, size %u\n", addr1, addr2, size);
  334. if (memcmp(addr1, addr2, size) != 0) {
  335. ret = CMD_RET_FAILURE;
  336. }
  337. printf("memcmp : %s\n", (ret == CMD_RET_SUCCESS) ? "OK" : "ERROR");
  338. return ret;
  339. }
  340. #if CONFIG_IS_ENABLED(CMD_MMC_SWRITE)
  341. static lbaint_t mmc_sparse_write(struct sparse_storage *info, lbaint_t blk,
  342. lbaint_t blkcnt, const void *buffer)
  343. {
  344. struct blk_desc *dev_desc = info->priv;
  345. return blk_dwrite(dev_desc, blk, blkcnt, buffer);
  346. }
  347. static lbaint_t mmc_sparse_reserve(struct sparse_storage *info,
  348. lbaint_t blk, lbaint_t blkcnt)
  349. {
  350. return blkcnt;
  351. }
  352. static int do_mmc_sparse_write(cmd_tbl_t *cmdtp, int flag,
  353. int argc, char * const argv[])
  354. {
  355. struct sparse_storage sparse;
  356. struct blk_desc *dev_desc;
  357. struct mmc *mmc;
  358. char dest[11];
  359. void *addr;
  360. u32 blk;
  361. if (argc != 3)
  362. return CMD_RET_USAGE;
  363. addr = (void *)simple_strtoul(argv[1], NULL, 16);
  364. blk = simple_strtoul(argv[2], NULL, 16);
  365. if (!is_sparse_image(addr)) {
  366. printf("Not a sparse image\n");
  367. return CMD_RET_FAILURE;
  368. }
  369. mmc = init_mmc_device(curr_device, false);
  370. if (!mmc)
  371. return CMD_RET_FAILURE;
  372. printf("\nMMC Sparse write: dev # %d, block # %d ... ",
  373. curr_device, blk);
  374. if (mmc_getwp(mmc) == 1) {
  375. printf("Error: card is write protected!\n");
  376. return CMD_RET_FAILURE;
  377. }
  378. dev_desc = mmc_get_blk_desc(mmc);
  379. sparse.priv = dev_desc;
  380. sparse.blksz = 512;
  381. sparse.start = blk;
  382. sparse.size = dev_desc->lba - blk;
  383. sparse.write = mmc_sparse_write;
  384. sparse.reserve = mmc_sparse_reserve;
  385. sparse.mssg = NULL;
  386. sprintf(dest, "0x" LBAF, sparse.start * sparse.blksz);
  387. if (write_sparse_image(&sparse, dest, addr, NULL))
  388. return CMD_RET_FAILURE;
  389. else
  390. return CMD_RET_SUCCESS;
  391. }
  392. #endif
  393. #if CONFIG_IS_ENABLED(MMC_WRITE)
  394. static int do_mmc_test(cmd_tbl_t *cmdtp, int flag,
  395. int argc, char * const argv[])
  396. {
  397. memset((void *)0x10000000, 0xff, 1024);
  398. return CMD_RET_SUCCESS;
  399. }
  400. static int do_mmc_write(cmd_tbl_t *cmdtp, int flag,
  401. int argc, char * const argv[])
  402. {
  403. struct mmc *mmc;
  404. u32 blk, cnt, n;
  405. void *addr;
  406. if (argc != 4)
  407. return CMD_RET_USAGE;
  408. addr = (void *)simple_strtoul(argv[1], NULL, 16);
  409. blk = simple_strtoul(argv[2], NULL, 16);
  410. cnt = simple_strtoul(argv[3], NULL, 16);
  411. mmc = init_mmc_device(curr_device, false);
  412. if (!mmc)
  413. return CMD_RET_FAILURE;
  414. printf("\nMMC write: dev # %d, block # %d, count %d ... ",
  415. curr_device, blk, cnt);
  416. if (mmc_getwp(mmc) == 1) {
  417. printf("Error: card is write protected!\n");
  418. return CMD_RET_FAILURE;
  419. }
  420. n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
  421. printf("%d blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR");
  422. return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
  423. }
  424. static int do_mmc_erase(cmd_tbl_t *cmdtp, int flag,
  425. int argc, char * const argv[])
  426. {
  427. struct mmc *mmc;
  428. u32 blk, cnt, n;
  429. if (argc != 3)
  430. return CMD_RET_USAGE;
  431. blk = simple_strtoul(argv[1], NULL, 16);
  432. cnt = simple_strtoul(argv[2], NULL, 16);
  433. mmc = init_mmc_device(curr_device, false);
  434. if (!mmc)
  435. return CMD_RET_FAILURE;
  436. printf("\nMMC erase: dev # %d, block # %d, count %d ... ",
  437. curr_device, blk, cnt);
  438. if (mmc_getwp(mmc) == 1) {
  439. printf("Error: card is write protected!\n");
  440. return CMD_RET_FAILURE;
  441. }
  442. n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
  443. printf("%d blocks erased: %s\n", n, (n == cnt) ? "OK" : "ERROR");
  444. return (n == cnt) ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
  445. }
  446. #endif
  447. #ifdef CONFIG_TARGET_LIGHT_C910
  448. extern int snps_sdhci_init(struct mmc *mmc);
  449. #endif
  450. static int do_mmc_rescan(cmd_tbl_t *cmdtp, int flag,
  451. int argc, char * const argv[])
  452. {
  453. struct mmc *mmc;
  454. #ifdef CONFIG_TARGET_LIGHT_C910
  455. mmc = find_mmc_device(curr_device);
  456. if (!mmc) {
  457. printf("no mmc device at slot %x\n", curr_device);
  458. return CMD_RET_FAILURE;
  459. }
  460. if (0 != snps_mmc_init(mmc))
  461. return CMD_RET_FAILURE;
  462. if (IS_SD(mmc)) {
  463. sd_resetore_sd_modes_by_pref();
  464. } else {
  465. mmc_resetore_mmc_modes_by_pref();
  466. }
  467. #endif
  468. mmc = init_mmc_device(curr_device, true);
  469. if (!mmc)
  470. return CMD_RET_FAILURE;
  471. return CMD_RET_SUCCESS;
  472. }
  473. extern volatile uint32_t DELAY_LANE;
  474. static int do_mmc_set_delay_lane(cmd_tbl_t *cmdtp, int flag,
  475. int argc, char * const argv[])
  476. {
  477. struct mmc *mmc;
  478. u32 val;
  479. val = simple_strtoul(argv[1], NULL, 10);
  480. DELAY_LANE = val;
  481. printf("set DELAY_LANE = %d\n", DELAY_LANE);
  482. mmc = find_mmc_device(curr_device);
  483. if (!mmc) {
  484. printf("no mmc device at slot %x\n", curr_device);
  485. return CMD_RET_FAILURE;
  486. }
  487. if (0 != snps_mmc_init(mmc))
  488. return CMD_RET_FAILURE;
  489. mmc = init_mmc_device(curr_device, true);
  490. if (!mmc)
  491. return CMD_RET_FAILURE;
  492. return CMD_RET_SUCCESS;
  493. }
  494. static int do_mmc_turning(cmd_tbl_t *cmdtp, int flag,
  495. int argc, char * const argv[])
  496. {
  497. struct mmc *mmc;
  498. int i = 0, n;
  499. for(i = 0; i <= 128; i++) {
  500. DELAY_LANE = i;
  501. printf("set DELAY_LANE = %d\n", DELAY_LANE);
  502. mmc = find_mmc_device(curr_device);
  503. if (!mmc) {
  504. printf("no mmc device at slot %x\n", curr_device);
  505. return CMD_RET_FAILURE;
  506. }
  507. if (0 != snps_mmc_init(mmc)) {
  508. printf("Error: mmc init error!\n");
  509. return CMD_RET_FAILURE;
  510. }
  511. mmc = init_mmc_device(curr_device, true);
  512. if (!mmc) {
  513. continue;
  514. }
  515. if (mmc_getwp(mmc) == 1) {
  516. printf("Error: card is write protected!\n");
  517. return CMD_RET_FAILURE;
  518. }
  519. n = blk_dwrite(mmc_get_blk_desc(mmc), 0, 1, 0);
  520. if (n == 1) {
  521. printf("blocks written: %s\n", "OK" );
  522. return CMD_RET_SUCCESS;
  523. } else {
  524. printf("written: %s\n", "error");
  525. }
  526. }
  527. if (i > 128) {
  528. return CMD_RET_FAILURE;
  529. }
  530. return CMD_RET_SUCCESS;
  531. }
  532. static int do_mmc_part(cmd_tbl_t *cmdtp, int flag,
  533. int argc, char * const argv[])
  534. {
  535. struct blk_desc *mmc_dev;
  536. struct mmc *mmc;
  537. mmc = init_mmc_device(curr_device, false);
  538. if (!mmc)
  539. return CMD_RET_FAILURE;
  540. mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device);
  541. if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) {
  542. part_print(mmc_dev);
  543. return CMD_RET_SUCCESS;
  544. }
  545. puts("get mmc type error!\n");
  546. return CMD_RET_FAILURE;
  547. }
  548. static int do_mmc_dev(cmd_tbl_t *cmdtp, int flag,
  549. int argc, char * const argv[])
  550. {
  551. int dev, part = 0, ret;
  552. struct mmc *mmc;
  553. if (argc == 1) {
  554. dev = curr_device;
  555. } else if (argc == 2) {
  556. dev = simple_strtoul(argv[1], NULL, 10);
  557. } else if (argc == 3) {
  558. dev = (int)simple_strtoul(argv[1], NULL, 10);
  559. part = (int)simple_strtoul(argv[2], NULL, 10);
  560. if (part > PART_ACCESS_MASK) {
  561. printf("#part_num shouldn't be larger than %d\n",
  562. PART_ACCESS_MASK);
  563. return CMD_RET_FAILURE;
  564. }
  565. } else {
  566. return CMD_RET_USAGE;
  567. }
  568. mmc = init_mmc_device(dev, true);
  569. if (!mmc)
  570. return CMD_RET_FAILURE;
  571. ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dev, part);
  572. printf("switch to partitions #%d, %s\n",
  573. part, (!ret) ? "OK" : "ERROR");
  574. if (ret)
  575. return 1;
  576. curr_device = dev;
  577. if (mmc->part_config == MMCPART_NOAVAILABLE)
  578. printf("mmc%d is current device\n", curr_device);
  579. else
  580. printf("mmc%d(part %d) is current device\n",
  581. curr_device, mmc_get_blk_desc(mmc)->hwpart);
  582. return CMD_RET_SUCCESS;
  583. }
  584. static int do_mmc_list(cmd_tbl_t *cmdtp, int flag,
  585. int argc, char * const argv[])
  586. {
  587. print_mmc_devices('\n');
  588. return CMD_RET_SUCCESS;
  589. }
  590. #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
  591. static int parse_hwpart_user(struct mmc_hwpart_conf *pconf,
  592. int argc, char * const argv[])
  593. {
  594. int i = 0;
  595. memset(&pconf->user, 0, sizeof(pconf->user));
  596. while (i < argc) {
  597. if (!strcmp(argv[i], "enh")) {
  598. if (i + 2 >= argc)
  599. return -1;
  600. pconf->user.enh_start =
  601. simple_strtoul(argv[i+1], NULL, 10);
  602. pconf->user.enh_size =
  603. simple_strtoul(argv[i+2], NULL, 10);
  604. i += 3;
  605. } else if (!strcmp(argv[i], "wrrel")) {
  606. if (i + 1 >= argc)
  607. return -1;
  608. pconf->user.wr_rel_change = 1;
  609. if (!strcmp(argv[i+1], "on"))
  610. pconf->user.wr_rel_set = 1;
  611. else if (!strcmp(argv[i+1], "off"))
  612. pconf->user.wr_rel_set = 0;
  613. else
  614. return -1;
  615. i += 2;
  616. } else {
  617. break;
  618. }
  619. }
  620. return i;
  621. }
  622. static int parse_hwpart_gp(struct mmc_hwpart_conf *pconf, int pidx,
  623. int argc, char * const argv[])
  624. {
  625. int i;
  626. memset(&pconf->gp_part[pidx], 0, sizeof(pconf->gp_part[pidx]));
  627. if (1 >= argc)
  628. return -1;
  629. pconf->gp_part[pidx].size = simple_strtoul(argv[0], NULL, 10);
  630. i = 1;
  631. while (i < argc) {
  632. if (!strcmp(argv[i], "enh")) {
  633. pconf->gp_part[pidx].enhanced = 1;
  634. i += 1;
  635. } else if (!strcmp(argv[i], "wrrel")) {
  636. if (i + 1 >= argc)
  637. return -1;
  638. pconf->gp_part[pidx].wr_rel_change = 1;
  639. if (!strcmp(argv[i+1], "on"))
  640. pconf->gp_part[pidx].wr_rel_set = 1;
  641. else if (!strcmp(argv[i+1], "off"))
  642. pconf->gp_part[pidx].wr_rel_set = 0;
  643. else
  644. return -1;
  645. i += 2;
  646. } else {
  647. break;
  648. }
  649. }
  650. return i;
  651. }
  652. static int do_mmc_hwpartition(cmd_tbl_t *cmdtp, int flag,
  653. int argc, char * const argv[])
  654. {
  655. struct mmc *mmc;
  656. struct mmc_hwpart_conf pconf = { };
  657. enum mmc_hwpart_conf_mode mode = MMC_HWPART_CONF_CHECK;
  658. int i, r, pidx;
  659. mmc = init_mmc_device(curr_device, false);
  660. if (!mmc)
  661. return CMD_RET_FAILURE;
  662. if (argc < 1)
  663. return CMD_RET_USAGE;
  664. i = 1;
  665. while (i < argc) {
  666. if (!strcmp(argv[i], "user")) {
  667. i++;
  668. r = parse_hwpart_user(&pconf, argc-i, &argv[i]);
  669. if (r < 0)
  670. return CMD_RET_USAGE;
  671. i += r;
  672. } else if (!strncmp(argv[i], "gp", 2) &&
  673. strlen(argv[i]) == 3 &&
  674. argv[i][2] >= '1' && argv[i][2] <= '4') {
  675. pidx = argv[i][2] - '1';
  676. i++;
  677. r = parse_hwpart_gp(&pconf, pidx, argc-i, &argv[i]);
  678. if (r < 0)
  679. return CMD_RET_USAGE;
  680. i += r;
  681. } else if (!strcmp(argv[i], "check")) {
  682. mode = MMC_HWPART_CONF_CHECK;
  683. i++;
  684. } else if (!strcmp(argv[i], "set")) {
  685. mode = MMC_HWPART_CONF_SET;
  686. i++;
  687. } else if (!strcmp(argv[i], "complete")) {
  688. mode = MMC_HWPART_CONF_COMPLETE;
  689. i++;
  690. } else {
  691. return CMD_RET_USAGE;
  692. }
  693. }
  694. puts("Partition configuration:\n");
  695. if (pconf.user.enh_size) {
  696. puts("\tUser Enhanced Start: ");
  697. print_size(((u64)pconf.user.enh_start) << 9, "\n");
  698. puts("\tUser Enhanced Size: ");
  699. print_size(((u64)pconf.user.enh_size) << 9, "\n");
  700. } else {
  701. puts("\tNo enhanced user data area\n");
  702. }
  703. if (pconf.user.wr_rel_change)
  704. printf("\tUser partition write reliability: %s\n",
  705. pconf.user.wr_rel_set ? "on" : "off");
  706. for (pidx = 0; pidx < 4; pidx++) {
  707. if (pconf.gp_part[pidx].size) {
  708. printf("\tGP%i Capacity: ", pidx+1);
  709. print_size(((u64)pconf.gp_part[pidx].size) << 9,
  710. pconf.gp_part[pidx].enhanced ?
  711. " ENH\n" : "\n");
  712. } else {
  713. printf("\tNo GP%i partition\n", pidx+1);
  714. }
  715. if (pconf.gp_part[pidx].wr_rel_change)
  716. printf("\tGP%i write reliability: %s\n", pidx+1,
  717. pconf.gp_part[pidx].wr_rel_set ? "on" : "off");
  718. }
  719. if (!mmc_hwpart_config(mmc, &pconf, mode)) {
  720. if (mode == MMC_HWPART_CONF_COMPLETE)
  721. puts("Partitioning successful, "
  722. "power-cycle to make effective\n");
  723. return CMD_RET_SUCCESS;
  724. } else {
  725. puts("Failed!\n");
  726. return CMD_RET_FAILURE;
  727. }
  728. }
  729. #endif
  730. #ifdef CONFIG_SUPPORT_EMMC_BOOT
  731. static int do_mmc_bootbus(cmd_tbl_t *cmdtp, int flag,
  732. int argc, char * const argv[])
  733. {
  734. int dev;
  735. struct mmc *mmc;
  736. u8 width, reset, mode;
  737. if (argc != 5)
  738. return CMD_RET_USAGE;
  739. dev = simple_strtoul(argv[1], NULL, 10);
  740. width = simple_strtoul(argv[2], NULL, 10);
  741. reset = simple_strtoul(argv[3], NULL, 10);
  742. mode = simple_strtoul(argv[4], NULL, 10);
  743. mmc = init_mmc_device(dev, false);
  744. if (!mmc)
  745. return CMD_RET_FAILURE;
  746. if (IS_SD(mmc)) {
  747. puts("BOOT_BUS_WIDTH only exists on eMMC\n");
  748. return CMD_RET_FAILURE;
  749. }
  750. /* acknowledge to be sent during boot operation */
  751. return mmc_set_boot_bus_width(mmc, width, reset, mode);
  752. }
  753. static int do_mmc_boot_resize(cmd_tbl_t *cmdtp, int flag,
  754. int argc, char * const argv[])
  755. {
  756. int dev;
  757. struct mmc *mmc;
  758. u32 bootsize, rpmbsize;
  759. if (argc != 4)
  760. return CMD_RET_USAGE;
  761. dev = simple_strtoul(argv[1], NULL, 10);
  762. bootsize = simple_strtoul(argv[2], NULL, 10);
  763. rpmbsize = simple_strtoul(argv[3], NULL, 10);
  764. mmc = init_mmc_device(dev, false);
  765. if (!mmc)
  766. return CMD_RET_FAILURE;
  767. if (IS_SD(mmc)) {
  768. printf("It is not a EMMC device\n");
  769. return CMD_RET_FAILURE;
  770. }
  771. if (mmc_boot_partition_size_change(mmc, bootsize, rpmbsize)) {
  772. printf("EMMC boot partition Size change Failed.\n");
  773. return CMD_RET_FAILURE;
  774. }
  775. printf("EMMC boot partition Size %d MB\n", bootsize);
  776. printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
  777. return CMD_RET_SUCCESS;
  778. }
  779. static int mmc_partconf_print(struct mmc *mmc)
  780. {
  781. u8 ack, access, part;
  782. if (mmc->part_config == MMCPART_NOAVAILABLE) {
  783. printf("No part_config info for ver. 0x%x\n", mmc->version);
  784. return CMD_RET_FAILURE;
  785. }
  786. access = EXT_CSD_EXTRACT_PARTITION_ACCESS(mmc->part_config);
  787. ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config);
  788. part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
  789. printf("EXT_CSD[179], PARTITION_CONFIG:\n"
  790. "BOOT_ACK: 0x%x\n"
  791. "BOOT_PARTITION_ENABLE: 0x%x\n"
  792. "PARTITION_ACCESS: 0x%x\n", ack, part, access);
  793. return CMD_RET_SUCCESS;
  794. }
  795. static int do_mmc_partconf(cmd_tbl_t *cmdtp, int flag,
  796. int argc, char * const argv[])
  797. {
  798. int dev;
  799. struct mmc *mmc;
  800. u8 ack, part_num, access;
  801. if (argc != 2 && argc != 5)
  802. return CMD_RET_USAGE;
  803. dev = simple_strtoul(argv[1], NULL, 10);
  804. mmc = init_mmc_device(dev, false);
  805. if (!mmc)
  806. return CMD_RET_FAILURE;
  807. if (IS_SD(mmc)) {
  808. puts("PARTITION_CONFIG only exists on eMMC\n");
  809. return CMD_RET_FAILURE;
  810. }
  811. if (argc == 2)
  812. return mmc_partconf_print(mmc);
  813. ack = simple_strtoul(argv[2], NULL, 10);
  814. part_num = simple_strtoul(argv[3], NULL, 10);
  815. access = simple_strtoul(argv[4], NULL, 10);
  816. /* acknowledge to be sent during boot operation */
  817. return mmc_set_part_conf(mmc, ack, part_num, access);
  818. }
  819. static int do_mmc_rst_func(cmd_tbl_t *cmdtp, int flag,
  820. int argc, char * const argv[])
  821. {
  822. int dev;
  823. struct mmc *mmc;
  824. u8 enable;
  825. /*
  826. * Set the RST_n_ENABLE bit of RST_n_FUNCTION
  827. * The only valid values are 0x0, 0x1 and 0x2 and writing
  828. * a value of 0x1 or 0x2 sets the value permanently.
  829. */
  830. if (argc != 3)
  831. return CMD_RET_USAGE;
  832. dev = simple_strtoul(argv[1], NULL, 10);
  833. enable = simple_strtoul(argv[2], NULL, 10);
  834. if (enable > 2) {
  835. puts("Invalid RST_n_ENABLE value\n");
  836. return CMD_RET_USAGE;
  837. }
  838. mmc = init_mmc_device(dev, false);
  839. if (!mmc)
  840. return CMD_RET_FAILURE;
  841. if (IS_SD(mmc)) {
  842. puts("RST_n_FUNCTION only exists on eMMC\n");
  843. return CMD_RET_FAILURE;
  844. }
  845. return mmc_set_rst_n_function(mmc, enable);
  846. }
  847. #endif
  848. static int do_mmc_setdsr(cmd_tbl_t *cmdtp, int flag,
  849. int argc, char * const argv[])
  850. {
  851. struct mmc *mmc;
  852. u32 val;
  853. int ret;
  854. if (argc != 2)
  855. return CMD_RET_USAGE;
  856. val = simple_strtoul(argv[1], NULL, 16);
  857. mmc = find_mmc_device(curr_device);
  858. if (!mmc) {
  859. printf("no mmc device at slot %x\n", curr_device);
  860. return CMD_RET_FAILURE;
  861. }
  862. ret = mmc_set_dsr(mmc, val);
  863. printf("set dsr %s\n", (!ret) ? "OK, force rescan" : "ERROR");
  864. if (!ret) {
  865. mmc->has_init = 0;
  866. if (mmc_init(mmc))
  867. return CMD_RET_FAILURE;
  868. else
  869. return CMD_RET_SUCCESS;
  870. }
  871. return ret;
  872. }
  873. static int do_mmc_set_speed(cmd_tbl_t *cmdtp, int flag,
  874. int argc, char * const argv[])
  875. {
  876. struct mmc *mmc;
  877. u32 mode, width;
  878. int ret = CMD_RET_SUCCESS;
  879. if (argc != 3)
  880. return CMD_RET_USAGE;
  881. mode = simple_strtoul(argv[1], NULL, 10);
  882. width = simple_strtoul(argv[2], NULL, 10);
  883. mmc = find_mmc_device(curr_device);
  884. if (!mmc) {
  885. printf("no mmc device at slot %x\n", curr_device);
  886. return CMD_RET_FAILURE;
  887. }
  888. if (!mmc)
  889. return CMD_RET_FAILURE;
  890. printf("\nMMC set mode: dev # %u\n", mode);
  891. mmc->bus_width = width;
  892. if (IS_SD(mmc)) {
  893. if (sd_select_speed_mode(mmc, mode) != 0) {
  894. ret = CMD_RET_FAILURE;
  895. }
  896. } else {
  897. if (mmc_select_speed_mode(mmc, mode) != 0) {
  898. ret = CMD_RET_FAILURE;
  899. }
  900. }
  901. if (0 != snps_mmc_init(mmc))
  902. return CMD_RET_FAILURE;
  903. mmc = init_mmc_device(curr_device, true);
  904. if (!mmc)
  905. return CMD_RET_FAILURE;
  906. #ifndef CONFIG_TARGET_LIGHT_C910
  907. if (IS_SD(mmc)) {
  908. sd_resetore_sd_modes_by_pref();
  909. } else {
  910. mmc_resetore_mmc_modes_by_pref();
  911. }
  912. #endif
  913. printf("set mode: %s\n", (ret == CMD_RET_SUCCESS) ? "OK" : "ERROR");
  914. return ret;
  915. }
  916. static int do_mmc_set_clock_freq(cmd_tbl_t *cmdtp, int flag,
  917. int argc, char * const argv[])
  918. {
  919. struct mmc *mmc;
  920. u32 freq;
  921. int ret = CMD_RET_SUCCESS;
  922. if (argc != 2)
  923. return CMD_RET_USAGE;
  924. freq = simple_strtoul(argv[1], NULL, 10);
  925. mmc = init_mmc_device(curr_device, false);
  926. if (!mmc)
  927. return CMD_RET_FAILURE;
  928. printf("\nMMC set freq :%u\n", freq);
  929. if (mmc_set_clock(mmc, freq, false) != 0) {
  930. ret = CMD_RET_FAILURE;
  931. }
  932. printf("set freq: %s\n", (ret == CMD_RET_SUCCESS) ? "OK" : "ERROR");
  933. return ret;
  934. }
  935. #ifdef CONFIG_CMD_BKOPS_ENABLE
  936. static int do_mmc_bkops_enable(cmd_tbl_t *cmdtp, int flag,
  937. int argc, char * const argv[])
  938. {
  939. int dev;
  940. struct mmc *mmc;
  941. if (argc != 2)
  942. return CMD_RET_USAGE;
  943. dev = simple_strtoul(argv[1], NULL, 10);
  944. mmc = init_mmc_device(dev, false);
  945. if (!mmc)
  946. return CMD_RET_FAILURE;
  947. if (IS_SD(mmc)) {
  948. puts("BKOPS_EN only exists on eMMC\n");
  949. return CMD_RET_FAILURE;
  950. }
  951. return mmc_set_bkops_enable(mmc);
  952. }
  953. #endif
  954. static cmd_tbl_t cmd_mmc[] = {
  955. U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""),
  956. U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""),
  957. U_BOOT_CMD_MKENT(memset, 4, 1, do_mmc_memset, "", ""),
  958. U_BOOT_CMD_MKENT(cmp, 4, 1, do_mmc_cmp, "", ""),
  959. U_BOOT_CMD_MKENT(memcmp, 4, 1, do_mem_cmp, "", ""),
  960. U_BOOT_CMD_MKENT(set_speed, 4, 1, do_mmc_set_speed, "", ""),
  961. U_BOOT_CMD_MKENT(set_clk, 4, 1, do_mmc_set_clock_freq, "", ""),
  962. #if CONFIG_IS_ENABLED(MMC_WRITE)
  963. U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""),
  964. U_BOOT_CMD_MKENT(test, 4, 0, do_mmc_test, "", ""),
  965. U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""),
  966. #endif
  967. #if CONFIG_IS_ENABLED(CMD_MMC_SWRITE)
  968. U_BOOT_CMD_MKENT(swrite, 3, 0, do_mmc_sparse_write, "", ""),
  969. #endif
  970. U_BOOT_CMD_MKENT(rescan, 1, 1, do_mmc_rescan, "", ""),
  971. U_BOOT_CMD_MKENT(set_delay, 4, 1, do_mmc_set_delay_lane, "", ""),
  972. U_BOOT_CMD_MKENT(turning, 4, 1, do_mmc_turning, "", ""),
  973. U_BOOT_CMD_MKENT(part, 1, 1, do_mmc_part, "", ""),
  974. U_BOOT_CMD_MKENT(dev, 3, 0, do_mmc_dev, "", ""),
  975. U_BOOT_CMD_MKENT(list, 1, 1, do_mmc_list, "", ""),
  976. #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
  977. U_BOOT_CMD_MKENT(hwpartition, 28, 0, do_mmc_hwpartition, "", ""),
  978. #endif
  979. #ifdef CONFIG_SUPPORT_EMMC_BOOT
  980. U_BOOT_CMD_MKENT(bootbus, 5, 0, do_mmc_bootbus, "", ""),
  981. U_BOOT_CMD_MKENT(bootpart-resize, 4, 0, do_mmc_boot_resize, "", ""),
  982. U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""),
  983. U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""),
  984. #endif
  985. #if CONFIG_IS_ENABLED(CMD_MMC_RPMB)
  986. U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""),
  987. #endif
  988. U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""),
  989. #ifdef CONFIG_CMD_BKOPS_ENABLE
  990. U_BOOT_CMD_MKENT(bkops-enable, 2, 0, do_mmc_bkops_enable, "", ""),
  991. #endif
  992. };
  993. static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  994. {
  995. cmd_tbl_t *cp;
  996. cp = find_cmd_tbl(argv[1], cmd_mmc, ARRAY_SIZE(cmd_mmc));
  997. /* Drop the mmc command */
  998. argc--;
  999. argv++;
  1000. if (cp == NULL || argc > cp->maxargs)
  1001. return CMD_RET_USAGE;
  1002. if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
  1003. return CMD_RET_SUCCESS;
  1004. if (curr_device < 0) {
  1005. if (get_mmc_num() > 0) {
  1006. curr_device = 0;
  1007. } else {
  1008. puts("No MMC device available\n");
  1009. return CMD_RET_FAILURE;
  1010. }
  1011. }
  1012. return cp->cmd(cmdtp, flag, argc, argv);
  1013. }
  1014. U_BOOT_CMD(
  1015. mmc, 29, 1, do_mmcops,
  1016. "MMC sub system",
  1017. "info - display info of the current MMC device\n"
  1018. "mmc read addr blk# cnt\n"
  1019. "mmc write addr blk# cnt\n"
  1020. "mmc cmp blk1 blk2# cnt\n"
  1021. "mmc memcmp addr1 addr2# size\n"
  1022. "mmc set_speed speed_mode bus_width(1, 4, 8):\n"
  1023. " - 0: MMC_LEGACY(emmc supported),\n"
  1024. " - 1: SD_LEGACY(sd supported),\n"
  1025. " - 2: MMC_HS(emmc supported),\n"
  1026. " - 3: SD_HS(sd supported),\n"
  1027. " - 4: MMC_HS_52 (emmc supported),\n"
  1028. " - 5: MMC_DDR_52(not supported),\n"
  1029. " - 6: UHS_SDR12(sd supported),\n"
  1030. " - 7: UHS_SDR25(sd supported),\n"
  1031. " - 8: UHS_SDR50(sd supported),\n"
  1032. " - 9: UHS_DDR50(not supported),\n"
  1033. " - 10: UHS_SDR104(sd supported),\n"
  1034. " - 11: MMC_HS_200(emmc supported),\n"
  1035. " - 12: MMC_HS_400(emmc supported),\n"
  1036. " - 13: MMC_HS_400_ES(not supported),\n"
  1037. "mmc set_clk freq\n"
  1038. #if CONFIG_IS_ENABLED(CMD_MMC_SWRITE)
  1039. "mmc swrite addr blk#\n"
  1040. #endif
  1041. "mmc erase blk# cnt\n"
  1042. "mmc rescan\n"
  1043. "mmc set_delay # val\n"
  1044. "mmc turning\n"
  1045. "mmc memset addr # lenght\n"
  1046. "mmc part - lists available partition on current mmc device\n"
  1047. "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
  1048. "mmc list - lists available devices\n"
  1049. #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING)
  1050. "mmc hwpartition [args...] - does hardware partitioning\n"
  1051. " arguments (sizes in 512-byte blocks):\n"
  1052. " [user [enh start cnt] [wrrel {on|off}]] - sets user data area attributes\n"
  1053. " [gp1|gp2|gp3|gp4 cnt [enh] [wrrel {on|off}]] - general purpose partition\n"
  1054. " [check|set|complete] - mode, complete set partitioning completed\n"
  1055. " WARNING: Partitioning is a write-once setting once it is set to complete.\n"
  1056. " Power cycling is required to initialize partitions after set to complete.\n"
  1057. #endif
  1058. #ifdef CONFIG_SUPPORT_EMMC_BOOT
  1059. "mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode\n"
  1060. " - Set the BOOT_BUS_WIDTH field of the specified device\n"
  1061. "mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>\n"
  1062. " - Change sizes of boot and RPMB partitions of specified device\n"
  1063. "mmc partconf dev [boot_ack boot_partition partition_access]\n"
  1064. " - Show or change the bits of the PARTITION_CONFIG field of the specified device\n"
  1065. "mmc rst-function dev value\n"
  1066. " - Change the RST_n_FUNCTION field of the specified device\n"
  1067. " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n"
  1068. #endif
  1069. #if CONFIG_IS_ENABLED(CMD_MMC_RPMB)
  1070. "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n"
  1071. "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n"
  1072. "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n"
  1073. "mmc rpmb counter - read the value of the write counter\n"
  1074. #endif
  1075. "mmc setdsr <value> - set DSR register value\n"
  1076. #ifdef CONFIG_CMD_BKOPS_ENABLE
  1077. "mmc bkops-enable <dev> - enable background operations handshake on device\n"
  1078. " WARNING: This is a write-once setting.\n"
  1079. #endif
  1080. );
  1081. /* Old command kept for compatibility. Same as 'mmc info' */
  1082. U_BOOT_CMD(
  1083. mmcinfo, 1, 0, do_mmcinfo,
  1084. "display MMC info",
  1085. "- display info of the current MMC device"
  1086. );