/* * (C) Copyright 2009-2013 ADVANSEE * Benoît Thébaudeau <benoit.thebaudeau@advansee.com> * * Based on the mpc512x iim code: * Copyright 2008 Silicon Turnkey Express, Inc. * Martha Marx <mmarx@silicontkx.com> * * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> #include <command.h> #include <console.h> #include <fuse.h> #include <linux/errno.h> static int strtou32(const char *str, unsigned int base, u32 *result) { char *ep; *result = simple_strtoul(str, &ep, base); if (ep == str || *ep != '\0') return -EINVAL; return 0; } static int confirm_prog(void) { puts("Warning: Programming fuses is an irreversible operation!\n" " This may brick your system.\n" " Use this command only if you are sure of " "what you are doing!\n" "\nReally perform this fuse programming? <y/N>\n"); if (confirm_yesno()) return 1; puts("Fuse programming aborted\n"); return 0; } static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { const char *op = argc >= 2 ? argv[1] : NULL; int confirmed = argc >= 3 && !strcmp(argv[2], "-y"); u32 bank, word, cnt, val; int ret, i; argc -= 2 + confirmed; argv += 2 + confirmed; if (argc < 2 || strtou32(argv[0], 0, &bank) || strtou32(argv[1], 0, &word)) return CMD_RET_USAGE; if (!strcmp(op, "read")) { if (argc == 2) cnt = 1; else if (argc != 3 || strtou32(argv[2], 0, &cnt)) return CMD_RET_USAGE; printf("Reading bank %u:\n", bank); for (i = 0; i < cnt; i++, word++) { if (!(i % 4)) printf("\nWord 0x%.8x:", word); ret = fuse_read(bank, word, &val); if (ret) goto err; printf(" %.8x", val); } putc('\n'); } else if (!strcmp(op, "sense")) { if (argc == 2) cnt = 1; else if (argc != 3 || strtou32(argv[2], 0, &cnt)) return CMD_RET_USAGE; printf("Sensing bank %u:\n", bank); for (i = 0; i < cnt; i++, word++) { if (!(i % 4)) printf("\nWord 0x%.8x:", word); ret = fuse_sense(bank, word, &val); if (ret) goto err; printf(" %.8x", val); } putc('\n'); } else if (!strcmp(op, "prog")) { if (argc < 3) return CMD_RET_USAGE; for (i = 2; i < argc; i++, word++) { if (strtou32(argv[i], 16, &val)) return CMD_RET_USAGE; printf("Programming bank %u word 0x%.8x to 0x%.8x...\n", bank, word, val); if (!confirmed && !confirm_prog()) return CMD_RET_FAILURE; ret = fuse_prog(bank, word, val); if (ret) goto err; } } else if (!strcmp(op, "override")) { if (argc < 3) return CMD_RET_USAGE; for (i = 2; i < argc; i++, word++) { if (strtou32(argv[i], 16, &val)) return CMD_RET_USAGE; printf("Overriding bank %u word 0x%.8x with " "0x%.8x...\n", bank, word, val); ret = fuse_override(bank, word, val); if (ret) goto err; } } else { return CMD_RET_USAGE; } return 0; err: puts("ERROR\n"); return CMD_RET_FAILURE; } U_BOOT_CMD( fuse, CONFIG_SYS_MAXARGS, 0, do_fuse, "Fuse sub-system", "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n" " starting at 'word'\n" "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n" " starting at 'word'\n" "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n" " several fuse words, starting at 'word' (PERMANENT)\n" "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n" " several fuse words, starting at 'word'" );