[U-Boot] [PATCH] Add IC Ident. Module (IIM) support for ADS5121

IIM (IC Identification Module) is the fusebox for the mpc5121. Use #define CONFIG_IIM to turn on the clock for this module, use #define CONFIG_CMD_FUSE to add fusebox commands. Fusebox commands include the ability to read the status, read the register cache, override the register cache, program the fuses and sense them.
Signed-off-by: Martha Marx mmarx@silicontkx.com --- board/ads5121/Makefile | 1 + board/ads5121/ads5121.c | 3 + board/ads5121/ads5121_iim.c | 367 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/immap_512x.h | 20 +++- include/configs/ads5121.h | 6 + include/mpc512x.h | 25 +++ 6 files changed, 421 insertions(+), 1 deletions(-) create mode 100644 board/ads5121/ads5121_iim.c
diff --git a/board/ads5121/Makefile b/board/ads5121/Makefile index 52d0d3c..125ac60 100644 --- a/board/ads5121/Makefile +++ b/board/ads5121/Makefile @@ -32,6 +32,7 @@ COBJS-${CONFIG_FSL_DIU_FB} += ads5121_diu.o COBJS-${CONFIG_FSL_DIU_FB} += ../freescale/common/fsl_diu_fb.o COBJS-${CONFIG_FSL_DIU_FB} += ../freescale/common/fsl_logo_bmp.o COBJS-$(CONFIG_PCI) += pci.o +COBJS-$(CONFIG_IIM) += ads5121_iim.o
COBJS := $(COBJS-y) SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/ads5121/ads5121.c b/board/ads5121/ads5121.c index deaa292..4198826 100644 --- a/board/ads5121/ads5121.c +++ b/board/ads5121/ads5121.c @@ -101,6 +101,9 @@ int board_early_init_f (void) */ im->clk.sccr[0] = SCCR1_CLOCKS_EN; im->clk.sccr[1] = SCCR2_CLOCKS_EN; +#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE) + im->clk.sccr[1] |= CLOCK_SCCR2_IIM_EN; +#endif
return 0; } diff --git a/board/ads5121/ads5121_iim.c b/board/ads5121/ads5121_iim.c new file mode 100644 index 0000000..2dd2493 --- /dev/null +++ b/board/ads5121/ads5121_iim.c @@ -0,0 +1,367 @@ +/* + * 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 ads5121_fuse_read(int bank, int fstart, int num) +{ + volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim; + u32 *iim_fb, dummy; + int f, ctr; + + 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 = iim_fb[0]; + if (iim->err & IIM_ERR_RPE) { + printf("\tRead protect fuse is set\n"); + iim->err = 0; + 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) +{ + volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim; + u32 *iim_fb; + u32 iim_stat; + int i; + + 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 = iim_fb[0]; + if (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"); + iim->err = 0; + } + 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++) + iim_fb[i] = 0; + else + iim_fb[f] = val; + + return 0; +} + +int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) +{ + volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim; + int f, i; + int bitno; + + f = simple_strtoul(fuseno_bitno, NULL, 10); + if (f > IIM_FMAX) { + printf("Fuse row number ranges from 0-%d\n", IIM_FMAX); + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + bitno = -1; + for (i = 0; i < 8; i++) { + if (fuseno_bitno[i] == '_') { + bitno = simple_strtoul(&(fuseno_bitno[i+1]), NULL, 10); + break; + } else if (fuseno_bitno[i] == '\0') + break; + } + if (bitno > 8) { + printf("Bit number ranges from 0-7\n"); + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + iim->prg_p = IIM_PRG_P_SET; + iim->ua = IIM_SET_UA(bank, f); + iim->la = IIM_SET_LA(f, bitno); +#ifdef DEBUG + printf("Programming disabled with DEBUG defined \n"); + printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la); +#else + iim->fctl = IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG; + do + udelay(10); + while (iim->stat & IIM_STAT_BUSY); + if (iim->stat & IIM_STAT_PRGD) { + if (!(iim->err & (IIM_ERR_WPE | IIM_ERR_WPE))) { + printf("Fuse is successfully set "); + if (iim->err) + printf("- however there are other errors"); + printf("\n"); + } + iim->stat = 0; + } + if (iim->err) { + iim_err_msg(iim->err); + iim->err = 0; + } +#endif +} + +int ads5121_fuse_sense(int bank, int fstart, int num) +{ + volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim; + u32 iim_fbac; + u32 err_hold; + int f, ctr; + + if (bank == 0) + iim_fbac = iim->fbac0; + else + iim_fbac = iim->fbac1; + + if (iim_fbac & (IIM_FBAC_FBESP | IIM_FBAC_FBSP)) { + printf("Protection Fuses Bank %d = %#04x:\n", bank, (u8)iim_fbac); + printf("\tSense Protect is set\n"); + return 1; + } + if (iim->err & IIM_ERR_RPE) { + printf("\tRead protect fuse is set; " + "Sense Protect may be set but will be attempted\n"); + iim->err = 0; + } + printf("Sensing fuse(s) on Bank %d\n", bank); + for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) { + iim->ua = IIM_SET_UA(bank, f); + iim->la = IIM_SET_LA(f, 0); + iim->fctl = IIM_FCTL_ESNS_N; + do + udelay(100); + while (iim->stat & IIM_STAT_BUSY); + if (iim->err & IIM_ERR_SNSE) { + iim_err_msg(iim->err); + iim->err = 0; + return 1; + } + if (iim->stat & IIM_STAT_SNSD) { + iim->stat = 0; + if (ctr % 4 == 0) + printf("F%2d:", f); + printf("\t%#04x", (u8)(iim->sdat)); + if (ctr % 4 == 3) + printf("\n"); + } + if (iim->err) { + err_hold |= iim->err; + iim->err = 0; + } + } + if (ctr % 4 != 0) + printf("\n"); + if (err_hold) + iim_err_msg(err_hold); + + return 0; +} + +int ads5121_fuse_stat(int bank) +{ + volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim; + u32 iim_fbac; + + if (bank == 0) + iim_fbac = iim->fbac0; + else + iim_fbac = iim->fbac1; + if (iim->err) + iim_err_msg(iim->err); + if (iim_fbac & IIM_PROTECTION) + printf("Protection Fuses on Bank %d = %#04x:\n", bank, iim_fbac); + else if (!(iim->err & IIM_ERR_RPE)) + printf("No Protection fuses set\n"); + if (iim_fbac & IIM_FBAC_FBWP) + printf("\tWrite Protect is set\n"); + if (iim_fbac & IIM_FBAC_FBOP) + printf("\tOverride Protect is set\n"); + if (iim->err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) { + printf("\tRead protect fuse is set\n"); + if (iim_fbac == 0) + printf(" Settings can't be read - try sensing fuse 0;\n"); + } + if (iim_fbac & IIM_FBAC_FBESP || iim_fbac & IIM_FBAC_FBSP) + printf("\tSense Protect is set\n"); + iim->err = 0; + + return 0; +} + +int do_ads5121_fuse(cmd_tbl_t *cmdtp, + int flag, int argc, char *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) { + ads5121_fuse_stat(bank); + return 0; + } else if (strncmp(argv[1], "read", 4) == 0) { + ads5121_fuse_read(bank, 0, IIM_FMAX + 1); + return 0; + } else if (strncmp(argv[1], "sense", 5) == 0) { + ads5121_fuse_sense(bank, 0, IIM_FMAX + 1); + return 0; + } else if (strncmp(argv[1], "ovride", 6) == 0) { + ads5121_fuse_override(bank, IIM_FMAX + 1, 0); + return 0; + } else 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; + } else if (strncmp(argv[1], "read", 4) == 0) { + frow = (int)simple_strtoul(argv[2], NULL, 10); + if (frow > IIM_FMAX || frow < 0) { + printf("<frow> is the fuse row, 0-31 decimal\n\n"); + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + return ads5121_fuse_read(bank, frow, 1); + } else if (strncmp(argv[1], "ovride", 6) == 0) { + frow = (int)simple_strtoul(argv[2], NULL, 10); + return ads5121_fuse_override(bank, frow, 0); + } else if (strncmp(argv[1], "sense", 5) == 0) { + frow = (int)simple_strtoul(argv[2], NULL, 10); + return ads5121_fuse_sense(bank, frow, 1); + } else if (strncmp(argv[1], "prog", 4) == 0) { + return ads5121_fuse_prog(cmdtp, bank, argv[2]); + } + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + case 4: + if (strncmp(argv[1], "read", 4) == 0) { + frow = (int)simple_strtoul(argv[2], NULL, 10); + if (frow > IIM_FMAX || frow < 0) { + printf("<frow> is the fuse row, a decimal number 0-31\n\n"); + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + n = (int)simple_strtoul(argv[3], NULL, 10); + if (frow + n > IIM_FMAX + 1) { + printf("There are %d fuses per bank\n\n", IIM_FMAX); + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + return ads5121_fuse_read(bank, frow, n); + } else if (strncmp(argv[1], "ovride", 6) == 0) { + frow = (int)simple_strtoul(argv[2], NULL, 10); + if (frow > IIM_FMAX || frow < 0) { + printf("<frow> is the fuse row, 0-31 decimal\n\n"); + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + v = (int)simple_strtoul(argv[3], NULL, 10); + return ads5121_fuse_override(bank, frow, v); + } + 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, CFG_MAXARGS, 0, do_ads5121_fuse, + " - Read, Sense, Override or Program Fuses\n", + "bank <n> - Set the active Fuse Bank n (0 or 1) Default is 1\n" + "fuse stat - print active fuse bank's status\n" + "fuse read [<frow> [<num>]] - print <num> fuse rows starting at <frow>\n" + " - no args to print entire bank's fuses\n" + "fuse ovride [<frow> [<val>]] - override fuses at <frow> with <val> (default=0)\n" + " - no args resets entire bank\n" + "fuse sense [<frow>] - senses current fuse at <frow>, no args for entire bank\n" + "fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n" + " - <frow> ranges from 0-31, <bit> ranges from 0-7\n" + ); +#endif /* CONFIG_CMD_FUSE */ diff --git a/include/asm-ppc/immap_512x.h b/include/asm-ppc/immap_512x.h index cd90945..222d713 100644 --- a/include/asm-ppc/immap_512x.h +++ b/include/asm-ppc/immap_512x.h @@ -415,7 +415,25 @@ typedef struct ioctrl512x { * IIM */ typedef struct iim512x { - u8 fixme[0x1000]; + u32 stat; /* IIM status register */ + u32 statm; /* IIM status IRQ mask */ + u32 err; /* IIM errors register */ + u32 emask; /* IIM error IRQ mask */ + u32 fctl; /* IIM fuse control register */ + u32 ua; /* IIM upper address register */ + u32 la; /* IIM lower address register */ + u32 sdat; /* IIM explicit sense data */ + u8 res0[0x08]; + u32 prg_p; /* IIM program protection register */ + u8 res1[0x10]; + u32 divide; /* IIM divide factor register */ + u8 res2[0x7c0]; + u32 fbac0; /* IIM fuse bank 0 protection (for Freescale use) */ + u32 fb0w0[0x1f]; /* IIM fuse bank 0 data (for Freescale use) */ + u8 res3[0x380]; + u32 fbac1; /* IIM fuse bank 1 protection */ + u32 fb1w1[0x01f]; /* IIM fuse bank 1 data */ + u8 res4[0x380]; } iim512x_t;
/* diff --git a/include/configs/ads5121.h b/include/configs/ads5121.h index d6f7e02..1955fba 100644 --- a/include/configs/ads5121.h +++ b/include/configs/ads5121.h @@ -294,6 +294,11 @@ #endif
/* + * IIM - IC Identification Module + */ +#define CONFIG_IIM + +/* * EEPROM configuration */ #define CFG_I2C_EEPROM_ADDR_LEN 2 /* 16-bit EEPROM address */ @@ -348,6 +353,7 @@ #define CONFIG_CMD_REGINFO #define CONFIG_CMD_EEPROM #define CONFIG_CMD_DATE +#define CONFIG_CMD_FUSE
#if defined(CONFIG_PCI) #define CONFIG_CMD_PCI diff --git a/include/mpc512x.h b/include/mpc512x.h index cb418d1..49f5cd2 100644 --- a/include/mpc512x.h +++ b/include/mpc512x.h @@ -574,6 +574,31 @@ void iopin_initialize(iopin_t *,int); /* Register Offset Base */ #define MPC512X_FEC (CFG_IMMR + 0x02800)
+/* IIM control */ +#define IIM_SET_UA(bk, f) ((bk << 3) | (f >> 5)) +#define IIM_SET_LA(f, bit) (((f & 0x0000001f) << 3) | bit) +#define IIM_STAT_BUSY 0x00000080 +#define IIM_STAT_PRGD 0x00000002 +#define IIM_STAT_SNSD 0x00000001 +#define IIM_ERR_WPE 0x00000040 +#define IIM_ERR_OPE 0x00000020 +#define IIM_ERR_RPE 0x00000010 +#define IIM_ERR_WLRE 0x00000008 +#define IIM_ERR_SNSE 0x00000004 +#define IIM_ERR_PARITYE 0x00000002 +#define IIM_PRG_P_SET 0x000000aa +#define IIM_PRG_P_UNSET 0 +#define IIM_FCTL_PROG_PULSE 0x00000020 +#define IIM_FCTL_PROG 0x00000001 +#define IIM_FCTL_ESNS_N 0x00000008 +#define IIM_FBAC_FBWP 0x00000080 +#define IIM_FBAC_FBOP 0x00000040 +#define IIM_FBAC_FBRP 0x00000020 +#define IIM_FBAC_FBSP 0x00000010 +#define IIM_FBAC_FBESP 0x00000008 +#define IIM_PROTECTION 0x000000f8 +#define IIM_FMAX 31 + /* Number of I2C buses */ #define I2C_BUS_CNT 3

Hi Martha,
First, please replace the volatile pointer accesses with io accessors like in_bexx and out_bexx. Second, chip stuff should go in cpu/mpc512x.
John
On Tue, Oct 7, 2008 at 10:46 PM, Martha Marx mmarx@silicontkx.com wrote:
IIM (IC Identification Module) is the fusebox for the mpc5121. Use #define CONFIG_IIM to turn on the clock for this module, use #define CONFIG_CMD_FUSE to add fusebox commands. Fusebox commands include the ability to read the status, read the register cache, override the register cache, program the fuses and sense them.
Signed-off-by: Martha Marx mmarx@silicontkx.com
board/ads5121/Makefile | 1 + board/ads5121/ads5121.c | 3 + board/ads5121/ads5121_iim.c | 367 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ppc/immap_512x.h | 20 +++- include/configs/ads5121.h | 6 + include/mpc512x.h | 25 +++ 6 files changed, 421 insertions(+), 1 deletions(-) create mode 100644 board/ads5121/ads5121_iim.c
diff --git a/board/ads5121/Makefile b/board/ads5121/Makefile index 52d0d3c..125ac60 100644 --- a/board/ads5121/Makefile +++ b/board/ads5121/Makefile @@ -32,6 +32,7 @@ COBJS-${CONFIG_FSL_DIU_FB} += ads5121_diu.o COBJS-${CONFIG_FSL_DIU_FB} += ../freescale/common/fsl_diu_fb.o COBJS-${CONFIG_FSL_DIU_FB} += ../freescale/common/fsl_logo_bmp.o COBJS-$(CONFIG_PCI) += pci.o +COBJS-$(CONFIG_IIM) += ads5121_iim.o
COBJS := $(COBJS-y) SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/board/ads5121/ads5121.c b/board/ads5121/ads5121.c index deaa292..4198826 100644 --- a/board/ads5121/ads5121.c +++ b/board/ads5121/ads5121.c @@ -101,6 +101,9 @@ int board_early_init_f (void) */ im->clk.sccr[0] = SCCR1_CLOCKS_EN; im->clk.sccr[1] = SCCR2_CLOCKS_EN; +#if defined(CONFIG_IIM) || defined(CONFIG_CMD_FUSE)
im->clk.sccr[1] |= CLOCK_SCCR2_IIM_EN;
+#endif
return 0;
} diff --git a/board/ads5121/ads5121_iim.c b/board/ads5121/ads5121_iim.c new file mode 100644 index 0000000..2dd2493 --- /dev/null +++ b/board/ads5121/ads5121_iim.c @@ -0,0 +1,367 @@ +/*
- 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 ads5121_fuse_read(int bank, int fstart, int num) +{
volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim;
u32 *iim_fb, dummy;
int f, ctr;
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 = iim_fb[0];
if (iim->err & IIM_ERR_RPE) {
printf("\tRead protect fuse is set\n");
iim->err = 0;
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) +{
volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim;
u32 *iim_fb;
u32 iim_stat;
int i;
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 = iim_fb[0];
if (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");
iim->err = 0;
}
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++)
iim_fb[i] = 0;
else
iim_fb[f] = val;
return 0;
+}
+int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno) +{
volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim;
int f, i;
int bitno;
f = simple_strtoul(fuseno_bitno, NULL, 10);
if (f > IIM_FMAX) {
printf("Fuse row number ranges from 0-%d\n", IIM_FMAX);
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
bitno = -1;
for (i = 0; i < 8; i++) {
if (fuseno_bitno[i] == '_') {
bitno = simple_strtoul(&(fuseno_bitno[i+1]), NULL, 10);
break;
} else if (fuseno_bitno[i] == '\0')
break;
}
if (bitno > 8) {
printf("Bit number ranges from 0-7\n");
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
iim->prg_p = IIM_PRG_P_SET;
iim->ua = IIM_SET_UA(bank, f);
iim->la = IIM_SET_LA(f, bitno);
+#ifdef DEBUG
printf("Programming disabled with DEBUG defined \n");
printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
+#else
iim->fctl = IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG;
do
udelay(10);
while (iim->stat & IIM_STAT_BUSY);
if (iim->stat & IIM_STAT_PRGD) {
if (!(iim->err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
printf("Fuse is successfully set ");
if (iim->err)
printf("- however there are other errors");
printf("\n");
}
iim->stat = 0;
}
if (iim->err) {
iim_err_msg(iim->err);
iim->err = 0;
}
+#endif +}
+int ads5121_fuse_sense(int bank, int fstart, int num) +{
volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim;
u32 iim_fbac;
u32 err_hold;
int f, ctr;
if (bank == 0)
iim_fbac = iim->fbac0;
else
iim_fbac = iim->fbac1;
if (iim_fbac & (IIM_FBAC_FBESP | IIM_FBAC_FBSP)) {
printf("Protection Fuses Bank %d = %#04x:\n", bank, (u8)iim_fbac);
printf("\tSense Protect is set\n");
return 1;
}
if (iim->err & IIM_ERR_RPE) {
printf("\tRead protect fuse is set; "
"Sense Protect may be set but will be attempted\n");
iim->err = 0;
}
printf("Sensing fuse(s) on Bank %d\n", bank);
for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
iim->ua = IIM_SET_UA(bank, f);
iim->la = IIM_SET_LA(f, 0);
iim->fctl = IIM_FCTL_ESNS_N;
do
udelay(100);
while (iim->stat & IIM_STAT_BUSY);
if (iim->err & IIM_ERR_SNSE) {
iim_err_msg(iim->err);
iim->err = 0;
return 1;
}
if (iim->stat & IIM_STAT_SNSD) {
iim->stat = 0;
if (ctr % 4 == 0)
printf("F%2d:", f);
printf("\t%#04x", (u8)(iim->sdat));
if (ctr % 4 == 3)
printf("\n");
}
if (iim->err) {
err_hold |= iim->err;
iim->err = 0;
}
}
if (ctr % 4 != 0)
printf("\n");
if (err_hold)
iim_err_msg(err_hold);
return 0;
+}
+int ads5121_fuse_stat(int bank) +{
volatile iim512x_t *iim = &((immap_t *) CFG_IMMR)->iim;
u32 iim_fbac;
if (bank == 0)
iim_fbac = iim->fbac0;
else
iim_fbac = iim->fbac1;
if (iim->err)
iim_err_msg(iim->err);
if (iim_fbac & IIM_PROTECTION)
printf("Protection Fuses on Bank %d = %#04x:\n", bank, iim_fbac);
else if (!(iim->err & IIM_ERR_RPE))
printf("No Protection fuses set\n");
if (iim_fbac & IIM_FBAC_FBWP)
printf("\tWrite Protect is set\n");
if (iim_fbac & IIM_FBAC_FBOP)
printf("\tOverride Protect is set\n");
if (iim->err & IIM_ERR_RPE || iim_fbac & IIM_FBAC_FBRP) {
printf("\tRead protect fuse is set\n");
if (iim_fbac == 0)
printf(" Settings can't be read - try sensing fuse 0;\n");
}
if (iim_fbac & IIM_FBAC_FBESP || iim_fbac & IIM_FBAC_FBSP)
printf("\tSense Protect is set\n");
iim->err = 0;
return 0;
+}
+int do_ads5121_fuse(cmd_tbl_t *cmdtp,
int flag, int argc, char *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) {
ads5121_fuse_stat(bank);
return 0;
} else if (strncmp(argv[1], "read", 4) == 0) {
ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
return 0;
} else if (strncmp(argv[1], "sense", 5) == 0) {
ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
return 0;
} else if (strncmp(argv[1], "ovride", 6) == 0) {
ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
return 0;
} else 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;
} else if (strncmp(argv[1], "read", 4) == 0) {
frow = (int)simple_strtoul(argv[2], NULL, 10);
if (frow > IIM_FMAX || frow < 0) {
printf("<frow> is the fuse row, 0-31 decimal\n\n");
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
return ads5121_fuse_read(bank, frow, 1);
} else if (strncmp(argv[1], "ovride", 6) == 0) {
frow = (int)simple_strtoul(argv[2], NULL, 10);
return ads5121_fuse_override(bank, frow, 0);
} else if (strncmp(argv[1], "sense", 5) == 0) {
frow = (int)simple_strtoul(argv[2], NULL, 10);
return ads5121_fuse_sense(bank, frow, 1);
} else if (strncmp(argv[1], "prog", 4) == 0) {
return ads5121_fuse_prog(cmdtp, bank, argv[2]);
}
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
case 4:
if (strncmp(argv[1], "read", 4) == 0) {
frow = (int)simple_strtoul(argv[2], NULL, 10);
if (frow > IIM_FMAX || frow < 0) {
printf("<frow> is the fuse row, a decimal number 0-31\n\n");
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
n = (int)simple_strtoul(argv[3], NULL, 10);
if (frow + n > IIM_FMAX + 1) {
printf("There are %d fuses per bank\n\n", IIM_FMAX);
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
return ads5121_fuse_read(bank, frow, n);
} else if (strncmp(argv[1], "ovride", 6) == 0) {
frow = (int)simple_strtoul(argv[2], NULL, 10);
if (frow > IIM_FMAX || frow < 0) {
printf("<frow> is the fuse row, 0-31 decimal\n\n");
printf("Usage:\n%s\n", cmdtp->usage);
return 1;
}
v = (int)simple_strtoul(argv[3], NULL, 10);
return ads5121_fuse_override(bank, frow, v);
}
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, CFG_MAXARGS, 0, do_ads5121_fuse,
" - Read, Sense, Override or Program Fuses\n",
"bank <n> - Set the active Fuse Bank n (0 or 1) Default is 1\n"
"fuse stat - print active fuse bank's status\n"
"fuse read [<frow> [<num>]] - print <num> fuse rows starting at <frow>\n"
" - no args to print entire bank's fuses\n"
"fuse ovride [<frow> [<val>]] - override fuses at <frow> with <val> (default=0)\n"
" - no args resets entire bank\n"
"fuse sense [<frow>] - senses current fuse at <frow>, no args for entire bank\n"
"fuse prog <frow_bit> - program fuse at row <frow>, bit <_bit>\n"
" - <frow> ranges from 0-31, <bit> ranges from 0-7\n"
);
+#endif /* CONFIG_CMD_FUSE */ diff --git a/include/asm-ppc/immap_512x.h b/include/asm-ppc/immap_512x.h index cd90945..222d713 100644 --- a/include/asm-ppc/immap_512x.h +++ b/include/asm-ppc/immap_512x.h @@ -415,7 +415,25 @@ typedef struct ioctrl512x {
- IIM
*/ typedef struct iim512x {
u8 fixme[0x1000];
u32 stat; /* IIM status register */
u32 statm; /* IIM status IRQ mask */
u32 err; /* IIM errors register */
u32 emask; /* IIM error IRQ mask */
u32 fctl; /* IIM fuse control register */
u32 ua; /* IIM upper address register */
u32 la; /* IIM lower address register */
u32 sdat; /* IIM explicit sense data */
u8 res0[0x08];
u32 prg_p; /* IIM program protection register */
u8 res1[0x10];
u32 divide; /* IIM divide factor register */
u8 res2[0x7c0];
u32 fbac0; /* IIM fuse bank 0 protection (for Freescale use) */
u32 fb0w0[0x1f]; /* IIM fuse bank 0 data (for Freescale use) */
u8 res3[0x380];
u32 fbac1; /* IIM fuse bank 1 protection */
u32 fb1w1[0x01f]; /* IIM fuse bank 1 data */
u8 res4[0x380];
} iim512x_t;
/* diff --git a/include/configs/ads5121.h b/include/configs/ads5121.h index d6f7e02..1955fba 100644 --- a/include/configs/ads5121.h +++ b/include/configs/ads5121.h @@ -294,6 +294,11 @@ #endif
/*
- IIM - IC Identification Module
- */
+#define CONFIG_IIM
+/*
- EEPROM configuration
*/ #define CFG_I2C_EEPROM_ADDR_LEN 2 /* 16-bit EEPROM address */ @@ -348,6 +353,7 @@ #define CONFIG_CMD_REGINFO #define CONFIG_CMD_EEPROM #define CONFIG_CMD_DATE +#define CONFIG_CMD_FUSE
#if defined(CONFIG_PCI) #define CONFIG_CMD_PCI diff --git a/include/mpc512x.h b/include/mpc512x.h index cb418d1..49f5cd2 100644 --- a/include/mpc512x.h +++ b/include/mpc512x.h @@ -574,6 +574,31 @@ void iopin_initialize(iopin_t *,int); /* Register Offset Base */ #define MPC512X_FEC (CFG_IMMR + 0x02800)
+/* IIM control */ +#define IIM_SET_UA(bk, f) ((bk << 3) | (f >> 5)) +#define IIM_SET_LA(f, bit) (((f & 0x0000001f) << 3) | bit) +#define IIM_STAT_BUSY 0x00000080 +#define IIM_STAT_PRGD 0x00000002 +#define IIM_STAT_SNSD 0x00000001 +#define IIM_ERR_WPE 0x00000040 +#define IIM_ERR_OPE 0x00000020 +#define IIM_ERR_RPE 0x00000010 +#define IIM_ERR_WLRE 0x00000008 +#define IIM_ERR_SNSE 0x00000004 +#define IIM_ERR_PARITYE 0x00000002 +#define IIM_PRG_P_SET 0x000000aa +#define IIM_PRG_P_UNSET 0 +#define IIM_FCTL_PROG_PULSE 0x00000020 +#define IIM_FCTL_PROG 0x00000001 +#define IIM_FCTL_ESNS_N 0x00000008 +#define IIM_FBAC_FBWP 0x00000080 +#define IIM_FBAC_FBOP 0x00000040 +#define IIM_FBAC_FBRP 0x00000020 +#define IIM_FBAC_FBSP 0x00000010 +#define IIM_FBAC_FBESP 0x00000008 +#define IIM_PROTECTION 0x000000f8 +#define IIM_FMAX 31
/* Number of I2C buses */ #define I2C_BUS_CNT 3
-- 1.5.2.4
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (2)
-
John Rigby
-
Martha Marx