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