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