xref: /rk3399_rockchip-uboot/test/rockchip/test-storage.c (revision 474718ff26c6f7b4ebd8aaf8335fff141303aff5)
199d14b01SJoseph Chen /*
299d14b01SJoseph Chen  * (C) Copyright 2019 Rockchip Electronics Co., Ltd
399d14b01SJoseph Chen  *
499d14b01SJoseph Chen  * SPDX-License-Identifier:     GPL-2.0+
599d14b01SJoseph Chen  */
699d14b01SJoseph Chen 
799d14b01SJoseph Chen #include <common.h>
899d14b01SJoseph Chen #include <boot_rkimg.h>
999d14b01SJoseph Chen #include <cli.h>
1099d14b01SJoseph Chen #include <dm.h>
1199d14b01SJoseph Chen #include <environment.h>
1299d14b01SJoseph Chen #include <malloc.h>
1399d14b01SJoseph Chen #include <misc.h>
1499d14b01SJoseph Chen #include <sysmem.h>
1599d14b01SJoseph Chen #include <linux/ctype.h>
1699d14b01SJoseph Chen #include <asm/arch/vendor.h>
1799d14b01SJoseph Chen #include "test-rockchip.h"
1899d14b01SJoseph Chen 
1999d14b01SJoseph Chen #define DEFAULT_STORAGE_RW_PART		"userdata"
2099d14b01SJoseph Chen 
2199d14b01SJoseph Chen #if defined(CONFIG_MMC) || defined(CONFIG_RKNAND) || defined(CONFIG_BLK)
2299d14b01SJoseph Chen static int do_test_storage(cmd_tbl_t *cmdtp, int flag,
2399d14b01SJoseph Chen 			   int argc, char *const argv[],
2499d14b01SJoseph Chen 			   const char *devtype,
2599d14b01SJoseph Chen 			   const char *devnum,
2699d14b01SJoseph Chen 			   const char *label)
2799d14b01SJoseph Chen {
2899d14b01SJoseph Chen 	struct blk_desc *dev_desc;
29*474718ffSJoseph Chen 	disk_partition_t part;
3099d14b01SJoseph Chen 	u32 blocks, round, sector;
3199d14b01SJoseph Chen 	char *w_buf, *r_buf;
3299d14b01SJoseph Chen 	char cmd[64];
3399d14b01SJoseph Chen 	int i, ret;
3499d14b01SJoseph Chen 	ulong ts;
3599d14b01SJoseph Chen 
36*474718ffSJoseph Chen 	/* 1. Get test partition */
3799d14b01SJoseph Chen 	dev_desc = rockchip_get_bootdev();
3899d14b01SJoseph Chen 	if (!dev_desc) {
3999d14b01SJoseph Chen 		printf("%s: Can't find dev_desc\n", __func__);
4099d14b01SJoseph Chen 		return -ENODEV;
4199d14b01SJoseph Chen 	}
4299d14b01SJoseph Chen 
4399d14b01SJoseph Chen 	if (part_get_info_by_name(dev_desc,
4499d14b01SJoseph Chen 				  DEFAULT_STORAGE_RW_PART, &part) < 0) {
4599d14b01SJoseph Chen 		printf("%s: Can't find %s part\n",
4699d14b01SJoseph Chen 		       __func__, DEFAULT_STORAGE_RW_PART);
4799d14b01SJoseph Chen 		return -EINVAL;
4899d14b01SJoseph Chen 	}
4999d14b01SJoseph Chen 
5099d14b01SJoseph Chen 	/* 32MB */
5199d14b01SJoseph Chen 	sector = part.start;
5299d14b01SJoseph Chen 	blocks = part.size > 0x10000 ? 0x10000 : part.size;
5399d14b01SJoseph Chen 	round  = 4;
5499d14b01SJoseph Chen 
5599d14b01SJoseph Chen 	/* Round up */
5699d14b01SJoseph Chen 	if (blocks % 2)
5799d14b01SJoseph Chen 		blocks += 1;
5899d14b01SJoseph Chen 
5999d14b01SJoseph Chen 	printf("%s RW sectors on %s 0x%08x - 0x%08x(size: %ld MiB) for %d round\n\n",
60*474718ffSJoseph Chen 	       label, DEFAULT_STORAGE_RW_PART,
6199d14b01SJoseph Chen 	       sector, sector + blocks,
6299d14b01SJoseph Chen 	       (blocks * dev_desc->blksz) >> 20, round);
6399d14b01SJoseph Chen 
6499d14b01SJoseph Chen 	/* 2. Switch to devnum */
6599d14b01SJoseph Chen 	if (devtype) {
6699d14b01SJoseph Chen 		snprintf(cmd, sizeof(cmd), "%s dev %s", devtype, devnum);
6799d14b01SJoseph Chen 		if (run_command(cmd, 0)) {
6899d14b01SJoseph Chen 			printf("Switch to %s%s failed\n", devtype, devnum);
6999d14b01SJoseph Chen 			ret = -ENODEV;
7099d14b01SJoseph Chen 			goto err1;
7199d14b01SJoseph Chen 		}
7299d14b01SJoseph Chen 	}
7399d14b01SJoseph Chen 
7499d14b01SJoseph Chen 	/* 3. Prepare memory */
7599d14b01SJoseph Chen 	w_buf = sysmem_alloc_by_name("storage_w", blocks * dev_desc->blksz);
7699d14b01SJoseph Chen 	if (!w_buf) {
7799d14b01SJoseph Chen 		printf("No sysmem for w_buf!\n");
7899d14b01SJoseph Chen 		ret = -ENOMEM;
7999d14b01SJoseph Chen 		goto err1;
8099d14b01SJoseph Chen 	}
8199d14b01SJoseph Chen 
8299d14b01SJoseph Chen 	r_buf = sysmem_alloc_by_name("storage_r", blocks * dev_desc->blksz);
8399d14b01SJoseph Chen 	if (!r_buf) {
8499d14b01SJoseph Chen 		printf("No sysmem for r_buf!\n");
8599d14b01SJoseph Chen 		ret = -ENOMEM;
8699d14b01SJoseph Chen 		goto err2;
8799d14b01SJoseph Chen 	}
8899d14b01SJoseph Chen 
8999d14b01SJoseph Chen 	for (i = 0; i < blocks * dev_desc->blksz; i++) {
9099d14b01SJoseph Chen 		w_buf[i] = i;
9199d14b01SJoseph Chen 		r_buf[i] = 0;
9299d14b01SJoseph Chen 	}
9399d14b01SJoseph Chen 
9499d14b01SJoseph Chen 	/* 4. Write test */
9599d14b01SJoseph Chen 	ts = get_timer(0);
9699d14b01SJoseph Chen 	if (devtype) {
9799d14b01SJoseph Chen 		snprintf(cmd, sizeof(cmd), "%s write 0x%x 0x%x 0x%x",
9899d14b01SJoseph Chen 			 devtype, (u32)(ulong)w_buf, sector, blocks);
9999d14b01SJoseph Chen 		for (i = 0; i < round; i++) {
10099d14b01SJoseph Chen 			if (run_command(cmd, 0)) {
10199d14b01SJoseph Chen 				ret = -EIO;
10299d14b01SJoseph Chen 				goto err3;
10399d14b01SJoseph Chen 			}
10499d14b01SJoseph Chen 		}
10599d14b01SJoseph Chen 	} else {
10699d14b01SJoseph Chen 		for (i = 0; i < round; i++) {
10799d14b01SJoseph Chen 			ret = blk_dwrite(dev_desc, sector, blocks, w_buf);
10899d14b01SJoseph Chen 			if (ret != blocks) {
10999d14b01SJoseph Chen 				ret = -EIO;
11099d14b01SJoseph Chen 				goto err3;
11199d14b01SJoseph Chen 			}
11299d14b01SJoseph Chen 		}
11399d14b01SJoseph Chen 	}
11499d14b01SJoseph Chen 
11599d14b01SJoseph Chen 	ts = get_timer(0) - ts;
11699d14b01SJoseph Chen 	printf("\n%s write: size %dMB, used %ldms, speed %ldMB/s\n",
11799d14b01SJoseph Chen 	       label, blocks * round / 2048, ts, (blocks * round >> 1) / ts);
11899d14b01SJoseph Chen 
11999d14b01SJoseph Chen 	/* 5. Read test */
12099d14b01SJoseph Chen 	ts = get_timer(0);
12199d14b01SJoseph Chen 	if (devtype) {
12299d14b01SJoseph Chen 		snprintf(cmd, sizeof(cmd), "%s read 0x%x 0x%x 0x%x",
12399d14b01SJoseph Chen 			 devtype, (u32)(ulong)r_buf, sector, blocks);
12499d14b01SJoseph Chen 
12599d14b01SJoseph Chen 		for (i = 0; i < round; i++) {
12699d14b01SJoseph Chen 			if (run_command(cmd, 0)) {
12799d14b01SJoseph Chen 				ret = -EIO;
12899d14b01SJoseph Chen 				goto err3;
12999d14b01SJoseph Chen 			}
13099d14b01SJoseph Chen 		}
13199d14b01SJoseph Chen 	} else {
13299d14b01SJoseph Chen 		for (i = 0; i < round; i++) {
13399d14b01SJoseph Chen 			ret = blk_dread(dev_desc, sector, blocks, r_buf);
13499d14b01SJoseph Chen 			if (ret != blocks) {
13599d14b01SJoseph Chen 				ret = -EIO;
13699d14b01SJoseph Chen 				goto err3;
13799d14b01SJoseph Chen 			}
13899d14b01SJoseph Chen 		}
13999d14b01SJoseph Chen 	}
14099d14b01SJoseph Chen 
14199d14b01SJoseph Chen 	ts = get_timer(0) - ts;
14299d14b01SJoseph Chen 	printf("\n%s read: size %dMB, used %ldms, speed %ldMB/s\n",
14399d14b01SJoseph Chen 	       label, blocks * round / 2048, ts, (blocks * round >> 1) / ts);
14499d14b01SJoseph Chen 
14599d14b01SJoseph Chen 	/* 6. Verify the context */
14699d14b01SJoseph Chen 	for (i = 0; i < blocks * dev_desc->blksz; i++) {
14799d14b01SJoseph Chen 		if (w_buf[i] != r_buf[i]) {
14899d14b01SJoseph Chen 			printf("%s context compare error!\n", label);
14999d14b01SJoseph Chen 			ret = -EINVAL;
15099d14b01SJoseph Chen 			goto err3;
15199d14b01SJoseph Chen 		}
15299d14b01SJoseph Chen 	}
15399d14b01SJoseph Chen 
15499d14b01SJoseph Chen 	/* 7. Switch back to default system devnum */
15599d14b01SJoseph Chen 	if (devtype && !strcmp(devtype, "mmc") &&
15699d14b01SJoseph Chen 	    strcmp(devnum, env_get("devnum"))) {
15799d14b01SJoseph Chen 		ret = run_command(cmd, 0);
15899d14b01SJoseph Chen 		if (ret) {
15999d14b01SJoseph Chen 			printf("Switch to mmc1 failed\n");
16099d14b01SJoseph Chen 			ret = -ENODEV;
16199d14b01SJoseph Chen 			goto err3;
16299d14b01SJoseph Chen 		}
16399d14b01SJoseph Chen 	}
16499d14b01SJoseph Chen 
16599d14b01SJoseph Chen 	ret = 0;
16699d14b01SJoseph Chen err3:
16799d14b01SJoseph Chen 	sysmem_free((phys_addr_t)r_buf);
16899d14b01SJoseph Chen err2:
16999d14b01SJoseph Chen 	sysmem_free((phys_addr_t)w_buf);
17099d14b01SJoseph Chen err1:
17199d14b01SJoseph Chen 
17299d14b01SJoseph Chen 	return ret;
17399d14b01SJoseph Chen }
17499d14b01SJoseph Chen 
17599d14b01SJoseph Chen #ifdef CONFIG_MMC
17699d14b01SJoseph Chen static int do_test_emmc(cmd_tbl_t *cmdtp, int flag,
17799d14b01SJoseph Chen 			int argc, char *const argv[])
17899d14b01SJoseph Chen {
17999d14b01SJoseph Chen 	return do_test_storage(cmdtp, flag, argc, argv, "mmc", "0", "MMC0");
18099d14b01SJoseph Chen }
18199d14b01SJoseph Chen 
18299d14b01SJoseph Chen static int do_test_sdmmc(cmd_tbl_t *cmdtp, int flag,
18399d14b01SJoseph Chen 			 int argc, char *const argv[])
18499d14b01SJoseph Chen {
18599d14b01SJoseph Chen 	return do_test_storage(cmdtp, flag, argc, argv, "mmc", "1", "MMC1");
18699d14b01SJoseph Chen }
18799d14b01SJoseph Chen #endif
18899d14b01SJoseph Chen 
18999d14b01SJoseph Chen #ifdef CONFIG_RKNAND
19099d14b01SJoseph Chen static int do_test_rknand(cmd_tbl_t *cmdtp, int flag,
19199d14b01SJoseph Chen 			  int argc, char *const argv[])
19299d14b01SJoseph Chen {
19399d14b01SJoseph Chen 	return do_test_storage(cmdtp, flag, argc, argv, "rknand", "0", "RKNAND0");
19499d14b01SJoseph Chen }
19599d14b01SJoseph Chen #endif
19699d14b01SJoseph Chen 
19799d14b01SJoseph Chen static int do_test_blk(cmd_tbl_t *cmdtp, int flag,
19899d14b01SJoseph Chen 		       int argc, char *const argv[])
19999d14b01SJoseph Chen {
20099d14b01SJoseph Chen 	return do_test_storage(cmdtp, flag, argc, argv, NULL, NULL, "BLK");
20199d14b01SJoseph Chen }
20299d14b01SJoseph Chen #endif/* defined(CONFIG_MMC) || defined(CONFIG_RKNAND) || defined(CONFIG_BLK) */
20399d14b01SJoseph Chen 
20499d14b01SJoseph Chen #if defined(CONFIG_OPTEE_CLIENT) && defined(CONFIG_MMC)
20599d14b01SJoseph Chen static int do_test_secure_storage(cmd_tbl_t *cmdtp, int flag,
20699d14b01SJoseph Chen 				  int argc, char *const argv[])
20799d14b01SJoseph Chen {
20899d14b01SJoseph Chen 	return run_command("mmc testsecurestorage", 0);
20999d14b01SJoseph Chen }
21099d14b01SJoseph Chen #endif
21199d14b01SJoseph Chen 
21299d14b01SJoseph Chen #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) && \
21399d14b01SJoseph Chen 	!defined(CONFIG_SPL_BUILD)
21499d14b01SJoseph Chen static int do_test_env(cmd_tbl_t *cmdtp, int flag,
21599d14b01SJoseph Chen 		       int argc, char *const argv[])
21699d14b01SJoseph Chen {
21799d14b01SJoseph Chen 	int ret;
21899d14b01SJoseph Chen 
21999d14b01SJoseph Chen 	ret = env_save();
22099d14b01SJoseph Chen 	if (ret)
22199d14b01SJoseph Chen 		return ret;
22299d14b01SJoseph Chen 
22399d14b01SJoseph Chen 	return env_load();
22499d14b01SJoseph Chen }
22599d14b01SJoseph Chen #endif
22699d14b01SJoseph Chen 
22799d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
22899d14b01SJoseph Chen static int do_test_vendor(cmd_tbl_t *cmdtp, int flag,
22999d14b01SJoseph Chen 			  int argc, char *const argv[])
23099d14b01SJoseph Chen {
23199d14b01SJoseph Chen 	return vendor_storage_test();
23299d14b01SJoseph Chen }
23399d14b01SJoseph Chen #endif
23499d14b01SJoseph Chen 
23599d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_EFUSE
23699d14b01SJoseph Chen static int do_test_efuse(cmd_tbl_t *cmdtp, int flag,
23799d14b01SJoseph Chen 			 int argc, char *const argv[])
23899d14b01SJoseph Chen {
23999d14b01SJoseph Chen 	struct udevice *dev;
24099d14b01SJoseph Chen 	u8 fuses[128] = {0};
24199d14b01SJoseph Chen 	int ret;
24299d14b01SJoseph Chen 
24399d14b01SJoseph Chen 	ret = uclass_get_device(UCLASS_MISC, 0, &dev);
24499d14b01SJoseph Chen 	if (ret) {
24599d14b01SJoseph Chen 		printf("Can't find efuse device\n");
24699d14b01SJoseph Chen 		return 0;
24799d14b01SJoseph Chen 	}
24899d14b01SJoseph Chen 
24999d14b01SJoseph Chen 	ret = misc_read(dev, 0, &fuses, sizeof(fuses));
25099d14b01SJoseph Chen 	if (ret) {
25199d14b01SJoseph Chen 		printf("Efuse read failed\n");
25299d14b01SJoseph Chen 		return 0;
25399d14b01SJoseph Chen 	}
25499d14b01SJoseph Chen 
25599d14b01SJoseph Chen 	printf("Efuse-content:\n");
25699d14b01SJoseph Chen 	print_buffer(0, fuses, 1, 128, 16);
25799d14b01SJoseph Chen 
25899d14b01SJoseph Chen 	return 0;
25999d14b01SJoseph Chen }
26099d14b01SJoseph Chen #endif
26199d14b01SJoseph Chen 
26299d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_OTP
26399d14b01SJoseph Chen static int do_test_otp(cmd_tbl_t *cmdtp, int flag,
26499d14b01SJoseph Chen 		       int argc, char *const argv[])
26599d14b01SJoseph Chen {
26699d14b01SJoseph Chen 	struct udevice *dev;
26799d14b01SJoseph Chen 	u8 otps[64] = {0};
26899d14b01SJoseph Chen 	int ret;
26999d14b01SJoseph Chen 
27099d14b01SJoseph Chen 	/* retrieve the device */
27199d14b01SJoseph Chen 	ret = uclass_get_device_by_driver(UCLASS_MISC, 0, &dev);
27299d14b01SJoseph Chen 	if (ret) {
27399d14b01SJoseph Chen 		printf("Can't find otp device\n");
27499d14b01SJoseph Chen 		return 0;
27599d14b01SJoseph Chen 	}
27699d14b01SJoseph Chen 
27799d14b01SJoseph Chen 	ret = misc_read(dev, 0, &otps, sizeof(otps));
27899d14b01SJoseph Chen 	if (ret) {
27999d14b01SJoseph Chen 		printf("OTP read failed\n");
28099d14b01SJoseph Chen 		return 0;
28199d14b01SJoseph Chen 	}
28299d14b01SJoseph Chen 
28399d14b01SJoseph Chen 	printf("Otp-content:\n");
28499d14b01SJoseph Chen 	print_buffer(0, otps, 1, 64, 16);
28599d14b01SJoseph Chen 
28699d14b01SJoseph Chen 	return 0;
28799d14b01SJoseph Chen }
28899d14b01SJoseph Chen #endif
28999d14b01SJoseph Chen 
29099d14b01SJoseph Chen #ifdef CONFIG_PARTITIONS
29199d14b01SJoseph Chen static int do_test_part(cmd_tbl_t *cmdtp, int flag,
29299d14b01SJoseph Chen 			int argc, char *const argv[])
29399d14b01SJoseph Chen {
29499d14b01SJoseph Chen 	return run_command("part list ${devtype} ${devnum}", 0);
29599d14b01SJoseph Chen }
29699d14b01SJoseph Chen #endif
29799d14b01SJoseph Chen 
29899d14b01SJoseph Chen static cmd_tbl_t sub_cmd[] = {
29999d14b01SJoseph Chen #ifdef CONFIG_BLK
30099d14b01SJoseph Chen 	UNIT_CMD_DEFINE(blk, 0),
30199d14b01SJoseph Chen #endif
30299d14b01SJoseph Chen #ifdef CONFIG_MMC
30399d14b01SJoseph Chen 	UNIT_CMD_DEFINE(emmc, 0),
30499d14b01SJoseph Chen #endif
30599d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_EFUSE
30699d14b01SJoseph Chen 	UNIT_CMD_DEFINE(efuse, 0),
30799d14b01SJoseph Chen #endif
30899d14b01SJoseph Chen #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) && \
30999d14b01SJoseph Chen 	!defined(CONFIG_SPL_BUILD)
31099d14b01SJoseph Chen 	UNIT_CMD_DEFINE(env, 0),
31199d14b01SJoseph Chen #endif
31299d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_OTP
31399d14b01SJoseph Chen 	UNIT_CMD_DEFINE(otp, 0),
31499d14b01SJoseph Chen #endif
31599d14b01SJoseph Chen #ifdef CONFIG_RKNAND
31699d14b01SJoseph Chen 	UNIT_CMD_DEFINE(rknand, 0),
31799d14b01SJoseph Chen #endif
31899d14b01SJoseph Chen #if defined(CONFIG_OPTEE_CLIENT) && defined(CONFIG_MMC)
31999d14b01SJoseph Chen 	UNIT_CMD_DEFINE(secure_storage, 0),
32099d14b01SJoseph Chen #endif
32199d14b01SJoseph Chen #ifdef CONFIG_PARTITIONS
32299d14b01SJoseph Chen 	UNIT_CMD_DEFINE(part, 0),
32399d14b01SJoseph Chen #endif
32499d14b01SJoseph Chen #ifdef CONFIG_MMC
32599d14b01SJoseph Chen 	UNIT_CMD_DEFINE(sdmmc, 0),
32699d14b01SJoseph Chen #endif
32799d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
32899d14b01SJoseph Chen 	UNIT_CMD_DEFINE(vendor, 0),
32999d14b01SJoseph Chen #endif
33099d14b01SJoseph Chen };
33199d14b01SJoseph Chen 
33299d14b01SJoseph Chen static char sub_cmd_help[] =
33399d14b01SJoseph Chen #ifdef CONFIG_BLK
33499d14b01SJoseph Chen "    [.] rktest blk                         - test blk layer read/write\n"
33599d14b01SJoseph Chen #endif
33699d14b01SJoseph Chen #ifdef CONFIG_MMC
337*474718ffSJoseph Chen "    [.] rktest emmc                        - test emmc read/write speed\n"
33899d14b01SJoseph Chen "    [.] rktest sdmmc                       - test sd card and fat fs read/write\n"
33999d14b01SJoseph Chen #endif
34099d14b01SJoseph Chen #ifdef CONFIG_RKNAND
341*474718ffSJoseph Chen "    [.] rktest rknand                      - test rknand read/write speed\n"
34299d14b01SJoseph Chen #endif
34399d14b01SJoseph Chen #if defined(CONFIG_OPTEE_CLIENT) && defined(CONFIG_MMC)
34499d14b01SJoseph Chen "    [.] rktest secure_storage              - test secure storage\n"
34599d14b01SJoseph Chen #endif
34699d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_VENDOR_PARTITION
34799d14b01SJoseph Chen "    [.] rktest vendor                      - test vendor storage read/write\n"
34899d14b01SJoseph Chen #endif
34999d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_EFUSE
35099d14b01SJoseph Chen "    [.] rktest efuse                       - test efuse, dump content\n"
35199d14b01SJoseph Chen #endif
35299d14b01SJoseph Chen #ifdef CONFIG_ROCKCHIP_OTP
35399d14b01SJoseph Chen "    [.] rktest otp                         - test otp, dump content\n"
35499d14b01SJoseph Chen #endif
35599d14b01SJoseph Chen #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) && \
35699d14b01SJoseph Chen 	!defined(CONFIG_SPL_BUILD)
35799d14b01SJoseph Chen "    [.] rktest env                         - test save env to storage\n"
35899d14b01SJoseph Chen #endif
35999d14b01SJoseph Chen #ifdef CONFIG_PARTITIONS
36099d14b01SJoseph Chen "    [.] rktest part                        - test part list\n"
36199d14b01SJoseph Chen #endif
36299d14b01SJoseph Chen ;
36399d14b01SJoseph Chen 
36499d14b01SJoseph Chen const struct cmd_group cmd_grp_storage = {
36599d14b01SJoseph Chen 	.id	= TEST_ID_STORAGE,
36699d14b01SJoseph Chen 	.help	= sub_cmd_help,
36799d14b01SJoseph Chen 	.cmd	= sub_cmd,
36899d14b01SJoseph Chen 	.cmd_n	= ARRAY_SIZE(sub_cmd),
36999d14b01SJoseph Chen };
370