···11+/*
22+ * (C) Copyright 2009-2013 ADVANSEE
33+ * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
44+ *
55+ * Based on the mpc512x iim code:
66+ * Copyright 2008 Silicon Turnkey Express, Inc.
77+ * Martha Marx <mmarx@silicontkx.com>
88+ *
99+ * See file CREDITS for list of people who contributed to this
1010+ * project.
1111+ *
1212+ * This program is free software; you can redistribute it and/or
1313+ * modify it under the terms of the GNU General Public License as
1414+ * published by the Free Software Foundation; either version 2 of
1515+ * the License, or (at your option) any later version.
1616+ *
1717+ * This program is distributed in the hope that it will be useful,
1818+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2020+ * GNU General Public License for more details.
2121+ *
2222+ * You should have received a copy of the GNU General Public License
2323+ * along with this program; if not, write to the Free Software
2424+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2525+ * MA 02111-1307 USA
2626+ */
2727+2828+#include <common.h>
2929+#include <command.h>
3030+#include <fuse.h>
3131+#include <asm/errno.h>
3232+3333+static int strtou32(const char *str, unsigned int base, u32 *result)
3434+{
3535+ char *ep;
3636+3737+ *result = simple_strtoul(str, &ep, base);
3838+ if (ep == str || *ep != '\0')
3939+ return -EINVAL;
4040+4141+ return 0;
4242+}
4343+4444+static int confirm_prog(void)
4545+{
4646+ puts("Warning: Programming fuses is an irreversible operation!\n"
4747+ " This may brick your system.\n"
4848+ " Use this command only if you are sure of "
4949+ "what you are doing!\n"
5050+ "\nReally perform this fuse programming? <y/N>\n");
5151+5252+ if (getc() == 'y') {
5353+ int c;
5454+5555+ putc('y');
5656+ c = getc();
5757+ putc('\n');
5858+ if (c == '\r')
5959+ return 1;
6060+ }
6161+6262+ puts("Fuse programming aborted\n");
6363+ return 0;
6464+}
6565+6666+static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
6767+{
6868+ const char *op = argc >= 2 ? argv[1] : NULL;
6969+ int confirmed = argc >= 3 && !strcmp(argv[2], "-y");
7070+ u32 bank, word, cnt, val;
7171+ int ret, i;
7272+7373+ argc -= 2 + confirmed;
7474+ argv += 2 + confirmed;
7575+7676+ if (argc < 2 || strtou32(argv[0], 0, &bank) ||
7777+ strtou32(argv[1], 0, &word))
7878+ return CMD_RET_USAGE;
7979+8080+ if (!strcmp(op, "read")) {
8181+ if (argc == 2)
8282+ cnt = 1;
8383+ else if (argc != 3 || strtou32(argv[2], 0, &cnt))
8484+ return CMD_RET_USAGE;
8585+8686+ printf("Reading bank %u:\n", bank);
8787+ for (i = 0; i < cnt; i++, word++) {
8888+ if (!(i % 4))
8989+ printf("\nWord 0x%.8x:", word);
9090+9191+ ret = fuse_read(bank, word, &val);
9292+ if (ret)
9393+ goto err;
9494+9595+ printf(" %.8x", val);
9696+ }
9797+ putc('\n');
9898+ } else if (!strcmp(op, "sense")) {
9999+ if (argc == 2)
100100+ cnt = 1;
101101+ else if (argc != 3 || strtou32(argv[2], 0, &cnt))
102102+ return CMD_RET_USAGE;
103103+104104+ printf("Sensing bank %u:\n", bank);
105105+ for (i = 0; i < cnt; i++, word++) {
106106+ if (!(i % 4))
107107+ printf("\nWord 0x%.8x:", word);
108108+109109+ ret = fuse_sense(bank, word, &val);
110110+ if (ret)
111111+ goto err;
112112+113113+ printf(" %.8x", val);
114114+ }
115115+ putc('\n');
116116+ } else if (!strcmp(op, "prog")) {
117117+ if (argc < 3)
118118+ return CMD_RET_USAGE;
119119+120120+ for (i = 2; i < argc; i++, word++) {
121121+ if (strtou32(argv[i], 16, &val))
122122+ return CMD_RET_USAGE;
123123+124124+ printf("Programming bank %u word 0x%.8x to 0x%.8x...\n",
125125+ bank, word, val);
126126+ if (!confirmed && !confirm_prog())
127127+ return CMD_RET_FAILURE;
128128+ ret = fuse_prog(bank, word, val);
129129+ if (ret)
130130+ goto err;
131131+ }
132132+ } else if (!strcmp(op, "override")) {
133133+ if (argc < 3)
134134+ return CMD_RET_USAGE;
135135+136136+ for (i = 2; i < argc; i++, word++) {
137137+ if (strtou32(argv[i], 16, &val))
138138+ return CMD_RET_USAGE;
139139+140140+ printf("Overriding bank %u word 0x%.8x with "
141141+ "0x%.8x...\n", bank, word, val);
142142+ ret = fuse_override(bank, word, val);
143143+ if (ret)
144144+ goto err;
145145+ }
146146+ } else {
147147+ return CMD_RET_USAGE;
148148+ }
149149+150150+ return 0;
151151+152152+err:
153153+ puts("ERROR\n");
154154+ return ret;
155155+}
156156+157157+U_BOOT_CMD(
158158+ fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
159159+ "Fuse sub-system",
160160+ "read <bank> <word> [<cnt>] - read 1 or 'cnt' fuse words,\n"
161161+ " starting at 'word'\n"
162162+ "fuse sense <bank> <word> [<cnt>] - sense 1 or 'cnt' fuse words,\n"
163163+ " starting at 'word'\n"
164164+ "fuse prog [-y] <bank> <word> <hexval> [<hexval>...] - program 1 or\n"
165165+ " several fuse words, starting at 'word' (PERMANENT)\n"
166166+ "fuse override <bank> <word> <hexval> [<hexval>...] - override 1 or\n"
167167+ " several fuse words, starting at 'word'"
168168+);
+67
doc/README.fuse
···11+Fuse API functions and commands
22+33+The fuse API allows to control a fusebox and how it is used by the upper
44+hardware layers.
55+66+A fuse corresponds to a single non-volatile memory bit that can be programmed
77+(i.e. blown, set to 1) only once. The programming operation is irreversible. A
88+fuse that has not been programmed reads 0.
99+1010+Fuses can be used by SoCs to store various permanent configuration and data,
1111+e.g. boot configuration, security configuration, MAC addresses, etc.
1212+1313+A fuse word is the smallest group of fuses that can be read at once from the
1414+fusebox control IP registers. This is limited to 32 bits with the current API.
1515+1616+A fuse bank is the smallest group of fuse words having a common ID, as defined
1717+by each SoC.
1818+1919+Upon startup, the fusebox control IP reads the fuse values and stores them to a
2020+volatile shadow cache.
2121+2222+See the README files of the drivers implementing this API in order to know the
2323+SoC- and implementation-specific details.
2424+2525+Functions / commands:
2626+2727+ int fuse_read(u32 bank, u32 word, u32 *val);
2828+ fuse read <bank> <word> [<cnt>]
2929+ Read fuse words from the shadow cache.
3030+3131+ int fuse_sense(u32 bank, u32 word, u32 *val);
3232+ fuse sense <bank> <word> [<cnt>]
3333+ Sense - i.e. read directly from the fusebox, skipping the shadow cache -
3434+ fuse words. This operation does not update the shadow cache.
3535+3636+ This is useful to know the true value of fuses if an override has been
3737+ performed (see below).
3838+3939+ int fuse_prog(u32 bank, u32 word, u32 val);
4040+ fuse prog [-y] <bank> <word> <hexval> [<hexval>...]
4141+ Program fuse words. This operation directly affects the fusebox and is
4242+ irreversible. The shadow cache is updated accordingly or not, depending on
4343+ each IP.
4444+4545+ Only the bits to be programmed should be set in the input value (i.e. for
4646+ fuse bits that have already been programmed and hence should be left
4747+ unchanged by a further programming, it is preferable to clear the
4848+ corresponding bits in the input value in order not to perform a new
4949+ hardware programming operation on these fuse bits).
5050+5151+ int fuse_override(u32 bank, u32 word, u32 val);
5252+ fuse override <bank> <word> <hexval> [<hexval>...]
5353+ Override fuse words in the shadow cache.
5454+5555+ The fusebox is unaffected, so following this operation, the shadow cache
5656+ may differ from the fusebox values. Read or sense operations can then be
5757+ used to get the values from the shadow cache or from the fusebox.
5858+5959+ This is useful to change the behaviors linked to some cached fuse values,
6060+ either because this is needed only temporarily, or because some of the
6161+ fuses have already been programmed or are locked (if the SoC allows to
6262+ override a locked fuse).
6363+6464+Configuration:
6565+6666+ CONFIG_CMD_FUSE
6767+ Define this to enable the fuse commands.
+1
include/config_cmd_all.h
···4040#define CONFIG_CMD_FDOS /* Floppy DOS support */
4141#define CONFIG_CMD_FLASH /* flinfo, erase, protect */
4242#define CONFIG_CMD_FPGA /* FPGA configuration Support */
4343+#define CONFIG_CMD_FUSE /* Device fuse support */
4344#define CONFIG_CMD_GETTIME /* Get time since boot */
4445#define CONFIG_CMD_HASH /* calculate hash / digest */
4546#define CONFIG_CMD_HWFLOW /* RTS/CTS hw flow control */
+44
include/fuse.h
···11+/*
22+ * (C) Copyright 2009-2013 ADVANSEE
33+ * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
44+ *
55+ * Based on the mpc512x iim code:
66+ * Copyright 2008 Silicon Turnkey Express, Inc.
77+ * Martha Marx <mmarx@silicontkx.com>
88+ *
99+ * See file CREDITS for list of people who contributed to this
1010+ * project.
1111+ *
1212+ * This program is free software; you can redistribute it and/or
1313+ * modify it under the terms of the GNU General Public License as
1414+ * published by the Free Software Foundation; either version 2 of
1515+ * the License, or (at your option) any later version.
1616+ *
1717+ * This program is distributed in the hope that it will be useful,
1818+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1919+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2020+ * GNU General Public License for more details.
2121+ *
2222+ * You should have received a copy of the GNU General Public License
2323+ * along with this program; if not, write to the Free Software
2424+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2525+ * MA 02111-1307 USA
2626+ */
2727+2828+#ifndef _FUSE_H_
2929+#define _FUSE_H_
3030+3131+/*
3232+ * Read/Sense/Program/Override interface:
3333+ * bank: Fuse bank
3434+ * word: Fuse word within the bank
3535+ * val: Value to read/write
3636+ *
3737+ * Returns: 0 on success, not 0 on failure
3838+ */
3939+int fuse_read(u32 bank, u32 word, u32 *val);
4040+int fuse_sense(u32 bank, u32 word, u32 *val);
4141+int fuse_prog(u32 bank, u32 word, u32 val);
4242+int fuse_override(u32 bank, u32 word, u32 val);
4343+4444+#endif /* _FUSE_H_ */