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