]> git.sur5r.net Git - u-boot/commitdiff
Add fuse API and commands
authorBenoît Thébaudeau <benoit.thebaudeau@advansee.com>
Tue, 23 Apr 2013 10:17:40 +0000 (10:17 +0000)
committerStefano Babic <sbabic@denx.de>
Sun, 28 Apr 2013 09:07:40 +0000 (11:07 +0200)
This can be useful for fuse-like hardware, OTP SoC options, etc.

Signed-off-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
README
common/Makefile
common/cmd_fuse.c [new file with mode: 0644]
doc/README.fuse [new file with mode: 0644]
include/config_cmd_all.h
include/fuse.h [new file with mode: 0644]

diff --git a/README b/README
index 0bc0af570062451f195a7e01dbb387048d1c134b..7f9f547cff48494609ea91d7888fc2bbc1af2aa3 100644 (file)
--- a/README
+++ b/README
@@ -844,6 +844,7 @@ The following options need to be configured:
                CONFIG_CMD_FDOS         * Dos diskette Support
                CONFIG_CMD_FLASH          flinfo, erase, protect
                CONFIG_CMD_FPGA           FPGA device initialization support
+               CONFIG_CMD_FUSE           Device fuse support
                CONFIG_CMD_GETTIME      * Get time since boot
                CONFIG_CMD_GO           * the 'go' command (exec code)
                CONFIG_CMD_GREPENV      * search environment
index 0e0fff1ffa30a44d2ce27d91d31956916006b3e3..1cfb13210f17b0150896be047969ee5d66ae54d5 100644 (file)
@@ -111,6 +111,7 @@ ifdef CONFIG_FPGA
 COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o
 endif
 COBJS-$(CONFIG_CMD_FS_GENERIC) += cmd_fs.o
+COBJS-$(CONFIG_CMD_FUSE) += cmd_fuse.o
 COBJS-$(CONFIG_CMD_GETTIME) += cmd_gettime.o
 COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o
 COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o
diff --git a/common/cmd_fuse.c b/common/cmd_fuse.c
new file mode 100644 (file)
index 0000000..f24c01c
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * (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>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fuse.h>
+#include <asm/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 (getc() == 'y') {
+               int c;
+
+               putc('y');
+               c = getc();
+               putc('\n');
+               if (c == '\r')
+                       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 ret;
+}
+
+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'"
+);
diff --git a/doc/README.fuse b/doc/README.fuse
new file mode 100644 (file)
index 0000000..1bc91c4
--- /dev/null
@@ -0,0 +1,67 @@
+Fuse API functions and commands
+
+The fuse API allows to control a fusebox and how it is used by the upper
+hardware layers.
+
+A fuse corresponds to a single non-volatile memory bit that can be programmed
+(i.e. blown, set to 1) only once. The programming operation is irreversible. A
+fuse that has not been programmed reads 0.
+
+Fuses can be used by SoCs to store various permanent configuration and data,
+e.g. boot configuration, security configuration, MAC addresses, etc.
+
+A fuse word is the smallest group of fuses that can be read at once from the
+fusebox control IP registers. This is limited to 32 bits with the current API.
+
+A fuse bank is the smallest group of fuse words having a common ID, as defined
+by each SoC.
+
+Upon startup, the fusebox control IP reads the fuse values and stores them to a
+volatile shadow cache.
+
+See the README files of the drivers implementing this API in order to know the
+SoC- and implementation-specific details.
+
+Functions / commands:
+
+   int fuse_read(u32 bank, u32 word, u32 *val);
+   fuse read <bank> <word> [<cnt>]
+      Read fuse words from the shadow cache.
+
+   int fuse_sense(u32 bank, u32 word, u32 *val);
+   fuse sense <bank> <word> [<cnt>]
+      Sense - i.e. read directly from the fusebox, skipping the shadow cache -
+      fuse words. This operation does not update the shadow cache.
+
+      This is useful to know the true value of fuses if an override has been
+      performed (see below).
+
+   int fuse_prog(u32 bank, u32 word, u32 val);
+   fuse prog [-y] <bank> <word> <hexval> [<hexval>...]
+      Program fuse words. This operation directly affects the fusebox and is
+      irreversible. The shadow cache is updated accordingly or not, depending on
+      each IP.
+
+      Only the bits to be programmed should be set in the input value (i.e. for
+      fuse bits that have already been programmed and hence should be left
+      unchanged by a further programming, it is preferable to clear the
+      corresponding bits in the input value in order not to perform a new
+      hardware programming operation on these fuse bits).
+
+   int fuse_override(u32 bank, u32 word, u32 val);
+   fuse override <bank> <word> <hexval> [<hexval>...]
+      Override fuse words in the shadow cache.
+
+      The fusebox is unaffected, so following this operation, the shadow cache
+      may differ from the fusebox values. Read or sense operations can then be
+      used to get the values from the shadow cache or from the fusebox.
+
+      This is useful to change the behaviors linked to some cached fuse values,
+      either because this is needed only temporarily, or because some of the
+      fuses have already been programmed or are locked (if the SoC allows to
+      override a locked fuse).
+
+Configuration:
+
+   CONFIG_CMD_FUSE
+      Define this to enable the fuse commands.
index 53a2f054f9488b8e3fc08fcb62f69a8fc282bbe0..d84706969d1b4117705c7bc8752be2976ca413bd 100644 (file)
@@ -40,6 +40,7 @@
 #define CONFIG_CMD_FDOS                /* Floppy DOS support           */
 #define CONFIG_CMD_FLASH       /* flinfo, erase, protect       */
 #define CONFIG_CMD_FPGA                /* FPGA configuration Support   */
+#define CONFIG_CMD_FUSE                /* Device fuse support          */
 #define CONFIG_CMD_GETTIME     /* Get time since boot         */
 #define CONFIG_CMD_HASH                /* calculate hash / digest      */
 #define CONFIG_CMD_HWFLOW      /* RTS/CTS hw flow control      */
diff --git a/include/fuse.h b/include/fuse.h
new file mode 100644 (file)
index 0000000..b964137
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * (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>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _FUSE_H_
+#define _FUSE_H_
+
+/*
+ * Read/Sense/Program/Override interface:
+ *   bank:    Fuse bank
+ *   word:    Fuse word within the bank
+ *   val:     Value to read/write
+ *
+ *   Returns: 0 on success, not 0 on failure
+ */
+int fuse_read(u32 bank, u32 word, u32 *val);
+int fuse_sense(u32 bank, u32 word, u32 *val);
+int fuse_prog(u32 bank, u32 word, u32 val);
+int fuse_override(u32 bank, u32 word, u32 val);
+
+#endif /* _FUSE_H_ */