[U-Boot] [PATCH 0/5] Make iim support common to mpc and imx

Homogenize prg_p naming (the reference manuals are not always self-consistent for that). Add missing registers. Fix some registers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- .../arch/arm/include/asm/arch-mx25/imx-regs.h | 8 ++++++-- .../arch/arm/include/asm/arch-mx27/imx-regs.h | 2 +- .../arch/arm/include/asm/arch-mx31/imx-regs.h | 9 +++++++-- .../arch/arm/include/asm/arch-mx35/imx-regs.h | 7 ++++++- .../arch/arm/include/asm/arch-mx5/imx-regs.h | 6 +++++- 5 files changed, 25 insertions(+), 7 deletions(-)
diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx25/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx25/imx-regs.h index cf925d7..b7b4d07 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx25/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx25/imx-regs.h @@ -118,8 +118,12 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; - u32 res1[0x1f5]; + u32 iim_prg_p; + u32 iim_scs0; + u32 iim_scs1; + u32 iim_scs2; + u32 iim_scs3; + u32 res1[0x1f1]; struct fuse_bank { u32 fuse_regs[0x20]; u32 fuse_rsvd[0xe0]; diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx27/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx27/imx-regs.h index ced5b2a..bfca963 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx27/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx27/imx-regs.h @@ -197,7 +197,7 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; + u32 iim_prg_p; u32 iim_scs0; u32 iim_scs1; u32 iim_scs2; diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx31/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx31/imx-regs.h index 7ddbbd6..c2db85f 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx31/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx31/imx-regs.h @@ -79,7 +79,7 @@ struct wdog_regs { u16 wrsr; /* Reset Status */ };
-/* IIM Control Registers */ +/* IIM control registers */ struct iim_regs { u32 iim_stat; u32 iim_statm; @@ -91,11 +91,16 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; + u32 iim_prg_p; u32 iim_scs0; u32 iim_scs1; u32 iim_scs2; u32 iim_scs3; + u32 res[0x1f1]; + struct fuse_bank { + u32 fuse_regs[0x20]; + u32 fuse_rsvd[0xe0]; + } bank[3]; };
struct iomuxc_regs { diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx35/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx35/imx-regs.h index 3146006..f75e5c2 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx35/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx35/imx-regs.h @@ -283,11 +283,16 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; + u32 iim_prg_p; u32 iim_scs0; u32 iim_scs1; u32 iim_scs2; u32 iim_scs3; + u32 res1[0x1f1]; + struct fuse_bank { + u32 fuse_regs[0x20]; + u32 fuse_rsvd[0xe0]; + } bank[3]; };
/* General Purpose Timer (GPT) registers */ diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h index 7f66b61..33d2097 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -482,7 +482,7 @@ struct iim_regs { u32 sdat; u32 prev; u32 srev; - u32 preg_p; + u32 prg_p; u32 scs0; u32 scs1; u32 scs2; @@ -491,7 +491,11 @@ struct iim_regs { struct fuse_bank { u32 fuse_regs[0x20]; u32 fuse_rsvd[0xe0]; +#if defined(CONFIG_MX51) } bank[4]; +#elif defined(CONFIG_MX53) + } bank[5]; +#endif };
struct fuse_bank0_regs {

Homogenize prg_p naming (the reference manuals are not always self-consistent for that). Add missing registers. Fix some registers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- This patch supersedes http://patchwork.ozlabs.org/patch/177242/ . Changes for v2: - Rebase against latest master.
.../arch/arm/include/asm/arch-mx25/imx-regs.h | 8 ++++++-- .../arch/arm/include/asm/arch-mx27/imx-regs.h | 2 +- .../arch/arm/include/asm/arch-mx31/imx-regs.h | 9 +++++++-- .../arch/arm/include/asm/arch-mx35/imx-regs.h | 7 ++++++- .../arch/arm/include/asm/arch-mx5/imx-regs.h | 6 +++++- 5 files changed, 25 insertions(+), 7 deletions(-)
diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx25/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx25/imx-regs.h index 53aafe3..1b71168 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx25/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx25/imx-regs.h @@ -117,8 +117,12 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; - u32 res1[0x1f5]; + u32 iim_prg_p; + u32 iim_scs0; + u32 iim_scs1; + u32 iim_scs2; + u32 iim_scs3; + u32 res1[0x1f1]; struct fuse_bank { u32 fuse_regs[0x20]; u32 fuse_rsvd[0xe0]; diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx27/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx27/imx-regs.h index 2f6c823..aee058f 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx27/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx27/imx-regs.h @@ -176,7 +176,7 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; + u32 iim_prg_p; u32 iim_scs0; u32 iim_scs1; u32 iim_scs2; diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx31/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx31/imx-regs.h index 8fd3d08..e799f37 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx31/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx31/imx-regs.h @@ -79,7 +79,7 @@ struct wdog_regs { u16 wrsr; /* Reset Status */ };
-/* IIM Control Registers */ +/* IIM control registers */ struct iim_regs { u32 iim_stat; u32 iim_statm; @@ -91,11 +91,16 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; + u32 iim_prg_p; u32 iim_scs0; u32 iim_scs1; u32 iim_scs2; u32 iim_scs3; + u32 res[0x1f1]; + struct fuse_bank { + u32 fuse_regs[0x20]; + u32 fuse_rsvd[0xe0]; + } bank[3]; };
struct iomuxc_regs { diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx35/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx35/imx-regs.h index 7b09809..6161784 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx35/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx35/imx-regs.h @@ -258,11 +258,16 @@ struct iim_regs { u32 iim_sdat; u32 iim_prev; u32 iim_srev; - u32 iim_prog_p; + u32 iim_prg_p; u32 iim_scs0; u32 iim_scs1; u32 iim_scs2; u32 iim_scs3; + u32 res1[0x1f1]; + struct fuse_bank { + u32 fuse_regs[0x20]; + u32 fuse_rsvd[0xe0]; + } bank[3]; };
/* General Purpose Timer (GPT) registers */ diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx5/imx-regs.h index 1d060fd..8f0a7ec 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -508,7 +508,7 @@ struct iim_regs { u32 sdat; u32 prev; u32 srev; - u32 preg_p; + u32 prg_p; u32 scs0; u32 scs1; u32 scs2; @@ -517,7 +517,11 @@ struct iim_regs { struct fuse_bank { u32 fuse_regs[0x20]; u32 fuse_rsvd[0xe0]; +#if defined(CONFIG_MX51) } bank[4]; +#elif defined(CONFIG_MX53) + } bank[5]; +#endif };
struct fuse_bank0_regs {

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- This patch supersedes http://patchwork.ozlabs.org/patch/177243/ . Changes for v2: - Rebase against latest master.
.../arch/arm/include/asm/arch-mx25/imx-regs.h | 11 ++++++++++- .../arch/arm/include/asm/arch-mx31/imx-regs.h | 12 ++++++++++++ .../arch/arm/include/asm/arch-mx35/imx-regs.h | 12 ++++++++++++ .../arch/arm/include/asm/arch-mx5/imx-regs.h | 16 +++++++++++++++- 4 files changed, 49 insertions(+), 2 deletions(-)
diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx25/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx25/imx-regs.h index 1b71168..9037ee5 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx25/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx25/imx-regs.h @@ -130,10 +130,19 @@ struct iim_regs { };
struct fuse_bank0_regs { - u32 fuse0_25[0x1a]; + u32 fuse0_7[8]; + u32 uid[8]; + u32 fuse16_25[0xa]; u32 mac_addr[6]; };
+struct fuse_bank1_regs { + u32 fuse0_21[0x16]; + u32 usr5; + u32 fuse23_29[7]; + u32 usr6[2]; +}; + /* Multi-Layer AHB Crossbar Switch (MAX) registers */ struct max_regs { u32 mpr0; diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx31/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx31/imx-regs.h index e799f37..81b25ae 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx31/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx31/imx-regs.h @@ -103,6 +103,18 @@ struct iim_regs { } bank[3]; };
+struct fuse_bank0_regs { + u32 fuse0_5[6]; + u32 usr; + u32 fuse7_15[9]; +}; + +struct fuse_bank2_regs { + u32 fuse0; + u32 uid[8]; + u32 fuse9_15[7]; +}; + struct iomuxc_regs { u32 unused1; u32 unused2; diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx35/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx35/imx-regs.h index 6161784..b3c733b 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx35/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx35/imx-regs.h @@ -270,6 +270,18 @@ struct iim_regs { } bank[3]; };
+struct fuse_bank0_regs { + u32 fuse0_7[8]; + u32 uid[8]; + u32 fuse16_31[0x10]; +}; + +struct fuse_bank1_regs { + u32 fuse0_21[0x16]; + u32 usr; + u32 fuse23_31[9]; +}; + /* General Purpose Timer (GPT) registers */ struct gpt_regs { u32 ctrl; /* control */ diff --git u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-178d0cc/arch/arm/include/asm/arch-mx5/imx-regs.h index 8f0a7ec..70a5b1c 100644 --- u-boot-178d0cc.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-178d0cc/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -525,8 +525,14 @@ struct iim_regs { };
struct fuse_bank0_regs { - u32 fuse0_23[24]; + u32 fuse0_7[8]; + u32 uid[8]; + u32 fuse16_23[8]; +#if defined(CONFIG_MX51) + u32 imei[8]; +#elif defined(CONFIG_MX53) u32 gp[8]; +#endif };
struct fuse_bank1_regs { @@ -535,6 +541,14 @@ struct fuse_bank1_regs { u32 fuse15_31[0x11]; };
+#if defined(CONFIG_MX53) +struct fuse_bank4_regs { + u32 fuse0_4[5]; + u32 gp[3]; + u32 fuse8_31[0x18]; +}; +#endif + #endif /* __ASSEMBLER__*/
#endif /* __ASM_ARCH_MX5_IMX_REGS_H__ */

This can be useful for fuse-like hardware, OTP SoC options, etc.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de --- This patch supersedes http://patchwork.ozlabs.org/patch/177244/ . Changes for v2: - Rebase against latest master.
{u-boot-178d0cc.orig => u-boot-178d0cc}/README | 1 + .../common/Makefile | 1 + /dev/null => u-boot-178d0cc/common/cmd_fuse.c | 182 ++++++++++++++++++++ .../include/config_cmd_all.h | 1 + /dev/null => u-boot-178d0cc/include/fuse.h | 49 ++++++ 5 files changed, 234 insertions(+) create mode 100644 u-boot-178d0cc/common/cmd_fuse.c create mode 100644 u-boot-178d0cc/include/fuse.h
diff --git u-boot-178d0cc.orig/README u-boot-178d0cc/README index 2dc0984..cec071e 100644 --- u-boot-178d0cc.orig/README +++ u-boot-178d0cc/README @@ -819,6 +819,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_GO * the 'go' command (exec code) CONFIG_CMD_GREPENV * search environment CONFIG_CMD_HWFLOW * RTS/CTS hw flow control diff --git u-boot-178d0cc.orig/common/Makefile u-boot-178d0cc/common/Makefile index 9e43322..5212575 100644 --- u-boot-178d0cc.orig/common/Makefile +++ u-boot-178d0cc/common/Makefile @@ -100,6 +100,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_GPIO) += cmd_gpio.o COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o diff --git u-boot-178d0cc/common/cmd_fuse.c u-boot-178d0cc/common/cmd_fuse.c new file mode 100644 index 0000000..fd54d40 --- /dev/null +++ u-boot-178d0cc/common/cmd_fuse.c @@ -0,0 +1,182 @@ +/* + * (C) Copyright 2009-2012 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 do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + u32 bank, row, bit, cnt, val; + int ret, i; + + if (argc < 4 || strtou32(argv[2], 0, &bank) || + strtou32(argv[3], 0, &row)) + return CMD_RET_USAGE; + + if (!strcmp(argv[1], "read.bit")) { + if (argc != 5 || strtou32(argv[4], 0, &bit)) + return CMD_RET_USAGE; + + printf("Reading bank %u row 0x%.8x bit %u: ", bank, row, bit); + ret = fuse_read_bit(bank, row, bit, &val); + if (ret) + goto err; + + printf("%u\n", val); + } else if (!strcmp(argv[1], "read.row")) { + if (argc == 4) + cnt = 1; + else if (argc != 5 || strtou32(argv[4], 0, &cnt)) + return CMD_RET_USAGE; + + printf("Reading bank %u:\n", bank); + for (i = 0; i < cnt; i++, row++) { + if (!(i % 4)) + printf("\nRow 0x%.8x:", row); + + ret = fuse_read_row(bank, row, &val); + if (ret) + goto err; + + printf(" %.8x", val); + } + putc('\n'); + } else if (!strcmp(argv[1], "sense.bit")) { + if (argc != 5 || strtou32(argv[4], 0, &bit)) + return CMD_RET_USAGE; + + printf("Sensing bank %u row 0x%.8x bit %u: ", bank, row, bit); + ret = fuse_sense_bit(bank, row, bit, &val); + if (ret) + goto err; + + printf("%u\n", val); + } else if (!strcmp(argv[1], "sense.row")) { + if (argc == 4) + cnt = 1; + else if (argc != 5 || strtou32(argv[4], 0, &cnt)) + return CMD_RET_USAGE; + + printf("Sensing bank %u:\n", bank); + for (i = 0; i < cnt; i++, row++) { + if (!(i % 4)) + printf("\nRow 0x%.8x:", row); + + ret = fuse_sense_row(bank, row, &val); + if (ret) + goto err; + + printf(" %.8x", val); + } + putc('\n'); + } else if (!strcmp(argv[1], "prog.bit")) { + if (argc != 5 || strtou32(argv[4], 0, &bit)) + return CMD_RET_USAGE; + + printf("Programming bank %u row 0x%.8x bit %u...\n", + bank, row, bit); + ret = fuse_prog_bit(bank, row, bit); + if (ret) + goto err; + } else if (!strcmp(argv[1], "prog.row")) { + if (argc < 5) + return CMD_RET_USAGE; + + for (i = 4; i < argc; i++, row++) { + if (strtou32(argv[i], 16, &val)) + return CMD_RET_USAGE; + + printf("Programming bank %u row 0x%.8x to 0x%.8x...\n", + bank, row, val); + ret = fuse_prog_row(bank, row, val); + if (ret) + goto err; + } + } else if (!strcmp(argv[1], "ovride.bit")) { + if (argc != 6 || strtou32(argv[4], 0, &bit) || + strtou32(argv[5], 0, &val) || val > 1) + return CMD_RET_USAGE; + + printf("Overriding bank %u row 0x%.8x bit %u with %u...\n", + bank, row, bit, val); + ret = fuse_override_bit(bank, row, bit, val); + if (ret) + goto err; + } else if (!strcmp(argv[1], "ovride.row")) { + if (argc < 5) + return CMD_RET_USAGE; + + for (i = 4; i < argc; i++, row++) { + if (strtou32(argv[i], 16, &val)) + return CMD_RET_USAGE; + + printf("Overriding bank %u row 0x%.8x with 0x%.8x...\n", + bank, row, val); + ret = fuse_override_row(bank, row, 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.bit <bank> <row> <bit> - read a fuse bit\n" + "fuse read.row <bank> <row> [<cnt>] - read 1 or 'cnt' fuse rows,\n" + " starting at 'row'\n" + "fuse sense.bit <bank> <row> <bit> - sense a fuse bit\n" + "fuse sense.row <bank> <row> [<cnt>] - sense 1 or 'cnt' fuse rows,\n" + " starting at 'row'\n" + "fuse prog.bit <bank> <row> <bit> - program a fuse bit (PERMANENT)\n" + "fuse prog.row <bank> <row> <hexval> [<hexval>...] - program 1 or\n" + " several fuse rows, starting at 'row' (PERMANENT)\n" + "fuse ovride.bit <bank> <row> <bit> <val> - override a fuse bit\n" + "fuse ovride.row <bank> <row> <hexval> [<hexval>...] - override 1 or\n" + " several fuse rows, starting at 'row'" +); diff --git u-boot-178d0cc.orig/include/config_cmd_all.h u-boot-178d0cc/include/config_cmd_all.h index f434cd0..8f7d9ae 100644 --- u-boot-178d0cc.orig/include/config_cmd_all.h +++ u-boot-178d0cc/include/config_cmd_all.h @@ -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_HWFLOW /* RTS/CTS hw flow control */ #define CONFIG_CMD_I2C /* I2C serial bus support */ #define CONFIG_CMD_IDE /* IDE harddisk support */ diff --git u-boot-178d0cc/include/fuse.h u-boot-178d0cc/include/fuse.h new file mode 100644 index 0000000..baefefe --- /dev/null +++ u-boot-178d0cc/include/fuse.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2009-2012 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 + * row: Fuse row within the bank + * bit: Fuse bit within the row + * val: Value to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_read_row(u32 bank, u32 row, u32 *val); +int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_sense_row(u32 bank, u32 row, u32 *val); +int fuse_prog_bit(u32 bank, u32 row, u32 bit); +int fuse_prog_row(u32 bank, u32 row, u32 val); +int fuse_override_bit(u32 bank, u32 row, u32 bit, u32 val); +int fuse_override_row(u32 bank, u32 row, u32 val); + +#endif /* _FUSE_H_ */

Add a fsl_iim driver common to i.MX and MPC.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de --- This patch supersedes http://patchwork.ozlabs.org/patch/177245/ . Changes for v2: - Rebase against latest master.
.../drivers/misc/Makefile | 1 + /dev/null => u-boot-178d0cc/drivers/misc/fsl_iim.c | 318 ++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 u-boot-178d0cc/drivers/misc/fsl_iim.c
diff --git u-boot-178d0cc.orig/drivers/misc/Makefile u-boot-178d0cc/drivers/misc/Makefile index cdec88b..0833d78 100644 --- u-boot-178d0cc.orig/drivers/misc/Makefile +++ u-boot-178d0cc/drivers/misc/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libmisc.o
COBJS-$(CONFIG_ALI152X) += ali512x.o COBJS-$(CONFIG_DS4510) += ds4510.o +COBJS-$(CONFIG_FSL_IIM) += fsl_iim.o COBJS-$(CONFIG_FSL_LAW) += fsl_law.o COBJS-$(CONFIG_GPIO_LED) += gpio_led.o COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o diff --git u-boot-178d0cc/drivers/misc/fsl_iim.c u-boot-178d0cc/drivers/misc/fsl_iim.c new file mode 100644 index 0000000..1a3d5fc --- /dev/null +++ u-boot-178d0cc/drivers/misc/fsl_iim.c @@ -0,0 +1,318 @@ +/* + * (C) Copyright 2009-2012 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 <config.h> +#include <common.h> +#include <hwconfig.h> +#include <fuse.h> +#include <asm/errno.h> +#include <asm/byteorder.h> +#include <asm/io.h> + +/* FSL IIM-specific constants */ +#define STAT_BUSY 0x80 +#define STAT_PRGD 0x02 +#define STAT_SNSD 0x01 + +#define STATM_PRGD_M 0x02 +#define STATM_SNSD_M 0x01 + +#define ERR_PRGE 0x80 +#define ERR_WPE 0x40 +#define ERR_OPE 0x20 +#define ERR_RPE 0x10 +#define ERR_WLRE 0x08 +#define ERR_SNSE 0x04 +#define ERR_PARITYE 0x02 + +#define EMASK_PRGE_M 0x80 +#define EMASK_WPE_M 0x40 +#define EMASK_OPE_M 0x20 +#define EMASK_RPE_M 0x10 +#define EMASK_WLRE_M 0x08 +#define EMASK_SNSE_M 0x04 +#define EMASK_PARITYE_M 0x02 + +#define FCTL_DPC 0x80 +#define FCTL_PRG_LENGTH_MASK 0x70 +#define FCTL_ESNS_N 0x08 +#define FCTL_ESNS_0 0x04 +#define FCTL_ESNS_1 0x02 +#define FCTL_PRG 0x01 + +#define UA_A_BANK_MASK 0x38 +#define UA_A_ROWH_MASK 0x07 + +#define LA_A_ROWL_MASK 0xf8 +#define LA_A_BIT_MASK 0x07 + +#define PREV_PROD_REV_MASK 0xf8 +#define PREV_PROD_VT_MASK 0x07 + +/* Select the correct accessors depending on endianness */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define iim_read32 in_le32 +#define iim_write32 out_le32 +#define iim_clrsetbits32 clrsetbits_le32 +#define iim_clrbits32 clrbits_le32 +#define iim_setbits32 setbits_le32 +#elif __BYTE_ORDER == __BIG_ENDIAN +#define iim_read32 in_be32 +#define iim_write32 out_be32 +#define iim_clrsetbits32 clrsetbits_be32 +#define iim_clrbits32 clrbits_be32 +#define iim_setbits32 setbits_be32 +#else +#error "Endianess is not defined: please fix to continue" +#endif + +/* IIM control registers */ +struct fsl_iim { + u32 stat; + u32 statm; + u32 err; + u32 emask; + u32 fctl; + u32 ua; + u32 la; + u32 sdat; + u32 prev; + u32 srev; + u32 prg_p; + u32 scs[0x1f5]; + struct { + u32 row[0x100]; + } bank[8]; +}; + +int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val) +{ + int ret; + + if (bit >= 8) { + puts("fsl_iim fuse read: Invalid argument\n"); + return -EINVAL; + } + + ret = fuse_read_row(bank, row, val); + if (ret) + return ret; + + *val = !!(*val & 1 << bit); + return 0; +} + +int fuse_read_row(u32 bank, u32 row, u32 *val) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + val == NULL) { + puts("fsl_iim fuse read: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->err, iim_read32(®s->err)); + *val = iim_read32(®s->bank[bank].row[row]); + err = iim_read32(®s->err); + iim_write32(®s->err, iim_read32(®s->err)); + + if (err & ERR_RPE) { + puts("fsl_iim fuse read: Read protect error\n"); + return -EIO; + } + + return 0; +} + +int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val) +{ + int ret; + + if (bit >= 8) { + puts("fsl_iim fuse sense: Invalid argument\n"); + return -EINVAL; + } + + ret = fuse_sense_row(bank, row, val); + if (ret) + return ret; + + *val = !!(*val & 1 << bit); + return 0; +} + +int fuse_sense_row(u32 bank, u32 row, u32 *val) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 stat, err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + val == NULL) { + puts("fsl_iim fuse sense: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->ua, bank << 3 | row >> 5); + iim_write32(®s->la, row << 3 & 0xff); + iim_write32(®s->fctl, iim_read32(®s->fctl) | FCTL_ESNS_N); + while (iim_read32(®s->stat) & STAT_BUSY) + udelay(20); + stat = iim_read32(®s->stat); + err = iim_read32(®s->err); + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + + if (err & ERR_SNSE) { + puts("fsl_iim fuse sense: Explicit sense cycle error\n"); + return -EIO; + } + + if (!(stat & STAT_SNSD)) { + puts("fsl_iim fuse sense: Explicit sense cycle " + "did not complete\n"); + return -EIO; + } + + *val = iim_read32(®s->sdat); + return 0; +} + +int fuse_prog_bit(u32 bank, u32 row, u32 bit) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 stat, err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + bit >= 8) { + puts("fsl_iim fuse program: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->ua, bank << 3 | row >> 5); + iim_write32(®s->la, (row << 3 | bit) & 0xff); + iim_write32(®s->prg_p, 0xaa); + iim_write32(®s->fctl, iim_read32(®s->fctl) | FCTL_PRG); + while (iim_read32(®s->stat) & STAT_BUSY) + udelay(20); + stat = iim_read32(®s->stat); + err = iim_read32(®s->err); + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->prg_p, 0x00); + + if (err & ERR_PRGE) { + puts("fsl_iim fuse program: Program error\n"); + return -EIO; + } + + if (err & ERR_WPE) { + puts("fsl_iim fuse program: Write protect error\n"); + return -EIO; + } + + if (!(stat & STAT_PRGD)) { + puts("fsl_iim fuse program: Program did not complete\n"); + return -EIO; + } + + return 0; +} + +int fuse_prog_row(u32 bank, u32 row, u32 val) +{ + int bit, ret; + + if (val & ~0xff) { + puts("fsl_iim fuse program: Invalid argument\n"); + return -EINVAL; + } + + for (bit = 0; val; bit++, val >>= 1) + if (val & 0x01) { + ret = fuse_prog_bit(bank, row, bit); + if (ret) + return ret; + } + + return 0; +} + +int fuse_override_bit(u32 bank, u32 row, u32 bit, u32 val) +{ + u32 row_val; + int ret; + + if (bit >= 8 || val > 1) { + puts("fsl_iim fuse override: Invalid argument\n"); + return -EINVAL; + } + + ret = fuse_read_row(bank, row, &row_val); + if (ret) + return ret; + + return fuse_override_row(bank, row, + (row_val & ~(1 << bit)) | val << bit); +} + +int fuse_override_row(u32 bank, u32 row, u32 val) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + val & ~0xff) { + puts("fsl_iim fuse override: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->bank[bank].row[row], val); + err = iim_read32(®s->err); + iim_write32(®s->err, iim_read32(®s->err)); + + if (err & ERR_OPE) { + puts("fsl_iim fuse override: Override protect error\n"); + return -EIO; + } + + return 0; +}

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de Cc: Reinhard Arlt reinhard.arlt@esd-electronics.com Cc: Michael Weiss michael.weiss@ifm.com --- This patch supersedes http://patchwork.ozlabs.org/patch/177246/ . Changes for v2: - Rebase against latest master.
.../arch/powerpc/cpu/mpc512x/Makefile | 1 - .../arch/powerpc/cpu/mpc512x/iim.c => /dev/null | 394 -------------------- .../board/davedenx/aria/aria.c | 2 +- .../board/esd/mecp5123/mecp5123.c | 2 +- .../board/freescale/mpc5121ads/mpc5121ads.c | 2 +- .../board/pdm360ng/pdm360ng.c | 2 +- .../include/configs/aria.h | 2 +- .../include/configs/mecp5123.h | 2 +- .../include/configs/mpc5121ads.h | 2 +- 9 files changed, 7 insertions(+), 402 deletions(-) delete mode 100644 u-boot-178d0cc.orig/arch/powerpc/cpu/mpc512x/iim.c
diff --git u-boot-178d0cc.orig/arch/powerpc/cpu/mpc512x/Makefile u-boot-178d0cc/arch/powerpc/cpu/mpc512x/Makefile index b53232f..4f4c9ec 100644 --- u-boot-178d0cc.orig/arch/powerpc/cpu/mpc512x/Makefile +++ u-boot-178d0cc/arch/powerpc/cpu/mpc512x/Makefile @@ -38,7 +38,6 @@ COBJS-y += serial.o COBJS-y += speed.o COBJS-$(CONFIG_FSL_DIU_FB) += diu.o COBJS-$(CONFIG_CMD_IDE) += ide.o -COBJS-$(CONFIG_IIM) += iim.o COBJS-$(CONFIG_PCI) += pci.o
# Stub implementations of cache management functions for USB diff --git u-boot-178d0cc.orig/arch/powerpc/cpu/mpc512x/iim.c u-boot-178d0cc.orig/arch/powerpc/cpu/mpc512x/iim.c deleted file mode 100644 index abec8f6..0000000 --- u-boot-178d0cc.orig/arch/powerpc/cpu/mpc512x/iim.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2008 Silicon Turnkey Express, Inc. - * Martha Marx mmarx@silicontkx.com - * - * ADS5121 IIM (Fusebox) Interface - * - * 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 <asm/io.h> - -#ifdef CONFIG_CMD_FUSE - -DECLARE_GLOBAL_DATA_PTR; - -static char cur_bank = '1'; - -char *iim_err_msg(u32 err) -{ - static char *IIM_errs[] = { - "Parity Error in cache", - "Explicit Sense Cycle Error", - "Write to Locked Register Error", - "Read Protect Error", - "Override Protect Error", - "Write Protect Error"}; - - int i; - - if (!err) - return ""; - for (i = 1; i < 8; i++) - if (err & (1 << i)) - printf("IIM - %s\n", IIM_errs[i-1]); - return ""; -} - -int in_range(int n, int min, int max, char *err, char *usg) -{ - if (n > max || n < min) { - printf(err); - printf("Usage:\n%s\n", usg); - return 0; - } - return 1; -} - -int ads5121_fuse_read(int bank, int fstart, int num) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 *iim_fb, dummy; - int f, ctr; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fb = (u32 *)&(iim->fbac0); - else - iim_fb = (u32 *)&(iim->fbac1); -/* try a read to see if Read Protect is set */ - dummy = in_be32(&iim_fb[0]); - if (in_be32(&iim->err) & IIM_ERR_RPE) { - printf("\tRead protect fuse is set\n"); - out_be32(&iim->err, IIM_ERR_RPE); - return 0; - } - printf("Reading Bank %d cache\n", bank); - for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) { - if (ctr % 4 == 0) - printf("F%2d:", f); - printf("\t%#04x", (u8)(iim_fb[f])); - if (ctr % 4 == 3) - printf("\n"); - } - if (ctr % 4 != 0) - printf("\n"); -} - -int ads5121_fuse_override(int bank, int f, u8 val) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 *iim_fb; - u32 iim_stat; - int i; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fb = (u32 *)&(iim->fbac0); - else - iim_fb = (u32 *)&(iim->fbac1); -/* try a read to see if Read Protect is set */ - iim_stat = in_be32(&iim_fb[0]); - if (in_be32(&iim->err) & IIM_ERR_RPE) { - printf("Read protect fuse is set on bank %d;" - "Override protect may also be set\n", bank); - printf("An attempt will be made to override\n"); - out_be32(&iim->err, IIM_ERR_RPE); - } - if (iim_stat & IIM_FBAC_FBOP) { - printf("Override protect fuse is set on bank %d\n", bank); - return 1; - } - if (f > IIM_FMAX) /* reset the entire bank */ - for (i = 0; i < IIM_FMAX + 1; i++) - out_be32(&iim_fb[i], 0); - else - out_be32(&iim_fb[f], val); - return 0; -} - -int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - int f, i, bitno; - u32 stat, err; - - f = simple_strtol(fuseno_bitno, NULL, 10); - if (f == 0 && fuseno_bitno[0] != '0') - f = -1; - if (!in_range(f, 0, IIM_FMAX, - "<frow> must be between 0-31\n\n", cmdtp->usage)) - return 1; - bitno = -1; - for (i = 0; i < 6; i++) { - if (fuseno_bitno[i] == '_') { - bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10); - if (bitno == 0 && fuseno_bitno[i+1] != '0') - bitno = -1; - break; - } - } - if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n" - "Example of <frow_bitno>: "18_4" sets bit 4 of row 18\n", - cmdtp->usage)) - return 1; - out_be32(&iim->err, in_be32(&iim->err)); - out_be32(&iim->prg_p, IIM_PRG_P_SET); - out_be32(&iim->ua, IIM_SET_UA(bank, f)); - out_be32(&iim->la, IIM_SET_LA(f, bitno)); -#ifdef DEBUG - printf("Programming disabled with DEBUG defined \n"); - printf(""Set up to pro - printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la); -#else - out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG); - do - udelay(20); - while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY); - out_be32(&iim->prg_p, 0); - err = in_be32(&iim->err); - if (stat & IIM_STAT_PRGD) { - if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) { - printf("Fuse is successfully set"); - if (err) - printf(" - however there are other errors"); - printf("\n"); - } - iim->stat = 0; - } - if (err) { - iim_err_msg(err); - out_be32(&iim->err, in_be32(&iim->err)); - } -#endif -} - -int ads5121_fuse_sense(int bank, int fstart, int num) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 iim_fbac; - u32 stat, err, err_hold = 0; - int f, ctr; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fbac = in_be32(&iim->fbac0); - else - iim_fbac = in_be32(&iim->fbac1); - if (iim_fbac & IIM_FBAC_FBESP) { - printf("\tSense Protect disallows this operation\n"); - out_be32(&iim->err, IIM_FBAC_FBESP); - return 1; - } - err = in_be32(&iim->err); - if (err) { - iim_err_msg(err); - err_hold |= err; - } - if (err & IIM_ERR_RPE) - printf("\tRead protect fuse is set; " - "Sense Protect may be set but will be attempted\n"); - if (err) - out_be32(&iim->err, err); - printf("Sensing fuse(s) on Bank %d\n", bank); - for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) { - out_be32(&iim->ua, IIM_SET_UA(bank, f)); - out_be32(&iim->la, IIM_SET_LA(f, 0)); - out_be32(&iim->fctl, IIM_FCTL_ESNS_N); - do - udelay(20); - while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY); - err = in_be32(&iim->err); - if (err & IIM_ERR_SNSE) { - iim_err_msg(err); - out_be32(&iim->err, IIM_ERR_SNSE); - return 1; - } - if (stat & IIM_STAT_SNSD) { - out_be32(&iim->stat, 0); - if (ctr % 4 == 0) - printf("F%2d:", f); - printf("\t%#04x", (u8)iim->sdat); - if (ctr % 4 == 3) - printf("\n"); - } - if (err) { - err_hold |= err; - out_be32(&iim->err, err); - } - } - if (ctr % 4 != 0) - printf("\n"); - if (err_hold) - iim_err_msg(err_hold); - - return 0; -} - -int ads5121_fuse_stat(int bank) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 iim_fbac; - u32 err; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fbac = in_be32(&iim->fbac0); - else - iim_fbac = in_be32(&iim->fbac1); - err = in_be32(&iim->err); - if (err) - iim_err_msg(err); - if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) { - if (iim_fbac == 0) - printf("Since protection settings can't be read - " - "try sensing fuse row 0;\n"); - return 0; - } - if (iim_fbac & IIM_PROTECTION) - printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac); - else if (!(err & IIM_ERR_RPE)) - printf("No Protection fuses are set\n"); - if (iim_fbac & IIM_FBAC_FBWP) - printf("\tWrite Protect fuse is set\n"); - if (iim_fbac & IIM_FBAC_FBOP) - printf("\tOverride Protect fuse is set\n"); - if (iim_fbac & IIM_FBAC_FBESP) - printf("\tSense Protect Fuse is set\n"); - out_be32(&iim->err, in_be32(&iim->err)); - - return 0; -} - -int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int frow, n, v, bank; - - if (cur_bank == '0') - bank = 0; - else - bank = 1; - - switch (argc) { - case 0: - case 1: - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - case 2: - if (strncmp(argv[1], "stat", 4) == 0) - return ads5121_fuse_stat(bank); - if (strncmp(argv[1], "read", 4) == 0) - return ads5121_fuse_read(bank, 0, IIM_FMAX + 1); - if (strncmp(argv[1], "sense", 5) == 0) - return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1); - if (strncmp(argv[1], "ovride", 6) == 0) - return ads5121_fuse_override(bank, IIM_FMAX + 1, 0); - if (strncmp(argv[1], "bank", 4) == 0) { - printf("Active Fuse Bank is %c\n", cur_bank); - return 0; - } - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - case 3: - if (strncmp(argv[1], "bank", 4) == 0) { - if (argv[2][0] == '0') - cur_bank = '0'; - else if (argv[2][0] == '1') - cur_bank = '1'; - else { - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - } - - printf("Setting Active Fuse Bank to %c\n", cur_bank); - return 0; - } - if (strncmp(argv[1], "prog", 4) == 0) - return ads5121_fuse_prog(cmdtp, bank, argv[2]); - - frow = (int)simple_strtol(argv[2], NULL, 10); - if (frow == 0 && argv[2][0] != '0') - frow = -1; - if (!in_range(frow, 0, IIM_FMAX, - "<frow> must be between 0-31\n\n", cmdtp->usage)) - return 1; - if (strncmp(argv[1], "read", 4) == 0) - return ads5121_fuse_read(bank, frow, 1); - if (strncmp(argv[1], "ovride", 6) == 0) - return ads5121_fuse_override(bank, frow, 0); - if (strncmp(argv[1], "sense", 5) == 0) - return ads5121_fuse_sense(bank, frow, 1); - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - case 4: - frow = (int)simple_strtol(argv[2], NULL, 10); - if (frow == 0 && argv[2][0] != '0') - frow = -1; - if (!in_range(frow, 0, IIM_FMAX, - "<frow> must be between 0-31\n\n", cmdtp->usage)) - return 1; - if (strncmp(argv[1], "read", 4) == 0) { - n = (int)simple_strtol(argv[3], NULL, 10); - if (!in_range(frow + n, frow + 1, IIM_FMAX + 1, - "<frow>+<n> must be between 1-32\n\n", - cmdtp->usage)) - return 1; - return ads5121_fuse_read(bank, frow, n); - } - if (strncmp(argv[1], "ovride", 6) == 0) { - v = (int)simple_strtol(argv[3], NULL, 10); - return ads5121_fuse_override(bank, frow, v); - } - if (strncmp(argv[1], "sense", 5) == 0) { - n = (int)simple_strtol(argv[3], NULL, 10); - if (!in_range(frow + n, frow + 1, IIM_FMAX + 1, - "<frow>+<n> must be between 1-32\n\n", - cmdtp->usage)) - return 1; - return ads5121_fuse_sense(bank, frow, n); - } - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - default: /* at least 5 args */ - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - } -} - -U_BOOT_CMD( - fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse, - " - Read, Sense, Override or Program Fuses\n", - "bank <n> - sets active Fuse Bank to 0 or 1\n" - " no args shows current active bank\n" - "fuse stat - print active fuse bank's protection status\n" - "fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n" - " no args to print entire bank's fuses\n" - "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n" - " no <v> defaults to 0 for the row\n" - " no args resets entire bank to 0\n" - " NOTE - settings persist until hard reset\n" - "fuse sense [<frow>] - senses current fuse at <frow>\n" - " no args for entire bank\n" - "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n" - " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n" - " WARNING - this is permanent" -); -#endif /* CONFIG_CMD_FUSE */ diff --git u-boot-178d0cc.orig/board/davedenx/aria/aria.c u-boot-178d0cc/board/davedenx/aria/aria.c index 31b079b..d2ffba4 100644 --- u-boot-178d0cc.orig/board/davedenx/aria/aria.c +++ u-boot-178d0cc/board/davedenx/aria/aria.c @@ -92,7 +92,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-178d0cc.orig/board/esd/mecp5123/mecp5123.c u-boot-178d0cc/board/esd/mecp5123/mecp5123.c index 748ad7c..804a022 100644 --- u-boot-178d0cc.orig/board/esd/mecp5123/mecp5123.c +++ u-boot-178d0cc/board/esd/mecp5123/mecp5123.c @@ -110,7 +110,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-178d0cc.orig/board/freescale/mpc5121ads/mpc5121ads.c u-boot-178d0cc/board/freescale/mpc5121ads/mpc5121ads.c index 97eeab3..0d33680 100644 --- u-boot-178d0cc.orig/board/freescale/mpc5121ads/mpc5121ads.c +++ u-boot-178d0cc/board/freescale/mpc5121ads/mpc5121ads.c @@ -129,7 +129,7 @@ int board_early_init_f(void) */ out_be32 (&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32 (&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32 (&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-178d0cc.orig/board/pdm360ng/pdm360ng.c u-boot-178d0cc/board/pdm360ng/pdm360ng.c index a2a1323..da81590 100644 --- u-boot-178d0cc.orig/board/pdm360ng/pdm360ng.c +++ u-boot-178d0cc/board/pdm360ng/pdm360ng.c @@ -94,7 +94,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-178d0cc.orig/include/configs/aria.h u-boot-178d0cc/include/configs/aria.h index 0b31c50..7905e45 100644 --- u-boot-178d0cc.orig/include/configs/aria.h +++ u-boot-178d0cc/include/configs/aria.h @@ -379,7 +379,7 @@ /* * IIM - IC Identification Module */ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/* * EEPROM configuration for Atmel AT24C32A-10TQ-2.7: diff --git u-boot-178d0cc.orig/include/configs/mecp5123.h u-boot-178d0cc/include/configs/mecp5123.h index cafc273..8db47ed 100644 --- u-boot-178d0cc.orig/include/configs/mecp5123.h +++ u-boot-178d0cc/include/configs/mecp5123.h @@ -251,7 +251,7 @@ /* * IIM - IC Identification Module */ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/* * EEPROM configuration diff --git u-boot-178d0cc.orig/include/configs/mpc5121ads.h u-boot-178d0cc/include/configs/mpc5121ads.h index 3f55d35..5b34124 100644 --- u-boot-178d0cc.orig/include/configs/mpc5121ads.h +++ u-boot-178d0cc/include/configs/mpc5121ads.h @@ -347,7 +347,7 @@ /* * IIM - IC Identification Module */ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/* * EEPROM configuration

On 27/11/2012 14:30, Benoît Thébaudeau wrote:
Homogenize prg_p naming (the reference manuals are not always self-consistent for that). Add missing registers. Fix some registers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
Hi Benoît,
checking again which patches were left in an unknow state, I face again with you IIM patchset. My last status was that it shouldbe better to add some test check (as we have for nand scrub..) to avoid to destroy at the first attempt the SOC. Anyway, it is a minor point, and can be added later - I am convinced that who works with U-Boot must know what he is doing.
It would be a pity if we miss to merge this patchset - so my plan is to merge it now into u-boot-imx, asking Anatolji if he agree with 5/5 (related to MPC-5121 only). Or do you plan to submit a new version ?
Best regards, Stefano

Hi Stefano,
On Monday, March 18, 2013 1:07:42 PM, Stefano Babic wrote:
On 27/11/2012 14:30, Benoît Thébaudeau wrote:
Homogenize prg_p naming (the reference manuals are not always self-consistent for that). Add missing registers. Fix some registers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
Hi Benoît,
checking again which patches were left in an unknow state, I face again with you IIM patchset. My last status was that it shouldbe better to add some test check (as we have for nand scrub..) to avoid to destroy at the first attempt the SOC. Anyway, it is a minor point, and can be added later - I am convinced that who works with U-Boot must know what he is doing.
It would be a pity if we miss to merge this patchset - so my plan is to merge it now into u-boot-imx, asking Anatolji if he agree with 5/5 (related to MPC-5121 only). Or do you plan to submit a new version ?
I had a plan to send a new version: what you mention, but also some documentation and other types of improvements that Otavio and Eric asked for. I also wanted to add support for i.MX6 OTG, but it might take a bit longer, so that could be done separately. I will try to send early this week the new version with the minor improvements.
Best regards, Benoît

On Monday, March 18, 2013 1:08:23 PM, Benoît Thébaudeau wrote:
Hi Stefano,
On Monday, March 18, 2013 1:07:42 PM, Stefano Babic wrote:
On 27/11/2012 14:30, Benoît Thébaudeau wrote:
Homogenize prg_p naming (the reference manuals are not always self-consistent for that). Add missing registers. Fix some registers.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de
Hi Benoît,
checking again which patches were left in an unknow state, I face again with you IIM patchset. My last status was that it shouldbe better to add some test check (as we have for nand scrub..) to avoid to destroy at the first attempt the SOC. Anyway, it is a minor point, and can be added later - I am convinced that who works with U-Boot must know what he is doing.
It would be a pity if we miss to merge this patchset - so my plan is to merge it now into u-boot-imx, asking Anatolji if he agree with 5/5 (related to MPC-5121 only). Or do you plan to submit a new version ?
I had a plan to send a new version: what you mention, but also some documentation and other types of improvements that Otavio and Eric asked for. I also wanted to add support for i.MX6 OTG, but it might take a bit longer, so
^ s/OTG/OTP/
that could be done separately. I will try to send early this week the new version with the minor improvements.
Best regards, Benoît

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Stefano Babic sbabic@denx.de Cc: Wolfgang Denk wd@denx.de --- .../arch/arm/include/asm/arch-mx25/imx-regs.h | 11 ++++++++++- .../arch/arm/include/asm/arch-mx31/imx-regs.h | 12 ++++++++++++ .../arch/arm/include/asm/arch-mx35/imx-regs.h | 12 ++++++++++++ .../arch/arm/include/asm/arch-mx5/imx-regs.h | 16 +++++++++++++++- 4 files changed, 49 insertions(+), 2 deletions(-)
diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx25/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx25/imx-regs.h index b7b4d07..654f9e8 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx25/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx25/imx-regs.h @@ -131,10 +131,19 @@ struct iim_regs { };
struct fuse_bank0_regs { - u32 fuse0_25[0x1a]; + u32 fuse0_7[8]; + u32 uid[8]; + u32 fuse16_25[0xa]; u32 mac_addr[6]; };
+struct fuse_bank1_regs { + u32 fuse0_21[0x16]; + u32 usr5; + u32 fuse23_29[7]; + u32 usr6[2]; +}; + /* Multi-Layer AHB Crossbar Switch (MAX) registers */ struct max_regs { u32 mpr0; diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx31/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx31/imx-regs.h index c2db85f..00b347f 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx31/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx31/imx-regs.h @@ -103,6 +103,18 @@ struct iim_regs { } bank[3]; };
+struct fuse_bank0_regs { + u32 fuse0_5[6]; + u32 usr; + u32 fuse7_15[9]; +}; + +struct fuse_bank2_regs { + u32 fuse0; + u32 uid[8]; + u32 fuse9_15[7]; +}; + struct iomuxc_regs { u32 unused1; u32 unused2; diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx35/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx35/imx-regs.h index f75e5c2..1d1be2d 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx35/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx35/imx-regs.h @@ -295,6 +295,18 @@ struct iim_regs { } bank[3]; };
+struct fuse_bank0_regs { + u32 fuse0_7[8]; + u32 uid[8]; + u32 fuse16_31[0x10]; +}; + +struct fuse_bank1_regs { + u32 fuse0_21[0x16]; + u32 usr; + u32 fuse23_31[9]; +}; + /* General Purpose Timer (GPT) registers */ struct gpt_regs { u32 ctrl; /* control */ diff --git u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h index 33d2097..8ac3fac 100644 --- u-boot-4d3c95f.orig/arch/arm/include/asm/arch-mx5/imx-regs.h +++ u-boot-4d3c95f/arch/arm/include/asm/arch-mx5/imx-regs.h @@ -499,8 +499,14 @@ struct iim_regs { };
struct fuse_bank0_regs { - u32 fuse0_23[24]; + u32 fuse0_7[8]; + u32 uid[8]; + u32 fuse16_23[8]; +#if defined(CONFIG_MX51) + u32 imei[8]; +#elif defined(CONFIG_MX53) u32 gp[8]; +#endif };
struct fuse_bank1_regs { @@ -509,6 +515,14 @@ struct fuse_bank1_regs { u32 fuse15_31[0x11]; };
+#if defined(CONFIG_MX53) +struct fuse_bank4_regs { + u32 fuse0_4[5]; + u32 gp[3]; + u32 fuse8_31[0x18]; +}; +#endif + #endif /* __ASSEMBLER__*/
#endif /* __ASM_ARCH_MX5_IMX_REGS_H__ */

This can be useful for fuse-like hardware, OTP SoC options, etc.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de --- {u-boot-4d3c95f.orig => u-boot-4d3c95f}/README | 1 + .../common/Makefile | 1 + /dev/null => u-boot-4d3c95f/common/cmd_fuse.c | 182 ++++++++++++++++++++ .../include/config_cmd_all.h | 1 + /dev/null => u-boot-4d3c95f/include/fuse.h | 49 ++++++ 5 files changed, 234 insertions(+) create mode 100644 u-boot-4d3c95f/common/cmd_fuse.c create mode 100644 u-boot-4d3c95f/include/fuse.h
diff --git u-boot-4d3c95f.orig/README u-boot-4d3c95f/README index fb9d904..c40fd34 100644 --- u-boot-4d3c95f.orig/README +++ u-boot-4d3c95f/README @@ -780,6 +780,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_GO * the 'go' command (exec code) CONFIG_CMD_GREPENV * search environment CONFIG_CMD_HWFLOW * RTS/CTS hw flow control diff --git u-boot-4d3c95f.orig/common/Makefile u-boot-4d3c95f/common/Makefile index 3d62775..44ef757 100644 --- u-boot-4d3c95f.orig/common/Makefile +++ u-boot-4d3c95f/common/Makefile @@ -96,6 +96,7 @@ COBJS-$(CONFIG_CMD_FLASH) += cmd_flash.o ifdef CONFIG_FPGA COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o endif +COBJS-$(CONFIG_CMD_FUSE) += cmd_fuse.o COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o diff --git u-boot-4d3c95f/common/cmd_fuse.c u-boot-4d3c95f/common/cmd_fuse.c new file mode 100644 index 0000000..fd54d40 --- /dev/null +++ u-boot-4d3c95f/common/cmd_fuse.c @@ -0,0 +1,182 @@ +/* + * (C) Copyright 2009-2012 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 do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + u32 bank, row, bit, cnt, val; + int ret, i; + + if (argc < 4 || strtou32(argv[2], 0, &bank) || + strtou32(argv[3], 0, &row)) + return CMD_RET_USAGE; + + if (!strcmp(argv[1], "read.bit")) { + if (argc != 5 || strtou32(argv[4], 0, &bit)) + return CMD_RET_USAGE; + + printf("Reading bank %u row 0x%.8x bit %u: ", bank, row, bit); + ret = fuse_read_bit(bank, row, bit, &val); + if (ret) + goto err; + + printf("%u\n", val); + } else if (!strcmp(argv[1], "read.row")) { + if (argc == 4) + cnt = 1; + else if (argc != 5 || strtou32(argv[4], 0, &cnt)) + return CMD_RET_USAGE; + + printf("Reading bank %u:\n", bank); + for (i = 0; i < cnt; i++, row++) { + if (!(i % 4)) + printf("\nRow 0x%.8x:", row); + + ret = fuse_read_row(bank, row, &val); + if (ret) + goto err; + + printf(" %.8x", val); + } + putc('\n'); + } else if (!strcmp(argv[1], "sense.bit")) { + if (argc != 5 || strtou32(argv[4], 0, &bit)) + return CMD_RET_USAGE; + + printf("Sensing bank %u row 0x%.8x bit %u: ", bank, row, bit); + ret = fuse_sense_bit(bank, row, bit, &val); + if (ret) + goto err; + + printf("%u\n", val); + } else if (!strcmp(argv[1], "sense.row")) { + if (argc == 4) + cnt = 1; + else if (argc != 5 || strtou32(argv[4], 0, &cnt)) + return CMD_RET_USAGE; + + printf("Sensing bank %u:\n", bank); + for (i = 0; i < cnt; i++, row++) { + if (!(i % 4)) + printf("\nRow 0x%.8x:", row); + + ret = fuse_sense_row(bank, row, &val); + if (ret) + goto err; + + printf(" %.8x", val); + } + putc('\n'); + } else if (!strcmp(argv[1], "prog.bit")) { + if (argc != 5 || strtou32(argv[4], 0, &bit)) + return CMD_RET_USAGE; + + printf("Programming bank %u row 0x%.8x bit %u...\n", + bank, row, bit); + ret = fuse_prog_bit(bank, row, bit); + if (ret) + goto err; + } else if (!strcmp(argv[1], "prog.row")) { + if (argc < 5) + return CMD_RET_USAGE; + + for (i = 4; i < argc; i++, row++) { + if (strtou32(argv[i], 16, &val)) + return CMD_RET_USAGE; + + printf("Programming bank %u row 0x%.8x to 0x%.8x...\n", + bank, row, val); + ret = fuse_prog_row(bank, row, val); + if (ret) + goto err; + } + } else if (!strcmp(argv[1], "ovride.bit")) { + if (argc != 6 || strtou32(argv[4], 0, &bit) || + strtou32(argv[5], 0, &val) || val > 1) + return CMD_RET_USAGE; + + printf("Overriding bank %u row 0x%.8x bit %u with %u...\n", + bank, row, bit, val); + ret = fuse_override_bit(bank, row, bit, val); + if (ret) + goto err; + } else if (!strcmp(argv[1], "ovride.row")) { + if (argc < 5) + return CMD_RET_USAGE; + + for (i = 4; i < argc; i++, row++) { + if (strtou32(argv[i], 16, &val)) + return CMD_RET_USAGE; + + printf("Overriding bank %u row 0x%.8x with 0x%.8x...\n", + bank, row, val); + ret = fuse_override_row(bank, row, 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.bit <bank> <row> <bit> - read a fuse bit\n" + "fuse read.row <bank> <row> [<cnt>] - read 1 or 'cnt' fuse rows,\n" + " starting at 'row'\n" + "fuse sense.bit <bank> <row> <bit> - sense a fuse bit\n" + "fuse sense.row <bank> <row> [<cnt>] - sense 1 or 'cnt' fuse rows,\n" + " starting at 'row'\n" + "fuse prog.bit <bank> <row> <bit> - program a fuse bit (PERMANENT)\n" + "fuse prog.row <bank> <row> <hexval> [<hexval>...] - program 1 or\n" + " several fuse rows, starting at 'row' (PERMANENT)\n" + "fuse ovride.bit <bank> <row> <bit> <val> - override a fuse bit\n" + "fuse ovride.row <bank> <row> <hexval> [<hexval>...] - override 1 or\n" + " several fuse rows, starting at 'row'" +); diff --git u-boot-4d3c95f.orig/include/config_cmd_all.h u-boot-4d3c95f/include/config_cmd_all.h index f434cd0..8f7d9ae 100644 --- u-boot-4d3c95f.orig/include/config_cmd_all.h +++ u-boot-4d3c95f/include/config_cmd_all.h @@ -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_HWFLOW /* RTS/CTS hw flow control */ #define CONFIG_CMD_I2C /* I2C serial bus support */ #define CONFIG_CMD_IDE /* IDE harddisk support */ diff --git u-boot-4d3c95f/include/fuse.h u-boot-4d3c95f/include/fuse.h new file mode 100644 index 0000000..baefefe --- /dev/null +++ u-boot-4d3c95f/include/fuse.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2009-2012 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 + * row: Fuse row within the bank + * bit: Fuse bit within the row + * val: Value to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_read_row(u32 bank, u32 row, u32 *val); +int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_sense_row(u32 bank, u32 row, u32 *val); +int fuse_prog_bit(u32 bank, u32 row, u32 bit); +int fuse_prog_row(u32 bank, u32 row, u32 val); +int fuse_override_bit(u32 bank, u32 row, u32 bit, u32 val); +int fuse_override_row(u32 bank, u32 row, u32 val); + +#endif /* _FUSE_H_ */

On 14/08/2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
CC to Anatolji, he knows very well the MPC5121 that has currently support of fuses.
{u-boot-4d3c95f.orig => u-boot-4d3c95f}/README | 1 + .../common/Makefile | 1 + /dev/null => u-boot-4d3c95f/common/cmd_fuse.c | 182 ++++++++++++++++++++ .../include/config_cmd_all.h | 1 + /dev/null => u-boot-4d3c95f/include/fuse.h | 49 ++++++ 5 files changed, 234 insertions(+) create mode 100644 u-boot-4d3c95f/common/cmd_fuse.c create mode 100644 u-boot-4d3c95f/include/fuse.h
diff --git u-boot-4d3c95f.orig/README u-boot-4d3c95f/README index fb9d904..c40fd34 100644 --- u-boot-4d3c95f.orig/README +++ u-boot-4d3c95f/README @@ -780,6 +780,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_GO * the 'go' command (exec code) CONFIG_CMD_GREPENV * search environment CONFIG_CMD_HWFLOW * RTS/CTS hw flow controlCONFIG_CMD_FUSE Device fuse support
Agree in this split: we have a general fuse command and each SOC / SOC family can add its own implementation.
+static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{
- u32 bank, row, bit, cnt, val;
- int ret, i;
- if (argc < 4 || strtou32(argv[2], 0, &bank) ||
strtou32(argv[3], 0, &row))
return CMD_RET_USAGE;
- if (!strcmp(argv[1], "read.bit")) {
if (argc != 5 || strtou32(argv[4], 0, &bit))
return CMD_RET_USAGE;
printf("Reading bank %u row 0x%.8x bit %u: ", bank, row, bit);
ret = fuse_read_bit(bank, row, bit, &val);
if (ret)
goto err;
printf("%u\n", val);
- } else if (!strcmp(argv[1], "read.row")) {
if (argc == 4)
cnt = 1;
else if (argc != 5 || strtou32(argv[4], 0, &cnt))
return CMD_RET_USAGE;
printf("Reading bank %u:\n", bank);
for (i = 0; i < cnt; i++, row++) {
if (!(i % 4))
printf("\nRow 0x%.8x:", row);
ret = fuse_read_row(bank, row, &val);
if (ret)
goto err;
printf(" %.8x", val);
}
putc('\n');
- } else if (!strcmp(argv[1], "sense.bit")) {
if (argc != 5 || strtou32(argv[4], 0, &bit))
return CMD_RET_USAGE;
printf("Sensing bank %u row 0x%.8x bit %u: ", bank, row, bit);
Each command sends this output to the console. I am thinking about if instead of printf() we shoud use debug()
+U_BOOT_CMD(
- fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
- "Fuse sub-system",
"read.bit <bank> <row> <bit> - read a fuse bit\n"
- "fuse read.row <bank> <row> [<cnt>] - read 1 or 'cnt' fuse rows,\n"
- " starting at 'row'\n"
- "fuse sense.bit <bank> <row> <bit> - sense a fuse bit\n"
- "fuse sense.row <bank> <row> [<cnt>] - sense 1 or 'cnt' fuse rows,\n"
- " starting at 'row'\n"
- "fuse prog.bit <bank> <row> <bit> - program a fuse bit (PERMANENT)\n"
- "fuse prog.row <bank> <row> <hexval> [<hexval>...] - program 1 or\n"
- " several fuse rows, starting at 'row' (PERMANENT)\n"
- "fuse ovride.bit <bank> <row> <bit> <val> - override a fuse bit\n"
- "fuse ovride.row <bank> <row> <hexval> [<hexval>...] - override 1 or\n"
- " several fuse rows, starting at 'row'"
+);
General question: why do we need the "bit" interface ? I have thought it is enough the read row / prog row interface (even if there is a bit programming).
Best regards, Stefano Babic

Hi Stefano,
This can be useful for fuse-like hardware, OTP SoC options, etc.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
CC to Anatolji, he knows very well the MPC5121 that has currently support of fuses.
{u-boot-4d3c95f.orig => u-boot-4d3c95f}/README | 1 + .../common/Makefile | 1 + /dev/null => u-boot-4d3c95f/common/cmd_fuse.c | 182 ++++++++++++++++++++ .../include/config_cmd_all.h | 1 + /dev/null => u-boot-4d3c95f/include/fuse.h | 49 ++++++ 5 files changed, 234 insertions(+) create mode 100644 u-boot-4d3c95f/common/cmd_fuse.c create mode 100644 u-boot-4d3c95f/include/fuse.h
diff --git u-boot-4d3c95f.orig/README u-boot-4d3c95f/README index fb9d904..c40fd34 100644 --- u-boot-4d3c95f.orig/README +++ u-boot-4d3c95f/README @@ -780,6 +780,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_GO * the 'go' command (exec code) CONFIG_CMD_GREPENV * search environment CONFIG_CMD_HWFLOW * RTS/CTS hw flow controlCONFIG_CMD_FUSE Device fuse support
Agree in this split: we have a general fuse command and each SOC / SOC family can add its own implementation.
+static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{
- u32 bank, row, bit, cnt, val;
- int ret, i;
- if (argc < 4 || strtou32(argv[2], 0, &bank) ||
strtou32(argv[3], 0, &row))
return CMD_RET_USAGE;
- if (!strcmp(argv[1], "read.bit")) {
if (argc != 5 || strtou32(argv[4], 0, &bit))
return CMD_RET_USAGE;
printf("Reading bank %u row 0x%.8x bit %u: ", bank, row, bit);
ret = fuse_read_bit(bank, row, bit, &val);
if (ret)
goto err;
printf("%u\n", val);
- } else if (!strcmp(argv[1], "read.row")) {
if (argc == 4)
cnt = 1;
else if (argc != 5 || strtou32(argv[4], 0, &cnt))
return CMD_RET_USAGE;
printf("Reading bank %u:\n", bank);
for (i = 0; i < cnt; i++, row++) {
if (!(i % 4))
printf("\nRow 0x%.8x:", row);
ret = fuse_read_row(bank, row, &val);
if (ret)
goto err;
printf(" %.8x", val);
}
putc('\n');
- } else if (!strcmp(argv[1], "sense.bit")) {
if (argc != 5 || strtou32(argv[4], 0, &bit))
return CMD_RET_USAGE;
printf("Sensing bank %u row 0x%.8x bit %u: ", bank, row, bit);
Each command sends this output to the console. I am thinking about if instead of printf() we shoud use debug()
It's only a preamble to the result string. It's useful as feedback to the user to confirm addresses and values (hex or not, etc.). There is also this kind of indication for some existing commands, like md that confirms addresses. IMHO, it's better as printf() than as debug(), all the more fuse stuff is sensible.
+U_BOOT_CMD(
- fuse, CONFIG_SYS_MAXARGS, 0, do_fuse,
- "Fuse sub-system",
"read.bit <bank> <row> <bit> - read a fuse bit\n"
- "fuse read.row <bank> <row> [<cnt>] - read 1 or 'cnt' fuse
rows,\n"
- " starting at 'row'\n"
- "fuse sense.bit <bank> <row> <bit> - sense a fuse bit\n"
- "fuse sense.row <bank> <row> [<cnt>] - sense 1 or 'cnt' fuse
rows,\n"
- " starting at 'row'\n"
- "fuse prog.bit <bank> <row> <bit> - program a fuse bit
(PERMANENT)\n"
- "fuse prog.row <bank> <row> <hexval> [<hexval>...] - program 1
or\n"
- " several fuse rows, starting at 'row' (PERMANENT)\n"
- "fuse ovride.bit <bank> <row> <bit> <val> - override a fuse
bit\n"
- "fuse ovride.row <bank> <row> <hexval> [<hexval>...] - override 1
or\n"
- " several fuse rows, starting at 'row'"
+);
General question: why do we need the "bit" interface ? I have thought it is enough the read row / prog row interface (even if there is a bit programming).
For prog, it corresponds to the hardware API (at least on FSL IIM). It is also a matter of safety. Fuse operations are sensible, irreversible and operate on single bits, so it is less error prone for users to concentrate on the bit that they want to program.
For read/sense/override, it is mostly for API consistency with prog.
For all these commands, this is also useful to easily automate accesses to fuse bits from command line, e.g. for end-of-line programming of boards.
If some hardware implementations are more bit- than byte-oriented or the opposite, it also makes the API more flexible.
Best regards, Benoît

On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
Or shall I send my patch [1] to this mailing list for official review because the functionality here and there is orthogonal?
Thanks
Dirk
[1] https://github.com/dirkbehme/u-boot-imx6/commit/da718b338a79af160f7b7e542fe9...
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
{u-boot-4d3c95f.orig => u-boot-4d3c95f}/README | 1 + .../common/Makefile | 1 + /dev/null => u-boot-4d3c95f/common/cmd_fuse.c | 182 ++++++++++++++++++++ .../include/config_cmd_all.h | 1 + /dev/null => u-boot-4d3c95f/include/fuse.h | 49 ++++++ 5 files changed, 234 insertions(+) create mode 100644 u-boot-4d3c95f/common/cmd_fuse.c create mode 100644 u-boot-4d3c95f/include/fuse.h
diff --git u-boot-4d3c95f.orig/README u-boot-4d3c95f/README index fb9d904..c40fd34 100644 --- u-boot-4d3c95f.orig/README +++ u-boot-4d3c95f/README @@ -780,6 +780,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_GO * the 'go' command (exec code) CONFIG_CMD_GREPENV * search environment CONFIG_CMD_HWFLOW * RTS/CTS hw flow control
diff --git u-boot-4d3c95f.orig/common/Makefile u-boot-4d3c95f/common/Makefile index 3d62775..44ef757 100644 --- u-boot-4d3c95f.orig/common/Makefile +++ u-boot-4d3c95f/common/Makefile @@ -96,6 +96,7 @@ COBJS-$(CONFIG_CMD_FLASH) += cmd_flash.o ifdef CONFIG_FPGA COBJS-$(CONFIG_CMD_FPGA) += cmd_fpga.o endif +COBJS-$(CONFIG_CMD_FUSE) += cmd_fuse.o COBJS-$(CONFIG_CMD_GPIO) += cmd_gpio.o COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o COBJS-$(CONFIG_CMD_IDE) += cmd_ide.o diff --git u-boot-4d3c95f/common/cmd_fuse.c u-boot-4d3c95f/common/cmd_fuse.c new file mode 100644 index 0000000..fd54d40 --- /dev/null +++ u-boot-4d3c95f/common/cmd_fuse.c @@ -0,0 +1,182 @@ +/*
- (C) Copyright 2009-2012 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 do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{
u32 bank, row, bit, cnt, val;
int ret, i;
if (argc < 4 || strtou32(argv[2], 0, &bank) ||
strtou32(argv[3], 0, &row))
return CMD_RET_USAGE;
if (!strcmp(argv[1], "read.bit")) {
if (argc != 5 || strtou32(argv[4], 0, &bit))
return CMD_RET_USAGE;
printf("Reading bank %u row 0x%.8x bit %u: ", bank, row, bit);
ret = fuse_read_bit(bank, row, bit, &val);
if (ret)
goto err;
printf("%u\n", val);
} else if (!strcmp(argv[1], "read.row")) {
if (argc == 4)
cnt = 1;
else if (argc != 5 || strtou32(argv[4], 0, &cnt))
return CMD_RET_USAGE;
printf("Reading bank %u:\n", bank);
for (i = 0; i < cnt; i++, row++) {
if (!(i % 4))
printf("\nRow 0x%.8x:", row);
ret = fuse_read_row(bank, row, &val);
if (ret)
goto err;
printf(" %.8x", val);
}
putc('\n');
} else if (!strcmp(argv[1], "sense.bit")) {
if (argc != 5 || strtou32(argv[4], 0, &bit))
return CMD_RET_USAGE;
printf("Sensing bank %u row 0x%.8x bit %u: ", bank, row, bit);
ret = fuse_sense_bit(bank, row, bit, &val);
if (ret)
goto err;
printf("%u\n", val);
} else if (!strcmp(argv[1], "sense.row")) {
if (argc == 4)
cnt = 1;
else if (argc != 5 || strtou32(argv[4], 0, &cnt))
return CMD_RET_USAGE;
printf("Sensing bank %u:\n", bank);
for (i = 0; i < cnt; i++, row++) {
if (!(i % 4))
printf("\nRow 0x%.8x:", row);
ret = fuse_sense_row(bank, row, &val);
if (ret)
goto err;
printf(" %.8x", val);
}
putc('\n');
} else if (!strcmp(argv[1], "prog.bit")) {
if (argc != 5 || strtou32(argv[4], 0, &bit))
return CMD_RET_USAGE;
printf("Programming bank %u row 0x%.8x bit %u...\n",
bank, row, bit);
ret = fuse_prog_bit(bank, row, bit);
if (ret)
goto err;
} else if (!strcmp(argv[1], "prog.row")) {
if (argc < 5)
return CMD_RET_USAGE;
for (i = 4; i < argc; i++, row++) {
if (strtou32(argv[i], 16, &val))
return CMD_RET_USAGE;
printf("Programming bank %u row 0x%.8x to 0x%.8x...\n",
bank, row, val);
ret = fuse_prog_row(bank, row, val);
if (ret)
goto err;
}
} else if (!strcmp(argv[1], "ovride.bit")) {
if (argc != 6 || strtou32(argv[4], 0, &bit) ||
strtou32(argv[5], 0, &val) || val > 1)
return CMD_RET_USAGE;
printf("Overriding bank %u row 0x%.8x bit %u with %u...\n",
bank, row, bit, val);
ret = fuse_override_bit(bank, row, bit, val);
if (ret)
goto err;
} else if (!strcmp(argv[1], "ovride.row")) {
if (argc < 5)
return CMD_RET_USAGE;
for (i = 4; i < argc; i++, row++) {
if (strtou32(argv[i], 16, &val))
return CMD_RET_USAGE;
printf("Overriding bank %u row 0x%.8x with 0x%.8x...\n",
bank, row, val);
ret = fuse_override_row(bank, row, 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.bit <bank> <row> <bit> - read a fuse bit\n"
"fuse read.row <bank> <row> [<cnt>] - read 1 or 'cnt' fuse rows,\n"
" starting at 'row'\n"
"fuse sense.bit <bank> <row> <bit> - sense a fuse bit\n"
"fuse sense.row <bank> <row> [<cnt>] - sense 1 or 'cnt' fuse rows,\n"
" starting at 'row'\n"
"fuse prog.bit <bank> <row> <bit> - program a fuse bit (PERMANENT)\n"
"fuse prog.row <bank> <row> <hexval> [<hexval>...] - program 1 or\n"
" several fuse rows, starting at 'row' (PERMANENT)\n"
"fuse ovride.bit <bank> <row> <bit> <val> - override a fuse bit\n"
"fuse ovride.row <bank> <row> <hexval> [<hexval>...] - override 1 or\n"
" several fuse rows, starting at 'row'"
+); diff --git u-boot-4d3c95f.orig/include/config_cmd_all.h u-boot-4d3c95f/include/config_cmd_all.h index f434cd0..8f7d9ae 100644 --- u-boot-4d3c95f.orig/include/config_cmd_all.h +++ u-boot-4d3c95f/include/config_cmd_all.h @@ -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_HWFLOW /* RTS/CTS hw flow control */ #define CONFIG_CMD_I2C /* I2C serial bus support */ #define CONFIG_CMD_IDE /* IDE harddisk support */ diff --git u-boot-4d3c95f/include/fuse.h u-boot-4d3c95f/include/fuse.h new file mode 100644 index 0000000..baefefe --- /dev/null +++ u-boot-4d3c95f/include/fuse.h @@ -0,0 +1,49 @@ +/*
- (C) Copyright 2009-2012 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
- row: Fuse row within the bank
- bit: Fuse bit within the row
- val: Value to read/write
- Returns: 0 on success, not 0 on failure
- */
+int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_read_row(u32 bank, u32 row, u32 *val); +int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_sense_row(u32 bank, u32 row, u32 *val); +int fuse_prog_bit(u32 bank, u32 row, u32 bit); +int fuse_prog_row(u32 bank, u32 row, u32 val); +int fuse_override_bit(u32 bank, u32 row, u32 bit, u32 val); +int fuse_override_row(u32 bank, u32 row, u32 val);
+#endif /* _FUSE_H_ */ _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Hi Dirk,
On Wednesday, August 22, 2012 12:43:05 PM, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
Or shall I send my patch [1] to this mailing list for official review because the functionality here and there is orthogonal?
Thanks
Dirk
[1] https://github.com/dirkbehme/u-boot-imx6/commit/da718b338a79af160f7b7e542fe9...
This OTP IP is different from the IIM IP of other i.MXs, so having a different driver for it is fine.
What you can do is implement in your driver the fuse API that I've defined in this series. In that way, you could drop your common/cmd_imxotp.c and use the commands from this series. Then, you can send the resulting patches for review.
Best regards, Benoît

On 22.08.2012 13:11, Benoît Thébaudeau wrote:
Hi Dirk,
On Wednesday, August 22, 2012 12:43:05 PM, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
Or shall I send my patch [1] to this mailing list for official review because the functionality here and there is orthogonal?
Thanks
Dirk
[1] https://github.com/dirkbehme/u-boot-imx6/commit/da718b338a79af160f7b7e542fe9...
This OTP IP is different from the IIM IP of other i.MXs, so having a different driver for it is fine.
What you can do is implement in your driver the fuse API
You mean
http://lists.denx.de/pipermail/u-boot/2012-August/130904.html
here, correct?
that I've defined in this series. In that way, you could drop your common/cmd_imxotp.c and use the commands from this series.
Let's see how this fits to i.MX6:
My understanding is that the i.MX6 has 128 fuse 'registers' (#define IMX_OTP_ADDR_MAX 0x7F), each containing 32 fuses/bits. These fuses/bits can be written from 0 -> 1 once.
Looking at your API [2] we could set 'bank' to 0 and interpret 'row' as the 'register' number. That might fit. Doing this, fuse_read_bit/row() and fuse_prog_bit/row() could be used for i.MX6.
From i.MX6 point of view, as I don't know your use case, I'm not sure what fuse_sense_bit/row() and fuse_override_bit/row() might be good for?
Anybody else: Does this make sense? Or should we keep the i.MX6 specific common/cmd_imxotp.c (see [1] above)?.
Best regards
Dirk
[2]
+ * Read/Sense/Program/Override interface: + * bank: Fuse bank + * row: Fuse row within the bank + * bit: Fuse bit within the row + * val: Value to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_read_row(u32 bank, u32 row, u32 *val); +int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_sense_row(u32 bank, u32 row, u32 *val); +int fuse_prog_bit(u32 bank, u32 row, u32 bit); +int fuse_prog_row(u32 bank, u32 row, u32 val); +int fuse_override_bit(u32 bank, u32 row, u32 bit, u32 val); +int fuse_override_row(u32 bank, u32 row, u32 val);

Hi Dirk,
On Wednesday, August 22, 2012 6:25:57 PM, Dirk Behme wrote:
On 22.08.2012 13:11, Benoît Thébaudeau wrote:
Hi Dirk,
On Wednesday, August 22, 2012 12:43:05 PM, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
Or shall I send my patch [1] to this mailing list for official review because the functionality here and there is orthogonal?
Thanks
Dirk
[1] https://github.com/dirkbehme/u-boot-imx6/commit/da718b338a79af160f7b7e542fe9...
This OTP IP is different from the IIM IP of other i.MXs, so having a different driver for it is fine.
What you can do is implement in your driver the fuse API
You mean
http://lists.denx.de/pipermail/u-boot/2012-August/130904.html
here, correct?
Yes.
that I've defined in this series. In that way, you could drop your common/cmd_imxotp.c and use the commands from this series.
Let's see how this fits to i.MX6:
My understanding is that the i.MX6 has 128 fuse 'registers' (#define IMX_OTP_ADDR_MAX 0x7F), each containing 32 fuses/bits. These fuses/bits can be written from 0 -> 1 once.
Looking at your API [2] we could set 'bank' to 0 and interpret 'row' as the 'register' number. That might fit. Doing this, fuse_read_bit/row() and fuse_prog_bit/row() could be used for i.MX6.
Sounds good.
From i.MX6 point of view, as I don't know your use case, I'm not sure what fuse_sense_bit/row() and fuse_override_bit/row() might be good for?
These are hardware features on the other i.MXs' IIM that may exist on other hardware as well.
Override allows to change the value read from fuses without reprogramming the fuses. This change is lost after a power cycle. This can be useful e.g. to change some hardware behavior linked to values read from fuses.
Sense allows to get the real programmed value of a fuse without being disturbed by a pending override on this fuse.
I don't know if i.MX6's OTP has such features. If your driver is complete, i.MX6 doesn't have these features, so the corresponding functions should simply return an error.
Anybody else: Does this make sense? Or should we keep the i.MX6 specific common/cmd_imxotp.c (see [1] above)?.
Best regards
Dirk
[2]
- Read/Sense/Program/Override interface:
- bank: Fuse bank
- row: Fuse row within the bank
- bit: Fuse bit within the row
- val: Value to read/write
- Returns: 0 on success, not 0 on failure
- */
+int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_read_row(u32 bank, u32 row, u32 *val); +int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val); +int fuse_sense_row(u32 bank, u32 row, u32 *val); +int fuse_prog_bit(u32 bank, u32 row, u32 bit); +int fuse_prog_row(u32 bank, u32 row, u32 val); +int fuse_override_bit(u32 bank, u32 row, u32 bit, u32 val); +int fuse_override_row(u32 bank, u32 row, u32 val);
Best regards, Benoît

On 22/08/2012 12:43, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
I have not checked the details. but seeing the code it looks that the procedure to read / write are different. In this case, a further driver is ok.
Anyway, you should take a look if your patches can be used on a mxs (MX28) device, because they should be closer. And then I will not like to have a driver for each SOC.
Generally, I think we should use the approach of the common command and a specific fuse implementation. Then this API should be used by your patches as well.
Best regards, Stefano

On 08/23/2012 03:31 AM, Stefano Babic wrote:
On 22/08/2012 12:43, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
I have not checked the details. but seeing the code it looks that the procedure to read / write are different. In this case, a further driver is ok.
Anyway, you should take a look if your patches can be used on a mxs (MX28) device, because they should be closer. And then I will not like to have a driver for each SOC.
Generally, I think we should use the approach of the common command and a specific fuse implementation. Then this API should be used by your patches as well.
I agree.
The use of the fuse API will likely result in more code than the imxotp implementation, and more importantly, it will make the usage more confusing by introducing terms bank and row.
Reading and writing fuses is probably not an area that we want confusion.
Regards,
Eric

Hi Eric, all,
On Thursday, August 23, 2012 3:23:20 PM, Eric Nelson wrote:
On 08/23/2012 03:31 AM, Stefano Babic wrote:
On 22/08/2012 12:43, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
I have not checked the details. but seeing the code it looks that the procedure to read / write are different. In this case, a further driver is ok.
Anyway, you should take a look if your patches can be used on a mxs (MX28) device, because they should be closer. And then I will not like to have a driver for each SOC.
Generally, I think we should use the approach of the common command and a specific fuse implementation. Then this API should be used by your patches as well.
I agree.
The use of the fuse API will likely result in more code than the imxotp implementation, and more importantly, it will make the usage more confusing by introducing terms bank and row.
Reading and writing fuses is probably not an area that we want confusion.
I am looking again into this question now that I have the i.MX6 reference manual.
I don't see any difference between IIM and OCOTP features: - There are still banks: They exist as seen from the controller, even if they don't exist physically in the efusebox. See 46.2.1 and OCOTP memory map ("Value of OTP Bankx Wordy" shadow registers). - Rows are named words. - The read operations are read accesses to the shadow registers. - The sense operations are direct fuse reads (shadow reload + read), as explained by the steps in 46.2.1.2. - The prog operations are the programming of the fuses, as explained by the steps in 46.2.1.3. - The override operations are simple write accesses to the shadow registers, as explained in 46.2.1.3.
As to the vocabulary used, the differences are: - "row" -> "word". - "sense" -> "direct read".
Hence, the fuse API applies very well in this case too.
Best regards, Benoît

On 26.11.2012 17:03, Benoît Thébaudeau wrote:
Hi Eric, all,
On Thursday, August 23, 2012 3:23:20 PM, Eric Nelson wrote:
On 08/23/2012 03:31 AM, Stefano Babic wrote:
On 22/08/2012 12:43, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
I have not checked the details. but seeing the code it looks that the procedure to read / write are different. In this case, a further driver is ok.
Anyway, you should take a look if your patches can be used on a mxs (MX28) device, because they should be closer. And then I will not like to have a driver for each SOC.
Generally, I think we should use the approach of the common command and a specific fuse implementation. Then this API should be used by your patches as well.
I agree.
The use of the fuse API will likely result in more code than the imxotp implementation, and more importantly, it will make the usage more confusing by introducing terms bank and row.
Reading and writing fuses is probably not an area that we want confusion.
I am looking again into this question now that I have the i.MX6 reference manual.
I don't see any difference between IIM and OCOTP features:
- There are still banks: They exist as seen from the controller, even if they don't exist physically in the efusebox. See 46.2.1 and OCOTP memory map ("Value of OTP Bankx Wordy" shadow registers).
- Rows are named words.
- The read operations are read accesses to the shadow registers.
- The sense operations are direct fuse reads (shadow reload + read), as explained by the steps in 46.2.1.2.
- The prog operations are the programming of the fuses, as explained by the steps in 46.2.1.3.
- The override operations are simple write accesses to the shadow registers, as explained in 46.2.1.3.
As to the vocabulary used, the differences are:
- "row" -> "word".
- "sense" -> "direct read".
Hence, the fuse API applies very well in this case too.
Do you like to update/rebase your patches to the latest U-Boot and re-send? Maybe it makes sense to discuss your patches again, then?
Eric: What do you think?
Thanks
Dirk

On 11/27/2012 12:19 AM, Dirk Behme wrote:
On 26.11.2012 17:03, Benoît Thébaudeau wrote:
Hi Eric, all,
On Thursday, August 23, 2012 3:23:20 PM, Eric Nelson wrote:
On 08/23/2012 03:31 AM, Stefano Babic wrote:
On 22/08/2012 12:43, Dirk Behme wrote:
On 14.08.2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
For i.MX6, I have a port of the OTP support from Freescale's U-Boot to our mainline U-Boot in the queue [1].
As I don't have the overview over the various i.MXxx SoCs and don't understand much of this patch below: Should this implement the same functionality like my patch [1] for i.MX6?
I have not checked the details. but seeing the code it looks that the procedure to read / write are different. In this case, a further driver is ok.
Anyway, you should take a look if your patches can be used on a mxs (MX28) device, because they should be closer. And then I will not like to have a driver for each SOC.
Generally, I think we should use the approach of the common command and a specific fuse implementation. Then this API should be used by your patches as well.
I agree.
The use of the fuse API will likely result in more code than the imxotp implementation, and more importantly, it will make the usage more confusing by introducing terms bank and row.
Reading and writing fuses is probably not an area that we want confusion.
I am looking again into this question now that I have the i.MX6 reference manual.
I don't see any difference between IIM and OCOTP features:
- There are still banks: They exist as seen from the controller, even
if they don't exist physically in the efusebox. See 46.2.1 and OCOTP memory map ("Value of OTP Bankx Wordy" shadow registers).
- Rows are named words.
- The read operations are read accesses to the shadow registers.
- The sense operations are direct fuse reads (shadow reload + read), as explained by the steps in 46.2.1.2.
- The prog operations are the programming of the fuses, as explained
by the steps in 46.2.1.3.
- The override operations are simple write accesses to the shadow
registers, as explained in 46.2.1.3.
As to the vocabulary used, the differences are:
- "row" -> "word".
- "sense" -> "direct read".
Hence, the fuse API applies very well in this case too.
Do you like to update/rebase your patches to the latest U-Boot and re-send? Maybe it makes sense to discuss your patches again, then?
Eric: What do you think?
Hi Benoit and Dirk,
I don't have strong feelings one way or the other. If left to me, I'd probably stick with the imxotp command, but Benoît has clearly walked through the details and we're not talking about a lot of code either way.
Either way, this needs a general 'readme' for the fuse command conventions and some per-arch documentation about how to translate between the reference manual and the command.
It also seems appropriate to have documentation somewhere about the conventions used for things like mac address storage. AFAIK, the only place to find the mapping of OTP locations used for this is in the various bits of code that implement it.
Regards,
Eric

Hi Eric, Dirk,
On Tuesday, November 27, 2012 5:58:19 PM, Eric Nelson wrote:
I don't have strong feelings one way or the other. If left to me, I'd probably stick with the imxotp command, but Benoît has clearly walked through the details and we're not talking about a lot of code either way.
OK. The more code is in common, the easier it is to maintain.
Either way, this needs a general 'readme' for the fuse command conventions
Sure. I'll add a doc/README.fuse to v3.
and some per-arch documentation about how to translate between the reference manual and the command.
Yes. Should this documentation be located in the README.fuse, or in separate README files, or in the drivers themselves, e.g. fsl_iim.c?
It also seems appropriate to have documentation somewhere about the conventions used for things like mac address storage. AFAIK, the only place to find the mapping of OTP locations used for this is in the various bits of code that implement it.
Yes. Currently, it can be found in the various imx-regs.h, in the fuse_bankx_regs structures. This information could be added to README.imx*.
There is also an imx_get_mac_from_fuse() function implemented for each i.MX SoC to load the MAC address from the fuses for the FEC. Perhaps a similar function with a default implementation could be created by each applicable SoC and used by a new command in cmd_fuse.c to handle MAC addresses read/write operations. But this would perhaps be too specific for cmd_fuse.c. It might be better to either have only the README.imx* documentation, or to have SoC-specific commands for the MAC addresses, like for the clock commands. What do you think?
Best regards, Benoît

Hi Benoît,
On 11/27/2012 11:27 AM, Benoît Thébaudeau wrote:
Hi Eric, Dirk,
On Tuesday, November 27, 2012 5:58:19 PM, Eric Nelson wrote:
I don't have strong feelings one way or the other. If left to me, I'd probably stick with the imxotp command, but Benoît has clearly walked through the details and we're not talking about a lot of code either way.
OK. The more code is in common, the easier it is to maintain.
Either way, this needs a general 'readme' for the fuse command conventions
Sure. I'll add a doc/README.fuse to v3.
and some per-arch documentation about how to translate between the reference manual and the command.
Yes. Should this documentation be located in the README.fuse, or in separate README files, or in the drivers themselves, e.g. fsl_iim.c?
I think doc/readme.imx* is the right place.
Oops. It looks like we need one of these for i.MX6.
It also seems appropriate to have documentation somewhere about the conventions used for things like mac address storage. AFAIK, the only place to find the mapping of OTP locations used for this is in the various bits of code that implement it.
Yes. Currently, it can be found in the various imx-regs.h, in the fuse_bankx_regs structures. This information could be added to README.imx*.
There is also an imx_get_mac_from_fuse() function implemented for each i.MX SoC to load the MAC address from the fuses for the FEC. Perhaps a similar function with a default implementation could be created by each applicable SoC and used by a new command in cmd_fuse.c to handle MAC addresses read/write operations. But this would perhaps be too specific for cmd_fuse.c. It might be better to either have only the README.imx* documentation, or to have SoC-specific commands for the MAC addresses, like for the clock commands. What do you think?
Since this really only hits us board vendors, and is mostly used in the production process, it's probably overkill to implement a command to make it easier.
Best regards, Benoît
Regards,
Eric

Hi Eric,
On Tuesday, November 27, 2012 7:36:41 PM, Eric Nelson wrote:
Hi Benoît,
On 11/27/2012 11:27 AM, Benoît Thébaudeau wrote:
Hi Eric, Dirk,
and some per-arch documentation about how to translate between the reference manual and the command.
Yes. Should this documentation be located in the README.fuse, or in separate README files, or in the drivers themselves, e.g. fsl_iim.c?
I think doc/readme.imx* is the right place.
MPC/i.MX25/35/51/53 would have the same documentation here since they all use the IIM. On the other side, there would be the i.MX6 with the OCOTP. So this part of the documentation is rather IP-specific than SoC- or platform-specific. Hence, I think that the right place would be either README.fuse, or README.fsl_iim/README.fsl_ocotp[/...], or fsl_iim.c/fsl_ocotp.c[/...].
Best regards, Benoît

On 11/27/2012 12:23 PM, Benoît Thébaudeau wrote:
Hi Eric,
On Tuesday, November 27, 2012 7:36:41 PM, Eric Nelson wrote:
Hi Benoît,
On 11/27/2012 11:27 AM, Benoît Thébaudeau wrote:
Hi Eric, Dirk,
and some per-arch documentation about how to translate between the reference manual and the command.
Yes. Should this documentation be located in the README.fuse, or in separate README files, or in the drivers themselves, e.g. fsl_iim.c?
I think doc/readme.imx* is the right place.
MPC/i.MX25/35/51/53 would have the same documentation here since they all use the IIM. On the other side, there would be the i.MX6 with the OCOTP. So this part of the documentation is rather IP-specific than SoC- or platform-specific. Hence, I think that the right place would be either README.fuse, or README.fsl_iim/README.fsl_ocotp[/...], or fsl_iim.c/fsl_ocotp.c[/...].
Sounds good to me.

On 14/08/2012 14:52, Benoît Thébaudeau wrote:
This can be useful for fuse-like hardware, OTP SoC options, etc.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
Hi Benoît,
I agree with you that same code can be used then for i.MX6. There is no need of a parallel development.
I am thinking about if we need some kind of protection to avoid to destroy very easy the SOC. Running a fuse command can be much more dangerous as scrubbing NAND or erasing flash.
What about to add at least a "-y" option when we write the fuses, in the same way we have for the "nand scrub command" ? This does not forbid to use the command in scripts, but it can maybe avoid to destroy the SOC when the command is wrong tipped on the console.
What do you think ?
Best regards, Stefano Babic

Hi Stefano,
On Monday, December 3, 2012 10:03:22 AM, Stefano Babic wrote:
I am thinking about if we need some kind of protection to avoid to destroy very easy the SOC. Running a fuse command can be much more dangerous as scrubbing NAND or erasing flash.
What about to add at least a "-y" option when we write the fuses, in the same way we have for the "nand scrub command" ? This does not forbid to use the command in scripts, but it can maybe avoid to destroy the SOC when the command is wrong tipped on the console.
What do you think ?
That makes sense. There could be the same kind of warning confirmation defaulting to no that would repeat which fuse is about to be programmed.
As to the value passed for fuse row programming or overriding, do you think that it's fine to force it to be hex, or that choice should be given with '0x'? I don't really like implicit base selection, but it's clear in the help message, and it is handy for writing MAC addresses without repeating the '0x' for each byte.
Best regards, Benoît

On 03/12/2012 12:25, Benoît Thébaudeau wrote:
Hi Stefano,
On Monday, December 3, 2012 10:03:22 AM, Stefano Babic wrote:
I am thinking about if we need some kind of protection to avoid to destroy very easy the SOC. Running a fuse command can be much more dangerous as scrubbing NAND or erasing flash.
What about to add at least a "-y" option when we write the fuses, in the same way we have for the "nand scrub command" ? This does not forbid to use the command in scripts, but it can maybe avoid to destroy the SOC when the command is wrong tipped on the console.
What do you think ?
That makes sense. There could be the same kind of warning confirmation defaulting to no that would repeat which fuse is about to be programmed.
As to the value passed for fuse row programming or overriding, do you think that it's fine to force it to be hex, or that choice should be given with '0x'? I don't really like implicit base selection, but it's clear in the help message, and it is handy for writing MAC addresses without repeating the '0x' for each byte.
U-boot uses as default hex as base for numbers, not decimals, and if you use hex as default you are consistent with the rest of code.
Best regards, Stefano

Add a fsl_iim driver common to i.MX and MPC.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de --- .../drivers/misc/Makefile | 1 + /dev/null => u-boot-4d3c95f/drivers/misc/fsl_iim.c | 318 ++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 u-boot-4d3c95f/drivers/misc/fsl_iim.c
diff --git u-boot-4d3c95f.orig/drivers/misc/Makefile u-boot-4d3c95f/drivers/misc/Makefile index 271463c..31b8db8 100644 --- u-boot-4d3c95f.orig/drivers/misc/Makefile +++ u-boot-4d3c95f/drivers/misc/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libmisc.o
COBJS-$(CONFIG_ALI152X) += ali512x.o COBJS-$(CONFIG_DS4510) += ds4510.o +COBJS-$(CONFIG_FSL_IIM) += fsl_iim.o COBJS-$(CONFIG_FSL_LAW) += fsl_law.o COBJS-$(CONFIG_GPIO_LED) += gpio_led.o COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o diff --git u-boot-4d3c95f/drivers/misc/fsl_iim.c u-boot-4d3c95f/drivers/misc/fsl_iim.c new file mode 100644 index 0000000..1a3d5fc --- /dev/null +++ u-boot-4d3c95f/drivers/misc/fsl_iim.c @@ -0,0 +1,318 @@ +/* + * (C) Copyright 2009-2012 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 <config.h> +#include <common.h> +#include <hwconfig.h> +#include <fuse.h> +#include <asm/errno.h> +#include <asm/byteorder.h> +#include <asm/io.h> + +/* FSL IIM-specific constants */ +#define STAT_BUSY 0x80 +#define STAT_PRGD 0x02 +#define STAT_SNSD 0x01 + +#define STATM_PRGD_M 0x02 +#define STATM_SNSD_M 0x01 + +#define ERR_PRGE 0x80 +#define ERR_WPE 0x40 +#define ERR_OPE 0x20 +#define ERR_RPE 0x10 +#define ERR_WLRE 0x08 +#define ERR_SNSE 0x04 +#define ERR_PARITYE 0x02 + +#define EMASK_PRGE_M 0x80 +#define EMASK_WPE_M 0x40 +#define EMASK_OPE_M 0x20 +#define EMASK_RPE_M 0x10 +#define EMASK_WLRE_M 0x08 +#define EMASK_SNSE_M 0x04 +#define EMASK_PARITYE_M 0x02 + +#define FCTL_DPC 0x80 +#define FCTL_PRG_LENGTH_MASK 0x70 +#define FCTL_ESNS_N 0x08 +#define FCTL_ESNS_0 0x04 +#define FCTL_ESNS_1 0x02 +#define FCTL_PRG 0x01 + +#define UA_A_BANK_MASK 0x38 +#define UA_A_ROWH_MASK 0x07 + +#define LA_A_ROWL_MASK 0xf8 +#define LA_A_BIT_MASK 0x07 + +#define PREV_PROD_REV_MASK 0xf8 +#define PREV_PROD_VT_MASK 0x07 + +/* Select the correct accessors depending on endianness */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define iim_read32 in_le32 +#define iim_write32 out_le32 +#define iim_clrsetbits32 clrsetbits_le32 +#define iim_clrbits32 clrbits_le32 +#define iim_setbits32 setbits_le32 +#elif __BYTE_ORDER == __BIG_ENDIAN +#define iim_read32 in_be32 +#define iim_write32 out_be32 +#define iim_clrsetbits32 clrsetbits_be32 +#define iim_clrbits32 clrbits_be32 +#define iim_setbits32 setbits_be32 +#else +#error "Endianess is not defined: please fix to continue" +#endif + +/* IIM control registers */ +struct fsl_iim { + u32 stat; + u32 statm; + u32 err; + u32 emask; + u32 fctl; + u32 ua; + u32 la; + u32 sdat; + u32 prev; + u32 srev; + u32 prg_p; + u32 scs[0x1f5]; + struct { + u32 row[0x100]; + } bank[8]; +}; + +int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val) +{ + int ret; + + if (bit >= 8) { + puts("fsl_iim fuse read: Invalid argument\n"); + return -EINVAL; + } + + ret = fuse_read_row(bank, row, val); + if (ret) + return ret; + + *val = !!(*val & 1 << bit); + return 0; +} + +int fuse_read_row(u32 bank, u32 row, u32 *val) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + val == NULL) { + puts("fsl_iim fuse read: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->err, iim_read32(®s->err)); + *val = iim_read32(®s->bank[bank].row[row]); + err = iim_read32(®s->err); + iim_write32(®s->err, iim_read32(®s->err)); + + if (err & ERR_RPE) { + puts("fsl_iim fuse read: Read protect error\n"); + return -EIO; + } + + return 0; +} + +int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val) +{ + int ret; + + if (bit >= 8) { + puts("fsl_iim fuse sense: Invalid argument\n"); + return -EINVAL; + } + + ret = fuse_sense_row(bank, row, val); + if (ret) + return ret; + + *val = !!(*val & 1 << bit); + return 0; +} + +int fuse_sense_row(u32 bank, u32 row, u32 *val) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 stat, err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + val == NULL) { + puts("fsl_iim fuse sense: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->ua, bank << 3 | row >> 5); + iim_write32(®s->la, row << 3 & 0xff); + iim_write32(®s->fctl, iim_read32(®s->fctl) | FCTL_ESNS_N); + while (iim_read32(®s->stat) & STAT_BUSY) + udelay(20); + stat = iim_read32(®s->stat); + err = iim_read32(®s->err); + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + + if (err & ERR_SNSE) { + puts("fsl_iim fuse sense: Explicit sense cycle error\n"); + return -EIO; + } + + if (!(stat & STAT_SNSD)) { + puts("fsl_iim fuse sense: Explicit sense cycle " + "did not complete\n"); + return -EIO; + } + + *val = iim_read32(®s->sdat); + return 0; +} + +int fuse_prog_bit(u32 bank, u32 row, u32 bit) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 stat, err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + bit >= 8) { + puts("fsl_iim fuse program: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->ua, bank << 3 | row >> 5); + iim_write32(®s->la, (row << 3 | bit) & 0xff); + iim_write32(®s->prg_p, 0xaa); + iim_write32(®s->fctl, iim_read32(®s->fctl) | FCTL_PRG); + while (iim_read32(®s->stat) & STAT_BUSY) + udelay(20); + stat = iim_read32(®s->stat); + err = iim_read32(®s->err); + iim_write32(®s->stat, iim_read32(®s->stat)); + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->prg_p, 0x00); + + if (err & ERR_PRGE) { + puts("fsl_iim fuse program: Program error\n"); + return -EIO; + } + + if (err & ERR_WPE) { + puts("fsl_iim fuse program: Write protect error\n"); + return -EIO; + } + + if (!(stat & STAT_PRGD)) { + puts("fsl_iim fuse program: Program did not complete\n"); + return -EIO; + } + + return 0; +} + +int fuse_prog_row(u32 bank, u32 row, u32 val) +{ + int bit, ret; + + if (val & ~0xff) { + puts("fsl_iim fuse program: Invalid argument\n"); + return -EINVAL; + } + + for (bit = 0; val; bit++, val >>= 1) + if (val & 0x01) { + ret = fuse_prog_bit(bank, row, bit); + if (ret) + return ret; + } + + return 0; +} + +int fuse_override_bit(u32 bank, u32 row, u32 bit, u32 val) +{ + u32 row_val; + int ret; + + if (bit >= 8 || val > 1) { + puts("fsl_iim fuse override: Invalid argument\n"); + return -EINVAL; + } + + ret = fuse_read_row(bank, row, &row_val); + if (ret) + return ret; + + return fuse_override_row(bank, row, + (row_val & ~(1 << bit)) | val << bit); +} + +int fuse_override_row(u32 bank, u32 row, u32 val) +{ + volatile struct fsl_iim *regs = + (struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR; + u32 err; + + if (bank >= ARRAY_SIZE(regs->bank) || + row >= ARRAY_SIZE(regs->bank[0].row) || + val & ~0xff) { + puts("fsl_iim fuse override: Invalid argument\n"); + return -EINVAL; + } + + iim_write32(®s->err, iim_read32(®s->err)); + iim_write32(®s->bank[bank].row[row], val); + err = iim_read32(®s->err); + iim_write32(®s->err, iim_read32(®s->err)); + + if (err & ERR_OPE) { + puts("fsl_iim fuse override: Override protect error\n"); + return -EIO; + } + + return 0; +}

On 14/08/2012 14:52, Benoît Thébaudeau wrote:
Add a fsl_iim driver common to i.MX and MPC.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
.../drivers/misc/Makefile | 1 + /dev/null => u-boot-4d3c95f/drivers/misc/fsl_iim.c | 318 ++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 u-boot-4d3c95f/drivers/misc/fsl_iim.c
diff --git u-boot-4d3c95f.orig/drivers/misc/Makefile u-boot-4d3c95f/drivers/misc/Makefile index 271463c..31b8db8 100644 --- u-boot-4d3c95f.orig/drivers/misc/Makefile +++ u-boot-4d3c95f/drivers/misc/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libmisc.o
COBJS-$(CONFIG_ALI152X) += ali512x.o COBJS-$(CONFIG_DS4510) += ds4510.o +COBJS-$(CONFIG_FSL_IIM) += fsl_iim.o COBJS-$(CONFIG_FSL_LAW) += fsl_law.o COBJS-$(CONFIG_GPIO_LED) += gpio_led.o COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o diff --git u-boot-4d3c95f/drivers/misc/fsl_iim.c u-boot-4d3c95f/drivers/misc/fsl_iim.c new file mode 100644 index 0000000..1a3d5fc --- /dev/null +++ u-boot-4d3c95f/drivers/misc/fsl_iim.c @@ -0,0 +1,318 @@ +/*
- (C) Copyright 2009-2012 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 <config.h> +#include <common.h> +#include <hwconfig.h> +#include <fuse.h> +#include <asm/errno.h> +#include <asm/byteorder.h> +#include <asm/io.h>
+/* FSL IIM-specific constants */ +#define STAT_BUSY 0x80 +#define STAT_PRGD 0x02 +#define STAT_SNSD 0x01
+#define STATM_PRGD_M 0x02 +#define STATM_SNSD_M 0x01
+#define ERR_PRGE 0x80 +#define ERR_WPE 0x40 +#define ERR_OPE 0x20 +#define ERR_RPE 0x10 +#define ERR_WLRE 0x08 +#define ERR_SNSE 0x04 +#define ERR_PARITYE 0x02
+#define EMASK_PRGE_M 0x80 +#define EMASK_WPE_M 0x40 +#define EMASK_OPE_M 0x20 +#define EMASK_RPE_M 0x10 +#define EMASK_WLRE_M 0x08 +#define EMASK_SNSE_M 0x04 +#define EMASK_PARITYE_M 0x02
+#define FCTL_DPC 0x80 +#define FCTL_PRG_LENGTH_MASK 0x70 +#define FCTL_ESNS_N 0x08 +#define FCTL_ESNS_0 0x04 +#define FCTL_ESNS_1 0x02 +#define FCTL_PRG 0x01
+#define UA_A_BANK_MASK 0x38 +#define UA_A_ROWH_MASK 0x07
+#define LA_A_ROWL_MASK 0xf8 +#define LA_A_BIT_MASK 0x07
+#define PREV_PROD_REV_MASK 0xf8 +#define PREV_PROD_VT_MASK 0x07
+/* Select the correct accessors depending on endianness */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define iim_read32 in_le32 +#define iim_write32 out_le32 +#define iim_clrsetbits32 clrsetbits_le32 +#define iim_clrbits32 clrbits_le32 +#define iim_setbits32 setbits_le32 +#elif __BYTE_ORDER == __BIG_ENDIAN +#define iim_read32 in_be32 +#define iim_write32 out_be32 +#define iim_clrsetbits32 clrsetbits_be32 +#define iim_clrbits32 clrbits_be32 +#define iim_setbits32 setbits_be32 +#else +#error "Endianess is not defined: please fix to continue" +#endif
+/* IIM control registers */ +struct fsl_iim {
- u32 stat;
- u32 statm;
- u32 err;
- u32 emask;
- u32 fctl;
- u32 ua;
- u32 la;
- u32 sdat;
- u32 prev;
- u32 srev;
- u32 prg_p;
- u32 scs[0x1f5];
- struct {
u32 row[0x100];
- } bank[8];
+};
+int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val) +{
- int ret;
- if (bit >= 8) {
puts("fsl_iim fuse read: Invalid argument\n");
return -EINVAL;
- }
- ret = fuse_read_row(bank, row, val);
- if (ret)
return ret;
- *val = !!(*val & 1 << bit);
- return 0;
+}
+int fuse_read_row(u32 bank, u32 row, u32 *val) +{
- volatile struct fsl_iim *regs =
(struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR;
- u32 err;
- if (bank >= ARRAY_SIZE(regs->bank) ||
row >= ARRAY_SIZE(regs->bank[0].row) ||
val == NULL) {
puts("fsl_iim fuse read: Invalid argument\n");
return -EINVAL;
- }
- iim_write32(®s->err, iim_read32(®s->err));
- *val = iim_read32(®s->bank[bank].row[row]);
- err = iim_read32(®s->err);
- iim_write32(®s->err, iim_read32(®s->err));
- if (err & ERR_RPE) {
puts("fsl_iim fuse read: Read protect error\n");
return -EIO;
- }
- return 0;
+}
+int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val) +{
- int ret;
- if (bit >= 8) {
puts("fsl_iim fuse sense: Invalid argument\n");
return -EINVAL;
- }
- ret = fuse_sense_row(bank, row, val);
- if (ret)
return ret;
- *val = !!(*val & 1 << bit);
- return 0;
+}
+int fuse_sense_row(u32 bank, u32 row, u32 *val) +{
- volatile struct fsl_iim *regs =
(struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR;
- u32 stat, err;
- if (bank >= ARRAY_SIZE(regs->bank) ||
row >= ARRAY_SIZE(regs->bank[0].row) ||
val == NULL) {
puts("fsl_iim fuse sense: Invalid argument\n");
return -EINVAL;
- }
- iim_write32(®s->stat, iim_read32(®s->stat));
- iim_write32(®s->err, iim_read32(®s->err));
- iim_write32(®s->ua, bank << 3 | row >> 5);
- iim_write32(®s->la, row << 3 & 0xff);
- iim_write32(®s->fctl, iim_read32(®s->fctl) | FCTL_ESNS_N);
- while (iim_read32(®s->stat) & STAT_BUSY)
udelay(20);
- stat = iim_read32(®s->stat);
- err = iim_read32(®s->err);
- iim_write32(®s->stat, iim_read32(®s->stat));
- iim_write32(®s->err, iim_read32(®s->err));
- if (err & ERR_SNSE) {
puts("fsl_iim fuse sense: Explicit sense cycle error\n");
return -EIO;
- }
- if (!(stat & STAT_SNSD)) {
puts("fsl_iim fuse sense: Explicit sense cycle "
"did not complete\n");
return -EIO;
- }
- *val = iim_read32(®s->sdat);
- return 0;
+}
+int fuse_prog_bit(u32 bank, u32 row, u32 bit) +{
- volatile struct fsl_iim *regs =
(struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR;
The address depends on the SOC, and is not a board configuration option. Should we not use IIM_BASE_ADDR ?
Best regards, Stefano

Hi Stefano,
Add a fsl_iim driver common to i.MX and MPC.
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
.../drivers/misc/Makefile | 1 + /dev/null => u-boot-4d3c95f/drivers/misc/fsl_iim.c | 318 ++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 u-boot-4d3c95f/drivers/misc/fsl_iim.c
diff --git u-boot-4d3c95f.orig/drivers/misc/Makefile u-boot-4d3c95f/drivers/misc/Makefile index 271463c..31b8db8 100644 --- u-boot-4d3c95f.orig/drivers/misc/Makefile +++ u-boot-4d3c95f/drivers/misc/Makefile @@ -27,6 +27,7 @@ LIB := $(obj)libmisc.o
COBJS-$(CONFIG_ALI152X) += ali512x.o COBJS-$(CONFIG_DS4510) += ds4510.o +COBJS-$(CONFIG_FSL_IIM) += fsl_iim.o COBJS-$(CONFIG_FSL_LAW) += fsl_law.o COBJS-$(CONFIG_GPIO_LED) += gpio_led.o COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o diff --git u-boot-4d3c95f/drivers/misc/fsl_iim.c u-boot-4d3c95f/drivers/misc/fsl_iim.c new file mode 100644 index 0000000..1a3d5fc --- /dev/null +++ u-boot-4d3c95f/drivers/misc/fsl_iim.c @@ -0,0 +1,318 @@ +/*
- (C) Copyright 2009-2012 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 <config.h> +#include <common.h> +#include <hwconfig.h> +#include <fuse.h> +#include <asm/errno.h> +#include <asm/byteorder.h> +#include <asm/io.h>
+/* FSL IIM-specific constants */ +#define STAT_BUSY 0x80 +#define STAT_PRGD 0x02 +#define STAT_SNSD 0x01
+#define STATM_PRGD_M 0x02 +#define STATM_SNSD_M 0x01
+#define ERR_PRGE 0x80 +#define ERR_WPE 0x40 +#define ERR_OPE 0x20 +#define ERR_RPE 0x10 +#define ERR_WLRE 0x08 +#define ERR_SNSE 0x04 +#define ERR_PARITYE 0x02
+#define EMASK_PRGE_M 0x80 +#define EMASK_WPE_M 0x40 +#define EMASK_OPE_M 0x20 +#define EMASK_RPE_M 0x10 +#define EMASK_WLRE_M 0x08 +#define EMASK_SNSE_M 0x04 +#define EMASK_PARITYE_M 0x02
+#define FCTL_DPC 0x80 +#define FCTL_PRG_LENGTH_MASK 0x70 +#define FCTL_ESNS_N 0x08 +#define FCTL_ESNS_0 0x04 +#define FCTL_ESNS_1 0x02 +#define FCTL_PRG 0x01
+#define UA_A_BANK_MASK 0x38 +#define UA_A_ROWH_MASK 0x07
+#define LA_A_ROWL_MASK 0xf8 +#define LA_A_BIT_MASK 0x07
+#define PREV_PROD_REV_MASK 0xf8 +#define PREV_PROD_VT_MASK 0x07
+/* Select the correct accessors depending on endianness */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define iim_read32 in_le32 +#define iim_write32 out_le32 +#define iim_clrsetbits32 clrsetbits_le32 +#define iim_clrbits32 clrbits_le32 +#define iim_setbits32 setbits_le32 +#elif __BYTE_ORDER == __BIG_ENDIAN +#define iim_read32 in_be32 +#define iim_write32 out_be32 +#define iim_clrsetbits32 clrsetbits_be32 +#define iim_clrbits32 clrbits_be32 +#define iim_setbits32 setbits_be32 +#else +#error "Endianess is not defined: please fix to continue" +#endif
+/* IIM control registers */ +struct fsl_iim {
- u32 stat;
- u32 statm;
- u32 err;
- u32 emask;
- u32 fctl;
- u32 ua;
- u32 la;
- u32 sdat;
- u32 prev;
- u32 srev;
- u32 prg_p;
- u32 scs[0x1f5];
- struct {
u32 row[0x100];
- } bank[8];
+};
+int fuse_read_bit(u32 bank, u32 row, u32 bit, u32 *val) +{
- int ret;
- if (bit >= 8) {
puts("fsl_iim fuse read: Invalid argument\n");
return -EINVAL;
- }
- ret = fuse_read_row(bank, row, val);
- if (ret)
return ret;
- *val = !!(*val & 1 << bit);
- return 0;
+}
+int fuse_read_row(u32 bank, u32 row, u32 *val) +{
- volatile struct fsl_iim *regs =
(struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR;
- u32 err;
- if (bank >= ARRAY_SIZE(regs->bank) ||
row >= ARRAY_SIZE(regs->bank[0].row) ||
val == NULL) {
puts("fsl_iim fuse read: Invalid argument\n");
return -EINVAL;
- }
- iim_write32(®s->err, iim_read32(®s->err));
- *val = iim_read32(®s->bank[bank].row[row]);
- err = iim_read32(®s->err);
- iim_write32(®s->err, iim_read32(®s->err));
- if (err & ERR_RPE) {
puts("fsl_iim fuse read: Read protect error\n");
return -EIO;
- }
- return 0;
+}
+int fuse_sense_bit(u32 bank, u32 row, u32 bit, u32 *val) +{
- int ret;
- if (bit >= 8) {
puts("fsl_iim fuse sense: Invalid argument\n");
return -EINVAL;
- }
- ret = fuse_sense_row(bank, row, val);
- if (ret)
return ret;
- *val = !!(*val & 1 << bit);
- return 0;
+}
+int fuse_sense_row(u32 bank, u32 row, u32 *val) +{
- volatile struct fsl_iim *regs =
(struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR;
- u32 stat, err;
- if (bank >= ARRAY_SIZE(regs->bank) ||
row >= ARRAY_SIZE(regs->bank[0].row) ||
val == NULL) {
puts("fsl_iim fuse sense: Invalid argument\n");
return -EINVAL;
- }
- iim_write32(®s->stat, iim_read32(®s->stat));
- iim_write32(®s->err, iim_read32(®s->err));
- iim_write32(®s->ua, bank << 3 | row >> 5);
- iim_write32(®s->la, row << 3 & 0xff);
- iim_write32(®s->fctl, iim_read32(®s->fctl) | FCTL_ESNS_N);
- while (iim_read32(®s->stat) & STAT_BUSY)
udelay(20);
- stat = iim_read32(®s->stat);
- err = iim_read32(®s->err);
- iim_write32(®s->stat, iim_read32(®s->stat));
- iim_write32(®s->err, iim_read32(®s->err));
- if (err & ERR_SNSE) {
puts("fsl_iim fuse sense: Explicit sense cycle error\n");
return -EIO;
- }
- if (!(stat & STAT_SNSD)) {
puts("fsl_iim fuse sense: Explicit sense cycle "
"did not complete\n");
return -EIO;
- }
- *val = iim_read32(®s->sdat);
- return 0;
+}
+int fuse_prog_bit(u32 bank, u32 row, u32 bit) +{
- volatile struct fsl_iim *regs =
(struct fsl_iim *)CONFIG_SYS_FSL_IIM_ADDR;
The address depends on the SOC, and is not a board configuration option. Should we not use IIM_BASE_ADDR ?
CONFIG_SYS_FSL_IIM_ADDR is supposed to be a board configuration option, just like CONFIG_SYS_I2C_BASE. This makes things easier since on MPC this address comes from a struct (&((immap_t *) CONFIG_SYS_IMMR)->iim). Or we could define a FSL_IIM_BASE_ADDR in all supported register definition files, but that would mean including conditionally these files in fsl_iim.c.
Best regards, Benoît

On 21/08/2012 14:56, Benoît Thébaudeau wrote:
Hi Stefano,
Hi,
The address depends on the SOC, and is not a board configuration option. Should we not use IIM_BASE_ADDR ?
CONFIG_SYS_FSL_IIM_ADDR is supposed to be a board configuration option, just like CONFIG_SYS_I2C_BASE.
Ok, but the reason for CONFIG_SYS_I2C_BASE is that a SOC have multiple I2C controller, but u-boot supports only one of them (up now). Setting CONFIG_SYS_I2C_BASE we implicitely tell u-boot which controller is active.
There is not multiple iim in the SOCs. For this reason I thought it is not a configuration option.
This makes things easier since on MPC this address comes from a struct (&((immap_t *) CONFIG_SYS_IMMR)->iim). Or we could define a FSL_IIM_BASE_ADDR in all supported register definition files, but that would mean including conditionally these files in fsl_iim.c.
I understood the point. Ok, let's see which is the Anatolji's opinion for the PowerPC side. If he thinks it is ok, we can leave it with CONFIG_SYS_FSL_IIM_ADDR.
Regards, Stefano

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de --- .../arch/powerpc/cpu/mpc512x/Makefile | 1 - .../arch/powerpc/cpu/mpc512x/iim.c => /dev/null | 394 -------------------- .../board/davedenx/aria/aria.c | 2 +- .../board/esd/mecp5123/mecp5123.c | 2 +- .../board/freescale/mpc5121ads/mpc5121ads.c | 2 +- .../board/pdm360ng/pdm360ng.c | 2 +- .../include/configs/aria.h | 2 +- .../include/configs/mecp5123.h | 2 +- .../include/configs/mpc5121ads.h | 2 +- 9 files changed, 7 insertions(+), 402 deletions(-) delete mode 100644 u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c
diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile index b53232f..4f4c9ec 100644 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile +++ u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile @@ -38,7 +38,6 @@ COBJS-y += serial.o COBJS-y += speed.o COBJS-$(CONFIG_FSL_DIU_FB) += diu.o COBJS-$(CONFIG_CMD_IDE) += ide.o -COBJS-$(CONFIG_IIM) += iim.o COBJS-$(CONFIG_PCI) += pci.o
# Stub implementations of cache management functions for USB diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c deleted file mode 100644 index abec8f6..0000000 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2008 Silicon Turnkey Express, Inc. - * Martha Marx mmarx@silicontkx.com - * - * ADS5121 IIM (Fusebox) Interface - * - * 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 <asm/io.h> - -#ifdef CONFIG_CMD_FUSE - -DECLARE_GLOBAL_DATA_PTR; - -static char cur_bank = '1'; - -char *iim_err_msg(u32 err) -{ - static char *IIM_errs[] = { - "Parity Error in cache", - "Explicit Sense Cycle Error", - "Write to Locked Register Error", - "Read Protect Error", - "Override Protect Error", - "Write Protect Error"}; - - int i; - - if (!err) - return ""; - for (i = 1; i < 8; i++) - if (err & (1 << i)) - printf("IIM - %s\n", IIM_errs[i-1]); - return ""; -} - -int in_range(int n, int min, int max, char *err, char *usg) -{ - if (n > max || n < min) { - printf(err); - printf("Usage:\n%s\n", usg); - return 0; - } - return 1; -} - -int ads5121_fuse_read(int bank, int fstart, int num) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 *iim_fb, dummy; - int f, ctr; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fb = (u32 *)&(iim->fbac0); - else - iim_fb = (u32 *)&(iim->fbac1); -/* try a read to see if Read Protect is set */ - dummy = in_be32(&iim_fb[0]); - if (in_be32(&iim->err) & IIM_ERR_RPE) { - printf("\tRead protect fuse is set\n"); - out_be32(&iim->err, IIM_ERR_RPE); - return 0; - } - printf("Reading Bank %d cache\n", bank); - for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) { - if (ctr % 4 == 0) - printf("F%2d:", f); - printf("\t%#04x", (u8)(iim_fb[f])); - if (ctr % 4 == 3) - printf("\n"); - } - if (ctr % 4 != 0) - printf("\n"); -} - -int ads5121_fuse_override(int bank, int f, u8 val) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 *iim_fb; - u32 iim_stat; - int i; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fb = (u32 *)&(iim->fbac0); - else - iim_fb = (u32 *)&(iim->fbac1); -/* try a read to see if Read Protect is set */ - iim_stat = in_be32(&iim_fb[0]); - if (in_be32(&iim->err) & IIM_ERR_RPE) { - printf("Read protect fuse is set on bank %d;" - "Override protect may also be set\n", bank); - printf("An attempt will be made to override\n"); - out_be32(&iim->err, IIM_ERR_RPE); - } - if (iim_stat & IIM_FBAC_FBOP) { - printf("Override protect fuse is set on bank %d\n", bank); - return 1; - } - if (f > IIM_FMAX) /* reset the entire bank */ - for (i = 0; i < IIM_FMAX + 1; i++) - out_be32(&iim_fb[i], 0); - else - out_be32(&iim_fb[f], val); - return 0; -} - -int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - int f, i, bitno; - u32 stat, err; - - f = simple_strtol(fuseno_bitno, NULL, 10); - if (f == 0 && fuseno_bitno[0] != '0') - f = -1; - if (!in_range(f, 0, IIM_FMAX, - "<frow> must be between 0-31\n\n", cmdtp->usage)) - return 1; - bitno = -1; - for (i = 0; i < 6; i++) { - if (fuseno_bitno[i] == '_') { - bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10); - if (bitno == 0 && fuseno_bitno[i+1] != '0') - bitno = -1; - break; - } - } - if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n" - "Example of <frow_bitno>: "18_4" sets bit 4 of row 18\n", - cmdtp->usage)) - return 1; - out_be32(&iim->err, in_be32(&iim->err)); - out_be32(&iim->prg_p, IIM_PRG_P_SET); - out_be32(&iim->ua, IIM_SET_UA(bank, f)); - out_be32(&iim->la, IIM_SET_LA(f, bitno)); -#ifdef DEBUG - printf("Programming disabled with DEBUG defined \n"); - printf(""Set up to pro - printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la); -#else - out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG); - do - udelay(20); - while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY); - out_be32(&iim->prg_p, 0); - err = in_be32(&iim->err); - if (stat & IIM_STAT_PRGD) { - if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) { - printf("Fuse is successfully set"); - if (err) - printf(" - however there are other errors"); - printf("\n"); - } - iim->stat = 0; - } - if (err) { - iim_err_msg(err); - out_be32(&iim->err, in_be32(&iim->err)); - } -#endif -} - -int ads5121_fuse_sense(int bank, int fstart, int num) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 iim_fbac; - u32 stat, err, err_hold = 0; - int f, ctr; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fbac = in_be32(&iim->fbac0); - else - iim_fbac = in_be32(&iim->fbac1); - if (iim_fbac & IIM_FBAC_FBESP) { - printf("\tSense Protect disallows this operation\n"); - out_be32(&iim->err, IIM_FBAC_FBESP); - return 1; - } - err = in_be32(&iim->err); - if (err) { - iim_err_msg(err); - err_hold |= err; - } - if (err & IIM_ERR_RPE) - printf("\tRead protect fuse is set; " - "Sense Protect may be set but will be attempted\n"); - if (err) - out_be32(&iim->err, err); - printf("Sensing fuse(s) on Bank %d\n", bank); - for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) { - out_be32(&iim->ua, IIM_SET_UA(bank, f)); - out_be32(&iim->la, IIM_SET_LA(f, 0)); - out_be32(&iim->fctl, IIM_FCTL_ESNS_N); - do - udelay(20); - while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY); - err = in_be32(&iim->err); - if (err & IIM_ERR_SNSE) { - iim_err_msg(err); - out_be32(&iim->err, IIM_ERR_SNSE); - return 1; - } - if (stat & IIM_STAT_SNSD) { - out_be32(&iim->stat, 0); - if (ctr % 4 == 0) - printf("F%2d:", f); - printf("\t%#04x", (u8)iim->sdat); - if (ctr % 4 == 3) - printf("\n"); - } - if (err) { - err_hold |= err; - out_be32(&iim->err, err); - } - } - if (ctr % 4 != 0) - printf("\n"); - if (err_hold) - iim_err_msg(err_hold); - - return 0; -} - -int ads5121_fuse_stat(int bank) -{ - iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim; - u32 iim_fbac; - u32 err; - - out_be32(&iim->err, in_be32(&iim->err)); - if (bank == 0) - iim_fbac = in_be32(&iim->fbac0); - else - iim_fbac = in_be32(&iim->fbac1); - err = in_be32(&iim->err); - if (err) - iim_err_msg(err); - if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) { - if (iim_fbac == 0) - printf("Since protection settings can't be read - " - "try sensing fuse row 0;\n"); - return 0; - } - if (iim_fbac & IIM_PROTECTION) - printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac); - else if (!(err & IIM_ERR_RPE)) - printf("No Protection fuses are set\n"); - if (iim_fbac & IIM_FBAC_FBWP) - printf("\tWrite Protect fuse is set\n"); - if (iim_fbac & IIM_FBAC_FBOP) - printf("\tOverride Protect fuse is set\n"); - if (iim_fbac & IIM_FBAC_FBESP) - printf("\tSense Protect Fuse is set\n"); - out_be32(&iim->err, in_be32(&iim->err)); - - return 0; -} - -int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - int frow, n, v, bank; - - if (cur_bank == '0') - bank = 0; - else - bank = 1; - - switch (argc) { - case 0: - case 1: - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - case 2: - if (strncmp(argv[1], "stat", 4) == 0) - return ads5121_fuse_stat(bank); - if (strncmp(argv[1], "read", 4) == 0) - return ads5121_fuse_read(bank, 0, IIM_FMAX + 1); - if (strncmp(argv[1], "sense", 5) == 0) - return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1); - if (strncmp(argv[1], "ovride", 6) == 0) - return ads5121_fuse_override(bank, IIM_FMAX + 1, 0); - if (strncmp(argv[1], "bank", 4) == 0) { - printf("Active Fuse Bank is %c\n", cur_bank); - return 0; - } - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - case 3: - if (strncmp(argv[1], "bank", 4) == 0) { - if (argv[2][0] == '0') - cur_bank = '0'; - else if (argv[2][0] == '1') - cur_bank = '1'; - else { - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - } - - printf("Setting Active Fuse Bank to %c\n", cur_bank); - return 0; - } - if (strncmp(argv[1], "prog", 4) == 0) - return ads5121_fuse_prog(cmdtp, bank, argv[2]); - - frow = (int)simple_strtol(argv[2], NULL, 10); - if (frow == 0 && argv[2][0] != '0') - frow = -1; - if (!in_range(frow, 0, IIM_FMAX, - "<frow> must be between 0-31\n\n", cmdtp->usage)) - return 1; - if (strncmp(argv[1], "read", 4) == 0) - return ads5121_fuse_read(bank, frow, 1); - if (strncmp(argv[1], "ovride", 6) == 0) - return ads5121_fuse_override(bank, frow, 0); - if (strncmp(argv[1], "sense", 5) == 0) - return ads5121_fuse_sense(bank, frow, 1); - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - case 4: - frow = (int)simple_strtol(argv[2], NULL, 10); - if (frow == 0 && argv[2][0] != '0') - frow = -1; - if (!in_range(frow, 0, IIM_FMAX, - "<frow> must be between 0-31\n\n", cmdtp->usage)) - return 1; - if (strncmp(argv[1], "read", 4) == 0) { - n = (int)simple_strtol(argv[3], NULL, 10); - if (!in_range(frow + n, frow + 1, IIM_FMAX + 1, - "<frow>+<n> must be between 1-32\n\n", - cmdtp->usage)) - return 1; - return ads5121_fuse_read(bank, frow, n); - } - if (strncmp(argv[1], "ovride", 6) == 0) { - v = (int)simple_strtol(argv[3], NULL, 10); - return ads5121_fuse_override(bank, frow, v); - } - if (strncmp(argv[1], "sense", 5) == 0) { - n = (int)simple_strtol(argv[3], NULL, 10); - if (!in_range(frow + n, frow + 1, IIM_FMAX + 1, - "<frow>+<n> must be between 1-32\n\n", - cmdtp->usage)) - return 1; - return ads5121_fuse_sense(bank, frow, n); - } - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - default: /* at least 5 args */ - printf("Usage:\n%s\n", cmdtp->usage); - return 1; - } -} - -U_BOOT_CMD( - fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse, - " - Read, Sense, Override or Program Fuses\n", - "bank <n> - sets active Fuse Bank to 0 or 1\n" - " no args shows current active bank\n" - "fuse stat - print active fuse bank's protection status\n" - "fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n" - " no args to print entire bank's fuses\n" - "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n" - " no <v> defaults to 0 for the row\n" - " no args resets entire bank to 0\n" - " NOTE - settings persist until hard reset\n" - "fuse sense [<frow>] - senses current fuse at <frow>\n" - " no args for entire bank\n" - "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n" - " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n" - " WARNING - this is permanent" -); -#endif /* CONFIG_CMD_FUSE */ diff --git u-boot-4d3c95f.orig/board/davedenx/aria/aria.c u-boot-4d3c95f/board/davedenx/aria/aria.c index 31b079b..d2ffba4 100644 --- u-boot-4d3c95f.orig/board/davedenx/aria/aria.c +++ u-boot-4d3c95f/board/davedenx/aria/aria.c @@ -92,7 +92,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c index 748ad7c..804a022 100644 --- u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c +++ u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c @@ -110,7 +110,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c index 97eeab3..0d33680 100644 --- u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c +++ u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c @@ -129,7 +129,7 @@ int board_early_init_f(void) */ out_be32 (&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32 (&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32 (&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c u-boot-4d3c95f/board/pdm360ng/pdm360ng.c index 2082ad4..dcff9c5 100644 --- u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c +++ u-boot-4d3c95f/board/pdm360ng/pdm360ng.c @@ -94,7 +94,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/include/configs/aria.h u-boot-4d3c95f/include/configs/aria.h index b21b495..cb20641 100644 --- u-boot-4d3c95f.orig/include/configs/aria.h +++ u-boot-4d3c95f/include/configs/aria.h @@ -378,7 +378,7 @@ /* * IIM - IC Identification Module */ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/* * EEPROM configuration for Atmel AT24C32A-10TQ-2.7: diff --git u-boot-4d3c95f.orig/include/configs/mecp5123.h u-boot-4d3c95f/include/configs/mecp5123.h index b41bda9..52a159a 100644 --- u-boot-4d3c95f.orig/include/configs/mecp5123.h +++ u-boot-4d3c95f/include/configs/mecp5123.h @@ -250,7 +250,7 @@ /* * IIM - IC Identification Module */ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/* * EEPROM configuration diff --git u-boot-4d3c95f.orig/include/configs/mpc5121ads.h u-boot-4d3c95f/include/configs/mpc5121ads.h index 9d1327f..88dd9bb 100644 --- u-boot-4d3c95f.orig/include/configs/mpc5121ads.h +++ u-boot-4d3c95f/include/configs/mpc5121ads.h @@ -346,7 +346,7 @@ /* * IIM - IC Identification Module */ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/* * EEPROM configuration

Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
Adding missing board maintainers to Cc.
.../arch/powerpc/cpu/mpc512x/Makefile | 1 - .../arch/powerpc/cpu/mpc512x/iim.c => /dev/null | 394
.../board/davedenx/aria/aria.c | 2 +- .../board/esd/mecp5123/mecp5123.c | 2 +- .../board/freescale/mpc5121ads/mpc5121ads.c | 2 +- .../board/pdm360ng/pdm360ng.c | 2 +- .../include/configs/aria.h | 2 +- .../include/configs/mecp5123.h | 2 +- .../include/configs/mpc5121ads.h | 2 +- 9 files changed, 7 insertions(+), 402 deletions(-) delete mode 100644 u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c
diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile index b53232f..4f4c9ec 100644 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile +++ u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile @@ -38,7 +38,6 @@ COBJS-y += serial.o COBJS-y += speed.o COBJS-$(CONFIG_FSL_DIU_FB) += diu.o COBJS-$(CONFIG_CMD_IDE) += ide.o -COBJS-$(CONFIG_IIM) += iim.o COBJS-$(CONFIG_PCI) += pci.o
# Stub implementations of cache management functions for USB diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c deleted file mode 100644 index abec8f6..0000000 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c +++ /dev/null @@ -1,394 +0,0 @@ -/*
- Copyright 2008 Silicon Turnkey Express, Inc.
- Martha Marx mmarx@silicontkx.com
- ADS5121 IIM (Fusebox) Interface
- 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 <asm/io.h>
-#ifdef CONFIG_CMD_FUSE
-DECLARE_GLOBAL_DATA_PTR;
-static char cur_bank = '1';
-char *iim_err_msg(u32 err) -{
- static char *IIM_errs[] = {
"Parity Error in cache",
"Explicit Sense Cycle Error",
"Write to Locked Register Error",
"Read Protect Error",
"Override Protect Error",
"Write Protect Error"};
- int i;
- if (!err)
return "";
- for (i = 1; i < 8; i++)
if (err & (1 << i))
printf("IIM - %s\n", IIM_errs[i-1]);
- return "";
-}
-int in_range(int n, int min, int max, char *err, char *usg) -{
- if (n > max || n < min) {
printf(err);
printf("Usage:\n%s\n", usg);
return 0;
- }
- return 1;
-}
-int ads5121_fuse_read(int bank, int fstart, int num) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 *iim_fb, dummy;
- int f, ctr;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fb = (u32 *)&(iim->fbac0);
- else
iim_fb = (u32 *)&(iim->fbac1);
-/* try a read to see if Read Protect is set */
- dummy = in_be32(&iim_fb[0]);
- if (in_be32(&iim->err) & IIM_ERR_RPE) {
printf("\tRead protect fuse is set\n");
out_be32(&iim->err, IIM_ERR_RPE);
return 0;
- }
- printf("Reading Bank %d cache\n", bank);
- for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
if (ctr % 4 == 0)
printf("F%2d:", f);
printf("\t%#04x", (u8)(iim_fb[f]));
if (ctr % 4 == 3)
printf("\n");
- }
- if (ctr % 4 != 0)
printf("\n");
-}
-int ads5121_fuse_override(int bank, int f, u8 val) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 *iim_fb;
- u32 iim_stat;
- int i;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fb = (u32 *)&(iim->fbac0);
- else
iim_fb = (u32 *)&(iim->fbac1);
-/* try a read to see if Read Protect is set */
- iim_stat = in_be32(&iim_fb[0]);
- if (in_be32(&iim->err) & IIM_ERR_RPE) {
printf("Read protect fuse is set on bank %d;"
"Override protect may also be set\n", bank);
printf("An attempt will be made to override\n");
out_be32(&iim->err, IIM_ERR_RPE);
- }
- if (iim_stat & IIM_FBAC_FBOP) {
printf("Override protect fuse is set on bank %d\n", bank);
return 1;
- }
- if (f > IIM_FMAX) /* reset the entire bank */
for (i = 0; i < IIM_FMAX + 1; i++)
out_be32(&iim_fb[i], 0);
- else
out_be32(&iim_fb[f], val);
- return 0;
-}
-int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- int f, i, bitno;
- u32 stat, err;
- f = simple_strtol(fuseno_bitno, NULL, 10);
- if (f == 0 && fuseno_bitno[0] != '0')
f = -1;
- if (!in_range(f, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
- bitno = -1;
- for (i = 0; i < 6; i++) {
if (fuseno_bitno[i] == '_') {
bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
if (bitno == 0 && fuseno_bitno[i+1] != '0')
bitno = -1;
break;
}
- }
- if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
"Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
cmdtp->usage))
return 1;
- out_be32(&iim->err, in_be32(&iim->err));
- out_be32(&iim->prg_p, IIM_PRG_P_SET);
- out_be32(&iim->ua, IIM_SET_UA(bank, f));
- out_be32(&iim->la, IIM_SET_LA(f, bitno));
-#ifdef DEBUG
- printf("Programming disabled with DEBUG defined \n");
- printf(""Set up to pro
- printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
-#else
- out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
- do
udelay(20);
- while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
- out_be32(&iim->prg_p, 0);
- err = in_be32(&iim->err);
- if (stat & IIM_STAT_PRGD) {
if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
printf("Fuse is successfully set");
if (err)
printf(" - however there are other errors");
printf("\n");
}
iim->stat = 0;
- }
- if (err) {
iim_err_msg(err);
out_be32(&iim->err, in_be32(&iim->err));
- }
-#endif -}
-int ads5121_fuse_sense(int bank, int fstart, int num) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 iim_fbac;
- u32 stat, err, err_hold = 0;
- int f, ctr;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fbac = in_be32(&iim->fbac0);
- else
iim_fbac = in_be32(&iim->fbac1);
- if (iim_fbac & IIM_FBAC_FBESP) {
printf("\tSense Protect disallows this operation\n");
out_be32(&iim->err, IIM_FBAC_FBESP);
return 1;
- }
- err = in_be32(&iim->err);
- if (err) {
iim_err_msg(err);
err_hold |= err;
- }
- if (err & IIM_ERR_RPE)
printf("\tRead protect fuse is set; "
"Sense Protect may be set but will be attempted\n");
- if (err)
out_be32(&iim->err, err);
- printf("Sensing fuse(s) on Bank %d\n", bank);
- for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
out_be32(&iim->ua, IIM_SET_UA(bank, f));
out_be32(&iim->la, IIM_SET_LA(f, 0));
out_be32(&iim->fctl, IIM_FCTL_ESNS_N);
do
udelay(20);
while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
err = in_be32(&iim->err);
if (err & IIM_ERR_SNSE) {
iim_err_msg(err);
out_be32(&iim->err, IIM_ERR_SNSE);
return 1;
}
if (stat & IIM_STAT_SNSD) {
out_be32(&iim->stat, 0);
if (ctr % 4 == 0)
printf("F%2d:", f);
printf("\t%#04x", (u8)iim->sdat);
if (ctr % 4 == 3)
printf("\n");
}
if (err) {
err_hold |= err;
out_be32(&iim->err, err);
}
- }
- if (ctr % 4 != 0)
printf("\n");
- if (err_hold)
iim_err_msg(err_hold);
- return 0;
-}
-int ads5121_fuse_stat(int bank) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 iim_fbac;
- u32 err;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fbac = in_be32(&iim->fbac0);
- else
iim_fbac = in_be32(&iim->fbac1);
- err = in_be32(&iim->err);
- if (err)
iim_err_msg(err);
- if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) {
if (iim_fbac == 0)
printf("Since protection settings can't be read - "
"try sensing fuse row 0;\n");
return 0;
- }
- if (iim_fbac & IIM_PROTECTION)
printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
- else if (!(err & IIM_ERR_RPE))
printf("No Protection fuses are set\n");
- if (iim_fbac & IIM_FBAC_FBWP)
printf("\tWrite Protect fuse is set\n");
- if (iim_fbac & IIM_FBAC_FBOP)
printf("\tOverride Protect fuse is set\n");
- if (iim_fbac & IIM_FBAC_FBESP)
printf("\tSense Protect Fuse is set\n");
- out_be32(&iim->err, in_be32(&iim->err));
- return 0;
-}
-int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{
- int frow, n, v, bank;
- if (cur_bank == '0')
bank = 0;
- else
bank = 1;
- switch (argc) {
- case 0:
- case 1:
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 2:
if (strncmp(argv[1], "stat", 4) == 0)
return ads5121_fuse_stat(bank);
if (strncmp(argv[1], "read", 4) == 0)
return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
if (strncmp(argv[1], "sense", 5) == 0)
return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
if (strncmp(argv[1], "ovride", 6) == 0)
return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
if (strncmp(argv[1], "bank", 4) == 0) {
printf("Active Fuse Bank is %c\n", cur_bank);
return 0;
}
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 3:
if (strncmp(argv[1], "bank", 4) == 0) {
if (argv[2][0] == '0')
cur_bank = '0';
else if (argv[2][0] == '1')
cur_bank = '1';
else {
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
printf("Setting Active Fuse Bank to %c\n", cur_bank);
return 0;
}
if (strncmp(argv[1], "prog", 4) == 0)
return ads5121_fuse_prog(cmdtp, bank, argv[2]);
frow = (int)simple_strtol(argv[2], NULL, 10);
if (frow == 0 && argv[2][0] != '0')
frow = -1;
if (!in_range(frow, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
if (strncmp(argv[1], "read", 4) == 0)
return ads5121_fuse_read(bank, frow, 1);
if (strncmp(argv[1], "ovride", 6) == 0)
return ads5121_fuse_override(bank, frow, 0);
if (strncmp(argv[1], "sense", 5) == 0)
return ads5121_fuse_sense(bank, frow, 1);
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 4:
frow = (int)simple_strtol(argv[2], NULL, 10);
if (frow == 0 && argv[2][0] != '0')
frow = -1;
if (!in_range(frow, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
if (strncmp(argv[1], "read", 4) == 0) {
n = (int)simple_strtol(argv[3], NULL, 10);
if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
"<frow>+<n> must be between 1-32\n\n",
cmdtp->usage))
return 1;
return ads5121_fuse_read(bank, frow, n);
}
if (strncmp(argv[1], "ovride", 6) == 0) {
v = (int)simple_strtol(argv[3], NULL, 10);
return ads5121_fuse_override(bank, frow, v);
}
if (strncmp(argv[1], "sense", 5) == 0) {
n = (int)simple_strtol(argv[3], NULL, 10);
if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
"<frow>+<n> must be between 1-32\n\n",
cmdtp->usage))
return 1;
return ads5121_fuse_sense(bank, frow, n);
}
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- default: /* at least 5 args */
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- }
-}
-U_BOOT_CMD(
- fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
- " - Read, Sense, Override or Program Fuses\n",
- "bank <n> - sets active Fuse Bank to 0 or 1\n"
- " no args shows current active bank\n"
- "fuse stat - print active fuse bank's protection status\n"
- "fuse read [<frow> [<n>]] - print <n> fuse rows starting at
<frow>\n"
- " no args to print entire bank's fuses\n"
- "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
- " no <v> defaults to 0 for the row\n"
- " no args resets entire bank to 0\n"
- " NOTE - settings persist until hard reset\n"
- "fuse sense [<frow>] - senses current fuse at <frow>\n"
- " no args for entire bank\n"
- "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n"
- " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
- " WARNING - this is permanent"
-); -#endif /* CONFIG_CMD_FUSE */ diff --git u-boot-4d3c95f.orig/board/davedenx/aria/aria.c u-boot-4d3c95f/board/davedenx/aria/aria.c index 31b079b..d2ffba4 100644 --- u-boot-4d3c95f.orig/board/davedenx/aria/aria.c +++ u-boot-4d3c95f/board/davedenx/aria/aria.c @@ -92,7 +92,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c index 748ad7c..804a022 100644 --- u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c +++ u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c @@ -110,7 +110,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c index 97eeab3..0d33680 100644 --- u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c +++ u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c @@ -129,7 +129,7 @@ int board_early_init_f(void) */ out_be32 (&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32 (&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32 (&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c u-boot-4d3c95f/board/pdm360ng/pdm360ng.c index 2082ad4..dcff9c5 100644 --- u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c +++ u-boot-4d3c95f/board/pdm360ng/pdm360ng.c @@ -94,7 +94,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/include/configs/aria.h u-boot-4d3c95f/include/configs/aria.h index b21b495..cb20641 100644 --- u-boot-4d3c95f.orig/include/configs/aria.h +++ u-boot-4d3c95f/include/configs/aria.h @@ -378,7 +378,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration for Atmel AT24C32A-10TQ-2.7:
diff --git u-boot-4d3c95f.orig/include/configs/mecp5123.h u-boot-4d3c95f/include/configs/mecp5123.h index b41bda9..52a159a 100644 --- u-boot-4d3c95f.orig/include/configs/mecp5123.h +++ u-boot-4d3c95f/include/configs/mecp5123.h @@ -250,7 +250,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration
diff --git u-boot-4d3c95f.orig/include/configs/mpc5121ads.h u-boot-4d3c95f/include/configs/mpc5121ads.h index 9d1327f..88dd9bb 100644 --- u-boot-4d3c95f.orig/include/configs/mpc5121ads.h +++ u-boot-4d3c95f/include/configs/mpc5121ads.h @@ -346,7 +346,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration

On 14/08/2012 14:53, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
.../arch/powerpc/cpu/mpc512x/Makefile | 1 - .../arch/powerpc/cpu/mpc512x/iim.c => /dev/null | 394 -------------------- .../board/davedenx/aria/aria.c | 2 +- .../board/esd/mecp5123/mecp5123.c | 2 +- .../board/freescale/mpc5121ads/mpc5121ads.c | 2 +- .../board/pdm360ng/pdm360ng.c | 2 +- .../include/configs/aria.h | 2 +- .../include/configs/mecp5123.h | 2 +- .../include/configs/mpc5121ads.h | 2 +- 9 files changed, 7 insertions(+), 402 deletions(-) delete mode 100644 u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c
diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile index b53232f..4f4c9ec 100644 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile +++ u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile @@ -38,7 +38,6 @@ COBJS-y += serial.o COBJS-y += speed.o COBJS-$(CONFIG_FSL_DIU_FB) += diu.o COBJS-$(CONFIG_CMD_IDE) += ide.o -COBJS-$(CONFIG_IIM) += iim.o COBJS-$(CONFIG_PCI) += pci.o
# Stub implementations of cache management functions for USB diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c deleted file mode 100644 index abec8f6..0000000 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c +++ /dev/null @@ -1,394 +0,0 @@ -/*
- Copyright 2008 Silicon Turnkey Express, Inc.
- Martha Marx mmarx@silicontkx.com
- ADS5121 IIM (Fusebox) Interface
- 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 <asm/io.h>
-#ifdef CONFIG_CMD_FUSE
-DECLARE_GLOBAL_DATA_PTR;
-static char cur_bank = '1';
-char *iim_err_msg(u32 err) -{
- static char *IIM_errs[] = {
"Parity Error in cache",
"Explicit Sense Cycle Error",
"Write to Locked Register Error",
"Read Protect Error",
"Override Protect Error",
"Write Protect Error"};
- int i;
- if (!err)
return "";
- for (i = 1; i < 8; i++)
if (err & (1 << i))
printf("IIM - %s\n", IIM_errs[i-1]);
- return "";
-}
-int in_range(int n, int min, int max, char *err, char *usg) -{
- if (n > max || n < min) {
printf(err);
printf("Usage:\n%s\n", usg);
return 0;
- }
- return 1;
-}
-int ads5121_fuse_read(int bank, int fstart, int num) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 *iim_fb, dummy;
- int f, ctr;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fb = (u32 *)&(iim->fbac0);
- else
iim_fb = (u32 *)&(iim->fbac1);
-/* try a read to see if Read Protect is set */
- dummy = in_be32(&iim_fb[0]);
- if (in_be32(&iim->err) & IIM_ERR_RPE) {
printf("\tRead protect fuse is set\n");
out_be32(&iim->err, IIM_ERR_RPE);
return 0;
- }
- printf("Reading Bank %d cache\n", bank);
- for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
if (ctr % 4 == 0)
printf("F%2d:", f);
printf("\t%#04x", (u8)(iim_fb[f]));
if (ctr % 4 == 3)
printf("\n");
- }
- if (ctr % 4 != 0)
printf("\n");
-}
-int ads5121_fuse_override(int bank, int f, u8 val) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 *iim_fb;
- u32 iim_stat;
- int i;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fb = (u32 *)&(iim->fbac0);
- else
iim_fb = (u32 *)&(iim->fbac1);
-/* try a read to see if Read Protect is set */
- iim_stat = in_be32(&iim_fb[0]);
- if (in_be32(&iim->err) & IIM_ERR_RPE) {
printf("Read protect fuse is set on bank %d;"
"Override protect may also be set\n", bank);
printf("An attempt will be made to override\n");
out_be32(&iim->err, IIM_ERR_RPE);
- }
- if (iim_stat & IIM_FBAC_FBOP) {
printf("Override protect fuse is set on bank %d\n", bank);
return 1;
- }
- if (f > IIM_FMAX) /* reset the entire bank */
for (i = 0; i < IIM_FMAX + 1; i++)
out_be32(&iim_fb[i], 0);
- else
out_be32(&iim_fb[f], val);
- return 0;
-}
-int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- int f, i, bitno;
- u32 stat, err;
- f = simple_strtol(fuseno_bitno, NULL, 10);
- if (f == 0 && fuseno_bitno[0] != '0')
f = -1;
- if (!in_range(f, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
- bitno = -1;
- for (i = 0; i < 6; i++) {
if (fuseno_bitno[i] == '_') {
bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
if (bitno == 0 && fuseno_bitno[i+1] != '0')
bitno = -1;
break;
}
- }
- if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
"Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
cmdtp->usage))
return 1;
- out_be32(&iim->err, in_be32(&iim->err));
- out_be32(&iim->prg_p, IIM_PRG_P_SET);
- out_be32(&iim->ua, IIM_SET_UA(bank, f));
- out_be32(&iim->la, IIM_SET_LA(f, bitno));
-#ifdef DEBUG
- printf("Programming disabled with DEBUG defined \n");
- printf(""Set up to pro
- printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
-#else
- out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
- do
udelay(20);
- while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
- out_be32(&iim->prg_p, 0);
- err = in_be32(&iim->err);
- if (stat & IIM_STAT_PRGD) {
if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
printf("Fuse is successfully set");
if (err)
printf(" - however there are other errors");
printf("\n");
}
iim->stat = 0;
- }
- if (err) {
iim_err_msg(err);
out_be32(&iim->err, in_be32(&iim->err));
- }
-#endif -}
-int ads5121_fuse_sense(int bank, int fstart, int num) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 iim_fbac;
- u32 stat, err, err_hold = 0;
- int f, ctr;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fbac = in_be32(&iim->fbac0);
- else
iim_fbac = in_be32(&iim->fbac1);
- if (iim_fbac & IIM_FBAC_FBESP) {
printf("\tSense Protect disallows this operation\n");
out_be32(&iim->err, IIM_FBAC_FBESP);
return 1;
- }
- err = in_be32(&iim->err);
- if (err) {
iim_err_msg(err);
err_hold |= err;
- }
- if (err & IIM_ERR_RPE)
printf("\tRead protect fuse is set; "
"Sense Protect may be set but will be attempted\n");
- if (err)
out_be32(&iim->err, err);
- printf("Sensing fuse(s) on Bank %d\n", bank);
- for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
out_be32(&iim->ua, IIM_SET_UA(bank, f));
out_be32(&iim->la, IIM_SET_LA(f, 0));
out_be32(&iim->fctl, IIM_FCTL_ESNS_N);
do
udelay(20);
while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
err = in_be32(&iim->err);
if (err & IIM_ERR_SNSE) {
iim_err_msg(err);
out_be32(&iim->err, IIM_ERR_SNSE);
return 1;
}
if (stat & IIM_STAT_SNSD) {
out_be32(&iim->stat, 0);
if (ctr % 4 == 0)
printf("F%2d:", f);
printf("\t%#04x", (u8)iim->sdat);
if (ctr % 4 == 3)
printf("\n");
}
if (err) {
err_hold |= err;
out_be32(&iim->err, err);
}
- }
- if (ctr % 4 != 0)
printf("\n");
- if (err_hold)
iim_err_msg(err_hold);
- return 0;
-}
-int ads5121_fuse_stat(int bank) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 iim_fbac;
- u32 err;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fbac = in_be32(&iim->fbac0);
- else
iim_fbac = in_be32(&iim->fbac1);
- err = in_be32(&iim->err);
- if (err)
iim_err_msg(err);
- if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) {
if (iim_fbac == 0)
printf("Since protection settings can't be read - "
"try sensing fuse row 0;\n");
return 0;
- }
- if (iim_fbac & IIM_PROTECTION)
printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
- else if (!(err & IIM_ERR_RPE))
printf("No Protection fuses are set\n");
- if (iim_fbac & IIM_FBAC_FBWP)
printf("\tWrite Protect fuse is set\n");
- if (iim_fbac & IIM_FBAC_FBOP)
printf("\tOverride Protect fuse is set\n");
- if (iim_fbac & IIM_FBAC_FBESP)
printf("\tSense Protect Fuse is set\n");
- out_be32(&iim->err, in_be32(&iim->err));
- return 0;
-}
-int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{
- int frow, n, v, bank;
- if (cur_bank == '0')
bank = 0;
- else
bank = 1;
- switch (argc) {
- case 0:
- case 1:
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 2:
if (strncmp(argv[1], "stat", 4) == 0)
return ads5121_fuse_stat(bank);
if (strncmp(argv[1], "read", 4) == 0)
return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
if (strncmp(argv[1], "sense", 5) == 0)
return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
if (strncmp(argv[1], "ovride", 6) == 0)
return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
if (strncmp(argv[1], "bank", 4) == 0) {
printf("Active Fuse Bank is %c\n", cur_bank);
return 0;
}
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 3:
if (strncmp(argv[1], "bank", 4) == 0) {
if (argv[2][0] == '0')
cur_bank = '0';
else if (argv[2][0] == '1')
cur_bank = '1';
else {
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
printf("Setting Active Fuse Bank to %c\n", cur_bank);
return 0;
}
if (strncmp(argv[1], "prog", 4) == 0)
return ads5121_fuse_prog(cmdtp, bank, argv[2]);
frow = (int)simple_strtol(argv[2], NULL, 10);
if (frow == 0 && argv[2][0] != '0')
frow = -1;
if (!in_range(frow, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
if (strncmp(argv[1], "read", 4) == 0)
return ads5121_fuse_read(bank, frow, 1);
if (strncmp(argv[1], "ovride", 6) == 0)
return ads5121_fuse_override(bank, frow, 0);
if (strncmp(argv[1], "sense", 5) == 0)
return ads5121_fuse_sense(bank, frow, 1);
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 4:
frow = (int)simple_strtol(argv[2], NULL, 10);
if (frow == 0 && argv[2][0] != '0')
frow = -1;
if (!in_range(frow, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
if (strncmp(argv[1], "read", 4) == 0) {
n = (int)simple_strtol(argv[3], NULL, 10);
if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
"<frow>+<n> must be between 1-32\n\n",
cmdtp->usage))
return 1;
return ads5121_fuse_read(bank, frow, n);
}
if (strncmp(argv[1], "ovride", 6) == 0) {
v = (int)simple_strtol(argv[3], NULL, 10);
return ads5121_fuse_override(bank, frow, v);
}
if (strncmp(argv[1], "sense", 5) == 0) {
n = (int)simple_strtol(argv[3], NULL, 10);
if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
"<frow>+<n> must be between 1-32\n\n",
cmdtp->usage))
return 1;
return ads5121_fuse_sense(bank, frow, n);
}
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- default: /* at least 5 args */
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- }
-}
-U_BOOT_CMD(
- fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
- " - Read, Sense, Override or Program Fuses\n",
- "bank <n> - sets active Fuse Bank to 0 or 1\n"
- " no args shows current active bank\n"
- "fuse stat - print active fuse bank's protection status\n"
- "fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n"
- " no args to print entire bank's fuses\n"
- "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
- " no <v> defaults to 0 for the row\n"
- " no args resets entire bank to 0\n"
- " NOTE - settings persist until hard reset\n"
- "fuse sense [<frow>] - senses current fuse at <frow>\n"
- " no args for entire bank\n"
- "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n"
- " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
- " WARNING - this is permanent"
-); -#endif /* CONFIG_CMD_FUSE */ diff --git u-boot-4d3c95f.orig/board/davedenx/aria/aria.c u-boot-4d3c95f/board/davedenx/aria/aria.c index 31b079b..d2ffba4 100644 --- u-boot-4d3c95f.orig/board/davedenx/aria/aria.c +++ u-boot-4d3c95f/board/davedenx/aria/aria.c @@ -92,7 +92,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c index 748ad7c..804a022 100644 --- u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c +++ u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c @@ -110,7 +110,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c index 97eeab3..0d33680 100644 --- u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c +++ u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c @@ -129,7 +129,7 @@ int board_early_init_f(void) */ out_be32 (&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32 (&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32 (&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c u-boot-4d3c95f/board/pdm360ng/pdm360ng.c index 2082ad4..dcff9c5 100644 --- u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c +++ u-boot-4d3c95f/board/pdm360ng/pdm360ng.c @@ -94,7 +94,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/include/configs/aria.h u-boot-4d3c95f/include/configs/aria.h index b21b495..cb20641 100644 --- u-boot-4d3c95f.orig/include/configs/aria.h +++ u-boot-4d3c95f/include/configs/aria.h @@ -378,7 +378,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration for Atmel AT24C32A-10TQ-2.7:
diff --git u-boot-4d3c95f.orig/include/configs/mecp5123.h u-boot-4d3c95f/include/configs/mecp5123.h index b41bda9..52a159a 100644 --- u-boot-4d3c95f.orig/include/configs/mecp5123.h +++ u-boot-4d3c95f/include/configs/mecp5123.h @@ -250,7 +250,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration
diff --git u-boot-4d3c95f.orig/include/configs/mpc5121ads.h u-boot-4d3c95f/include/configs/mpc5121ads.h index 9d1327f..88dd9bb 100644 --- u-boot-4d3c95f.orig/include/configs/mpc5121ads.h +++ u-boot-4d3c95f/include/configs/mpc5121ads.h @@ -346,7 +346,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration
Generally agree if we can share code. This is MPC5121 specific, I will let Anatolji to add his comments.
Best regards, Stefano

Dear Anatolij Gustschin,
On Tuesday, August 21, 2012 10:15:00 AM, Stefano Babic wrote:
On 14/08/2012 14:53, Benoît Thébaudeau wrote:
Signed-off-by: Benoît Thébaudeau benoit.thebaudeau@advansee.com Cc: Wolfgang Denk wd@denx.de Cc: Stefano Babic sbabic@denx.de
.../arch/powerpc/cpu/mpc512x/Makefile | 1 - .../arch/powerpc/cpu/mpc512x/iim.c => /dev/null | 394
.../board/davedenx/aria/aria.c | 2 +- .../board/esd/mecp5123/mecp5123.c | 2 +- .../board/freescale/mpc5121ads/mpc5121ads.c | 2 +- .../board/pdm360ng/pdm360ng.c | 2 +- .../include/configs/aria.h | 2 +- .../include/configs/mecp5123.h | 2 +- .../include/configs/mpc5121ads.h | 2 +- 9 files changed, 7 insertions(+), 402 deletions(-) delete mode 100644 u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c
diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile index b53232f..4f4c9ec 100644 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/Makefile +++ u-boot-4d3c95f/arch/powerpc/cpu/mpc512x/Makefile @@ -38,7 +38,6 @@ COBJS-y += serial.o COBJS-y += speed.o COBJS-$(CONFIG_FSL_DIU_FB) += diu.o COBJS-$(CONFIG_CMD_IDE) += ide.o -COBJS-$(CONFIG_IIM) += iim.o COBJS-$(CONFIG_PCI) += pci.o
# Stub implementations of cache management functions for USB diff --git u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c deleted file mode 100644 index abec8f6..0000000 --- u-boot-4d3c95f.orig/arch/powerpc/cpu/mpc512x/iim.c +++ /dev/null @@ -1,394 +0,0 @@ -/*
- Copyright 2008 Silicon Turnkey Express, Inc.
- Martha Marx mmarx@silicontkx.com
- ADS5121 IIM (Fusebox) Interface
- 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 <asm/io.h>
-#ifdef CONFIG_CMD_FUSE
-DECLARE_GLOBAL_DATA_PTR;
-static char cur_bank = '1';
-char *iim_err_msg(u32 err) -{
- static char *IIM_errs[] = {
"Parity Error in cache",
"Explicit Sense Cycle Error",
"Write to Locked Register Error",
"Read Protect Error",
"Override Protect Error",
"Write Protect Error"};
- int i;
- if (!err)
return "";
- for (i = 1; i < 8; i++)
if (err & (1 << i))
printf("IIM - %s\n", IIM_errs[i-1]);
- return "";
-}
-int in_range(int n, int min, int max, char *err, char *usg) -{
- if (n > max || n < min) {
printf(err);
printf("Usage:\n%s\n", usg);
return 0;
- }
- return 1;
-}
-int ads5121_fuse_read(int bank, int fstart, int num) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 *iim_fb, dummy;
- int f, ctr;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fb = (u32 *)&(iim->fbac0);
- else
iim_fb = (u32 *)&(iim->fbac1);
-/* try a read to see if Read Protect is set */
- dummy = in_be32(&iim_fb[0]);
- if (in_be32(&iim->err) & IIM_ERR_RPE) {
printf("\tRead protect fuse is set\n");
out_be32(&iim->err, IIM_ERR_RPE);
return 0;
- }
- printf("Reading Bank %d cache\n", bank);
- for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
if (ctr % 4 == 0)
printf("F%2d:", f);
printf("\t%#04x", (u8)(iim_fb[f]));
if (ctr % 4 == 3)
printf("\n");
- }
- if (ctr % 4 != 0)
printf("\n");
-}
-int ads5121_fuse_override(int bank, int f, u8 val) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 *iim_fb;
- u32 iim_stat;
- int i;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fb = (u32 *)&(iim->fbac0);
- else
iim_fb = (u32 *)&(iim->fbac1);
-/* try a read to see if Read Protect is set */
- iim_stat = in_be32(&iim_fb[0]);
- if (in_be32(&iim->err) & IIM_ERR_RPE) {
printf("Read protect fuse is set on bank %d;"
"Override protect may also be set\n", bank);
printf("An attempt will be made to override\n");
out_be32(&iim->err, IIM_ERR_RPE);
- }
- if (iim_stat & IIM_FBAC_FBOP) {
printf("Override protect fuse is set on bank %d\n", bank);
return 1;
- }
- if (f > IIM_FMAX) /* reset the entire bank */
for (i = 0; i < IIM_FMAX + 1; i++)
out_be32(&iim_fb[i], 0);
- else
out_be32(&iim_fb[f], val);
- return 0;
-}
-int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- int f, i, bitno;
- u32 stat, err;
- f = simple_strtol(fuseno_bitno, NULL, 10);
- if (f == 0 && fuseno_bitno[0] != '0')
f = -1;
- if (!in_range(f, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
- bitno = -1;
- for (i = 0; i < 6; i++) {
if (fuseno_bitno[i] == '_') {
bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
if (bitno == 0 && fuseno_bitno[i+1] != '0')
bitno = -1;
break;
}
- }
- if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
"Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
cmdtp->usage))
return 1;
- out_be32(&iim->err, in_be32(&iim->err));
- out_be32(&iim->prg_p, IIM_PRG_P_SET);
- out_be32(&iim->ua, IIM_SET_UA(bank, f));
- out_be32(&iim->la, IIM_SET_LA(f, bitno));
-#ifdef DEBUG
- printf("Programming disabled with DEBUG defined \n");
- printf(""Set up to pro
- printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
-#else
- out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
- do
udelay(20);
- while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
- out_be32(&iim->prg_p, 0);
- err = in_be32(&iim->err);
- if (stat & IIM_STAT_PRGD) {
if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
printf("Fuse is successfully set");
if (err)
printf(" - however there are other errors");
printf("\n");
}
iim->stat = 0;
- }
- if (err) {
iim_err_msg(err);
out_be32(&iim->err, in_be32(&iim->err));
- }
-#endif -}
-int ads5121_fuse_sense(int bank, int fstart, int num) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 iim_fbac;
- u32 stat, err, err_hold = 0;
- int f, ctr;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fbac = in_be32(&iim->fbac0);
- else
iim_fbac = in_be32(&iim->fbac1);
- if (iim_fbac & IIM_FBAC_FBESP) {
printf("\tSense Protect disallows this operation\n");
out_be32(&iim->err, IIM_FBAC_FBESP);
return 1;
- }
- err = in_be32(&iim->err);
- if (err) {
iim_err_msg(err);
err_hold |= err;
- }
- if (err & IIM_ERR_RPE)
printf("\tRead protect fuse is set; "
"Sense Protect may be set but will be attempted\n");
- if (err)
out_be32(&iim->err, err);
- printf("Sensing fuse(s) on Bank %d\n", bank);
- for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
out_be32(&iim->ua, IIM_SET_UA(bank, f));
out_be32(&iim->la, IIM_SET_LA(f, 0));
out_be32(&iim->fctl, IIM_FCTL_ESNS_N);
do
udelay(20);
while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
err = in_be32(&iim->err);
if (err & IIM_ERR_SNSE) {
iim_err_msg(err);
out_be32(&iim->err, IIM_ERR_SNSE);
return 1;
}
if (stat & IIM_STAT_SNSD) {
out_be32(&iim->stat, 0);
if (ctr % 4 == 0)
printf("F%2d:", f);
printf("\t%#04x", (u8)iim->sdat);
if (ctr % 4 == 3)
printf("\n");
}
if (err) {
err_hold |= err;
out_be32(&iim->err, err);
}
- }
- if (ctr % 4 != 0)
printf("\n");
- if (err_hold)
iim_err_msg(err_hold);
- return 0;
-}
-int ads5121_fuse_stat(int bank) -{
- iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
- u32 iim_fbac;
- u32 err;
- out_be32(&iim->err, in_be32(&iim->err));
- if (bank == 0)
iim_fbac = in_be32(&iim->fbac0);
- else
iim_fbac = in_be32(&iim->fbac1);
- err = in_be32(&iim->err);
- if (err)
iim_err_msg(err);
- if (err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) {
if (iim_fbac == 0)
printf("Since protection settings can't be read - "
"try sensing fuse row 0;\n");
return 0;
- }
- if (iim_fbac & IIM_PROTECTION)
printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
- else if (!(err & IIM_ERR_RPE))
printf("No Protection fuses are set\n");
- if (iim_fbac & IIM_FBAC_FBWP)
printf("\tWrite Protect fuse is set\n");
- if (iim_fbac & IIM_FBAC_FBOP)
printf("\tOverride Protect fuse is set\n");
- if (iim_fbac & IIM_FBAC_FBESP)
printf("\tSense Protect Fuse is set\n");
- out_be32(&iim->err, in_be32(&iim->err));
- return 0;
-}
-int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{
- int frow, n, v, bank;
- if (cur_bank == '0')
bank = 0;
- else
bank = 1;
- switch (argc) {
- case 0:
- case 1:
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 2:
if (strncmp(argv[1], "stat", 4) == 0)
return ads5121_fuse_stat(bank);
if (strncmp(argv[1], "read", 4) == 0)
return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
if (strncmp(argv[1], "sense", 5) == 0)
return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
if (strncmp(argv[1], "ovride", 6) == 0)
return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
if (strncmp(argv[1], "bank", 4) == 0) {
printf("Active Fuse Bank is %c\n", cur_bank);
return 0;
}
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 3:
if (strncmp(argv[1], "bank", 4) == 0) {
if (argv[2][0] == '0')
cur_bank = '0';
else if (argv[2][0] == '1')
cur_bank = '1';
else {
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
printf("Setting Active Fuse Bank to %c\n", cur_bank);
return 0;
}
if (strncmp(argv[1], "prog", 4) == 0)
return ads5121_fuse_prog(cmdtp, bank, argv[2]);
frow = (int)simple_strtol(argv[2], NULL, 10);
if (frow == 0 && argv[2][0] != '0')
frow = -1;
if (!in_range(frow, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
if (strncmp(argv[1], "read", 4) == 0)
return ads5121_fuse_read(bank, frow, 1);
if (strncmp(argv[1], "ovride", 6) == 0)
return ads5121_fuse_override(bank, frow, 0);
if (strncmp(argv[1], "sense", 5) == 0)
return ads5121_fuse_sense(bank, frow, 1);
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- case 4:
frow = (int)simple_strtol(argv[2], NULL, 10);
if (frow == 0 && argv[2][0] != '0')
frow = -1;
if (!in_range(frow, 0, IIM_FMAX,
"<frow> must be between 0-31\n\n", cmdtp->usage))
return 1;
if (strncmp(argv[1], "read", 4) == 0) {
n = (int)simple_strtol(argv[3], NULL, 10);
if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
"<frow>+<n> must be between 1-32\n\n",
cmdtp->usage))
return 1;
return ads5121_fuse_read(bank, frow, n);
}
if (strncmp(argv[1], "ovride", 6) == 0) {
v = (int)simple_strtol(argv[3], NULL, 10);
return ads5121_fuse_override(bank, frow, v);
}
if (strncmp(argv[1], "sense", 5) == 0) {
n = (int)simple_strtol(argv[3], NULL, 10);
if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
"<frow>+<n> must be between 1-32\n\n",
cmdtp->usage))
return 1;
return ads5121_fuse_sense(bank, frow, n);
}
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- default: /* at least 5 args */
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
- }
-}
-U_BOOT_CMD(
- fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
- " - Read, Sense, Override or Program Fuses\n",
- "bank <n> - sets active Fuse Bank to 0 or 1\n"
- " no args shows current active bank\n"
- "fuse stat - print active fuse bank's protection status\n"
- "fuse read [<frow> [<n>]] - print <n> fuse rows starting at
<frow>\n"
- " no args to print entire bank's fuses\n"
- "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
- " no <v> defaults to 0 for the row\n"
- " no args resets entire bank to 0\n"
- " NOTE - settings persist until hard reset\n"
- "fuse sense [<frow>] - senses current fuse at <frow>\n"
- " no args for entire bank\n"
- "fuse prog <frow_bit> - program fuse at row <frow>, bit
<_bit>\n"
- " <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
- " WARNING - this is permanent"
-); -#endif /* CONFIG_CMD_FUSE */ diff --git u-boot-4d3c95f.orig/board/davedenx/aria/aria.c u-boot-4d3c95f/board/davedenx/aria/aria.c index 31b079b..d2ffba4 100644 --- u-boot-4d3c95f.orig/board/davedenx/aria/aria.c +++ u-boot-4d3c95f/board/davedenx/aria/aria.c @@ -92,7 +92,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c index 748ad7c..804a022 100644 --- u-boot-4d3c95f.orig/board/esd/mecp5123/mecp5123.c +++ u-boot-4d3c95f/board/esd/mecp5123/mecp5123.c @@ -110,7 +110,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c index 97eeab3..0d33680 100644 --- u-boot-4d3c95f.orig/board/freescale/mpc5121ads/mpc5121ads.c +++ u-boot-4d3c95f/board/freescale/mpc5121ads/mpc5121ads.c @@ -129,7 +129,7 @@ int board_early_init_f(void) */ out_be32 (&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32 (&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32 (&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c u-boot-4d3c95f/board/pdm360ng/pdm360ng.c index 2082ad4..dcff9c5 100644 --- u-boot-4d3c95f.orig/board/pdm360ng/pdm360ng.c +++ u-boot-4d3c95f/board/pdm360ng/pdm360ng.c @@ -94,7 +94,7 @@ int board_early_init_f(void) */ out_be32(&im->clk.sccr[0], SCCR1_CLOCKS_EN); out_be32(&im->clk.sccr[1], SCCR2_CLOCKS_EN); -#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) +#if defined(CONFIG_FSL_IIM) || defined(CONFIG_CMD_FUSE) setbits_be32(&im->clk.sccr[1], CLOCK_SCCR2_IIM_EN); #endif
diff --git u-boot-4d3c95f.orig/include/configs/aria.h u-boot-4d3c95f/include/configs/aria.h index b21b495..cb20641 100644 --- u-boot-4d3c95f.orig/include/configs/aria.h +++ u-boot-4d3c95f/include/configs/aria.h @@ -378,7 +378,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration for Atmel AT24C32A-10TQ-2.7:
diff --git u-boot-4d3c95f.orig/include/configs/mecp5123.h u-boot-4d3c95f/include/configs/mecp5123.h index b41bda9..52a159a 100644 --- u-boot-4d3c95f.orig/include/configs/mecp5123.h +++ u-boot-4d3c95f/include/configs/mecp5123.h @@ -250,7 +250,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration
diff --git u-boot-4d3c95f.orig/include/configs/mpc5121ads.h u-boot-4d3c95f/include/configs/mpc5121ads.h index 9d1327f..88dd9bb 100644 --- u-boot-4d3c95f.orig/include/configs/mpc5121ads.h +++ u-boot-4d3c95f/include/configs/mpc5121ads.h @@ -346,7 +346,7 @@ /*
- IIM - IC Identification Module
*/ -#undef CONFIG_IIM +#undef CONFIG_FSL_IIM
/*
- EEPROM configuration
Generally agree if we can share code. This is MPC5121 specific, I will let Anatolji to add his comments.
Can you review this series please?
Thanks in advance.
Best regards, Benoît
participants (5)
-
Benoît Thébaudeau
-
Dirk Behme
-
Dirk Behme
-
Eric Nelson
-
Stefano Babic