12e192b24SSimon Glass /* 22e192b24SSimon Glass * (C) Copyright 2009-2013 ADVANSEE 32e192b24SSimon Glass * Benoît Thébaudeau <benoit.thebaudeau@advansee.com> 42e192b24SSimon Glass * 52e192b24SSimon Glass * Based on the mpc512x iim code: 62e192b24SSimon Glass * Copyright 2008 Silicon Turnkey Express, Inc. 72e192b24SSimon Glass * Martha Marx <mmarx@silicontkx.com> 82e192b24SSimon Glass * 92e192b24SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 102e192b24SSimon Glass */ 112e192b24SSimon Glass 122e192b24SSimon Glass #include <common.h> 132e192b24SSimon Glass #include <command.h> 142e192b24SSimon Glass #include <console.h> 152e192b24SSimon Glass #include <fuse.h> 16*1221ce45SMasahiro Yamada #include <linux/errno.h> 172e192b24SSimon Glass 182e192b24SSimon Glass static int strtou32(const char *str, unsigned int base, u32 *result) 192e192b24SSimon Glass { 202e192b24SSimon Glass char *ep; 212e192b24SSimon Glass 222e192b24SSimon Glass *result = simple_strtoul(str, &ep, base); 232e192b24SSimon Glass if (ep == str || *ep != '\0') 242e192b24SSimon Glass return -EINVAL; 252e192b24SSimon Glass 262e192b24SSimon Glass return 0; 272e192b24SSimon Glass } 282e192b24SSimon Glass 292e192b24SSimon Glass static int confirm_prog(void) 302e192b24SSimon Glass { 312e192b24SSimon Glass puts("Warning: Programming fuses is an irreversible operation!\n" 322e192b24SSimon Glass " This may brick your system.\n" 332e192b24SSimon Glass " Use this command only if you are sure of " 342e192b24SSimon Glass "what you are doing!\n" 352e192b24SSimon Glass "\nReally perform this fuse programming? <y/N>\n"); 362e192b24SSimon Glass 372e192b24SSimon Glass if (confirm_yesno()) 382e192b24SSimon Glass return 1; 392e192b24SSimon Glass 402e192b24SSimon Glass puts("Fuse programming aborted\n"); 412e192b24SSimon Glass return 0; 422e192b24SSimon Glass } 432e192b24SSimon Glass 442e192b24SSimon Glass static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 452e192b24SSimon Glass { 462e192b24SSimon Glass const char *op = argc >= 2 ? argv[1] : NULL; 472e192b24SSimon Glass int confirmed = argc >= 3 && !strcmp(argv[2], "-y"); 482e192b24SSimon Glass u32 bank, word, cnt, val; 492e192b24SSimon Glass int ret, i; 502e192b24SSimon Glass 512e192b24SSimon Glass argc -= 2 + confirmed; 522e192b24SSimon Glass argv += 2 + confirmed; 532e192b24SSimon Glass 542e192b24SSimon Glass if (argc < 2 || strtou32(argv[0], 0, &bank) || 552e192b24SSimon Glass strtou32(argv[1], 0, &word)) 562e192b24SSimon Glass return CMD_RET_USAGE; 572e192b24SSimon Glass 582e192b24SSimon Glass if (!strcmp(op, "read")) { 592e192b24SSimon Glass if (argc == 2) 602e192b24SSimon Glass cnt = 1; 612e192b24SSimon Glass else if (argc != 3 || strtou32(argv[2], 0, &cnt)) 622e192b24SSimon Glass return CMD_RET_USAGE; 632e192b24SSimon Glass 642e192b24SSimon Glass printf("Reading bank %u:\n", bank); 652e192b24SSimon Glass for (i = 0; i < cnt; i++, word++) { 662e192b24SSimon Glass if (!(i % 4)) 672e192b24SSimon Glass printf("\nWord 0x%.8x:", word); 682e192b24SSimon Glass 692e192b24SSimon Glass ret = fuse_read(bank, word, &val); 702e192b24SSimon Glass if (ret) 712e192b24SSimon Glass goto err; 722e192b24SSimon Glass 732e192b24SSimon Glass printf(" %.8x", val); 742e192b24SSimon Glass } 752e192b24SSimon Glass putc('\n'); 762e192b24SSimon Glass } else if (!strcmp(op, "sense")) { 772e192b24SSimon Glass if (argc == 2) 782e192b24SSimon Glass cnt = 1; 792e192b24SSimon Glass else if (argc != 3 || strtou32(argv[2], 0, &cnt)) 802e192b24SSimon Glass return CMD_RET_USAGE; 812e192b24SSimon Glass 822e192b24SSimon Glass printf("Sensing bank %u:\n", bank); 832e192b24SSimon Glass for (i = 0; i < cnt; i++, word++) { 842e192b24SSimon Glass if (!(i % 4)) 852e192b24SSimon Glass printf("\nWord 0x%.8x:", word); 862e192b24SSimon Glass 872e192b24SSimon Glass ret = fuse_sense(bank, word, &val); 882e192b24SSimon Glass if (ret) 892e192b24SSimon Glass goto err; 902e192b24SSimon Glass 912e192b24SSimon Glass printf(" %.8x", val); 922e192b24SSimon Glass } 932e192b24SSimon Glass putc('\n'); 942e192b24SSimon Glass } else if (!strcmp(op, "prog")) { 952e192b24SSimon Glass if (argc < 3) 962e192b24SSimon Glass return CMD_RET_USAGE; 972e192b24SSimon Glass 982e192b24SSimon Glass for (i = 2; i < argc; i++, word++) { 992e192b24SSimon Glass if (strtou32(argv[i], 16, &val)) 1002e192b24SSimon Glass return CMD_RET_USAGE; 1012e192b24SSimon Glass 1022e192b24SSimon Glass printf("Programming bank %u word 0x%.8x to 0x%.8x...\n", 1032e192b24SSimon Glass bank, word, val); 1042e192b24SSimon Glass if (!confirmed && !confirm_prog()) 1052e192b24SSimon Glass return CMD_RET_FAILURE; 1062e192b24SSimon Glass ret = fuse_prog(bank, word, val); 1072e192b24SSimon Glass if (ret) 1082e192b24SSimon Glass goto err; 1092e192b24SSimon Glass } 1102e192b24SSimon Glass } else if (!strcmp(op, "override")) { 1112e192b24SSimon Glass if (argc < 3) 1122e192b24SSimon Glass return CMD_RET_USAGE; 1132e192b24SSimon Glass 1142e192b24SSimon Glass for (i = 2; i < argc; i++, word++) { 1152e192b24SSimon Glass if (strtou32(argv[i], 16, &val)) 1162e192b24SSimon Glass return CMD_RET_USAGE; 1172e192b24SSimon Glass 1182e192b24SSimon Glass printf("Overriding bank %u word 0x%.8x with " 1192e192b24SSimon Glass "0x%.8x...\n", bank, word, val); 1202e192b24SSimon Glass ret = fuse_override(bank, word, val); 1212e192b24SSimon Glass if (ret) 1222e192b24SSimon Glass goto err; 1232e192b24SSimon Glass } 1242e192b24SSimon Glass } else { 1252e192b24SSimon Glass return CMD_RET_USAGE; 1262e192b24SSimon Glass } 1272e192b24SSimon Glass 1282e192b24SSimon Glass return 0; 1292e192b24SSimon Glass 1302e192b24SSimon Glass err: 1312e192b24SSimon Glass puts("ERROR\n"); 1322e192b24SSimon Glass return CMD_RET_FAILURE; 1332e192b24SSimon Glass } 1342e192b24SSimon Glass 1352e192b24SSimon Glass U_BOOT_CMD( 1362e192b24SSimon Glass fuse, CONFIG_SYS_MAXARGS, 0, do_fuse, 1372e192b24SSimon Glass "Fuse sub-system", 1382e192b24SSimon Glass "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n" 1392e192b24SSimon Glass " starting at 'word'\n" 1402e192b24SSimon Glass "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n" 1412e192b24SSimon Glass " starting at 'word'\n" 1422e192b24SSimon Glass "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n" 1432e192b24SSimon Glass " several fuse words, starting at 'word' (PERMANENT)\n" 1442e192b24SSimon Glass "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n" 1452e192b24SSimon Glass " several fuse words, starting at 'word'" 1462e192b24SSimon Glass ); 147