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