1 /* 2 * (C) Copyright 2009-2013 ADVANSEE 3 * Benoît Thébaudeau <benoit.thebaudeau@advansee.com> 4 * 5 * Based on the mpc512x iim code: 6 * Copyright 2008 Silicon Turnkey Express, Inc. 7 * Martha Marx <mmarx@silicontkx.com> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include <common.h> 13 #include <command.h> 14 #include <console.h> 15 #include <fuse.h> 16 #include <linux/errno.h> 17 18 static int strtou32(const char *str, unsigned int base, u32 *result) 19 { 20 char *ep; 21 22 *result = simple_strtoul(str, &ep, base); 23 if (ep == str || *ep != '\0') 24 return -EINVAL; 25 26 return 0; 27 } 28 29 static int confirm_prog(void) 30 { 31 puts("Warning: Programming fuses is an irreversible operation!\n" 32 " This may brick your system.\n" 33 " Use this command only if you are sure of " 34 "what you are doing!\n" 35 "\nReally perform this fuse programming? <y/N>\n"); 36 37 if (confirm_yesno()) 38 return 1; 39 40 puts("Fuse programming aborted\n"); 41 return 0; 42 } 43 44 static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 45 { 46 const char *op = argc >= 2 ? argv[1] : NULL; 47 int confirmed = argc >= 3 && !strcmp(argv[2], "-y"); 48 u32 bank, word, cnt, val; 49 int ret, i; 50 51 argc -= 2 + confirmed; 52 argv += 2 + confirmed; 53 54 if (argc < 2 || strtou32(argv[0], 0, &bank) || 55 strtou32(argv[1], 0, &word)) 56 return CMD_RET_USAGE; 57 58 if (!strcmp(op, "read")) { 59 if (argc == 2) 60 cnt = 1; 61 else if (argc != 3 || strtou32(argv[2], 0, &cnt)) 62 return CMD_RET_USAGE; 63 64 printf("Reading bank %u:\n", bank); 65 for (i = 0; i < cnt; i++, word++) { 66 if (!(i % 4)) 67 printf("\nWord 0x%.8x:", word); 68 69 ret = fuse_read(bank, word, &val); 70 if (ret) 71 goto err; 72 73 printf(" %.8x", val); 74 } 75 putc('\n'); 76 } else if (!strcmp(op, "sense")) { 77 if (argc == 2) 78 cnt = 1; 79 else if (argc != 3 || strtou32(argv[2], 0, &cnt)) 80 return CMD_RET_USAGE; 81 82 printf("Sensing bank %u:\n", bank); 83 for (i = 0; i < cnt; i++, word++) { 84 if (!(i % 4)) 85 printf("\nWord 0x%.8x:", word); 86 87 ret = fuse_sense(bank, word, &val); 88 if (ret) 89 goto err; 90 91 printf(" %.8x", val); 92 } 93 putc('\n'); 94 } else if (!strcmp(op, "prog")) { 95 if (argc < 3) 96 return CMD_RET_USAGE; 97 98 for (i = 2; i < argc; i++, word++) { 99 if (strtou32(argv[i], 16, &val)) 100 return CMD_RET_USAGE; 101 102 printf("Programming bank %u word 0x%.8x to 0x%.8x...\n", 103 bank, word, val); 104 if (!confirmed && !confirm_prog()) 105 return CMD_RET_FAILURE; 106 ret = fuse_prog(bank, word, val); 107 if (ret) 108 goto err; 109 } 110 } else if (!strcmp(op, "override")) { 111 if (argc < 3) 112 return CMD_RET_USAGE; 113 114 for (i = 2; i < argc; i++, word++) { 115 if (strtou32(argv[i], 16, &val)) 116 return CMD_RET_USAGE; 117 118 printf("Overriding bank %u word 0x%.8x with " 119 "0x%.8x...\n", bank, word, val); 120 ret = fuse_override(bank, word, val); 121 if (ret) 122 goto err; 123 } 124 } else { 125 return CMD_RET_USAGE; 126 } 127 128 return 0; 129 130 err: 131 puts("ERROR\n"); 132 return CMD_RET_FAILURE; 133 } 134 135 U_BOOT_CMD( 136 fuse, CONFIG_SYS_MAXARGS, 0, do_fuse, 137 "Fuse sub-system", 138 "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n" 139 " starting at 'word'\n" 140 "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n" 141 " starting at 'word'\n" 142 "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n" 143 " several fuse words, starting at 'word' (PERMANENT)\n" 144 "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n" 145 " several fuse words, starting at 'word'" 146 ); 147