From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from tango.tkos.co.il ([62.219.50.35]) by bombadil.infradead.org with esmtps (Exim 4.72 #1 (Red Hat Linux)) id 1OjTGC-00053p-4X for barebox@lists.infradead.org; Thu, 12 Aug 2010 08:35:40 +0000 From: Baruch Siach Date: Thu, 12 Aug 2010 11:35:04 +0300 Message-Id: <5a5cd75e51961a57b99c0727faa8b3eaa619b943.1281601710.git.baruch@tkos.co.il> In-Reply-To: <20100810070909.GB10920@game.jcrosoft.org> References: <20100810070909.GB10920@game.jcrosoft.org> List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: barebox-bounces@lists.infradead.org Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: [PATCH v2 1/2] cmd: add fuse_blow/fuse_sense for the i.MX IIM fusebox To: barebox@lists.infradead.org This has only been tested on i.MX25, but should work on other i.MX chips with IIM. Signed-off-by: Baruch Siach --- Changes from v1: Improve commands documentation and add a comment describing the fuse commands. Make fuse_blow and fuse_sense build independent from each other. commands/Kconfig | 10 +++ commands/Makefile | 2 + commands/fuse.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 0 deletions(-) create mode 100644 commands/fuse.c diff --git a/commands/Kconfig b/commands/Kconfig index 9d11a8b..1eae0d7 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -173,6 +173,16 @@ config CMD_MTEST_ALTERNATIVE depends on CMD_MTEST prompt "alternative mtest implementation" +config CMD_FUSE_BLOW + tristate + depends on ARCH_IMX25 || ARCH_IMX35 + prompt "fuse_blow" + +config CMD_FUSE_SENSE + tristate + depends on ARCH_IMX25 || ARCH_IMX35 + prompt "fuse_sense" + endmenu menu "flash " diff --git a/commands/Makefile b/commands/Makefile index 276af85..3c4e1d1 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -8,6 +8,8 @@ obj-$(CONFIG_CMD_ECHO) += echo.o obj-$(CONFIG_CMD_MEMORY) += mem.o obj-$(CONFIG_CMD_LOADS) += s_record.o obj-$(CONFIG_CMD_MTEST) += memtest.o +obj-$(CONFIG_CMD_FUSE_BLOW) += fuse.o +obj-$(CONFIG_CMD_FUSE_SENSE) += fuse.o obj-$(CONFIG_CMD_EDIT) += edit.o obj-$(CONFIG_CMD_EXEC) += exec.o obj-$(CONFIG_CMD_SLEEP) += sleep.o diff --git a/commands/fuse.c b/commands/fuse.c new file mode 100644 index 0000000..c9059b3 --- /dev/null +++ b/commands/fuse.c @@ -0,0 +1,175 @@ +/* + * fuse.c - i.MX IIM fusebox programing and sensing + * + * Provide an interface for programming and sensing the information that are + * stored in on-chip fuse elements. This functionality is part of the IC + * Identification Module (IIM), which is present on some i.MX CPUs. + * + * Copyright (c) 2010 Baruch Siach , + * Orex Computed Radiography + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_CMD_FUSE_BLOW + +static int do_fuse_blow(struct command *cmdtp, int argc, char *argv[]) +{ + unsigned int bank, row, value; + int bit, ret = 0; + u8 err, stat; + + if (argc != 4) + return COMMAND_ERROR_USAGE; + + bank = simple_strtoul(argv[1], NULL, 0); + row = simple_strtoul(argv[2], NULL, 0); + value = simple_strtoul(argv[3], NULL, 0); + + if (bank > 7) { + printf("fuse_blow: invalid bank number\n"); + return 1; + } + + if (row > 0x3ff) { + printf("fuse_blow: invalid row offset\n"); + return 1; + } + + if (value > 0xff) { + printf("fuse_blow: invalid value\n"); + return 1; + } + + /* clear status and error registers */ + writeb(3, IMX_IIM_BASE + IIM_STATM); + writeb(0xfe, IMX_IIM_BASE + IIM_ERR); + + /* unprotect fuse programing */ + writeb(0xaa, IMX_IIM_BASE + IIM_PREG_P); + + /* upper half address register */ + writeb((bank << 3) | (row >> 7), IMX_IIM_BASE + IIM_UA); + + for (bit = 0; bit < 8; bit++) { + if (((value >> bit) & 1) == 0) + continue; + + /* lower half address register */ + writeb(((row << 1) | bit), IMX_IIM_BASE + IIM_LA); + + /* start fuse programing */ + writeb(0x71, IMX_IIM_BASE + IIM_FCTL); + + /* wait for program done */ + while ((readb(IMX_IIM_BASE + IIM_STAT) & 0x80) != 0) + ; + + /* clear program done status */ + stat = readb(IMX_IIM_BASE + IIM_STAT); + writeb(stat, IMX_IIM_BASE + IIM_STAT); + + err = readb(IMX_IIM_BASE + IIM_ERR); + if (err) { + printf("fuse_blow: bit %d program error (0x%02x)\n", + bit, err); + ret = 1; + goto out; + } + } + +out: + /* protect fuse programing */ + writeb(0, IMX_IIM_BASE + IIM_PREG_P); + return ret; +} + +static const __maybe_unused char cmd_fuse_blow_help[] = +"Usage: fuse_blow \n" +"Blow unblown fuses in to match \n" +"Blown fuses are read as 1. Unblown fuses are read as 0.\n" +"WARNING: blown fuses can not be unblown. Use this command carefully.\n"; + +BAREBOX_CMD_START(fuse_blow) + .cmd = do_fuse_blow, + .usage = "program a row of fuses (8 bit)", + BAREBOX_CMD_HELP(cmd_fuse_blow_help) +BAREBOX_CMD_END + +#endif /* CONFIG_CMD_FUSE_BLOW */ + +#ifdef CONFIG_CMD_FUSE_SENSE + +static int do_fuse_sense(struct command *cmdtp, int argc, char *argv[]) +{ + unsigned int bank, row; + u8 err, stat; + + if (argc != 3) + return COMMAND_ERROR_USAGE; + + bank = simple_strtoul(argv[1], NULL, 0); + row = simple_strtoul(argv[2], NULL, 0); + + if (bank > 7) { + printf("fuse_sense: invalid bank number\n"); + return 1; + } + + if (row > 0x3ff) { + printf("fuse_sense: invalid row offset\n"); + return 1; + } + + /* clear status and error registers */ + writeb(3, IMX_IIM_BASE + IIM_STATM); + writeb(0xfe, IMX_IIM_BASE + IIM_ERR); + + /* upper and lower address halves */ + writeb((bank << 3) | (row >> 7), IMX_IIM_BASE + IIM_UA); + writeb((row << 1) & 0xf8, IMX_IIM_BASE + IIM_LA); + + /* start fuse sensing */ + writeb(0x08, IMX_IIM_BASE + IIM_FCTL); + + /* wait for sense done */ + while ((readb(IMX_IIM_BASE + IIM_STAT) & 0x80) != 0) + ; + + stat = readb(IMX_IIM_BASE + IIM_STAT); + writeb(stat, IMX_IIM_BASE + IIM_STAT); + + err = readb(IMX_IIM_BASE + IIM_ERR); + if (err) { + printf("fuse_sense: sense error (0x%02x)\n", err); + return 1; + } + + printf("bank %u row 0x%02x: 0x%02x\n", bank, row, + readb(IMX_IIM_BASE + IIM_SDAT)); + + return 0; +} + +static const __maybe_unused char cmd_fuse_sense_help[] = +"Usage: fuse_sense \n" +"Sense the fuses row at \n"; + +BAREBOX_CMD_START(fuse_sense) + .cmd = do_fuse_sense, + .usage = "sense a row of fuses (8 bit)", + BAREBOX_CMD_HELP(cmd_fuse_sense_help) +BAREBOX_CMD_END + +#endif /* CONFIG_CMD_FUSE_SENSE */ -- 1.7.1 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox