[PATCH v2 1/2] cmd: add fuse_blow/fuse_sense for the i.MX IIM fusebox

Sascha Hauer s.hauer at pengutronix.de
Thu Aug 12 05:06:00 EDT 2010


On Thu, Aug 12, 2010 at 11:35:04AM +0300, Baruch Siach wrote:
> This has only been tested on i.MX25, but should work on other i.MX chips with
> IIM.

I would prefer this command to be implemented as a device driver which
registers a file under /dev. This way we could use the standard md/mw
commands for this and look at a nice hexdump of all fuses and not only
one at a time.
As blowing fuses is quite dangerous, an additional iim.writeenable
variable would be good.

Sorry, but a command with three positional arguments is just so U-Boot.

Sascha

> 
> Signed-off-by: Baruch Siach <baruch at tkos.co.il>
> ---
> 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 <baruch at tkos.co.il>,
> + * 	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 <common.h>
> +#include <command.h>
> +#include <asm/io.h>
> +#include <mach/imx-regs.h>
> +#include <mach/iim.h>
> +
> +#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 <bank> <row> <value>\n"
> +"Blow unblown fuses in <bank> <row> to match <value>\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 <bank> <row>\n"
> +"Sense the fuses row at <bank> <row>\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 at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the barebox mailing list