blob: 35be1afbc3a8b8c0e137a5a5953d708bf8577024 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <malloc.h>
8#include <command.h>
9#include <linux/ctype.h>
Ruixuan.lib5755732024-02-01 16:01:14 +080010#include <amlogic/aml_mmc.h>
11#include <mmc.h>
Bo Lv72d0e902023-01-02 14:27:34 +000012#include "../drivers/mmc/mmc_private.h"
13#include <amlogic/partition_table.h>
14#include <amlogic/emmc_partitions.h>
15#include <asm/amlogic/arch/cpu_sdio.h>
16#include <asm/amlogic/arch/sd_emmc.h>
17#include <linux/sizes.h>
18#include <amlogic/cpu_id.h>
19#include <amlogic/aml_mmc.h>
20#include <linux/crc32.h>
21#include "../drivers/mtd/ubi/crc32.c"
22
23/* info system. */
24#define dtb_err(fmt, ...) printf( "%s()-%d: " fmt , \
25 __func__, __LINE__, ##__VA_ARGS__)
26
27#define dtb_wrn(fmt, ...) printf( "%s()-%d: " fmt , \
28 __func__, __LINE__, ##__VA_ARGS__)
29
30/* for detail debug info */
31#define dtb_info(fmt, ...) printf( "%s()-%d: " fmt , \
32 __func__, __LINE__, ##__VA_ARGS__)
33
34#define fb_err(fmt, ...) printf("%s()-%d: " fmt , \
35 __func__, __LINE__, ##__VA_ARGS__)
36#define CONFIG_SYS_MMC_ENV_DEV 1
37struct aml_dtb_rsv {
38 u8 data[DTB_BLK_SIZE*DTB_BLK_CNT - 4*sizeof(u32)];
39 u32 magic;
40 u32 version;
41 u32 timestamp;
42 u32 checksum;
43};
44
45struct aml_dtb_info {
46 u32 stamp[2];
47 u8 valid[2];
48};
49
Bo Lv72d0e902023-01-02 14:27:34 +000050/* glb dtb infos */
51static struct aml_dtb_info dtb_infos = {{0, 0}, {0, 0}};
52
53#define CONFIG_SECURITYKEY
54
55#if !defined(CONFIG_SYS_MMC_BOOT_DEV)
56 #define CONFIG_SYS_MMC_BOOT_DEV (CONFIG_SYS_MMC_ENV_DEV)
57#endif
58
59#define GXB_START_BLK 0
60#define GXL_START_BLK 1
61
62/* max 2MB for emmc in blks */
63#define UBOOT_SIZE (0x1000)
64
65
66extern int mmc_key_write(unsigned char *buf, unsigned int size, uint32_t *actual_length);
67extern int mmc_key_read(unsigned char *buf, unsigned int size, uint32_t *actual_length);
68
69/* move this out to storage */
70//int info_disprotect = 0;
71
72
73int mmc_read_status(struct mmc *mmc, int timeout)
74{
75 struct mmc_cmd cmd;
76 int err, retries = 5;
77 int status;
78
79 cmd.cmdidx = MMC_CMD_SEND_STATUS;
80 cmd.resp_type = MMC_RSP_R1;
81 if (!mmc_host_is_spi(mmc))
82 cmd.cmdarg = mmc->rca << 16;
83 do {
84 err = mmc_send_cmd(mmc, &cmd, NULL);
85 if (!err) {
86 if ((cmd.response[0] & MMC_STATUS_RDY_FOR_DATA) &&
87 (cmd.response[0] & MMC_STATUS_CURR_STATE) !=
88 MMC_STATE_PRG)
89 break;
90 else if (cmd.response[0] & MMC_STATUS_MASK) {
91 printf("Status Error: 0x%08X\n",
92 cmd.response[0]);
93 return -18;
94 }
95 } else if (--retries < 0)
96 return err;
97
98 udelay(1000);
99
100 } while (timeout--);
101
102 status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
103 printf("CURR STATE:%d, status = 0x%x\n", status, cmd.response[0]);
104
105 if (timeout <= 0) {
106 printf("read status Timeout waiting card ready\n");
107 return -19;
108 }
109 if (cmd.response[0] & MMC_STATUS_SWITCH_ERROR) {
110 printf("mmc status switch error status =0x%x\n", status);
111 return -21;
112 }
113 return 0;
114}
115
116bool emmckey_is_protected (struct mmc *mmc)
117{
118#ifdef CONFIG_STORE_COMPATIBLE
119#ifdef CONFIG_SECURITYKEY
120 if (info_disprotect & DISPROTECT_KEY) {
121 printf("%s(): disprotect\n", __func__);
122 return 0;
123 }else{
124 printf("%s(): protect\n", __func__);
125 return 1;
126 }
127#else
128 return 0;
129#endif
130#else
131#ifdef CONFIG_SECURITYKEY
132 //return mmc->key_protect;
133 return 0; /* fixme, */
134#else
135 return 0;
136#endif
137#endif
138}
139
140unsigned emmc_cur_partition = 0;
141
142
143static int get_off_size(struct mmc * mmc, char * name, uint64_t offset, uint64_t size, u64 * blk, u64 * cnt, u64 * sz_byte)
144{
145 struct partitions *part_info = NULL;
146 uint64_t off = 0;
147 int blk_shift = 0;
148
149 blk_shift = ffs(mmc->read_bl_len) - 1;
150 if (blk_shift < 0) {
151 printf("Bad shift.\n");
152 return 0;
153 }
154 // printf("blk_shift:%d , off:0x%llx , size:0x%llx.\n ",blk_shift,off,size );
155 part_info = find_mmc_partition_by_name(name);
156 if (part_info == NULL) {
157 printf("get partition info failed !!\n");
158 return -1;
159 }
160 off = part_info->offset + offset;
161
162 // printf("part_info->offset:0x%llx , off:0x%llx , size:0x%llx.\n",part_info->offset ,off,size);
163
164 *blk = off >> blk_shift;
165 *cnt = size >> blk_shift;
166 *sz_byte = size - ((*cnt) << blk_shift);
167
168 // printf("get_partition_off_size : blk:0x%llx , cnt:0x%llx.\n",*blk,*cnt);
169 return 0;
170}
171
172static int get_partition_size(unsigned char* name, uint64_t* addr)
173{
174 struct partitions *part_info = NULL;
175 part_info = find_mmc_partition_by_name((char *)name);
176 if (part_info == NULL) {
177 printf("get partition info failed !!\n");
178 return -1;
179 }
180
181 *addr = part_info->size >> 9; // unit: 512 bytes
182 return 0;
183}
184
185static inline int isstring(char *p)
186{
187 char *endptr = p;
188 while (*endptr != '\0') {
189 if (!(((*endptr >= '0') && (*endptr <= '9'))
190 || ((*endptr >= 'a') && (*endptr <= 'f'))
191 || ((*endptr >= 'A') && (*endptr <= 'F'))
192 || (*endptr == 'x') || (*endptr == 'X')))
193 return 1;
194 endptr++;
195 }
196
197 return 0;
198}
199
200/*
201 erase bootloader on user/boot0/boot1 which indicate by map.
202 bit 0: user
203 bit 1: boot0
204 bit 2: boot1
205*/
206int amlmmc_erase_bootloader(int dev, int map)
207{
208 int ret = 0, i, count = 3;
209 int blk_shift;
210 unsigned long n;
211 char *partname[3] = {"user", "boot0", "boot1"};
212 cpu_id_t cpu_id = get_cpu_id();
213 struct mmc *mmc = find_mmc_device(dev);
214
215 /* do nothing */
216 if (0 == map)
217 goto _out;
218
219 if (!mmc) {
220 printf("%s() %d: not valid emmc %d\n", __func__, __LINE__, dev);
221 ret = -1;
222 goto _out;
223 }
224 /* make sure mmc is initialized! */
225 ret = mmc_init(mmc);
226 if (ret) {
227 printf("%s() %d: emmc %d init %d\n", __func__, __LINE__, dev, ret);
228 ret = -2;
229 goto _out;
230 }
231
232 blk_shift = ffs(mmc->read_bl_len) -1;
233 if (blk_shift < 0) {
234 printf("bad shift.\n");
235 ret = -3;
236 goto _out;
237 }
238 /* erase bootloader in user/boot0/boot1 */
239 for (i = 0; i < count; i++) {
240 if (map & (0x1 << i)) {
ruixuan.li554d4e92023-02-28 17:11:25 +0800241 if (!blk_select_hwpart_devnum(UCLASS_MMC, 1, i)) {
Bo Lv72d0e902023-01-02 14:27:34 +0000242 lbaint_t start = 0, blkcnt;
243
Bo Lv72d0e902023-01-02 14:27:34 +0000244 if (0 == i) {
Ruixuan.li6a7e07c2024-01-11 20:10:29 +0800245 blkcnt = mmc->capacity >> blk_shift;
Bo Lv72d0e902023-01-02 14:27:34 +0000246 struct partitions *part_info;
247 /* get info by partition */
248 part_info = find_mmc_partition_by_name(MMC_BOOT_NAME);
249 if (part_info == NULL) {
250 printf("%s() %d: error!!\n", __func__, __LINE__);
251 /* fixme, do somthing! */
252 continue;
253 } else {
254 start = part_info->offset >> blk_shift;
255 blkcnt = part_info->size >> blk_shift;
256 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
257 start = GXL_START_BLK;
258 blkcnt -= GXL_START_BLK;
259 }
260 }
Ruixuan.li6a7e07c2024-01-11 20:10:29 +0800261 } else {
262 blkcnt = mmc->capacity_boot >> blk_shift;
Bo Lv72d0e902023-01-02 14:27:34 +0000263 }
264/* some customer may use boot1 higher 2M as private data. */
265#ifdef CONFIG_EMMC_BOOT1_TOUCH_REGION
266 if (2 == i && CONFIG_EMMC_BOOT1_TOUCH_REGION <= mmc->capacity) {
267 blkcnt = CONFIG_EMMC_BOOT1_TOUCH_REGION >> blk_shift;
268 }
269#endif/* CONFIG_EMMC_BOOT1_TOUCH_REGION */
270
271 if (i == 0 && (aml_gpt_valid(mmc) == 0))
272 continue;
273
274 printf("Erasing blocks " LBAFU " to " LBAFU " @ %s\n",
275 start, blkcnt, partname[i]);
276 n = blk_derase(mmc_get_blk_desc(mmc), start, blkcnt);
Ruixuan.li6a7e07c2024-01-11 20:10:29 +0800277 if (n != blkcnt) {
Bo Lv72d0e902023-01-02 14:27:34 +0000278 printf("mmc erase %s failed\n", partname[i]);
279 ret = -3;
Ruixuan.li6a7e07c2024-01-11 20:10:29 +0800280 goto _out;
Bo Lv72d0e902023-01-02 14:27:34 +0000281 }
282 } else
283 printf("%s() %d: switch dev %d to %s fail\n",
284 __func__, __LINE__, dev, partname[i]);
285 }
286 }
287 /* try to switch back to user. */
Ruixuan.li6a7e07c2024-01-11 20:10:29 +0800288 ret = blk_select_hwpart_devnum(UCLASS_MMC, 1, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000289
290_out:
291 return ret;
292}
293
294/*
295 write bootloader on user/boot0/boot1 which indicate by map.
296 bit 0: user
297 bit 1: boot0
298 bit 2: boot1
299*/
300int amlmmc_write_bootloader(int dev, int map, unsigned int size, const void *src)
301{
302 int ret = 0, i, count = 3;
303 unsigned long n;
304 char *partname[3] = {"user", "boot0", "boot1"};
305 struct mmc *mmc = find_mmc_device(dev);
306 lbaint_t start = GXB_START_BLK, blkcnt;
307 cpu_id_t cpu_id = get_cpu_id();
308
309 /* do nothing */
310 if (0 == map)
311 goto _out;
312
313 if (!mmc) {
314 printf("%s() %d: not valid emmc %d\n", __func__, __LINE__, dev);
315 ret = -1;
316 goto _out;
317 }
318 /* make sure mmc is initialized! */
319 ret = mmc_init(mmc);
320 if (ret) {
321 printf("%s() %d: emmc %d init %d\n", __func__, __LINE__, dev, ret);
322 ret = -2;
323 goto _out;
324 }
325
326 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL)
327 start = GXL_START_BLK;
328 blkcnt = (size + mmc->read_bl_len - 1) / mmc->read_bl_len;
329
330 /* erase bootloader in user/boot0/boot1 */
331 for (i = 0; i < count; i++) {
332 if (map & (0x1 << i)) {
ruixuan.li554d4e92023-02-28 17:11:25 +0800333 if (!blk_select_hwpart_devnum(UCLASS_MMC, 1, i)) {
Bo Lv72d0e902023-01-02 14:27:34 +0000334/* some customer may use boot1 higher 2M as private data. */
335#ifdef CONFIG_EMMC_BOOT1_TOUCH_REGION
336 if (2 == i && CONFIG_EMMC_BOOT1_TOUCH_REGION <= size) {
337 printf("%s(), size %d exceeds TOUCH_REGION %d, skip\n",
338 __func__, size, CONFIG_EMMC_BOOT1_TOUCH_REGION);
339 break;
340 }
341#endif /* CONFIG_EMMC_BOOT1_TOUCH_REGION */
342 if (i == 0 && (aml_gpt_valid(mmc) == 0))
343 continue;
344
345 printf("Writing blocks " LBAFU " to " LBAFU " @ %s\n",
346 start, blkcnt, partname[i]);
347 n = blk_dwrite(mmc_get_blk_desc(mmc), start, blkcnt, src);
348 if (n != blkcnt) {
349 printf("mmc write %s failed\n", partname[i]);
350 ret = -3;
Xindong Xud9441422024-01-18 10:20:45 +0800351 goto _out;
Bo Lv72d0e902023-01-02 14:27:34 +0000352 }
353 } else
354 printf("%s() %d: switch dev %d to %s fail\n",
355 __func__, __LINE__, dev, partname[i]);
356 }
357 }
358 /* try to switch back to user. */
Xindong Xud9441422024-01-18 10:20:45 +0800359 ret = blk_select_hwpart_devnum(UCLASS_MMC, 1, 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000360
361_out:
362 return ret;
363}
364
365static int amlmmc_erase_in_dev(int argc, char *const argv[])
366{
367 int dev = 0;
368 u64 cnt = 0, blk = 0, n = 0;
369 struct mmc *mmc;
370
371 dev = simple_strtoul(argv[2], NULL, 10);
372 blk = simple_strtoull(argv[3], NULL, 16);
373 cnt = simple_strtoull(argv[4], NULL, 16);
374
375 if (dev < 0) {
376 printf("Cannot find dev.\n");
377 return 1;
378 }
379
380 mmc = find_mmc_device(dev);
381
382 if (!mmc)
383 return 1;
384
385 printf("MMC erase: dev # %d, start_erase_address(in block) # %#llx,\
386 several blocks # %lld will be erased ...\n ",
387 dev, blk, cnt);
388
389 mmc_init(mmc);
390
391 if (cnt != 0)
392 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
393
394 printf("dev # %d, %s, several blocks erased %s\n",
395 dev, " ", (n == 0) ? "OK" : "ERROR");
396
397 return (n == 0) ? 0 : 1;
398}
399
400static int amlmmc_erase_in_card(int argc, char *const argv[])
401{
402 int dev = 0;
403 u64 cnt = 0, blk = 0, n = 0;
404 /*sz_byte =0;*/
405 char *name = NULL;
406 u64 offset_addr = 0, size = 0;
407 struct mmc *mmc;
408 int tmp_shift;
409
410 name = argv[2];
411 dev = find_dev_num_by_partition_name (name);
412 if (dev < 0) {
413 printf("Cannot find dev.\n");
414 return 1;
415 }
416 offset_addr = simple_strtoull(argv[3], NULL, 16);
417 size = simple_strtoull(argv[4], NULL, 16);
418 mmc = find_mmc_device(dev);
419 if (!mmc) {
420 printf("[%s] no mmc devices available\n", __func__);
421 return 1;
422 }
423
424 tmp_shift = ffs(mmc->read_bl_len) -1;
425 if (tmp_shift < 0) {
426 printf("bad shift.\n");
427 return 1;
428 }
429 cnt = size >> tmp_shift;
430 blk = offset_addr >> tmp_shift;
431 /* sz_byte = size - (cnt<<tmp_shift); */
432
433
434 mmc = find_mmc_device(dev);
435 if (!mmc) {
436 printf("[%s] no mmc devices available\n", __func__);
437 return 1;
438 }
439
440 printf("MMC erase: dev # %d, start_erase_address(in block) # %#llx,\
441 several blocks # %lld will be erased ...\n ",
442 dev, blk, cnt);
443
444 mmc_init(mmc);
445
446 if (cnt != 0)
447 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
448
449 printf("dev # %d, %s, several blocks erased %s\n",
450 dev, argv[2], (n == 0) ? "OK" : "ERROR");
451
452 return (n == 0) ? 0 : 1;
453}
454
455static int amlmmc_erase_in_part(int argc, char *const argv[])
456{
457 int dev = 0;
458 u64 cnt = 0, blk = 0, n = 0, sz_byte =0;
459 char *name = NULL;
460 u64 offset_addr = 0, size = 0;
461 struct mmc *mmc;
462 struct partitions *part_info;
463
464 name = argv[2];
465 dev = find_dev_num_by_partition_name(name);
466 if (dev < 0) {
467 printf("Cannot find dev.\n");
468 return 1;
469 }
470 offset_addr = simple_strtoull(argv[3], NULL, 16);
471 size = simple_strtoull(argv[4], NULL, 16);
472 part_info = find_mmc_partition_by_name(name);
473 if (part_info == NULL) {
474 printf("Bad part_info\n");
475 return 1;
476 }
477
478 mmc = find_mmc_device(dev);
479 if (!mmc)
480 return 1;
481
482 if (offset_addr >= part_info->size) {
483 printf("Start address out #%s# partition'address region,(addr_byte < 0x%llx)\n",
484 name, part_info->size);
485 return 1;
486 }
487 if ((offset_addr+size) > part_info->size) {
488 printf("End address exceeds #%s# partition,(offset = 0x%llx,size = 0x%llx)\n",
489 name, part_info->offset,part_info->size);
490 return 1;
491 }
492
493 get_off_size(mmc, name, offset_addr, size, &blk, &cnt, &sz_byte);
494 printf("MMC erase: dev # %d, start_erase_address(in block) # %#llx,\
495 several blocks # %lld will be erased ...\n ",
496 dev, blk, cnt);
497
498 mmc_init(mmc);
499
500 if (cnt != 0)
501 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
502
503 printf("dev # %d, %s, several blocks erased %s\n",
504 dev, argv[2], (n == 0) ? "OK" : "ERROR");
505 return (n == 0) ? 0 : 1;
506}
507
508static int amlmmc_erase_by_add(int argc, char *const argv[])
509{
510 int ret = 0;
511
512 if (argc != 5)
513 return CMD_RET_USAGE;
514
515 if (isdigit(argv[2][0]))
516 ret = amlmmc_erase_in_dev(argc, argv);
517 else if (strcmp(argv[2], "card") == 0)
518 ret = amlmmc_erase_in_card(argc, argv);
519 else if (isstring(argv[2]))
520 ret = amlmmc_erase_in_part(argc, argv);
521
522 return ret;
523}
524
525static int amlmmc_erase_non_loader(int argc, char *const argv[])
526{
527 int dev;
528 u32 n = 0;
529 int blk_shift;
530 u64 blk = 0, start_blk = 0;
531 struct partitions *part_info;
532 struct mmc *mmc;
533
534 dev = 1;
535 mmc = find_mmc_device(dev);
536 if (!mmc) {
537 printf("[%s] no mmc devices available\n", __func__);
538 return 1;
539 }
540
541 mmc_init(mmc);
542
543 blk_shift = ffs(mmc->read_bl_len) -1;
544 if (blk_shift < 0) {
545 printf("bad shift.\n");
546 return 1;
547 }
548 part_info = find_mmc_partition_by_name(MMC_BOOT_NAME);
549
550 if (part_info == NULL) {
551 start_blk = 0;
552 printf("no uboot partition for eMMC boot, just erase from 0\n");
553 }
554 else
555 start_blk = (part_info->offset + part_info->size) >> blk_shift;
556
557 if (emmckey_is_protected(mmc)) {
558 part_info = find_mmc_partition_by_name(MMC_RESERVED_NAME);
559 if (part_info == NULL) {
560 return 1;
561 }
562 blk = part_info->offset;
563 // it means: there should be other partitions before reserve-partition.
564 if (blk > 0)
565 blk -= PARTITION_RESERVED;
566 blk >>= blk_shift;
567 blk -= start_blk;
568 // (1) erase all the area before reserve-partition
569 if (blk > 0)
570 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, blk);
571 if (n == 0) { // not error
572 // (2) erase all the area after reserve-partition
573 start_blk = (part_info->offset + part_info->size + PARTITION_RESERVED)
574 >> blk_shift;
575 u64 erase_cnt = (mmc->capacity >> blk_shift) - start_blk;
576 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, erase_cnt);
577 }
578 } else {
579 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, 0); // erase the whole card
580 }
581 return (n == 0) ? 0 : 1;
582}
583
584static int amlmmc_erase_single_part(int argc, char *const argv[])
585{
586 char *name = NULL;
587 int dev;
588 u32 n = 0;
589 int blk_shift;
590 u64 cnt = 0, blk = 0;
591 struct partitions *part_info;
592 struct mmc *mmc;
593 name = argv[2];
594 dev = find_dev_num_by_partition_name(name);
595 if (dev < 0) {
596 printf("Cannot find dev.\n");
597 return 1;
598 }
599 mmc = find_mmc_device(dev);
600
601 if (!mmc)
602 return 1;
603
604 mmc_init(mmc);
605
606 blk_shift = ffs(mmc->read_bl_len) -1;
607 if (blk_shift < 0) {
608 printf("bad shift.\n");
609 return 1;
610 }
611 if (emmckey_is_protected(mmc)
612 && (strncmp(name, MMC_RESERVED_NAME, sizeof(MMC_RESERVED_NAME)) == 0x00)) {
613 printf("\"%s-partition\" is been protecting and should no be erased!\n",
614 MMC_RESERVED_NAME);
615 return 1;
616 }
617
618 part_info = find_mmc_partition_by_name(name);
619 if (part_info == NULL) {
620 return 1;
621 }
622
623 blk = part_info->offset >> blk_shift;
624 if (emmc_cur_partition && !strncmp(name, "bootloader", strlen("bootloader")))
625 cnt = 0;
626 else
627 cnt = part_info->size >> blk_shift;
628 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
629
Ruixuan.li6a7e07c2024-01-11 20:10:29 +0800630 return (n == cnt) ? 0 : 1;
Bo Lv72d0e902023-01-02 14:27:34 +0000631}
632
633static int amlmmc_erase_whole(int argc, char *const argv[])
634{
635 char *name = NULL;
636 int dev;
637 u32 n = 0;
638 int blk_shift;
639 //u64 cnt = 0,
640 u64 blk = 0, start_blk = 0;
641 struct partitions *part_info;
642 struct mmc *mmc;
643 int map;
644
645 name = "logo";
646 dev = find_dev_num_by_partition_name(name);
647 if (dev < 0) {
648 printf("Cannot find dev.\n");
649 return 1;
650 }
651 mmc = find_mmc_device(dev);
652 if (!mmc)
653 return 1;
654 mmc_init(mmc);
655 blk_shift = ffs(mmc->read_bl_len) -1;
656 if (blk_shift < 0) {
657 printf("bad shift.\n");
658 return 1;
659 }
660 start_blk = 0;
661
662 if (emmckey_is_protected(mmc)) {
663 part_info = find_mmc_partition_by_name(MMC_RESERVED_NAME);
664 if (part_info == NULL) {
665 return 1;
666 }
667 blk = part_info->offset;
668 // it means: there should be other partitions before reserve-partition.
669 if (blk > 0)
670 blk -= PARTITION_RESERVED;
671 blk >>= blk_shift;
672 blk -= start_blk;
673 // (1) erase all the area before reserve-partition
674 if (blk > 0)
675 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, blk);
676 if (n == 0) { // not error
677 // (2) erase all the area after reserve-partition
678 start_blk = (part_info->offset + part_info->size + PARTITION_RESERVED)
679 >> blk_shift;
680 u64 erase_cnt = (mmc->capacity >> blk_shift) - start_blk;
681 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, erase_cnt);
682 }
683 } else {
684 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, 0); // erase the whole card
685 }
686 map = AML_BL_BOOT;
687 if (n == 0)
688 n = amlmmc_erase_bootloader(dev, map);
689 if (n)
690 printf("erase bootloader in boot partition failed\n");
691 return (n == 0) ? 0 : 1;
692}
693
694static int amlmmc_erase_non_cache(int arc, char *const argv[])
695{
696 char *name = NULL;
697 int dev;
698 u32 n = 0;
699 int blk_shift;
700 u64 blk = 0, start_blk = 0;
701 struct partitions *part_info;
702 struct mmc *mmc;
703 int map;
704
705 name = "logo";
706 dev = find_dev_num_by_partition_name(name);
707 if (dev < 0) {
708 printf("Cannot find dev.\n");
709 return 1;
710 }
711 mmc = find_mmc_device(dev);
712 if (!mmc)
713 return 1;
714 mmc_init(mmc);
715 blk_shift = ffs(mmc->read_bl_len) -1;
716 if (blk_shift < 0) {
717 printf("bad shift.\n");
718 return 1;
719 }
720 if (emmckey_is_protected(mmc)) {
721 part_info = find_mmc_partition_by_name(MMC_RESERVED_NAME);
722 if (part_info == NULL) {
723 return 1;
724 }
725
726 blk = part_info->offset;
727 // it means: there should be other partitions before reserve-partition.
728 if (blk > 0) {
729 blk -= PARTITION_RESERVED;
730 }
731 blk >>= blk_shift;
732 blk -= start_blk;
733 // (1) erase all the area before reserve-partition
734 if (blk > 0) {
735 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, blk);
736 // printf("(1) erase blk: 0 --> %llx %s\n", blk, (n == 0) ? "OK" : "ERROR");
737 }
738 if (n == 0) { // not error
739 // (2) erase all the area after reserve-partition
740 part_info = find_mmc_partition_by_name(MMC_CACHE_NAME);
741 if (part_info == NULL) {
742 return 1;
743 }
744 start_blk = (part_info->offset + part_info->size + PARTITION_RESERVED)
745 >> blk_shift;
746 u64 erase_cnt = (mmc->capacity >> blk_shift) - start_blk;
747 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, erase_cnt);
748 }
749 } else {
750 n = blk_derase(mmc_get_blk_desc(mmc), start_blk, 0); // erase the whole card
751 }
752 map = AML_BL_BOOT;
753 if (n == 0) {
754 n = amlmmc_erase_bootloader(dev, map);
755 if (n)
756 printf("erase bootloader in boot partition failed\n");
757 }
758 return (n == 0) ? 0 : 1;
759}
760
761static int amlmmc_erase_dev(int argc, char *const argv[])
762{
763 return amlmmc_erase_whole(argc, argv);
764}
765
766static int amlmmc_erase_allbootloader(int argc, char*const argv[])
767{
768 int map;
769 int rc;
Bo Lv72d0e902023-01-02 14:27:34 +0000770 map = AML_BL_ALL;
771
Ruixuan.li6a7e07c2024-01-11 20:10:29 +0800772 rc = amlmmc_erase_bootloader(STORAGE_EMMC, map);
Bo Lv72d0e902023-01-02 14:27:34 +0000773 return rc;
774}
775
776static int amlmmc_erase_by_part(int argc, char *const argv[])
777{
778 int ret = CMD_RET_USAGE;
779
780 if (argc != 3)
781 return ret;
782
783 if (isdigit(argv[2][0]))
784 ret = amlmmc_erase_dev(argc, argv);
785 else if (strcmp(argv[2], "whole") == 0)
786 ret = amlmmc_erase_whole(argc, argv);
787 else if (strcmp(argv[2], "non_cache") == 0)
788 ret = amlmmc_erase_non_cache(argc, argv);
789 else if (strcmp(argv[2], "non_loader") == 0)
790 ret = amlmmc_erase_non_loader(argc, argv);
791 else if (strcmp(argv[2], "allbootloader") == 0)
792 ret = amlmmc_erase_allbootloader(argc, argv);
793 else
794 ret = amlmmc_erase_single_part(argc, argv);
795 return ret;
796}
797
798static int do_amlmmc_erase(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
799{
800 int ret = CMD_RET_USAGE;
801
802 if (argc == 3)
803 ret = amlmmc_erase_by_part(argc, argv);
804 else if (argc == 5)
805 ret = amlmmc_erase_by_add(argc, argv);
806
807 return ret;
808}
809
810static int amlmmc_write_in_part(int argc, char *const argv[])
811{
812 int dev;
813 void *addr = NULL;
814 u64 cnt = 0, n = 0, blk = 0, sz_byte = 0;
815 char *name = NULL;
816 u64 offset = 0, size = 0;
817 cpu_id_t cpu_id = get_cpu_id();
818 struct mmc *mmc;
819
820 name = argv[2];
821 if (strcmp(name, "bootloader") == 0)
822 dev = CONFIG_SYS_MMC_BOOT_DEV;
823 else
824 dev = find_dev_num_by_partition_name (name);
825 addr = (void *)simple_strtoul(argv[3], NULL, 16);
826 offset = simple_strtoull(argv[4], NULL, 16);
827 size = simple_strtoull(argv[5], NULL, 16);
828 if (dev < 0) {
829 printf("Cannot find dev.\n");
830 return 1;
831 }
832 mmc = find_mmc_device(dev);
833 if (!mmc)
834 return 1;
835
836 if (strcmp(name, "bootloader") == 0) {
837 cnt = UBOOT_SIZE;
838 if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) {
839 blk = GXL_START_BLK;
840 cnt -= GXL_START_BLK;
841 }
842 else
843 blk = GXB_START_BLK;
844 } else
845 get_off_size(mmc, name, offset, size, &blk, &cnt, &sz_byte);
846
847 mmc_init(mmc);
848 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
849 //write sz_byte bytes
850 if ((n == cnt) && (sz_byte != 0)) {
851 // printf("sz_byte=%#llx bytes\n",sz_byte);
852 void *addr_tmp = malloc(mmc->write_bl_len);
853 void *addr_byte = (void*)(addr+cnt*(mmc->write_bl_len));
854 ulong start_blk = blk+cnt;
855
856 if (addr_tmp == NULL) {
857 printf("mmc write: malloc fail\n");
858 return 1;
859 }
860
861 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
862 free(addr_tmp);
863 printf("mmc read 1 block fail\n");
864 return 1;
865 }
866
867 memcpy(addr_tmp, addr_byte, sz_byte);
868 if (blk_dwrite(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // write 1 block
869 free(addr_tmp);
870 printf("mmc write 1 block fail\n");
871 return 1;
872 }
873 free(addr_tmp);
874 }
875 //printf("%#llx blocks , %#llx bytes written: %s\n", n, sz_byte, (n==cnt) ? "OK" : "ERROR");
876 return (n == cnt) ? 0 : 1;
877}
878
879static int amlmmc_write_in_card(int argc, char *const argv[])
880{
881 int dev;
882 void *addr = NULL;
883 u64 cnt = 0, n = 0, blk = 0, sz_byte = 0;
884 char *name = NULL;
885 u64 offset = 0, size = 0;
886 struct mmc *mmc;
887
888 name = argv[2];
889 dev = find_dev_num_by_partition_name (name);
890 addr = (void *)simple_strtoul(argv[3], NULL, 16);
891 offset = simple_strtoull(argv[4], NULL, 16);
892 size = simple_strtoull(argv[5], NULL, 16);
893 if (dev < 0) {
894 printf("Cannot find dev.\n");
895 return 1;
896 }
897 mmc = find_mmc_device(dev);
898 if (!mmc)
899 return 1;
900
901 int blk_shift = ffs( mmc->read_bl_len) -1;
902 if (blk_shift < 0) {
903 printf("bad shift.\n");
904 return 1;
905 }
906 cnt = size >> blk_shift;
907 blk = offset >> blk_shift;
908 sz_byte = size - (cnt<<blk_shift);
909 mmc_init(mmc);
910
911 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
912
913 //write sz_byte bytes
914 if ((n == cnt) && (sz_byte != 0)) {
915 // printf("sz_byte=%#llx bytes\n",sz_byte);
916 void *addr_tmp = malloc(mmc->write_bl_len);
917 void *addr_byte = (void*)(addr+cnt*(mmc->write_bl_len));
918 ulong start_blk = blk+cnt;
919
920 if (addr_tmp == NULL) {
921 printf("mmc write: malloc fail\n");
922 return 1;
923 }
924
925 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
926 free(addr_tmp);
927 printf("mmc read 1 block fail\n");
928 return 1;
929 }
930
931 memcpy(addr_tmp, addr_byte, sz_byte);
932 if (blk_dwrite(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // write 1 block
933 free(addr_tmp);
934 printf("mmc write 1 block fail\n");
935 return 1;
936 }
937 free(addr_tmp);
938 }
939 //printf("%#llx blocks , %#llx bytes written: %s\n", n, sz_byte, (n==cnt) ? "OK" : "ERROR");
940 return (n == cnt) ? 0 : 1;
941}
942
943static int amlmmc_write_in_dev(int argc, char *const argv[])
944{
945 int dev;
946 void *addr = NULL;
947 u64 cnt = 0, n = 0, blk = 0;
948 struct mmc *mmc;
949 dev = simple_strtoul(argv[2], NULL, 10);
950 addr = (void *)simple_strtoul(argv[3], NULL, 16);
951 blk = simple_strtoull(argv[4], NULL, 16);
952 cnt = simple_strtoull(argv[5], NULL, 16);
953 if (dev < 0) {
954 printf("Cannot find dev.\n");
955 return 1;
956 }
957 mmc = find_mmc_device(dev);
958 if (!mmc)
959 return 1;
960
961 //printf("MMC write: dev # %d, block # %#llx, count # %#llx ... ",
962 //dev, blk, cnt);
963
964 mmc_init(mmc);
965
966 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
967 return (n == cnt) ? 0 : 1;
968}
969
970static int do_amlmmc_write(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
971{
972 int ret = 0;
973 if (argc != 6)
974 return CMD_RET_USAGE;
975
976 if (isdigit(argv[2][0]))
977 ret = amlmmc_write_in_dev(argc, argv);
978 else if (strcmp(argv[2], "card") == 0)
979 ret = amlmmc_write_in_card(argc, argv);
980 else if (isstring(argv[2]))
981 ret = amlmmc_write_in_part(argc, argv);
982
983 return ret;
984}
985
986static int amlmmc_read_in_dev(int argc, char *const argv[])
987{
988 int dev;
989 void *addr = NULL;
990 u64 cnt =0, n = 0, blk = 0;
991 struct mmc *mmc;
992
993 dev = simple_strtoul(argv[2], NULL, 10);
994 addr = (void *)simple_strtoul(argv[3], NULL, 16);
995 blk = simple_strtoull(argv[4], NULL, 16);
996 cnt = simple_strtoull(argv[5], NULL, 16);
997
998 if (dev < 0) {
999 printf("Cannot find dev.\n");
1000 return 1;
1001 }
1002
1003 mmc = find_mmc_device(dev);
1004 if (!mmc)
1005 return 1;
1006 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
1007 return (n == cnt) ? 0 : 1;
1008}
1009
1010static int amlmmc_read_in_card(int argc, char *const argv[])
1011{
1012 int dev;
1013 void *addr = NULL;
1014 //u32 flag =0;
1015 u64 cnt =0, n = 0, blk = 0, sz_byte = 0;
1016 char *name = NULL;
1017 u64 offset = 0, size = 0;
1018 int blk_shift;
1019 struct mmc *mmc;
1020 void *addr_tmp;
1021 void *addr_byte;
1022 ulong start_blk;
1023
1024 name = argv[2];
1025 dev = find_dev_num_by_partition_name (name);
1026 addr = (void *)simple_strtoul(argv[3], NULL, 16);
1027 size = simple_strtoull(argv[5], NULL, 16);
1028 offset = simple_strtoull(argv[4], NULL, 16);
1029
1030 if (dev < 0) {
1031 printf("Cannot find dev.\n");
1032 return 1;
1033 }
1034
1035 mmc = find_mmc_device(dev);
1036 if (!mmc)
1037 return 1;
1038
1039 blk_shift = ffs( mmc->read_bl_len) - 1;
1040 if (blk_shift < 0) {
1041 printf("bad shift.\n");
1042 return 1;
1043 }
1044 cnt = size >> blk_shift;
1045 blk = offset >> blk_shift;
1046 sz_byte = size - (cnt<<blk_shift);
1047
1048 mmc_init(mmc);
1049 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
1050
1051 //read sz_byte bytes
1052 if ((n == cnt) && (sz_byte != 0)) {
1053 addr_tmp = malloc(mmc->read_bl_len);
1054 addr_byte = (void *)(addr+cnt*(mmc->read_bl_len));
1055 start_blk = blk+cnt;
1056 if (addr_tmp == NULL) {
1057 printf("mmc read: malloc fail\n");
1058 return 1;
1059 }
1060 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
1061 free(addr_tmp);
1062 printf("mmc read 1 block fail\n");
1063 return 1;
1064 }
1065 memcpy(addr_byte, addr_tmp, sz_byte);
1066 free(addr_tmp);
1067 }
1068 return (n == cnt) ? 0 : 1;
1069}
1070
1071static int amlmmc_read_in_part(int argc, char *const argv[])
1072{
1073 int dev;
1074 void *addr = NULL;
1075 u64 cnt = 0, n = 0, blk = 0, sz_byte = 0;
1076 char *name = NULL;
1077 u64 offset = 0, size = 0;
1078 struct mmc *mmc;
1079 void *addr_tmp;
1080 void *addr_byte;
1081 ulong start_blk;
1082
1083 name = argv[2];
1084 dev = find_dev_num_by_partition_name (name);
1085 addr = (void *)simple_strtoul(argv[3], NULL, 16);
1086 offset = simple_strtoull(argv[4], NULL, 16);
1087 size = simple_strtoull(argv[5], NULL, 16);
1088
1089 if (dev < 0) {
1090 printf("Cannot find dev.\n");
1091 return 1;
1092 }
1093
1094 mmc = find_mmc_device(dev);
1095 if (!mmc)
1096 return 1;
1097
1098 get_off_size(mmc, name, offset, size, &blk, &cnt, &sz_byte);
1099 mmc_init(mmc);
1100 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
1101
1102 //read sz_byte bytes
1103 if ((n == cnt) && (sz_byte != 0)) {
1104 /*printf("sz_byte=%#llx bytes\n",sz_byte);*/
1105 addr_tmp = malloc(mmc->read_bl_len);
1106 addr_byte = (void *)(addr+cnt*(mmc->read_bl_len));
1107 start_blk = blk+cnt;
1108
1109 if (addr_tmp == NULL) {
1110 printf("mmc read: malloc fail\n");
1111 return 1;
1112 }
1113
1114 if (blk_dread(mmc_get_blk_desc(mmc), start_blk, 1, addr_tmp) != 1) { // read 1 block
1115 free(addr_tmp);
1116 printf("mmc read 1 block fail\n");
1117 return 1;
1118 }
1119
1120 memcpy(addr_byte, addr_tmp, sz_byte);
1121 free(addr_tmp);
1122 }
1123 return (n == cnt) ? 0 : 1;
1124}
1125
1126static int do_amlmmc_read(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1127{
1128 int ret = 0;
1129 if (argc != 6)
1130 return CMD_RET_USAGE;
1131
1132 if (isdigit(argv[2][0]))
1133 ret = amlmmc_read_in_dev(argc, argv);
1134 else if (strcmp(argv[2], "card") == 0)
1135 ret = amlmmc_read_in_card(argc, argv);
1136 else if (isstring(argv[2]))
1137 ret = amlmmc_read_in_part(argc, argv);
1138
1139 return ret;
1140}
1141
1142static int do_amlmmc_env(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1143{
1144 printf("herh\n");
1145 env_relocate();
1146 return 0;
1147}
1148
1149static int do_amlmmc_list(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1150{
1151 print_mmc_devices('\n');
1152 return 0;
1153}
1154
1155static int do_amlmmc_size(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1156{
1157 char *name;
1158 uint64_t* addr = NULL;
1159 int dev;
1160 struct mmc *mmc = NULL;
1161
1162 if (argc != 4)
1163 return CMD_RET_USAGE;
1164
1165 name = argv[2];
1166 addr = (uint64_t *)simple_strtoul(argv[3], NULL, 16);
1167 if (!strcmp(name, "wholeDev")) {
1168 dev = CONFIG_SYS_MMC_BOOT_DEV;
1169 mmc = find_mmc_device(dev);
1170 if (!mmc) {
1171 puts("no mmc devices available\n");
1172 return 1;
1173 }
1174 mmc_init(mmc);
1175
1176 *addr = mmc->capacity >> 9; // unit: 512 bytes
1177 return 0;
1178 }
1179 return get_partition_size((unsigned char *)name, addr);
1180}
1181
1182static int amlmmc_get_ext_csd(int argc, char *const argv[])
1183{
1184 int ret= 0;
1185 u8 ext_csd[512] = {0};
1186 int dev, byte;
1187 struct mmc *mmc;
1188
1189 if (argc != 4)
1190 return CMD_RET_USAGE;
1191
1192 dev = simple_strtoul(argv[2], NULL, 10);
1193 byte = simple_strtoul(argv[3], NULL, 10);
1194 mmc = find_mmc_device(dev);
1195
1196 if (!mmc) {
1197 puts("no mmc devices available\n");
1198 return 1;
1199 }
1200 mmc_init(mmc);
1201 ret = mmc_get_ext_csd(mmc, ext_csd);
1202 printf("read EXT_CSD byte[%d] val[0x%x] %s\n",
1203 byte, ext_csd[byte], (ret == 0) ? "ok" : "fail");
1204 return ret;
1205}
1206
1207static int amlmmc_set_ext_csd(int argc, char *const argv[])
1208{
1209 int ret = 0;
1210 int dev, byte;
1211 struct mmc *mmc;
1212 int val;
1213
1214 if (argc != 5)
1215 return CMD_RET_USAGE;
1216
1217 dev = simple_strtoul(argv[2], NULL, 10);
1218 byte = simple_strtoul(argv[3], NULL, 10);
1219 val = simple_strtoul(argv[4], NULL, 16);
1220 if ((byte > 191) || (byte < 0)) {
1221 printf("byte is not able to write!\n");
1222 return 1;
1223 }
1224
1225 mmc = find_mmc_device(dev);
1226
1227 if (!mmc) {
1228 puts("no mmc devices available\n");
1229 return 1;
1230 }
1231
1232 mmc_init(mmc);
1233
1234 ret = mmc_set_ext_csd(mmc, byte, val);
1235 printf("write EXT_CSD byte[%d] val[0x%x] %s\n",
1236 byte, val, (ret == 0) ? "ok" : "fail");
1237 return ret;
1238}
1239
1240static int do_amlmmc_ext_csd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1241{
1242 int ret = CMD_RET_USAGE;
1243
1244 if (argc == 4)
1245 ret = amlmmc_get_ext_csd(argc,argv);
1246 else if (argc == 5)
1247 ret = amlmmc_set_ext_csd(argc,argv);
1248
1249 return ret;
1250}
1251
1252static int do_amlmmc_switch(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1253{
1254 int rc = 0;
1255 int dev;
1256 struct mmc *mmc;
1257
1258 if (argc != 4)
1259 return CMD_RET_USAGE;
1260
1261 dev = simple_strtoul(argv[2], NULL, 10);
1262 mmc = find_mmc_device(dev);
1263
1264 if (!mmc) {
1265 puts("no mmc devices available\n");
1266 return 1;
1267 }
1268
1269 mmc_init(mmc);
1270 printf("mmc switch to ");
1271
1272 if (strcmp(argv[3], "boot0") == 0) {
1273 rc = mmc_switch_part(mmc, 1);
1274 if (rc == 0) {
1275 emmc_cur_partition = 1;
1276 printf("boot0 success\n");
1277 } else {
1278 printf("boot0 failed\n");
1279 }
1280 }
1281 else if(strcmp(argv[3], "boot1") == 0) {
1282 rc = mmc_switch_part(mmc, 2);
1283 if (rc == 0) {
1284 emmc_cur_partition = 2;
1285 printf("boot1 success\n");
1286 } else {
1287 printf("boot1 failed\n");
1288 }
1289 }
1290 else if(strcmp(argv[3], "user") == 0) {
1291 rc = mmc_switch_part(mmc, 0);
1292 if (rc == 0) {
1293 emmc_cur_partition = 0;
1294 printf("user success\n");
1295 } else {
1296 printf("user failed\n");
1297 }
1298 }
1299#ifdef CONFIG_SUPPORT_EMMC_RPMB
1300 else if(strcmp(argv[3], "rpmb") == 0) {
1301 rc = mmc_switch_part(mmc, 3);
1302 if (rc == 0) {
1303 emmc_cur_partition = 3;
1304 printf("rpmb success\n");
1305 } else {
1306 printf("rpmb failed\n");
1307 }
1308 }
1309#endif
1310 else
1311 printf("%s failed\n", argv[3]);
1312 return rc;
1313}
1314
1315static int do_amlmmc_controller(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1316{
1317 /*int dev;
1318 struct mmc *mmc;
1319 struct aml_card_sd_info *aml_priv;
1320 struct sd_emmc_global_regs *sd_emmc_reg;
1321
1322 if (argc != 3)
1323 return CMD_RET_USAGE;
1324
1325 dev = simple_strtoul(argv[2], NULL, 10);
1326
1327 if (dev < 0) {
1328 printf("Cannot find dev.\n");
1329 return 1;
1330 }
1331
1332 mmc = find_mmc_device(dev);
1333
1334 if (!mmc)
1335 return 1;
1336
1337 aml_priv = mmc->priv;
1338 sd_emmc_reg = aml_priv->sd_emmc_reg;
1339
1340 printf("sd_emmc_reg->gclock = 0x%x\n", sd_emmc_reg->gclock);
1341 printf("sd_emmc_reg->gdelay = 0x%x\n", sd_emmc_reg->gdelay);
1342 printf("sd_emmc_reg->gadjust = 0x%x\n", sd_emmc_reg->gadjust);
1343 printf("sd_emmc_reg->gcalout = 0x%x\n", sd_emmc_reg->gcalout);
1344 if (!mmc->has_init) {
1345 printf("mmc dev %d has not been initialed\n", dev);
1346 return 1;
1347 }
1348 printf("sd_emmc_reg->gstart = 0x%x\n", sd_emmc_reg->gstart);
1349 printf("sd_emmc_reg->gcfg = 0x%x\n", sd_emmc_reg->gcfg);
1350 printf("sd_emmc_reg->gstatus = 0x%x\n", sd_emmc_reg->gstatus);
1351 printf("sd_emmc_reg->girq_en = 0x%x\n", sd_emmc_reg->girq_en);
1352 printf("sd_emmc_reg->gcmd_cfg = 0x%x\n", sd_emmc_reg->gcmd_cfg);
1353 printf("sd_emmc_reg->gcmd_arg = 0x%x\n", sd_emmc_reg->gcmd_arg);
1354 printf("sd_emmc_reg->gcmd_dat = 0x%x\n", sd_emmc_reg->gcmd_dat);
1355 printf("sd_emmc_reg->gcmd_rsp0 = 0x%x\n", sd_emmc_reg->gcmd_rsp0);
1356 printf("sd_emmc_reg->gcmd_rsp1 = 0x%x\n", sd_emmc_reg->gcmd_rsp1);
1357 printf("sd_emmc_reg->gcmd_rsp2 = 0x%x\n", sd_emmc_reg->gcmd_rsp2);
1358 printf("sd_emmc_reg->gcmd_rsp3 = 0x%x\n", sd_emmc_reg->gcmd_rsp3);*/
1359 return 0;
1360}
1361
1362static int do_amlmmc_response(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1363{
1364 /*int dev;
1365 struct mmc *mmc;
1366 struct aml_card_sd_info *aml_priv;
1367 struct sd_emmc_global_regs *sd_emmc_reg;
1368
1369 if (argc != 3)
1370 return CMD_RET_USAGE;
1371
1372 dev = simple_strtoul(argv[2], NULL, 10);
1373
1374 if (dev < 0) {
1375 printf("Cannot find dev.\n");
1376 return 1;
1377 }
1378
1379 mmc = find_mmc_device(dev);
1380
1381 if (!mmc)
1382 return 1;
1383 if (!mmc->has_init) {
1384 printf("mmc dev %d has not been initialed\n", dev);
1385 return 1;
1386 }
1387
1388 aml_priv = mmc->priv;
1389 sd_emmc_reg = aml_priv->sd_emmc_reg;
1390
1391 printf("last cmd = %d, response0 = 0x%x\n",
1392 (sd_emmc_reg->gcmd_cfg & 0x3f), sd_emmc_reg->gcmd_rsp0);*/
1393 return 0;
1394}
1395
1396static int do_amlmmc_status(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1397{
1398 int rc = 0;
1399 int dev;
1400 struct mmc *mmc;
1401
1402 if (argc != 3)
1403 return CMD_RET_USAGE;
1404
1405 dev = simple_strtoul(argv[2], NULL, 10);
1406
1407 if (dev < 0) {
1408 printf("Cannot find dev.\n");
1409 return 1;
1410 }
1411 mmc = find_mmc_device(dev);
1412
1413 if (!mmc)
1414 return 1;
1415 if (!mmc->has_init) {
1416 printf("mmc dev %d has not been initialed\n", dev);
1417 return 1;
1418 }
1419 rc = mmc_read_status(mmc, 1000);
1420 if (rc)
1421 return 1;
1422 else
1423 return 0;
1424}
1425
1426static int do_amlmmc_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1427{
1428 int dev;
1429 struct blk_desc *mmc_dev;
1430 struct mmc *mmc;
1431
1432 if (argc != 3)
1433 return CMD_RET_USAGE;
1434
1435 dev = simple_strtoul(argv[2], NULL, 10);
1436 mmc = find_mmc_device(dev);
1437
1438 if (!mmc) {
1439 puts("no mmc devices available\n");
1440 return 1;
1441 }
1442 mmc_init(mmc);
1443 mmc_dev = mmc_get_blk_desc(mmc);
1444 if (mmc_dev != NULL &&
1445 mmc_dev->type != DEV_TYPE_UNKNOWN) {
1446 part_print(mmc_dev);
1447 return 0;
1448 }
1449 puts("get mmc type error!\n");
1450 return 1;
1451}
1452
1453static int do_amlmmc_rescan(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1454{
1455 int dev;
1456 struct mmc *mmc;
1457
1458 if (argc != 3)
1459 return CMD_RET_USAGE;
1460
1461 dev = simple_strtoul(argv[2], NULL, 10);
1462
1463 if (dev < 0) {
1464 printf("Cannot find dev.\n");
1465 return 1;
1466 }
1467
1468 mmc = find_mmc_device(dev);
1469
1470 if (!mmc)
1471 return 1;
1472 mmc->has_init =0;
1473 return mmc_init(mmc);
1474}
1475
1476#ifdef CONFIG_SECURITYKEY
1477static int do_amlmmc_key(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1478{
1479 struct mmc *mmc;
1480 int dev;
1481
1482 //char *name = "logo";
1483 dev = CONFIG_SYS_MMC_BOOT_DEV;
1484 mmc = find_mmc_device(dev);
1485 if (!mmc) {
1486 printf("device %d is invalid\n",dev);
1487 return 1;
1488 }
1489 //mmc->key_protect = 0;
1490#ifdef CONFIG_STORE_COMPATIBLE
1491 info_disprotect |= DISPROTECT_KEY; //disprotect
1492 printf("emmc disprotect key\n");
1493#endif
1494 return 0;
1495}
1496#endif
1497
1498static int set_write_prot(struct mmc *mmc, u64 start)
1499{
1500 struct mmc_cmd cmd;
1501 int err;
1502
1503 cmd.cmdidx = MMC_CMD_SET_WRITE_PROTECT;
1504 cmd.cmdarg = start;
1505 cmd.resp_type = MMC_RSP_R1b;
1506
1507 err = mmc_send_cmd(mmc, &cmd, NULL);
1508 if (err)
1509 goto err_out;
1510
1511 return 0;
1512
1513err_out:
1514 puts("Failed: mmc write protect failed\n");
1515 return err;
1516}
1517
1518static int set_us_wp_en(struct mmc *mmc, u8 *ext_csd, u8 wp_enable_type)
1519{
1520 u8 index = EXT_CSD_USER_WP;
1521 u8 user_wp = ext_csd[index];
1522 user_wp = user_wp & (~WP_ENABLE_MASK);
1523 user_wp = user_wp | wp_enable_type;
1524 int err = 0;
1525 err = mmc_set_ext_csd(mmc, index, user_wp);
1526 if (err)
1527 printf("Failed: set write protect enable failed\n");
1528 return err;
1529}
1530
1531static int mmc_set_us_perm_wp_dis(struct mmc *mmc, u8 *ext_csd)
1532{
1533 u8 usr_wp = ext_csd[EXT_CSD_USER_WP];
1534 u8 perm_disable_bit = US_PERM_WP_DIS_BIT;
1535
1536 int err;
1537 if (usr_wp & perm_disable_bit)
1538 return 0;
1539
1540 usr_wp = usr_wp | perm_disable_bit;
1541 err = mmc_set_ext_csd(mmc, EXT_CSD_USER_WP, usr_wp);
1542 if (err) {
1543 printf("Failed: set permanent write protect disable failed\n");
1544 return 1;
1545 }
1546 return 0;
1547}
1548
1549static int mmc_is_us_pwr_wp_dis(u8 user_wp)
1550{
1551 return user_wp & US_PWR_WP_DIS_BIT;
1552}
1553
1554static int mmc_is_us_perm_wp_dis(u8 user_wp)
1555{
1556 return user_wp & US_PERM_WP_DIS_BIT;
1557}
1558
1559static int check_wp_type(u8 *addr, u8 wp_type, u64 set_protect_cnt)
1560{
1561 u8 type_mask = WP_TYPE_MASK;
1562 u64 cnt = set_protect_cnt;
1563 u8 times = 0;
1564 u8 index = 7;
1565 u8 cur_group_wp_type = addr[index];
1566
1567 while (cnt != 0) {
1568 if (wp_type != ((type_mask)&(cur_group_wp_type))) {
1569 return 1;
1570 }
1571 if (times == 3) {
1572 times = 0;
1573 index--;
1574 cur_group_wp_type = addr[index];
1575 }
1576 else {
1577 cur_group_wp_type = cur_group_wp_type >> 2;
1578 times++;
1579 }
1580 cnt--;
1581 }
1582 return 0;
1583}
1584
1585static int set_register_to_temporary(struct mmc *mmc, u8 *ext_csd)
1586{
1587 int err;
1588 u8 wp_enable_type = WP_TEMPORARY_EN_BIT;
1589 err = set_us_wp_en(mmc, ext_csd, wp_enable_type);
1590 if (err)
1591 printf("Failed: set temporary write protect failed\n");
1592 return err;
1593}
1594
1595static int set_register_to_pwr(struct mmc *mmc, u8 *ext_csd)
1596{
1597 int err;
1598 u8 user_wp = ext_csd[EXT_CSD_USER_WP];
1599 u8 wp_enable_type = WP_POWER_ON_EN_BIT;
1600 if (mmc_is_us_pwr_wp_dis(user_wp)) {
1601 printf("Failed: power on protection had been disabled\n");
1602 return 1;
1603 }
1604
1605 err = mmc_set_us_perm_wp_dis(mmc, ext_csd);
1606 if (err) {
1607 printf("Failed: set permanent protection disable failed\n");
1608 return 1;
1609 }
1610
1611 err = set_us_wp_en(mmc, ext_csd, wp_enable_type);
1612 if (err) {
1613 printf("Failed: set power on write protect enable failed\n");
1614 return 1;
1615 }
1616 return 0;
1617}
1618
1619static int set_register_to_perm(struct mmc *mmc, u8 *ext_csd)
1620{
1621 int err;
1622 u8 wp_enable_type = WP_PERM_EN_BIT;
1623 u8 user_wp = ext_csd[EXT_CSD_USER_WP];
1624
1625 if (mmc_is_us_perm_wp_dis(user_wp)) {
1626 printf("Failed: Permanent protection had been disabled\n");
1627 return 1;
1628 }
1629
1630 err = set_us_wp_en(mmc, ext_csd, wp_enable_type);
1631 if (err) {
1632 printf("Failed: set permanent write protect enable failed\n");
1633 return 1;
1634 }
1635 return 0;
1636}
1637
1638static int set_wp_register(struct mmc *mmc, u8 *ext_csd, u8 wp_type)
1639{
1640 int ret = 1;
1641 if (wp_type == WP_POWER_ON_TYPE)
1642 ret = set_register_to_pwr(mmc, ext_csd);
1643 else if (wp_type == WP_PERMANENT_TYPE)
1644 ret = set_register_to_perm(mmc, ext_csd);
1645 else if (wp_type == WP_TEMPORARY_TYPE)
1646 ret = set_register_to_temporary(mmc, ext_csd);
1647 return ret;
1648}
1649
1650static u64 write_protect_group_size(struct mmc *mmc, u8 *ext_csd)
1651{
1652 int erase_group_def = ext_csd[EXT_CSD_ERASE_GROUP_DEF];
1653 u64 write_protect_group_size;
1654 u64 wp_grp_size = mmc->csd[2] & WP_GRP_SIZE_MASK;
1655 u64 hc_wp_grp_size = ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
1656
1657 if (erase_group_def == 0)
1658 write_protect_group_size = (wp_grp_size + 1) * mmc->erase_grp_size;
1659 else
1660 write_protect_group_size = hc_wp_grp_size * mmc->erase_grp_size;
1661
1662 return write_protect_group_size;
1663}
1664
1665int is_write_protect_valid(u8 *ext_csd)
1666{
1667 u8 class_6_ctrl = ext_csd[EXT_CSD_CLASS_6_CTRL];
1668 if (class_6_ctrl == 0)
1669 return 1;
1670 return 0;
1671}
1672
1673static int compute_write_protect_range(struct mmc *mmc, char *name,
1674 u8 *ext_csd, u64 *wp_grp_size_addr, u64 *start_addr, u64 *end)
1675{
1676 int blk_shift;
1677 struct partitions *part_info;
1678 u64 cnt;
1679 u64 start = *start_addr;
1680 u64 align_start = *start_addr;
1681 u64 wp_grp_size = 0;
1682 u64 group_num;
1683 u64 partition_end;
1684
1685 wp_grp_size = write_protect_group_size(mmc, ext_csd);
1686 if (wp_grp_size == 0) {
1687 printf("bad wp_grp_size.\n");
1688 return 1;
1689 }
1690
1691 blk_shift = ffs(mmc->read_bl_len) -1;
1692 if (blk_shift < 0) {
1693 printf("bad shift.\n");
1694 return 1;
1695 }
1696
1697 part_info = find_mmc_partition_by_name(name);
1698 if (part_info == NULL)
1699 return 1;
1700
1701 start = part_info->offset >> blk_shift;
1702 printf("start:%d wp_grp_size:%d",(int)start,(int)wp_grp_size);
1703 if ((start % wp_grp_size)) {
1704 align_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
1705 printf("Caution! The partition start address isn't' aligned"
1706 "to group size\n"
1707 "the start address is change from 0x%llx to 0x%llx\n",
1708 start, align_start);
1709 } else {
1710 align_start = start;
1711 }
1712 if (emmc_cur_partition && !strncmp(name, "bootloader", strlen("bootloader")))
1713 cnt =0;
1714 else
1715 cnt = part_info->size >> blk_shift;
1716 if (cnt < wp_grp_size) {
1717 printf("Caution: The partition size is 0x%llx sector smaller than "
1718 "the group size 0x%llx sector, \n"
1719 "so the partition can't be protect\n", cnt, wp_grp_size);
1720 return 1;
1721 }
1722
1723 *start_addr = align_start;
1724 *wp_grp_size_addr = wp_grp_size;
1725 partition_end = start + cnt - 1;
1726 group_num = (cnt - (align_start - start)) / wp_grp_size;
1727 *end = align_start + group_num * wp_grp_size - 1;
1728
1729 if (partition_end != *end) {
1730 printf("Caution! The boundary of partition isn't aligned with write "
1731 "protected group,\n"
1732 "so the write protected boundary of the "
1733 "partition is 0x%llx, rather than 0x%llx\n",
1734 *end, partition_end);
1735 }
1736
1737 printf("write_protect group size is 0x%llx sector\n", wp_grp_size);
1738 printf("The %s partition write protect group number is %lld\n", name, group_num);
1739#ifdef WP_DEBUG
1740 printf("the start address is 0x%llx, group size is 0x%llx, end is 0x%llx\n",
1741 *start_addr, *wp_grp_size_addr, *end);
1742#endif
1743 return 0;
1744}
1745
1746static int send_wp_prot_type(struct mmc *mmc, void *dst, u64 blk)
1747{
1748 struct mmc_cmd cmd;
1749 int err;
1750 struct mmc_data data;
1751
1752 cmd.cmdidx = MMC_CMD_SEND_WRITE_PROT_TYPE;
1753 cmd.cmdarg = blk;
1754 cmd.resp_type = MMC_RSP_R1;
1755
1756 data.dest = (char* )dst;
1757 data.blocks = 1;
1758 data.blocksize = 8;
1759 data.flags = MMC_DATA_READ;
1760
1761 err = mmc_send_cmd(mmc, &cmd, &data);
1762 if (err)
1763 goto err_out;
1764
1765 return 0;
1766
1767err_out:
1768 puts("Failed: mmc send write protect type failed\n");
1769 return err;
1770}
1771
1772static int is_wp_set_failed(struct mmc *mmc, u8 wp_type, u64 start, u64 group_cnt)
1773{
1774 u8 *addr = NULL;
1775 u8 err = 0;
1776
1777 addr = malloc(sizeof(u64));
1778 if (addr == NULL) {
1779 printf("Failed: malloc failed\n");
1780 return 1;
1781 }
1782
1783 err = send_wp_prot_type(mmc, addr, start);
1784 if (err)
1785 goto err_out;
1786
1787#ifdef WP_DEBUG
1788 int i;
1789 for (i = 0; i < 8; i++)
1790 printf("write_protect status is %x\n", ((u8 *)addr)[i]);
1791#endif
1792 if (check_wp_type(addr, wp_type, group_cnt)) {
1793 printf("Failed: Write Protection set failed\n");
1794 goto err_out;
1795 }
1796 return 0;
1797
1798err_out:
1799 free(addr);
1800 return 1;
1801}
1802
1803static int send_part_wp_type(struct mmc *mmc, char *name)
1804{
1805 int err = 0;
1806 u8 ext_csd[512] = {0};
1807 u64 wp_grp_size, start = 0, part_end;
1808 u64 group_start;
1809 void *addr = NULL;
1810 int i;
1811 int ret;
1812
1813 ret = mmc_get_ext_csd(mmc, ext_csd);
1814 if (ret) {
1815 printf("Failed: get ext_csd failed\n");
1816 return 1;
1817 }
1818
1819 if (!is_write_protect_valid(ext_csd)) {
1820 printf("Failed: CLASS_6_CTRL isn't '0' "
1821 "write protect process is invalid\n");
1822 return 1;
1823 }
1824
1825 addr = (char* )malloc(sizeof(u64));
1826 if (addr == NULL) {
1827 printf("Failed: malloc failed\n");
1828 return 1;
1829 }
1830
1831 err = compute_write_protect_range(mmc, name, ext_csd,
1832 &wp_grp_size, &start, &part_end);
1833 if (err) {
1834 free(addr);
1835 return 1;
1836 }
1837
1838 group_start = start;
1839
1840 while ((group_start + wp_grp_size - 1) <= part_end) {
1841 err = send_wp_prot_type(mmc, addr, group_start);
1842 if (err) {
1843 free(addr);
1844 return 1;
1845 }
1846 printf("The write protect type for the 32 groups after 0x%llx is: \n0x",
1847 group_start);
1848 for (i = 0; i < 8; i++)
1849 printf("%02x", ((u8*)addr)[i]);
1850 printf("\n");
1851 group_start += 32 * wp_grp_size;
1852 }
1853
1854 free(addr);
1855 return 0;
1856}
1857
1858static int send_add_wp_type(struct mmc *mmc, u64 start, u64 cnt)
1859{
1860 u8 ext_csd[512] = {0};
1861 u64 wp_grp_size = 0;
1862 u64 part_end = 0;
1863 u64 group_start;
1864 u64 mmc_boundary;
1865 int blk_shift;
1866 void *addr = NULL;
1867 int i;
1868 int ret;
1869
1870 ret = mmc_get_ext_csd(mmc, ext_csd);
1871 if (ret) {
1872 printf("Failed: get ext_csd failed\n");
1873 return 1;
1874 }
1875
1876 if (!is_write_protect_valid(ext_csd)) {
1877 printf("Failed: CLASS_6_CTRL isn't '0' "
1878 "write protect process is invalid\n");
1879 return 1;
1880 }
1881
1882 addr = malloc(sizeof(u64));
1883 if (addr == NULL) {
1884 printf("Failed: malloc failed\n");
1885 return 1;
1886 }
1887
1888 wp_grp_size = write_protect_group_size(mmc, ext_csd);
1889
1890 if ((start % wp_grp_size)) {
1891 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
1892 printf("Caution! The partition start address isn't' aligned"
1893 "to group size\n"
1894 "the start address is change from 0x%llx to 0x%llx\n",
1895 start, group_start);
1896 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
1897 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
1898 cnt - 1, cnt);
1899 } else {
1900 group_start = start;
1901 part_end = group_start + cnt * wp_grp_size - 1;
1902 }
1903
1904 blk_shift = ffs(mmc->read_bl_len) - 1;
1905 if (blk_shift < 0) {
1906 printf("bad shift.\n");
1907 free(addr);
1908 return 1;
1909 }
1910 mmc_boundary = mmc->capacity>>blk_shift;
1911
1912 if ((part_end + 1) > mmc_boundary) {
1913 printf("Error: the operation cross the boundary of mmc\n");
1914 free(addr);
1915 return 1;
1916 }
1917
1918 while ((group_start + wp_grp_size - 1) <= part_end) {
1919 ret = send_wp_prot_type(mmc, addr, group_start);
1920 if (ret) {
1921 free(addr);
1922 return 1;
1923 }
1924 printf("The write protect type for the 32 groups after 0x%llx is: \n0x",
1925 group_start);
1926 for (i = 0; i < 8; i++)
1927 printf("%02x", ((u8*)addr)[i]);
1928 printf("\n");
1929 group_start += 32 * wp_grp_size;
1930 }
1931
1932 free(addr);
1933 return 0;
1934}
1935
1936static int set_part_write_protect(struct mmc *mmc, u8 wp_type, char *name)
1937{
1938 int err = 0;
1939 u8 ext_csd[512] = {0};
1940 u8 group_num = 32;
1941 u64 wp_grp_size, start = 0, part_end;
1942 u64 group_start;
1943 u64 check_group_start;
1944 u64 set_protect_cnt = 0;
1945
1946 err = mmc_get_ext_csd(mmc, ext_csd);
1947 if (err) {
1948 printf("Failed: get ext_csd failed\n");
1949 return 1;
1950 }
1951
1952 if (!is_write_protect_valid(ext_csd)) {
1953 printf("Failed: CLASS_6_CTRL isn't '0' "
1954 "write protect process is invalid\n");
1955 return 1;
1956 }
1957
1958 err = compute_write_protect_range(mmc, name, ext_csd,
1959 &wp_grp_size, &start, &part_end);
1960 if (err)
1961 return 1;
1962
1963 group_start = start;
1964 err = set_wp_register(mmc, ext_csd, wp_type);
1965 if (err)
1966 return 1;
1967 while ((group_start + wp_grp_size - 1) <= part_end) {
1968 err = set_write_prot(mmc, group_start);
1969 if (err)
1970 return 1;
1971 group_start += wp_grp_size;
1972 set_protect_cnt++;
1973//check write protect type every 32 group
1974 if (set_protect_cnt % 32 == 0) {
1975 check_group_start = group_start - group_num * wp_grp_size;
1976 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
1977 if (err)
1978 return 1;
1979 }
1980 }
1981
1982 group_num = set_protect_cnt % 32;
1983 check_group_start = group_start - group_num * wp_grp_size;
1984
1985 if (group_num) {
1986 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
1987 if (err)
1988 return 1;
1989 }
1990
1991 return 0;
1992}
1993
1994static int set_add_write_protect(struct mmc *mmc, u8 wp_type, u64 start, u64 cnt)
1995{
1996 int err = 0;
1997 u8 ext_csd[512] = {0};
1998 int group_num = 32;
1999 u64 wp_grp_size, part_end;
2000 u64 group_start;
2001 u64 check_group_start;
2002 u64 set_protect_cnt = 0;
2003 u64 mmc_boundary = 0;
2004 int blk_shift;
2005 err = mmc_get_ext_csd(mmc, ext_csd);
2006
2007 if (err) {
2008 printf("Failed: get ext_csd failed\n");
2009 return 1;
2010 }
2011
2012 if (!is_write_protect_valid(ext_csd)) {
2013 printf("Failed: CLASS_6_CTRL isn't '0' "
2014 "write protect process is invalid\n");
2015 return 1;
2016 }
2017
2018 wp_grp_size = write_protect_group_size(mmc, ext_csd);
2019
2020 if ((start % wp_grp_size)) {
2021 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
2022 printf("Caution! The partition start address isn't' aligned"
2023 "to group size\n"
2024 "the start address is change from 0x%llx to 0x%llx\n",
2025 start, group_start);
2026 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
2027 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
2028 cnt - 1, cnt);
2029 } else {
2030 group_start = start;
2031 part_end = group_start + cnt * wp_grp_size - 1;
2032 }
2033
2034 blk_shift = ffs(mmc->read_bl_len) - 1;
2035 if (blk_shift < 0) {
2036 printf("bad shift.\n");
2037 return 1;
2038 }
2039 mmc_boundary = mmc->capacity>>blk_shift;
2040
2041 if ((part_end + 1) > mmc_boundary) {
2042 printf("Error: the operation cross the boundary of mmc\n");
2043 return 1;
2044 }
2045
2046 err = set_wp_register(mmc, ext_csd, wp_type);
2047 if (err)
2048 return 1;
2049
2050 while ((group_start + wp_grp_size - 1) <= part_end) {
2051 err = set_write_prot(mmc, group_start);
2052 if (err)
2053 return 1;
2054 group_start += wp_grp_size;
2055 set_protect_cnt++;
2056//check write protect type every 32 group
2057 if (set_protect_cnt % 32 == 0) {
2058 check_group_start = group_start - group_num * wp_grp_size;
2059 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2060 if (err)
2061 return 1;
2062 }
2063 }
2064
2065 group_num = set_protect_cnt % 32;
2066 check_group_start = group_start - group_num * wp_grp_size;
2067
2068 if (group_num) {
2069 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2070 if (err)
2071 return 1;
2072 }
2073
2074 return 0;
2075}
2076
2077static int do_amlmmc_write_protect(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2078{
2079 int ret = CMD_RET_USAGE;
2080 struct mmc *mmc;
2081 int dev = 1;
2082 char *name = NULL;
2083 char *wp_type_str = NULL;
2084 u8 write_protect_type;
2085 u64 start, cnt;
2086
2087 if (argc > 5 || argc < 4)
2088 return ret;
2089 if (argc == 4) {
2090 name = argv[2];
2091 wp_type_str = argv[3];
2092 dev = find_dev_num_by_partition_name(name);
2093 if (dev < 0) {
2094 printf("Error: Cannot find dev.\n");
2095 return CMD_RET_USAGE;
2096 }
2097 } else {
2098 start = simple_strtoull(argv[2], NULL, 16);
2099 cnt = simple_strtoull(argv[3], NULL, 0);
2100 wp_type_str = argv[4];
2101 }
2102
2103 mmc = find_mmc_device(dev);
2104 if (!mmc) {
2105 printf("[%s] no mmc devices available\n", __func__);
2106 return 1;
2107 }
2108
2109 if (IS_SD(mmc)) {
2110 mmc = find_mmc_device(~dev);
2111 if (mmc && IS_SD(mmc)) {
2112 printf("SD card can not be write protect\n");
2113 return 1;
2114 }
2115 }
2116
2117 mmc_init(mmc);
2118
2119 if (strcmp(wp_type_str, "temporary") == 0)
2120 write_protect_type = WP_TEMPORARY_TYPE;
2121 else if (strcmp(wp_type_str, "power_on") == 0 )
2122 write_protect_type = WP_POWER_ON_TYPE;
2123 else if (strcmp(wp_type_str, "permanent") == 0)
2124 write_protect_type = WP_PERMANENT_TYPE;
2125 else
2126 return ret;
2127
2128 if (argc == 4)
2129 ret = set_part_write_protect(mmc, write_protect_type, name);
2130 else
2131 ret = set_add_write_protect(mmc, write_protect_type, start, cnt);
2132
2133 return ret;
2134}
2135
2136static int do_amlmmc_boot_wp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2137{
2138 int ret = CMD_RET_USAGE;
2139 u8 ext_csd[512] = {0};
2140 char *name = NULL;
2141 char *type = NULL;
2142 struct mmc *mmc;
2143 int dev = 1;
2144 u8 boot_wp = 0;
2145 u8 boot_wp_status = 0;
2146 u8 perm_dis = 0;
2147 u8 perm_en = 0;
2148
2149 if (argc != 4)
2150 return ret;
2151
2152 name = argv[2];
2153 type = argv[3];
2154 mmc = find_mmc_device(dev);
2155 if (!mmc)
2156 return 1;
2157
2158 if (IS_SD(mmc)) {
2159 mmc = find_mmc_device(~dev);
2160 if (!mmc)
2161 return 1;
2162 if (IS_SD(mmc)) {
2163 printf("SD card can not be write protect\n");
2164 return 1;
2165 }
2166 }
2167
2168 mmc_init(mmc);
2169
2170 ret = mmc_get_ext_csd(mmc, ext_csd);
2171 if (ret)
2172 printf("get ext_csd failed\n");
2173
2174 boot_wp = ext_csd[EXT_CSD_BOOT_WP];
2175 boot_wp_status = ext_csd[EXT_CSD_BOOT_WP_STATUS];
2176
2177 perm_dis = boot_wp & 0x10;
2178 perm_en = boot_wp & 0x4;
2179
2180 if (!strcmp(type, "permanent") && perm_dis == 0) {
2181 if (!strcmp(name, "both"))
2182 boot_wp = 0x4;
2183 else if (!strcmp(name, "boot0"))
2184 boot_wp = 0x84;
2185 else if (!strcmp(name, "boot1"))
2186 boot_wp = 0x8c;
2187 else
2188 return -1;
2189 }
2190
2191 if (!strcmp(type, "poweron")) {
2192 if (!strcmp(name, "both") && perm_en == 0) {
2193 boot_wp |= 0x1;
2194 } else if (!strcmp(name, "boot0")) {
2195 boot_wp |= 0x81;
2196 boot_wp |= boot_wp_status & 0x8;
2197 } else if (!strcmp(name, "boot1")) {
2198 boot_wp |= 0x83;
2199 } else {
2200 return -1;
2201 }
2202 }
2203
2204 printf("boot_wp is 0x%x\n", boot_wp);
2205
2206 ret = mmc_set_ext_csd(mmc, EXT_CSD_BOOT_WP, boot_wp);
2207 if (ret) {
2208 printf("set ext_csd boot_wp field failed\n");
2209 return ret;
2210 }
2211
2212 return ret;
2213}
2214
2215static int do_amlmmc_boot_wp_status(cmd_tbl_t *cmdtp,
2216 int flag, int argc, char *const argv[])
2217{
2218 int ret = CMD_RET_USAGE;
2219 u8 ext_csd[512] = {0};
2220 u8 boot_wp_status;
2221 struct mmc *mmc;
2222 int dev = 1;
2223
2224 if (argc != 2)
2225 return ret;
2226
2227 mmc = find_mmc_device(dev);
2228 if (!mmc)
2229 return ret;
2230
2231 if (IS_SD(mmc)) {
2232 mmc = find_mmc_device(~dev);
2233 if (!mmc)
2234 return ret;
2235 if (IS_SD(mmc)) {
2236 printf("SD card can not be write protect\n");
2237 return 1;
2238 }
2239 }
2240
2241 mmc_init(mmc);
2242 ret = mmc_get_ext_csd(mmc, ext_csd);
2243 if (ret)
2244 printf("get ext_csd failed\n");
2245 boot_wp_status = ext_csd[EXT_CSD_BOOT_WP_STATUS];
2246
2247 if ((boot_wp_status & 0x3) == 0)
2248 printf("boot0 is not protected\n");
2249 else if ((boot_wp_status & 0x3) == 1)
2250 printf("boot0 is power on protected\n");
2251 else if ((boot_wp_status & 0x3) == 2)
2252 printf("boot0 is permanently protected\n");
2253
2254 if ((boot_wp_status & 0xc) == 0)
2255 printf("boot1 is not protected\n");
2256 else if ((boot_wp_status & 0xc) == 4)
2257 printf("boot1 is power on protected\n");
2258 else if ((boot_wp_status & 0xc) == 8)
2259 printf("boot1 is permanently protected\n");
2260
2261 return ret;
2262}
2263
2264static int clear_write_prot_per_group(struct mmc *mmc, u64 blk)
2265{
2266 struct mmc_cmd cmd;
2267 int err;
2268
2269 cmd.cmdidx = MMC_CMD_CLR_WRITE_PROT;
2270 cmd.cmdarg = blk;
2271 cmd.resp_type = MMC_RSP_R1b;
2272
2273 err = mmc_send_cmd(mmc, &cmd, NULL);
2274
2275 return err;
2276}
2277
2278static int set_part_clear_wp(struct mmc *mmc, char *name)
2279{
2280 int err = 0;
2281 u8 ext_csd[512] = {0};
2282 u8 group_num = 32;
2283 u64 wp_grp_size, start = 0, part_end;
2284 u64 group_start;
2285 u64 check_group_start;
2286 u64 set_protect_cnt = 0;
2287 u8 wp_type = WP_CLEAR_TYPE;
2288
2289 err = mmc_get_ext_csd(mmc, ext_csd);
2290 if (err) {
2291 printf("get ext_csd failed\n");
2292 return 1;
2293 }
2294
2295 if (!is_write_protect_valid(ext_csd)) {
2296 printf("CLASS_6_CTRL isn't '0' write protect process is invalid\n");
2297 return 1;
2298 }
2299
2300 err = compute_write_protect_range(mmc, name, ext_csd,
2301 &wp_grp_size, &start, &part_end);
2302 if (err)
2303 return 1;
2304
2305 group_start = start;
2306/*
2307 if (!is_wp_type_temporary(ext_csd)) {
2308 printf("The write protect can't be clear\n");
2309 return 1;
2310 }
2311*/
2312 while ((group_start + wp_grp_size - 1) <= part_end) {
2313 err = clear_write_prot_per_group(mmc, group_start);
2314 if (err) {
2315 printf("Error: The write protect can't be clear\n");
2316 return 1;
2317 }
2318 group_start += wp_grp_size;
2319 set_protect_cnt++;
2320//check write protect type every 32 group
2321 if (set_protect_cnt % 32 == 0) {
2322 check_group_start = group_start - group_num * wp_grp_size;
2323 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2324 if (err)
2325 return 1;
2326 }
2327 }
2328
2329 group_num = set_protect_cnt % 32;
2330 check_group_start = group_start - group_num * wp_grp_size;
2331
2332 if (group_num) {
2333 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2334 if (err)
2335 return 1;
2336 }
2337
2338 return 0;
2339}
2340
2341static int set_add_clear_wp(struct mmc *mmc, u64 start, u64 cnt)
2342{
2343 int err = 0;
2344 u8 ext_csd[512] = {0};
2345 u8 group_num = 32;
2346 u64 wp_grp_size, part_end;
2347 u64 group_start;
2348 u64 check_group_start;
2349 u64 set_protect_cnt = 0;
2350 u8 wp_type = WP_CLEAR_TYPE;
2351 int blk_shift;
2352 u64 mmc_boundary;
2353
2354 err = mmc_get_ext_csd(mmc, ext_csd);
2355 if (err) {
2356 printf("get ext_csd failed\n");
2357 return 1;
2358 }
2359
2360 if (!is_write_protect_valid(ext_csd)) {
2361 printf("CLASS_6_CTRL isn't '0' write protect process is invalid\n");
2362 return 1;
2363 }
2364
2365 wp_grp_size = write_protect_group_size(mmc, ext_csd);
2366
2367 if ((start % wp_grp_size)) {
2368 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
2369 printf("Caution! The partition start address isn't' aligned"
2370 "to group size\n"
2371 "the start address is change from 0x%llx to 0x%llx\n",
2372 start, group_start);
2373 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
2374 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
2375 cnt - 1, cnt);
2376 } else {
2377 group_start = start;
2378 part_end = group_start + cnt * wp_grp_size - 1;
2379 }
2380
2381 blk_shift = ffs(mmc->read_bl_len) - 1;
2382 if (blk_shift < 0) {
2383 printf("bad shift.\n");
2384 return 1;
2385 }
2386 mmc_boundary = mmc->capacity>>blk_shift;
2387
2388 if ((part_end + 1) > mmc_boundary) {
2389 printf("Error: the operation cross the boundary of mmc\n");
2390 return 1;
2391 }
2392
2393 while ((group_start + wp_grp_size - 1) <= part_end) {
2394 err = clear_write_prot_per_group(mmc, group_start);
2395 if (err) {
2396 printf("Error: The write protect can't be clear\n");
2397 return 1;
2398 }
2399 group_start += wp_grp_size;
2400 set_protect_cnt++;
2401//check write protect type every 32 group
2402 if (set_protect_cnt % 32 == 0) {
2403 check_group_start = group_start - group_num * wp_grp_size;
2404 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2405 if (err)
2406 return 1;
2407 }
2408 }
2409
2410 group_num = set_protect_cnt % 32;
2411 check_group_start = group_start - group_num * wp_grp_size;
2412
2413 if (group_num) {
2414 err = is_wp_set_failed(mmc, wp_type, check_group_start, group_num);
2415 if (err)
2416 return 1;
2417 }
2418
2419 return 0;
2420}
2421
2422static int do_amlmmc_clear_wp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
2423{
2424 int ret = CMD_RET_USAGE;
2425 struct mmc *mmc;
2426 int dev = 1;
2427 char *name = NULL;
2428 u64 start, cnt;
2429
2430 if (argc < 3 || argc > 4)
2431 return ret;
2432
2433 if (argc == 3) {
2434 name = argv[2];
2435 dev = find_dev_num_by_partition_name(name);
2436 if (dev < 0) {
2437 printf("Error: Cannot find dev.\n");
2438 return CMD_RET_USAGE;
2439 }
2440 } else {
2441 start = simple_strtoull(argv[2], NULL, 16);
2442 cnt = simple_strtoull(argv[3], NULL, 10);
2443 }
2444
2445 mmc = find_mmc_device(dev);
2446 if (!mmc)
2447 return 1;
2448
2449 if (IS_SD(mmc)) {
2450 mmc = find_mmc_device(~dev);
2451 if (mmc && IS_SD(mmc)) {
2452 printf("SD card can not be write protect\n");
2453 return 1;
2454 }
2455 }
2456
2457 mmc_init(mmc);
2458
2459 if (argc == 3)
2460 ret = set_part_clear_wp(mmc, name);
2461 else
2462 ret = set_add_clear_wp(mmc, start, cnt);
2463
2464 return ret;
2465}
2466
2467static int send_write_prot_status_group(struct mmc *mmc, u64 blk)
2468{
2469 struct mmc_cmd cmd;
2470 struct mmc_data data;
2471 int err;
2472 void *addr = NULL;
2473 int i = 0;
2474 addr = malloc(4*sizeof(u8));
2475
2476 if (addr == NULL) {
2477 printf("Failed: malloc failed\n");
2478 return 1;
2479 }
2480
2481 cmd.cmdidx = MMC_CMD_SEND_WRITE_PROT;
2482 cmd.cmdarg = blk;
2483 cmd.resp_type = MMC_RSP_R1;
2484
2485 data.dest = addr;
2486 data.blocks = 1;
2487 data.blocksize = 4;
2488 data.flags = MMC_DATA_READ;
2489
2490 err = mmc_send_cmd(mmc, &cmd, &data);
2491 if (err)
2492 goto err_out;
2493
2494 printf("The write protect type for the 32 groups after 0x%llx is:\n0x",
2495 blk);
2496 for (i = 0 ; i < 4; i++)
2497 printf("%02x", ((u8 *)addr)[i]);
2498 printf("\n");
2499
2500 free(addr);
2501 return 0;
2502err_out:
2503 free(addr);
2504 return 1;
2505}
2506
2507static int send_part_wp_status(struct mmc *mmc, char *name)
2508{
2509 int err = 0;
2510 u8 ext_csd[512] = {0};
2511 u64 wp_grp_size, start = 0, part_end;
2512 u64 group_start;
2513
2514 err = mmc_get_ext_csd(mmc, ext_csd);
2515 if (err) {
2516 printf("Failed: get ext_csd failed\n");
2517 return 1;
2518 }
2519
2520 if (!is_write_protect_valid(ext_csd)) {
2521 printf("Failed: CLASS_6_CTRL isn't '0' "
2522 "write protect process is invalid\n");
2523 return 1;
2524 }
2525
2526 err = compute_write_protect_range(mmc, name, ext_csd,
2527 &wp_grp_size, &start, &part_end);
2528 if (err)
2529 return 1;
2530
2531 group_start = start;
2532
2533 while ((group_start + wp_grp_size - 1) <= part_end) {
2534 err = send_write_prot_status_group(mmc, group_start);
2535 if (err)
2536 return 1;
2537 group_start += 32 * wp_grp_size;
2538 }
2539
2540 return 0;
2541}
2542
2543static int send_add_wp_status(struct mmc *mmc, u64 start, u64 cnt)
2544{
2545 int err = 0;
2546 u8 ext_csd[512] = {0};
2547 u64 wp_grp_size, part_end;
2548 u64 group_start;
2549 int blk_shift;
2550 u64 mmc_boundary;
2551 err = mmc_get_ext_csd(mmc, ext_csd);
2552 if (err) {
2553 printf("Failed: get ext_csd failed\n");
2554 return 1;
2555 }
2556
2557 if (!is_write_protect_valid(ext_csd)) {
2558 printf("Failed: CLASS_6_CTRL isn't '0' "
2559 "write protect process is invalid\n");
2560 return 1;
2561 }
2562
2563 wp_grp_size = write_protect_group_size(mmc, ext_csd);
2564
2565 if ((start % wp_grp_size)) {
2566 group_start = (start + wp_grp_size - 1) / wp_grp_size * wp_grp_size;
2567 printf("Caution! The partition start address isn't' aligned"
2568 "to group size\n"
2569 "the start address is change from 0x%llx to 0x%llx\n",
2570 start, group_start);
2571 part_end = group_start + (cnt - 1) * wp_grp_size - 1;
2572 printf("The write protect group number is 0x%llx, rather than 0x%lld\n",
2573 cnt - 1, cnt);
2574 } else {
2575 group_start = start;
2576 part_end = group_start + cnt * wp_grp_size - 1;
2577 }
2578
2579 blk_shift = ffs(mmc->read_bl_len) - 1;
2580 if (blk_shift < 0) {
2581 printf("bad shift.\n");
2582 return 1;
2583 }
2584 mmc_boundary = mmc->capacity>>blk_shift;
2585
2586 if ((part_end + 1) > mmc_boundary) {
2587 printf("Error: the operation cross the boundary of mmc\n");
2588 return 1;
2589 }
2590
2591 while ((group_start + wp_grp_size - 1) <= part_end) {
2592 err = send_write_prot_status_group(mmc, group_start);
2593 if (err)
2594 return 1;
2595 group_start += 32 * wp_grp_size;
2596 }
2597
2598 return 0;
2599}
2600
2601static int do_amlmmc_send_wp_status(cmd_tbl_t *cmdtp,
2602 int flag, int argc, char *const argv[])
2603{
2604 int ret = CMD_RET_USAGE;
2605 struct mmc *mmc;
2606 int dev = 1;
2607 char *name = NULL;
2608 u64 start, cnt;
2609
2610 if (argc < 3 || argc > 4)
2611 return ret;
2612
2613 if (argc == 3) {
2614 name = argv[2];
2615 dev = find_dev_num_by_partition_name(name);
2616 if (dev < 0) {
2617 printf("Error: Cannot find dev.\n");
2618 return 1;
2619 }
2620 } else {
2621 start = simple_strtoull(argv[2], NULL, 16);
2622 cnt = simple_strtoull(argv[3], NULL, 0);
2623 }
2624
2625 mmc = find_mmc_device(dev);
2626 if (!mmc) {
2627 printf("[%s] no mmc devices available\n", __func__);
2628 return 1;
2629 }
2630
2631 if (IS_SD(mmc)) {
2632 mmc = find_mmc_device(~dev);
2633 if (mmc && IS_SD(mmc)) {
2634 printf("SD card can not be write protect\n");
2635 return 1;
2636 }
2637 }
2638
2639 mmc_init(mmc);
2640
2641 if (argc == 3)
2642 ret = send_part_wp_status(mmc, name);
2643 else
2644 ret = send_add_wp_status(mmc, start, cnt);
2645
2646 if (ret) {
2647 printf("Failed: send partition write protect status failed\n");
2648 }
2649
2650 return ret;
2651}
2652
2653static int do_amlmmc_send_wp_type(cmd_tbl_t *cmdtp,
2654 int flag, int argc, char *const argv[])
2655{
2656 int ret = CMD_RET_USAGE;
2657 struct mmc *mmc;
2658 int dev = 1;
2659 char *name = NULL;
2660 u64 start, cnt;
2661
2662 if (argc < 3 || argc > 4)
2663 return ret;
2664
2665 if (argc == 3) {
2666 name = argv[2];
2667 dev = find_dev_num_by_partition_name(name);
2668 if (dev < 0) {
2669 printf("Error: Cannot find dev.\n");
2670 return 1;
2671 }
2672 } else {
2673 start = simple_strtoull(argv[2], NULL, 16);
2674 cnt = simple_strtoull(argv[3], NULL, 0);
2675 }
2676
2677 mmc = find_mmc_device(dev);
2678 if (!mmc) {
2679 printf("[%s] no mmc devices available\n", __func__);
2680 return 1;
2681 }
2682
2683 if (IS_SD(mmc)) {
2684 mmc = find_mmc_device(~dev);
2685 if (mmc && IS_SD(mmc)) {
2686 printf("SD card can not be write protect\n");
2687 return 1;
2688 }
2689 }
2690
2691 mmc_init(mmc);
2692
2693 if (argc == 3)
2694 ret = send_part_wp_type(mmc, name);
2695 else
2696 ret = send_add_wp_type(mmc, start, cnt);
2697
2698 if (ret) {
2699 printf("Failed: send partitions write protect type failed\n");
2700 }
2701
2702 return ret;
2703}
2704
2705static int set_driver_strength(struct mmc *mmc, int strength)
2706{
2707 int ret = 0;
2708 u8 ext_csd[512] = {0};
2709 u8 strength_type = 0;
2710 u8 driver_strength;
2711 u8 hs_timing = 0;
2712 ret = mmc_get_ext_csd(mmc, ext_csd);
2713 if (ret) {
2714 printf("get ext_csd failed\n");
2715 return ret;
2716 }
2717 strength_type = 1 << strength;
2718 driver_strength = ext_csd[EXT_CSD_DRIVER_STRENGTH];
2719 if (0 == (strength_type & driver_strength)) {
2720 printf("Failed: This device didn't support strength type %d\n", strength);
2721 return 1;
2722 }
2723
2724 hs_timing = ext_csd[EXT_CSD_HS_TIMING];
2725 if ((hs_timing >> 4) > 0) {
2726 printf("Failed: The driver strength has been set already, \
2727 please reset the device\n");
2728 return 1;
2729 }
2730
2731 hs_timing = hs_timing | (strength << 4);
2732
2733 ret = mmc_set_ext_csd(mmc, EXT_CSD_HS_TIMING, hs_timing);
2734 if (ret) {
2735 printf("set ext_csd hs_timing field failed\n");
2736 return ret;
2737 }
2738 ret = mmc_get_ext_csd(mmc, ext_csd);
2739 if (ret) {
2740 printf("get ext_csd failed\n");
2741 return ret;
2742 }
2743 printf("The ext_csd[HS_TIMING] has been set to 0x%x\n",
2744 ext_csd[EXT_CSD_HS_TIMING]);
2745 return ret;
2746}
2747
2748static int get_driver_strength(struct mmc *mmc)
2749{
2750 int ret = 0;
2751 u8 ext_csd[512] = {0};
2752 u8 support_ds_type = 0;
2753 u8 cur_driver_strength;
2754 u8 hs_timing = 0;
2755 ret = mmc_get_ext_csd(mmc, ext_csd);
2756 if (ret) {
2757 printf("get ext_csd failed\n");
2758 return ret;
2759 }
2760
2761 support_ds_type = ext_csd[EXT_CSD_DRIVER_STRENGTH];
2762
2763 hs_timing = ext_csd[EXT_CSD_HS_TIMING];
2764 cur_driver_strength = hs_timing >> 4;
2765
2766 printf("current strength type is: ");
2767 int strength_type = 0;
2768 while (support_ds_type) {
2769 if (support_ds_type & 1) {
2770 if (cur_driver_strength == strength_type)
2771 printf("[%d] ", strength_type);
2772 else
2773 printf("%d ", strength_type);
2774 }
2775 strength_type++;
2776 support_ds_type = support_ds_type >> 1;
2777 }
2778 printf("\n");
2779 return ret;
2780}
2781
2782static int amlmmc_set_driver_strength(int argc, char *const argv[])
2783{
2784 int ret = CMD_RET_USAGE;
2785 int dev, strength;
2786 struct mmc *mmc;
2787
2788 if (argc != 4)
2789 return CMD_RET_USAGE;
2790
2791 dev = simple_strtoul(argv[2], NULL, 10);
2792 strength = simple_strtoul(argv[3], NULL, 10);
2793 mmc = find_mmc_device(dev);
2794 if (!mmc) {
2795 puts("no mmc devices available\n");
2796 return 1;
2797 }
2798 mmc_init(mmc);
2799
2800 ret = set_driver_strength(mmc, strength);
2801
2802 return ret;
2803}
2804
2805static int amlmmc_get_driver_strength(int argc, char *const argv[])
2806{
2807 int ret = CMD_RET_USAGE;
2808 int dev;
2809 struct mmc *mmc;
2810
2811 if (argc != 3)
2812 return CMD_RET_USAGE;
2813
2814 dev = simple_strtoul(argv[2], NULL, 10);
2815 mmc = find_mmc_device(dev);
2816 if (!mmc) {
2817 puts("no mmc devices available\n");
2818 return 1;
2819 }
2820 mmc_init(mmc);
2821
2822 ret = get_driver_strength(mmc);
2823
2824 return ret;
2825}
2826
2827static int do_amlmmc_driver_strength(cmd_tbl_t *cmdtp,
2828 int flag, int argc, char *const argv[])
2829{
2830 int ret = CMD_RET_USAGE;
2831
2832 if (argc == 3)
2833 ret = amlmmc_get_driver_strength(argc,argv);
2834 else if (argc == 4)
2835 ret = amlmmc_set_driver_strength(argc,argv);
2836
2837 return ret;
2838}
2839
2840static cmd_tbl_t cmd_amlmmc[] = {
2841 U_BOOT_CMD_MKENT(read, 6, 0, do_amlmmc_read, "", ""),
2842 U_BOOT_CMD_MKENT(write, 6, 0, do_amlmmc_write, "", ""),
2843 U_BOOT_CMD_MKENT(erase, 5, 0, do_amlmmc_erase, "", ""),
2844 U_BOOT_CMD_MKENT(rescan, 3, 0, do_amlmmc_rescan, "", ""),
2845 U_BOOT_CMD_MKENT(part, 3, 0, do_amlmmc_part, "", ""),
2846 U_BOOT_CMD_MKENT(list, 2, 0, do_amlmmc_list, "", ""),
2847 U_BOOT_CMD_MKENT(switch, 4, 0, do_amlmmc_switch, "", ""),
2848 U_BOOT_CMD_MKENT(status, 3, 0, do_amlmmc_status, "", ""),
2849 U_BOOT_CMD_MKENT(ext_csd, 5, 0, do_amlmmc_ext_csd, "", ""),
2850 U_BOOT_CMD_MKENT(response, 3, 0, do_amlmmc_response, "", ""),
2851 U_BOOT_CMD_MKENT(controller, 3, 0, do_amlmmc_controller, "", ""),
2852 U_BOOT_CMD_MKENT(size, 4, 0, do_amlmmc_size, "", ""),
2853 U_BOOT_CMD_MKENT(env, 2, 0, do_amlmmc_env, "", ""),
2854 U_BOOT_CMD_MKENT(write_protect, 5, 0, do_amlmmc_write_protect, "", ""),
2855 U_BOOT_CMD_MKENT(send_wp_status, 4, 0, do_amlmmc_send_wp_status, "", ""),
2856 U_BOOT_CMD_MKENT(send_wp_type, 4, 0, do_amlmmc_send_wp_type, "", ""),
2857 U_BOOT_CMD_MKENT(clear_wp, 4, 0, do_amlmmc_clear_wp, "", ""),
2858 U_BOOT_CMD_MKENT(boot_wp, 4, 0, do_amlmmc_boot_wp, "", ""),
2859 U_BOOT_CMD_MKENT(boot_wp_status, 2, 0, do_amlmmc_boot_wp_status, "", ""),
2860 U_BOOT_CMD_MKENT(ds, 4, 0, do_amlmmc_driver_strength, "", ""),
2861#ifdef CONFIG_SECURITYKEY
2862 U_BOOT_CMD_MKENT(key, 2, 0, do_amlmmc_key, "", ""),
2863#endif
2864};
2865
2866static int do_amlmmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
2867{
2868 cmd_tbl_t *cp;
2869
2870 cp = find_cmd_tbl(argv[1], cmd_amlmmc, ARRAY_SIZE(cmd_amlmmc));
2871
2872 if (cp == NULL || argc > cp->maxargs)
2873 return CMD_RET_USAGE;
2874
2875 if (flag == CMD_FLAG_REPEAT && !cp->cmd_rep)
2876 return CMD_RET_SUCCESS;
2877
2878 return cp->cmd(cmdtp, flag, argc, argv);
2879}
2880
2881U_BOOT_CMD(
2882 amlmmc, 6, 1, do_amlmmcops,
2883 "AMLMMC sub system",
2884 "read <partition_name> ram_addr addr_byte# cnt_byte\n"
2885 "amlmmc write <partition_name> ram_addr addr_byte# cnt_byte\n"
2886 "amlmmc erase <partition_name> addr_byte# cnt_byte\n"
2887 "amlmmc erase <partition_name>/<device num>\n"
2888 "amlmmc rescan <device_num>\n"
2889 "amlmmc part <device_num> - show partition information of mmc\n"
2890 "amlmmc list - lists available devices\n"
2891 "amlmmc env - display env partition offset\n"
2892 "amlmmc switch <device_num> <part name> - part name : boot0, boot1, user\n"
2893 "amlmmc status <device_num> - read sd/emmc device status\n"
2894 "amlmmc ext_csd <device_num> <byte> - read sd/emmc device EXT_CSD [byte]\n"
2895 "amlmmc ext_csd <device_num> <byte> <value> - write sd/emmc device EXT_CSD [byte] value\n"
2896 "amlmmc response <device_num> - read sd/emmc last command response\n"
2897 "amlmmc controller <device_num> - read sd/emmc controller register\n"
2898 "amlmmc write_protect <partition_name> <write_protect_type>\n"
2899 " - set write protect on partition through power_on or temporary\n"
2900 "amlmmc write_protect <addr_base16> <cnt_base10> <write_protect_type>\n"
2901 " - set write protect on specified address through power_on or temporary\n"
2902 "amlmmc send_wp_status <partition_name> send protect status of partition\n"
2903 "amlmmc send_wp_status <addr_base16> <cnt_base10> send protect status on specified address\n"
2904 "amlmmc send_wp_type <partition_name> send protect type of partition\n"
2905 "amlmmc send_wp_type <addr_base16> <cnt_base10> send protect type on specified address\n"
2906 "amlmmc clear_wp <partition_name> clear write protect of partition\n"
2907 "amlmmc clear_wp <addr_base16> <cnt_base10> clear write protect on specified address\n"
2908 "amlmmc boot_wp <boot number> <write protect type> boot0/boot1/both, /poweron/permanent\n"
2909 "amlmmc boot_wp_status send boot write protect status\n"
2910 "amlmmc ds <dev_num> <val> set driver strength\n"
2911#ifdef CONFIG_SECURITYKEY
2912 "amlmmc key - disprotect key partition\n"
2913#endif
2914);
2915
2916/* dtb read&write operation with backup updates */
2917static u32 _calc_dtb_checksum(struct aml_dtb_rsv * dtb)
2918{
2919 int i = 0;
2920 int size = sizeof(struct aml_dtb_rsv) - sizeof(u32);
2921 u32 * buffer;
2922 u32 checksum = 0;
2923
2924 if ((u64)dtb % 4 != 0) {
2925 BUG();
2926 }
2927
2928 size = size >> 2;
2929 buffer = (u32*) dtb;
2930 while (i < size)
2931 checksum += buffer[i++];
2932
2933 return checksum;
2934}
2935
2936static int _verify_dtb_checksum(struct aml_dtb_rsv * dtb)
2937{
2938 u32 checksum;
2939
2940 checksum = _calc_dtb_checksum(dtb);
2941 dtb_info("calc %x, store %x\n", checksum, dtb->checksum);
2942
2943 return !(checksum == dtb->checksum);
2944}
2945
2946static int _dtb_read(struct mmc *mmc, u64 blk, u64 cnt, void * addr)
2947{
2948 int dev = EMMC_DTB_DEV;
2949 u64 n;
2950 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
2951 if (n != cnt) {
2952 dtb_err("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
2953 __func__, dev, blk, cnt);
2954 }
2955
2956 return (n != cnt);
2957}
2958
2959static int _dtb_write(struct mmc *mmc, u64 blk, u64 cnt, void * addr)
2960{
2961 int dev = EMMC_DTB_DEV;
2962 u64 n;
2963 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
2964 if (n != cnt) {
2965 dtb_err("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
2966 __func__, dev, blk, cnt);
2967 }
2968
2969 return (n != cnt);
2970}
2971
2972static struct mmc *_dtb_init(void)
2973{
2974 struct mmc *mmc = find_mmc_device(EMMC_DTB_DEV);
2975 if (!mmc) {
2976 dtb_err("not find mmc\n");
2977 return NULL;
2978 }
2979
2980 if (mmc_init(mmc)) {
2981 dtb_err("mmc init failed\n");
2982 return NULL;
2983 }
2984 return mmc;
2985}
2986
2987static int dtb_read_shortcut(struct mmc * mmc, void *addr)
2988{
2989 u64 blk, cnt, dtb_glb_offset;
2990 int dev = EMMC_DTB_DEV;
2991 struct aml_dtb_info *info = &dtb_infos;
2992 struct partitions * part = NULL;
2993 struct virtual_partition *vpart = NULL;
2994 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
2995 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
2996 dtb_glb_offset = part->offset + vpart->offset;
2997 /* short cut */
2998 if (info->valid[0]) {
2999 dtb_info("short cut in...\n");
3000 blk = dtb_glb_offset / mmc->read_bl_len;
3001 cnt = vpart->size / mmc->read_bl_len;
3002 if (_dtb_read(mmc, blk, cnt, addr)) {
3003 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3004 __func__, dev, blk, cnt);
3005 /*try dtb2 if it's valid */
3006 if (info->valid[1]) {
3007 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3008 cnt = vpart->size / mmc->read_bl_len;
3009 if (_dtb_read(mmc, blk, cnt, addr)) {
3010 dtb_err("%s: dev # %d, block # %#llx, cnt # %#llx ERROR!\n",
3011 __func__, dev, blk, cnt);
3012 return -1;
3013 }
3014 }
3015 }
3016 return 0;
3017 }
3018 return -2;
3019}
3020
3021static int update_dtb_info(struct mmc *mmc, void *addr)
3022{
3023 int ret = 0, dev = EMMC_DTB_DEV;
3024 u64 blk, cnt, dtb_glb_offset;
3025 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3026 struct aml_dtb_info *info = &dtb_infos;
3027 int cpy = 1, valid = 0;
3028 struct partitions * part = NULL;
3029 struct virtual_partition *vpart = NULL;
3030 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3031 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3032 dtb_glb_offset = part->offset + vpart->offset;
3033
3034 while (cpy >= 0) {
3035 blk = (dtb_glb_offset + cpy * (vpart->size)) / mmc->read_bl_len;
3036 cnt = vpart->size / mmc->read_bl_len;
3037 ret = _dtb_read(mmc, blk, cnt, addr);
3038 if (ret) {
3039 dtb_err("%s: dev # %d, block # %#llx, cnt # %#llx ERROR!\n",
3040 __func__, dev, blk, cnt);
3041 } else {
3042 ret = _verify_dtb_checksum(dtb);
3043 /* check magic avoid whole 0 issue */
3044 if (!ret && (dtb->magic != 0)) {
3045 info->stamp[cpy] = dtb->timestamp;
3046 info->valid[cpy] = 1;
3047 }
3048 else
3049 dtb_wrn("cpy %d is not valid\n", cpy);
3050 }
3051 valid += info->valid[cpy];
3052 cpy --;
3053 }
3054 return valid;
3055}
3056
3057static int update_invalid_dtb(struct mmc *mmc, void *addr)
3058{
3059 int ret = 0, dev = EMMC_DTB_DEV;
3060 u64 blk, cnt, dtb_glb_offset;
3061 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3062 struct aml_dtb_info *info = &dtb_infos;
3063 struct partitions * part = NULL;
3064 struct virtual_partition *vpart = NULL;
3065 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3066 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3067 dtb_glb_offset = part->offset + vpart->offset;
3068 cnt = vpart->size / mmc->read_bl_len;
3069
3070 if (info->valid[1]) {
3071 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3072 if (_dtb_read(mmc, blk, cnt, addr)) {
3073 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3074 __func__, dev, blk, cnt);
3075 ret = -2;
3076 }
3077 /* fixme, update the invalid one - dtb1 */
3078 blk = (dtb_glb_offset) / mmc->read_bl_len;
3079 if (_dtb_write(mmc, blk, cnt, addr)) {
3080 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3081 __func__, dev, blk, cnt);
3082 ret = -2;
3083 }
3084 info->valid[0] = 1;
3085 info->stamp[0] = dtb->timestamp;
3086 } else {
3087 dtb_info("update dtb2");
3088 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3089 if (_dtb_write(mmc, blk, cnt, addr)) {
3090 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3091 __func__, dev, blk, cnt);
3092 ret = -2;
3093 }
3094 info->valid[1] = 1;
3095 info->stamp[1] = dtb->timestamp;
3096 }
3097 return ret;
3098}
3099
3100int update_old_dtb(struct mmc *mmc, void *addr)
3101{
3102 int ret = 0, dev = EMMC_DTB_DEV;
3103 u64 blk, cnt, dtb_glb_offset;
3104 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3105 struct aml_dtb_info *info = &dtb_infos;
3106 struct partitions * part = NULL;
3107 struct virtual_partition *vpart = NULL;
3108 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3109 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3110 dtb_glb_offset = part->offset + vpart->offset;
3111 cnt = vpart->size / mmc->read_bl_len;
3112 if (stamp_after(info->stamp[1], info->stamp[0])) {
3113 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3114 if (_dtb_read(mmc, blk, cnt, addr)) {
3115 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3116 __func__, dev, blk, cnt);
3117 ret = -3;
3118 }
3119 /*update dtb1*/
3120 blk = dtb_glb_offset / mmc->read_bl_len;
3121 if (_dtb_write(mmc, blk, cnt, addr)) {
3122 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3123 __func__, dev, blk, cnt);
3124 ret = -3;
3125 }
3126 info->stamp[0] = dtb->timestamp;
3127 } else if (stamp_after(info->stamp[0], info->stamp[1])) {
3128 /*update dtb2*/
3129 blk = (dtb_glb_offset + vpart->size) / mmc->read_bl_len;
3130 if (_dtb_write(mmc, blk, cnt, addr)) {
3131 dtb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3132 __func__, dev, blk, cnt);
3133 ret = -3;
3134 }
3135 info->stamp[1] = dtb->timestamp;
3136 } else {
3137 dtb_info("do nothing\n");
3138 }
3139 return ret;
3140}
3141
3142int dtb_read(void *addr)
3143{
3144 int ret = 0;
3145 int valid = 0;
3146 struct mmc *mmc;
3147
3148 mmc = _dtb_init();
3149 if (mmc == NULL)
3150 return -10;
3151
3152 if (dtb_read_shortcut(mmc, addr) == 0)
3153 return ret;
3154
3155 valid = update_dtb_info(mmc, addr);
3156 dtb_info("total valid %d\n", valid);
3157 /* check valid */
3158 switch (valid) {
3159 /* none is valid, using the 1st one for compatibility*/
3160 case 0:
3161 ret = -1;
3162 goto _out;
3163 break;
3164 /* only 1 is valid, using the valid one */
3165 case 1:
3166 update_invalid_dtb(mmc, addr);
3167 break;
3168 /* both are valid, pickup new one. */
3169 case 2:
3170 update_old_dtb(mmc, addr);
3171 break;
3172 default:
3173 dtb_err("impossible valid values.\n");
3174 BUG();
3175 break;
3176 }
3177_out:
3178 return ret;
3179}
3180
3181
3182int dtb_write(void *addr)
3183{
3184 int ret = 0;
3185 struct aml_dtb_rsv * dtb = (struct aml_dtb_rsv *) addr;
3186 struct aml_dtb_info *info = &dtb_infos;
3187 u64 blk, cnt, dtb_glb_offset;
3188 int cpy, valid;
3189 struct mmc * mmc;
3190 struct partitions * part = NULL;
3191 struct virtual_partition *vpart = NULL;
3192 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3193 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3194 dtb_glb_offset = part->offset + vpart->offset;
3195
3196 mmc = _dtb_init();
3197 if (NULL == mmc)
3198 return -10;
3199
3200 /* stamp */
3201 valid = info->valid[0] + info->valid[1];
3202 dtb_info("valid %d\n", valid);
3203 if (0 == valid)
3204 dtb->timestamp = 0;
3205 else if (1 == valid) {
3206 dtb->timestamp = 1 + info->stamp[info->valid[0]?0:1];
3207 } else {
3208 /* both are valid */
3209 if (info->stamp[0] != info->stamp[1]) {
3210 dtb_wrn("timestamp are not same %d:%d\n",
3211 info->stamp[0], info->stamp[1]);
3212 dtb->timestamp = 1 + (stamp_after(info->stamp[1], info->stamp[0])?
3213 info->stamp[1]:info->stamp[0]);
3214 } else
3215 dtb->timestamp = 1 + info->stamp[0];
3216 }
3217 /*setting version and magic*/
3218 dtb->version = 1; /* base version */
3219 dtb->magic = 0x00447e41; /*A~D\0*/
3220 dtb->checksum = _calc_dtb_checksum(dtb);
3221 dtb_info("new stamp %d, checksum 0x%x, version %d, magic %s\n",
3222 dtb->timestamp, dtb->checksum, dtb->version, (char *)&dtb->magic);
3223
3224 for (cpy = 0; cpy < DTB_COPIES; cpy++) {
3225 blk = (dtb_glb_offset + cpy * (vpart->size)) / mmc->read_bl_len;
3226 cnt = vpart->size / mmc->read_bl_len;
3227 ret |= _dtb_write(mmc, blk, cnt, addr);
3228 info->valid[cpy] = 1;
3229 info->stamp[cpy] = dtb->timestamp;
3230 }
3231
3232 return ret;
3233}
3234
3235extern int check_valid_dts(unsigned char *buffer);
3236int renew_partition_tbl(unsigned char *buffer)
3237{
3238 int ret = 0;
3239
3240 unsigned char *temp = NULL;
3241 if (!buffer)
3242 return 1;
3243 temp = malloc (AML_DTB_IMG_MAX_SZ);
3244 if (!temp)
3245 return 1;
3246 memcpy(temp, buffer, AML_DTB_IMG_MAX_SZ);
3247 /* todo, check new dts imcoming.... */
3248 ret = check_valid_dts(temp);
3249 free(temp);
3250 /* todo, check new dts imcoming.... */
3251/* ret = check_valid_dts(buffer);*/
3252 /* only the dts new is valid */
3253 if (!ret) {
3254 free_partitions();
3255 ret = get_partition_from_dts(buffer);
3256 if (ret) {
3257 printf("Fail to get partition table from dts\n");
3258 goto _out;
3259 }
3260 if (0 == mmc_device_init(_dtb_init())) {
3261 printf("partition table success\n");
3262 ret = 0;
3263 goto _out;
3264 }
3265 printf("partition table error\n");
3266 ret = 1;
3267 }
3268
3269_out:
3270 return ret;
3271}
3272
3273int do_amlmmc_dtb_key(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3274{
3275 int dev, ret = 0;
3276 void *addr = NULL;
3277 u64 cnt = 0, n = 0, blk = 0;
3278 //u64 size;
3279 struct partitions *part = NULL;
3280 struct virtual_partition *vpart = NULL;
3281 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3282 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3283
3284 switch (argc) {
3285 case 3:
3286 if (strcmp(argv[1], "erase") == 0) {
3287 if (strcmp(argv[2], "dtb") == 0) {
3288 printf("start erase dtb......\n");
3289 dev = EMMC_DTB_DEV;
3290 struct mmc *mmc = find_mmc_device(dev);
3291 if (!mmc) {
3292 printf("not find mmc\n");
3293 return 1;
3294 }
3295 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3296 cnt = (vpart->size * 2) / mmc->read_bl_len;
3297 if (cnt != 0)
3298 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
3299 printf("dev # %d, %s, several blocks erased %s\n",
3300 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3301 return (n == 0) ? 0 : 1;
3302 }else if (strcmp(argv[2], "key") == 0){
3303 printf("start erase key......\n");
3304 dev = 1;
3305 struct mmc *mmc = find_mmc_device(dev);
3306 if (!mmc) {
3307 printf("not find mmc\n");
3308 return 1;
3309 }
3310 n = mmc_key_erase();
3311 printf("dev # %d, %s, several blocks erased %s\n",
3312 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3313 return (n == 0) ? 0 : 1;
3314 }
3315 } else if (strcmp(argv[1], "cali_pattern") == 0) {
3316
3317 if (strcmp(argv[2], "write") == 0) {
3318 dev = EMMC_DTB_DEV;
3319 struct mmc *mmc = find_mmc_device(dev);
3320 if (!mmc) {
3321 printf("not find mmc\n");
3322 return 1;
3323 }
3324 vpart = aml_get_virtual_partition_by_name(MMC_PATTERN_NAME);
3325 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3326 addr = (void *)malloc(vpart->size);
3327 if (addr == NULL) {
3328 printf("cali_pattern malloc fail\n");
3329 return 1;
3330 }
3331 mmc_write_cali_mattern(addr);
3332 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3333 cnt = vpart->size / mmc->read_bl_len;
3334 if (cnt != 0)
3335 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
3336 printf("dev # %d, %s, several calibration pattern blocks write %s\n",
3337 dev, (flag == 0) ? " ":(argv[2]),(n == cnt) ? "OK" : "ERROR");
3338 free(addr);
3339 return (n == cnt) ? 0 : 1;
3340 }
3341 }
3342 break;
3343 case 4:
3344 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3345 if (strcmp(argv[1], "dtb_read") == 0) {
3346 /* fixme, */
3347 ret = dtb_read(addr);
3348 return 0;
3349
3350 } else if (strcmp(argv[1], "dtb_write") == 0) {
3351 /* fixme, should we check the return value? */
3352 ret = dtb_write(addr);
3353 ret |= renew_partition_tbl(addr);
3354 return ret;
3355 }
3356 return 0;
3357 default:
3358 break;
3359 }
3360 return 1;
3361}
3362
3363/* update partition table in reserved partition. */
3364__weak int emmc_update_ept(unsigned char *buffer)
3365{
3366 int ret = 0;
3367
3368#ifndef DTB_BIND_KERNEL
3369 dtb_write(buffer);
3370#endif
3371 ret = renew_partition_tbl(buffer);
3372 return ret;
3373}
3374
3375/* fixme, should use renew_partition_tbl here! */
3376__weak int emmc_update_mbr(unsigned char *buffer)
3377{
3378 int ret = 0;
3379 cpu_id_t cpu_id = get_cpu_id();
3380
3381 if (cpu_id.family_id < MESON_CPU_MAJOR_ID_GXL) {
3382 ret = -1;
3383 printf("MBR not support, try dtb\n");
3384 goto _out;
3385 }
3386#ifndef DTB_BIND_KERNEL
3387 dtb_write(buffer);
3388#endif
3389 ret = get_partition_from_dts(buffer);
3390 if (ret) {
3391 printf("Fail to get partition table from dts\n");
3392 goto _out;
3393 }
3394 ret = mmc_device_init(_dtb_init());
3395 printf("%s: update mbr %s\n", __func__, ret?"Fail":"Success");
3396_out:
3397 return ret;
3398}
3399
3400int emmc_erase_rsv(struct mmc *mmc, char *rsv_part)
3401{
3402 u64 cnt = 0, n = 0, blk = 0;
3403 struct partitions *part = NULL;
3404 struct virtual_partition *vpart = NULL;
3405
3406 if (rsv_part == NULL)
3407 return -1;
3408
3409 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3410 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3411 if (strcmp(rsv_part, "dtb") == 0) {
3412 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3413 cnt = (vpart->size * 2) / mmc->read_bl_len;
3414 if (cnt != 0)
3415 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
3416 printf("%s is erased %s\n",
3417 rsv_part, (n == 0) ? "OK" : "ERROR");
3418 return (n == 0) ? 0 : 1;
3419 } else if (strcmp(rsv_part, "key") == 0) {
3420 n = mmc_key_erase();
3421 printf("%s is erased %s\n",
3422 rsv_part, (n == 0) ? "OK" : "ERROR");
3423 return (n == 0) ? 0 : 1;
3424 }
3425 return 1;
3426}
3427
3428int do_emmc_erase(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3429{
3430 int dev;
3431 u64 cnt = 0, n = 0, blk = 0;
3432 //u64 size;
3433 struct partitions *part = NULL;
3434 struct virtual_partition *vpart = NULL;
3435 struct mmc *mmc;
3436 if (argc != 3)
3437 return CMD_RET_USAGE;
3438
3439 vpart = aml_get_virtual_partition_by_name(MMC_DTB_NAME);
3440 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3441 if (strcmp(argv[2], "dtb") == 0) {
3442 printf("start erase dtb......\n");
3443 dev = EMMC_DTB_DEV;
3444 mmc = find_mmc_device(dev);
3445 if (!mmc) {
3446 printf("not find mmc\n");
3447 return 1;
3448 }
3449 blk = (part->offset + vpart->offset) / mmc->read_bl_len;
3450 cnt = (vpart->size * 2) / mmc->read_bl_len;
3451 if (cnt != 0)
3452 n = blk_derase(mmc_get_blk_desc(mmc), blk, cnt);
3453 printf("dev # %d, %s, several blocks erased %s\n",
3454 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3455 return (n == 0) ? 0 : 1;
3456 } else if (strcmp(argv[2], "key") == 0) {
3457 printf("start erase key......\n");
3458 dev = 1;
3459 mmc = find_mmc_device(dev);
3460 if (!mmc) {
3461 printf("not find mmc\n");
3462 return 1;
3463 }
3464 n = mmc_key_erase();
3465 printf("dev # %d, %s, several blocks erased %s\n",
3466 dev, (flag == 0) ? " ":(argv[2]),(n == 0) ? "OK" : "ERROR");
3467 return (n == 0) ? 0 : 1;
3468 }
3469 return 1;
3470}
3471
3472int do_emmc_dtb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3473{
3474 int ret = 0;
3475 void *addr = NULL;
3476
3477 if (argc != 4)
3478 return CMD_RET_USAGE;
3479
3480 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3481 ret = dtb_read(addr);
3482 return ret;
3483}
3484
3485int do_emmc_dtb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3486{
3487 int ret = 0;
3488 void *addr = NULL;
3489
3490 if (argc != 4)
3491 return CMD_RET_USAGE;
3492
3493 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3494 ret = dtb_write(addr);
3495 ret |= renew_partition_tbl(addr);
3496 return ret;
3497}
3498
3499static int _fastboot_context_read(struct mmc *mmc, u64 blk,
3500 u64 cnt, void *addr)
3501{
3502 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3503 u64 n;
3504
3505 n = blk_dread(mmc_get_blk_desc(mmc), blk, cnt, addr);
3506 if (n != cnt) {
3507 fb_err("%s: dev # %d, block # %#llx, count # %#llx ERROR!\n",
3508 __func__, dev, blk, cnt);
3509 }
3510
3511 return n != cnt;
3512}
3513
3514int fastboot_context_read(void *buf, size_t size)
3515{
3516 uint32_t crc_result;
3517 struct mmc *mmc;
3518 struct FastbootContext *fb_cont;
3519 int fb_size = sizeof(struct FastbootContext);
3520 u64 blk, cnt, fb_glb_offset;
3521 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3522 struct partitions *part = NULL;
3523 struct virtual_partition *vpart = NULL;
3524
3525 mmc = find_mmc_device(dev);
3526 if (!mmc) {
3527 puts("no mmc devices available\n");
3528 return 1;
3529 }
3530
3531 if (mmc_init(mmc)) {
3532 printf("%s() %d: emmc init failed\n", __func__, __LINE__);
3533 return 1;
3534 }
3535
3536 vpart = aml_get_virtual_partition_by_name(MMC_FASTBOOT_CONTEXT_NAME);
3537 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3538 fb_glb_offset = part->offset + vpart->offset;
3539
3540 blk = fb_glb_offset / mmc->read_bl_len;
3541 cnt = size / mmc->read_bl_len;
3542
3543 if (_fastboot_context_read(mmc, blk, cnt, buf))
3544 return 1;
3545
3546 fb_cont = (struct FastbootContext *)buf;
3547 crc_result = crc32(0, buf, fb_size - 4);
3548
3549 if (crc_result != fb_cont->crc32) {
3550 printf("%s %d: crc checksum ERROR!\n", __func__, __LINE__);
3551 return 1;
3552 }
3553 return 0;
3554}
3555
3556
3557int do_emmc_fb_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3558{
3559 int ret = 0;
3560 void *addr = NULL;
3561 u64 size;
3562
3563 if (argc != 4)
3564 return CMD_RET_USAGE;
3565
3566 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3567 size = simple_strtoull(argv[3], NULL, 16);
3568 ret = fastboot_context_read(addr, size);
3569 return ret;
3570}
3571
3572static int _fastboot_context_write(struct mmc *mmc, u64 blk,
3573 u64 cnt, void *addr)
3574{
3575 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3576 int n;
3577
3578 n = blk_dwrite(mmc_get_blk_desc(mmc), blk, cnt, addr);
3579
3580 if (n != cnt) {
3581 fb_err("%s: dev # %d, block # %#llx,cnt # %#llx ERROR!\n",
3582 __func__, dev, blk, cnt);
3583 }
3584
3585 return n != cnt;
3586}
3587
3588int fastboot_context_write(void *buf, size_t size)
3589{
3590 int ret = 0;
3591 struct FastbootContext *fb_cont = (struct FastbootContext *)buf;
3592 u64 blk, cnt, fb_glb_offset;
3593 struct mmc *mmc;
3594 struct partitions *part = NULL;
3595 struct virtual_partition *vpart = NULL;
3596 int dev = EMMC_FASTBOOT_CONTEXT_DEV;
3597 int fb_size = sizeof(struct FastbootContext);
3598
3599 mmc = find_mmc_device(dev);
3600 if (!mmc) {
3601 puts("no mmc devices available\n");
3602 return 1;
3603 }
3604
3605 ret = mmc_init(mmc);
3606 if (ret) {
3607 printf("%s() %d: emmc init failed\n", __func__, __LINE__);
3608 return 1;
3609 }
3610
3611 vpart = aml_get_virtual_partition_by_name(MMC_FASTBOOT_CONTEXT_NAME);
3612 part = aml_get_partition_by_name(MMC_RESERVED_NAME);
3613 fb_glb_offset = part->offset + vpart->offset;
3614 fb_cont->crc32 = crc32(0, buf, fb_size - 4);
3615 blk = fb_glb_offset / mmc->read_bl_len;
3616 cnt = size / mmc->read_bl_len;
3617 ret = _fastboot_context_write(mmc, blk, cnt, buf);
3618
3619 return ret;
3620}
3621
3622int do_emmc_fb_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3623{
3624 int ret = 0;
3625 void *addr = NULL;
3626 u64 size;
3627
3628 if (argc != 4)
3629 return CMD_RET_USAGE;
3630
3631 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3632 size = simple_strtoull(argv[3], NULL, 16);
3633 ret = fastboot_context_write(addr, size);
3634 return ret;
3635}
3636
3637int do_emmc_key_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3638{
3639 int ret = 0;
3640 void *addr = NULL;
3641 u64 size;
jinbiao0cd57162024-04-09 08:23:25 +00003642 u32 actual_length = 0;
Bo Lv72d0e902023-01-02 14:27:34 +00003643
3644 if (argc != 4)
3645 return CMD_RET_USAGE;
3646
3647 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3648 size = simple_strtoull(argv[3], NULL, 16);
3649 printf("enter emmc key read !!\n");
3650 printf("addr:%p size:%llx\n",addr,size);
3651 ret = mmc_key_read(addr, size, &actual_length);
3652 printf("ret:%d\n",ret);
3653 return ret;
3654}
3655
3656int do_emmc_key_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) {
3657
3658 int ret = 0;
3659 void *addr = NULL;
3660 u64 size;
jinbiao0cd57162024-04-09 08:23:25 +00003661 u32 actual_length = 0;
Bo Lv72d0e902023-01-02 14:27:34 +00003662
3663 if (argc != 4)
3664 return CMD_RET_USAGE;
3665
3666 addr = (void *)simple_strtoul(argv[2], NULL, 16);
3667 size = simple_strtoull(argv[3], NULL, 16);
jinbiao0cd57162024-04-09 08:23:25 +00003668 ret = mmc_key_write(addr, size, &actual_length);
Bo Lv72d0e902023-01-02 14:27:34 +00003669 return ret;
3670}
3671
3672static cmd_tbl_t cmd_emmc[] = {
3673 U_BOOT_CMD_MKENT(dtb_read, 4, 0, do_emmc_dtb_read, "", ""),
3674 U_BOOT_CMD_MKENT(dtb_write, 4, 0, do_emmc_dtb_write, "", ""),
3675 U_BOOT_CMD_MKENT(erase, 3, 0, do_emmc_erase, "", ""),
3676 U_BOOT_CMD_MKENT(fastboot_read, 4, 0, do_emmc_fb_read, "", ""),
3677 U_BOOT_CMD_MKENT(fastboot_write, 4, 0, do_emmc_fb_write, "", ""),
3678 U_BOOT_CMD_MKENT(key_read, 4, 0, do_emmc_key_read, "", ""),
3679 U_BOOT_CMD_MKENT(key_write, 4, 0, do_emmc_key_write, "", ""),
3680};
3681
3682static int do_emmc_dtb_key(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
3683{
3684 cmd_tbl_t *cp;
3685
3686 cp = find_cmd_tbl(argv[1], cmd_emmc, ARRAY_SIZE(cmd_emmc));
3687
3688 if (cp == NULL || argc > cp->maxargs)
3689 return CMD_RET_USAGE;
3690 if (flag == CMD_FLAG_REPEAT && !cp->cmd_rep)
3691 return CMD_RET_SUCCESS;
3692 return cp->cmd(cmdtp, flag, argc, argv);
3693}
3694
3695
3696U_BOOT_CMD(
3697 emmc, 4, 1, do_emmc_dtb_key,
3698 "EMMC sub system",
3699 "dtb_read addr size\n"
3700 "emmc dtb_write addr size\n"
3701 "emmc erase dtb\n"
3702 "emmc erase key\n"
3703 "emmc fastboot_read addr size\n"
3704 "emmc fastboot_write addr size\n"
3705 "emmc key_read addr size\n"
3706 "emmc key_write addr size\n"
3707);
3708