blob: d288bd96fb27f328089be93d9ffcdaff45a095a4 [file] [log] [blame]
Zhongfu Luo1e6af102023-07-27 17:23:27 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <config.h>
7#include <common.h>
8#include <command.h>
9#include <malloc.h>
10#include <asm/amlogic/arch/efuse.h>
11#include <asm/amlogic/arch/bl31_apis.h>
12#include <amlogic/aml_efuse.h>
13
14#define CMD_EFUSE_WRITE 0
15#define CMD_EFUSE_READ 1
16#define CMD_EFUSE_READ_CALI 2
17#define CMD_EFUSE_READ_CALI_ITEM 3
18#define CMD_EFUSE_CHECK_PATTERN_ITEM 10
19
20int cmd_efuse(int argc, char * const argv[], char *buf)
21{
22 int i, action = -1;
23 u64 offset;
24 u32 size = 0, max_size;
25 char *end;
26 char *s;
27 int ret;
28
29 if (strncmp(argv[1], "read", 4) == 0) {
30 action = CMD_EFUSE_READ;
31 } else if (strncmp(argv[1], "cali_read", 9) == 0) {
32 action = CMD_EFUSE_READ_CALI;
33 } else if (strncmp(argv[1], "item_read", 9) == 0) {
34 action = CMD_EFUSE_READ_CALI_ITEM;
35 goto efuse_action;
36 } else if (strncmp(argv[1], "check", 9) == 0) {
37 action = CMD_EFUSE_CHECK_PATTERN_ITEM;
38 goto efuse_action;
39 } else if (strncmp(argv[1], "write", 5) == 0) {
40 action = CMD_EFUSE_WRITE;
41 } else{
42 printf("%s arg error\n", argv[1]);
43 return CMD_RET_USAGE;
44 }
45
46 if (argc < 4)
47 return CMD_RET_USAGE;
48 /*check efuse user data max size*/
49 offset = simple_strtoul(argv[2], &end, 16);
50 size = simple_strtoul(argv[3], &end, 16);
51 printf("%s: offset is %lld size is %d\n", __func__, offset, size);
52 max_size = efuse_get_max();
53 if (!size) {
54 printf("\n error: size is zero!!!\n");
55 return -1;
56 }
57 if (offset > max_size) {
58 printf("\n error: offset is too large!!!\n");
59 printf("\n offset should be less than %d!\n", max_size);
60 return -1;
61 }
62 if (offset + size > max_size) {
63 printf("\n error: offset + size is too large!!!\n");
64 printf("\n offset + size should be less than %d!\n", max_size);
65 return -1;
66 }
67
68efuse_action:
69
70 /* efuse read */
71 if (action == CMD_EFUSE_READ) {
72 memset(buf, 0, size);
73 ret = efuse_read_usr(buf, size, (loff_t *)&offset);
74 if (ret == -1) {
75 printf("ERROR: efuse read user data fail!\n");
76 return -1;
77 }
78
79 if (ret != size)
80 printf("ERROR: read %d byte(s) not %d byte(s) data\n",
81 ret, size);
82 printf("efuse read data");
83 for (i = 0; i < size; i++) {
84 if (i % 16 == 0)
85 printf("\n");
86 printf(":%02x", buf[i]);
87 }
88 printf("\n");
89 }
90 else if (action == CMD_EFUSE_READ_CALI) {
91 memset(buf, 0, size);
92 ret = efuse_read_cali(buf, size, offset);
93 if (ret == -1) {
94 printf("ERROR: efuse read cali data fail!\n");
95 return -1;
96 }
97
98 if (ret != size)
99 printf("ERROR: read %d byte(s) not %d byte(s) data\n",
100 ret, size);
101 printf("efuse read cali data");
102 for (i = 0; i < size; i++) {
103 if (i % 16 == 0)
104 printf("\n");
105 printf(":%02x", buf[i]);
106 }
107 printf("\n");
108 }
109 else if (action == CMD_EFUSE_READ_CALI_ITEM) {
110 s = argv[2];
111 ret = efuse_get_cali_item(s);
112 if (ret < 0) {
113 printf("ERROR: efuse read cali item data fail!\n");
114 return -1;
115 }
116 printf("efuse %s cali data=0x%x\n",s,ret);
117 } else if (action == CMD_EFUSE_CHECK_PATTERN_ITEM) {
118 s = argv[2];
119 ret = efuse_check_pattern_item(s);
120 if (ret < 0) {
121 printf("ERROR: efuse check pattern fail!\n");
122 return -1;
123 }
124 printf("efuse %s %s\n", s, ret > 0 ? "has been written" : "is not write");
125 return ret == 0 ? 1 : 0; //cmd return 0: written, 1: not write
126 }
127
128 /* efuse write */
129 else if (action == CMD_EFUSE_WRITE) {
130 if (argc < 5) {
131 printf("arg count error\n");
132 return CMD_RET_USAGE;
133 }
134 memset(buf, 0, size);
135
136 s = argv[4];
137 memcpy(buf, s, strlen(s));
138 if (efuse_write_usr(buf, size, (loff_t *)&offset) < 0) {
139 printf("error: efuse write fail.\n");
140 return -1;
141 } else {
142 printf("%s written done.\n", __func__);
143 }
144 } else {
145 /*
146 * This part of the code is necessary to prevent unknown errors
147 */
148 /* coverity[dead_error_begin] */
149 printf("arg error\n");
150 return CMD_RET_USAGE;
151 }
152
153 return 0;
154}
155
156int do_efuse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
157{
158 char buf[EFUSE_BYTES];
159
160 memset(buf, 0, sizeof(buf));
161
162 if (argc < 2)
163 return CMD_RET_USAGE;
164
165 return cmd_efuse(argc, argv, buf);
166}
167
168static char efuse_help_text[] =
169 "[read/write offset size [data]]\n"
170 " [cali_read] -read from cali\n"
171 " example: [efuse cali_read 0 7]; offset is 0,size is 7. \n"
172 " [item_read] -read cali item\n"
173 " [item_read sensor/saradc/mipicsi/hdmirx/eth/cvbs/earcrx/earctx]\n"
174 " [check] -check if pattern is write\n"
175 " [check dgpk1|dgpk2|aud_id]\n"
176 " [read/write] - read or write 'size' data from\n"
177 " 'offset' from efuse user data ;\n"
178 " [offset] - the offset byte from the beginning\n"
179 " of efuse user data zone;\n"
180 " [size] - data size\n"
181 " [data] - the optional argument for 'write',\n"
182 " data is treated as characters\n"
183 " examples: efuse write 0xc 0xd abcdABCD1234\n";
184
185U_BOOT_CMD(
186 efuse, 5, 1, do_efuse,
187 "efuse commands", efuse_help_text
188);
189
190#ifdef CONFIG_EFUSE_OBJ_API
191
192efuse_obj_field_t efuse_field;
193
194static char *efuse_obj_err_parse(uint32_t efuse_obj_err_status)
195{
196 char *err_char = NULL;
197
198 switch (efuse_obj_err_status) {
199 case EFUSE_OBJ_ERR_INVALID_DATA:
200 err_char = "invalid data";
201 break;
202 case EFUSE_OBJ_ERR_NOT_FOUND:
203 err_char = "field not found";
204 break;
205 case EFUSE_OBJ_ERR_SIZE:
206 err_char = "size not match";
207 break;
208 case EFUSE_OBJ_ERR_NOT_SUPPORT:
209 err_char = "not support";
210 break;
211 case EFUSE_OBJ_ERR_ACCESS:
212 err_char = "access denied";
213 break;
214 case EFUSE_OBJ_ERR_WRITE_PROTECTED:
215 err_char = "write protected";
216 break;
217 case EFUSE_OBJ_ERR_INTERNAL:
218 case EFUSE_OBJ_ERR_OTHER_INTERNAL:
219 err_char = "internal error";
220 break;
221 default:
222 err_char = "unknown error";
223 break;
224 }
225
226 return err_char;
227}
228
229static int hex2bin(char *hex, void *bin, size_t binlen)
230{
231 int i, c, n1, n2, hexlen, k;
232
233 hexlen = strnlen(hex, 64);
234 k = 0;
235 n1 = -1;
236 n2 = -1;
237 for (i = 0; i < hexlen; i++) {
238 n2 = n1;
239 c = hex[i];
240 if (c >= '0' && c <= '9') {
241 n1 = c - '0';
242 } else if (c >= 'a' && c <= 'f') {
243 n1 = c - 'a' + 10;
244 } else if (c >= 'A' && c <= 'F') {
245 n1 = c - 'A' + 10;
246 } else if (c == ' ') {
247 n1 = -1;
248 continue;
249 } else {
250 return -1;
251 }
252
253 if (n1 >= 0 && n2 >= 0) {
254 ((uint8_t *)bin)[k] = (n2 << 4) | n1;
255 n1 = -1;
256 k++;
257 }
258 }
259 return k;
260}
261
262int do_efuse_obj(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
263{
264 uint32_t rc = CMD_RET_FAILURE;
265 uint8_t buff[32];
266 uint32_t bufflen = sizeof(buff);
267 char *name = NULL;
268
269 if (argc < 3 || argc > 4) {
270 printf("Invalid number of arguments %d\n", argc);
271 return CMD_RET_USAGE;
272 }
273
274 memset(&buff[0], 0, sizeof(buff));
275 memset(&efuse_field, 0, sizeof(efuse_field));
276
277 if (strcmp(argv[1], "get") == 0) {
278 // $0 get field
279 if (argc == 3) {
280 name = argv[2];
281 rc = efuse_obj_read(EFUSE_OBJ_EFUSE_DATA, name, buff, &bufflen);
282 if (rc == EFUSE_OBJ_SUCCESS) {
283 int i;
284
285 memset(&efuse_field, 0, sizeof(efuse_field));
286 strncpy(efuse_field.name, name, sizeof(efuse_field.name) - 1);
287 memcpy(efuse_field.data, buff, bufflen);
288 efuse_field.size = bufflen;
289
290 for (i = 0; i < bufflen; i++)
291 printf("%02x%s", buff[i],
292 ((i && i % 16 == 15) || (i == bufflen - 1)
293 ? "\n" : " "));
294 rc = CMD_RET_SUCCESS;
295 } else {
296 printf("Error getting eFUSE object: %s: %d\n",
297 efuse_obj_err_parse(rc), rc);
298 rc = CMD_RET_FAILURE;
299 }
300 } else {
301 printf("Error: too many arguments %d\n", argc);
302 rc = CMD_RET_USAGE;
303 }
304 } else if (strcmp(argv[1], "set") == 0) {
305 // $0 set field data
306 if (argc == 4) {
307 name = argv[2];
308 char *data = argv[3];
309 int dlen = strnlen(data, 64);
310 uint8_t databuf[32] = {0};
311
312 dlen = hex2bin(data, databuf, dlen);
313 if (dlen < 0) {
314 printf("parse data hex2bin error\n");
315 return CMD_RET_FAILURE;
316 }
317 rc = efuse_obj_write(EFUSE_OBJ_EFUSE_DATA, name, databuf, dlen);
318 if (rc == EFUSE_OBJ_SUCCESS) {
319 rc = CMD_RET_SUCCESS;
320 } else {
321 printf("Error setting eFUSE object: %s: %d\n",
322 efuse_obj_err_parse(rc), rc);
323 rc = CMD_RET_FAILURE;
324 }
325 } else {
326 printf("Error: too few arguments %d\n", argc);
327 rc = CMD_RET_USAGE;
328 }
329 } else if (strcmp(argv[1], "lock") == 0) {
330 // $0 lock field
331 if (argc == 3) {
332 name = argv[2];
333 rc = efuse_obj_write(EFUSE_OBJ_LOCK_STATUS, name, buff, bufflen);
334 if (rc == EFUSE_OBJ_SUCCESS) {
335 rc = CMD_RET_SUCCESS;
336 } else {
337 printf("Error setting eFUSE object: %s: %d\n",
338 efuse_obj_err_parse(rc), rc);
339 rc = CMD_RET_FAILURE;
340 }
341 } else {
342 printf("Error: too many arguments %d\n", argc);
343 rc = CMD_RET_USAGE;
344 }
345 } else if (strcmp(argv[1], "get_lock") == 0) {
346 // $0 get_lock field
347 if (argc == 3) {
348 name = argv[2];
349 rc = efuse_obj_read(EFUSE_OBJ_LOCK_STATUS, name, buff, &bufflen);
350 if (rc == EFUSE_OBJ_SUCCESS) {
351 int i;
352
353 memset(&efuse_field, 0, sizeof(efuse_field));
354 strncpy(efuse_field.name, name, sizeof(efuse_field.name) - 1);
355 memcpy(efuse_field.data, buff, bufflen);
356 efuse_field.size = bufflen;
357
358 for (i = 0; i < bufflen; i++)
359 printf("%02x%s", buff[i],
360 ((i && i % 16 == 15) || (i == bufflen - 1)
361 ? "\n" : " "));
362 rc = CMD_RET_SUCCESS;
363 } else {
364 printf("Error getting eFUSE object: %s: %d\n",
365 efuse_obj_err_parse(rc), rc);
366 rc = CMD_RET_FAILURE;
367 }
368 } else {
369 printf("Error: too many arguments %d\n", argc);
370 rc = CMD_RET_USAGE;
371 }
372 }
373
374 return rc;
375}
376
377static char efuse_obj_help_text[] =
378 "[set | get | lock | get_lock] <FIELD> {<field-value-hexdump-string>}\n"
379 "\n"
380 "get FIELD Get field value. FIELD is the field name\n"
381 " expected_data is an optional expected data\n"
382 "set FIELD DATA Set field to data. DATA is in continuous\n"
383 " hexdump format, e.g. aabb1122\n"
384 "lock FIELD Lock field. Program exits with status 0 if success\n"
385 "get_lock FIELD Check if field is locked. Program exits with\n"
386 " status 1 if locked, or 0 if unlocked\n"
387 " expected_result is 00 or 01, an optional expected lock result\n"
388 "\n";
389
390U_BOOT_CMD(efuse_obj, 4, 0, do_efuse_obj,
391 "eFUSE object program commands", efuse_obj_help_text
392);
393#endif /* CONFIG_EFUSE_OBJ_API */
394
395#ifdef CONFIG_EFUSE_MRK_GET_CHECKNUM
396int do_efuse_mrk(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
397{
398 uint32_t rc = CMD_RET_FAILURE;
399 char name[16];
400 uint32_t checknum = 0;
401
402 if (argc != 2) {
403 printf("Invalid number of arguments %d\n", argc);
404 return CMD_RET_USAGE;
405 }
406
407 memset(name, 0, sizeof(name));
408 strncpy(name, argv[1], sizeof(name) - 1);
409 if (!efuse_mrk_get_checknum(name, &checknum)) {
410 printf("%s: 0x%08x\n", argv[1], checknum);
411 rc = CMD_RET_SUCCESS;
412 } else {
413 printf("get mrk checknum for %s failed\n", argv[1]);
414 }
415
416 return rc;
417}
418
419static char efuse_mrk_help_text[] =
420 "<MRK>\n"
421 "Supported MRK includes: DVGK, DVUK,\n"
422 "DGPK1, DGPK2,\n"
423 "ETSI_SCK_0, ETSI_SCK_1, ETSI_SCK_2,\n"
424 "SCPU_ETSI_SCK_0, SCPU_ETSI_SCK_1, SEGK\n";
425
426U_BOOT_CMD(efuse_mrk, 2, 0, do_efuse_mrk,
427 "eFUSE mrk checknum", efuse_mrk_help_text
428);
429#endif /* CONFIG_EFUSE_MRK_GET_CHECKNUM */