summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Krummenacher <max.krummenacher@toradex.com>2014-03-10 17:42:59 +0100
committerMax Krummenacher <max.krummenacher@toradex.com>2014-03-10 17:42:59 +0100
commit71a6c00e3b3894de6bca804c21006e77f7389e62 (patch)
treef826a7fe975ba2392f0d97cfe4b22316903cccfc
parent88e175a12024462dd65cf2c4daac6d18bd3f7fa2 (diff)
pf0100: only program unprogrammed OTP
- add logic to check for an unprogrammed PMIC before programming - add #ifdef debug section to dump all PMIC registers
-rw-r--r--board/toradex/apalis_imx6/apalis_imx6.c2
-rw-r--r--board/toradex/apalis_imx6/pf0100.c138
-rw-r--r--board/toradex/apalis_imx6/pf0100.h21
3 files changed, 143 insertions, 18 deletions
diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c
index bbebe55d48..a8376226e0 100644
--- a/board/toradex/apalis_imx6/apalis_imx6.c
+++ b/board/toradex/apalis_imx6/apalis_imx6.c
@@ -789,7 +789,7 @@ int board_init(void)
setup_i2c(1, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info_loc);
setup_i2c(2, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info3);
- pmic_init();
+ (void) pmic_init();
#ifdef CONFIG_CMD_SATA
setup_sata();
diff --git a/board/toradex/apalis_imx6/pf0100.c b/board/toradex/apalis_imx6/pf0100.c
index 5c9d7b0566..5e29ac89f0 100644
--- a/board/toradex/apalis_imx6/pf0100.c
+++ b/board/toradex/apalis_imx6/pf0100.c
@@ -19,15 +19,19 @@
#include "pf0100_otp.inc"
#include "pf0100.h"
+/* define for PMIC register dump */
+/*#define DEBUG */
+
/* 7-bit I2C bus slave address */
#define PFUZE100_I2C_ADDR (0x08)
-iomux_v3_cfg_t const pmic_prog_pads[] = {
+static iomux_v3_cfg_t const pmic_prog_pads[] = {
MX6_PAD_GPIO_2__GPIO_1_2 | MUX_PAD_CTRL(NO_PAD_CTRL),
};
-void pmic_init(void)
+unsigned pmic_init(void)
{
+ unsigned programmed = 0;
uchar bus = 1;
uchar devid, revid, val;
@@ -35,27 +39,128 @@ void pmic_init(void)
if(!(0 == i2c_set_bus_num(bus) && (0 == i2c_probe(PFUZE100_I2C_ADDR))))
{
puts("i2c bus failed\n");
- return;
+ return 0;
}
/* get device ident */
if( i2c_read(PFUZE100_I2C_ADDR, PFUZE100_DEVICEID, 1, &devid, 1) < 0)
{
puts("i2c pmic devid read failed\n");
- return;
+ return 0;
}
if( i2c_read(PFUZE100_I2C_ADDR, PFUZE100_REVID, 1, &revid, 1) < 0)
{
puts("i2c pmic revid read failed\n");
- return;
+ return 0;
}
printf("device id: 0x%.2x, revision id: 0x%.2x\n", devid, revid);
+#ifdef DEBUG
+ {
+ unsigned i,j;
+
+ for(i=0; i<16; i++)
+ printf("\t%x",i);
+ for(j=0; j<0x80; )
+ {
+ printf("\n%2x",j);
+ for(i=0; i<16; i++)
+ {
+ i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
+ printf("\t%2x", val);
+ }
+ j += 0x10;
+ }
+ printf("\nEXT Page 1");
+
+ val = PFUZE100_PAGE_REGISTER_PAGE1;
+ if( i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, &val, 1))
+ {
+ puts("i2c write failed\n");
+ return 0;
+ }
+
+ for(j=0x80; j<0x100; )
+ {
+ printf("\n%2x",j);
+ for(i=0; i<16; i++)
+ {
+ i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
+ printf("\t%2x", val);
+ }
+ j += 0x10;
+ }
+ printf("\nEXT Page 2");
+
+ val = PFUZE100_PAGE_REGISTER_PAGE2;
+ if( i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, &val, 1))
+ {
+ puts("i2c write failed\n");
+ return 0;
+ }
+
+ for(j=0x80; j<0x100; )
+ {
+ printf("\n%2x",j);
+ for(i=0; i<16; i++)
+ {
+ i2c_read(PFUZE100_I2C_ADDR, j+i, 1, &val, 1);
+ printf("\t%2x", val);
+ }
+ j += 0x10;
+ }
+ printf("\n");
+ }
+#endif
+ /* get device programmed state */
+ val = PFUZE100_PAGE_REGISTER_PAGE1;
+ if( i2c_write(PFUZE100_I2C_ADDR, PFUZE100_PAGE_REGISTER, 1, &val, 1))
+ {
+ puts("i2c write failed\n");
+ return 0;
+ }
+ if( i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR1, 1, &val, 1) < 0)
+ {
+ puts("i2c fuse_por read failed\n");
+ return 0;
+ }
+ if(val & PFUZE100_FUSE_POR_M)
+ programmed++;
+
+ if( i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR2, 1, &val, 1) < 0)
+ {
+ puts("i2c fuse_por read failed\n");
+ return programmed;
+ }
+ if(val & PFUZE100_FUSE_POR_M)
+ programmed++;
+
+ if( i2c_read(PFUZE100_I2C_ADDR, PFUZE100_FUSE_POR3, 1, &val, 1) < 0)
+ {
+ puts("i2c fuse_por read failed\n");
+ return programmed;
+ }
+ if(val & PFUZE100_FUSE_POR_M)
+ programmed++;
+
+ switch (programmed) {
+ case 0:
+ printf("PMIC: not programmed\n");
+ break;
+ case 3:
+ printf("PMIC: programmed\n");
+ break;
+ default:
+ printf("PMIC: undefined progamming state\n");
+ break;
+ }
+
+ /* TODO the following should be removed for production */
/* set VGEN1 to 1.2V */
val = PFUZE100_VGEN1_VAL;
if( i2c_write(PFUZE100_I2C_ADDR, PFUZE100_VGEN1CTL, 1, &val, 1))
{
puts("i2c write failed\n");
- return;
+ return programmed;
}
/* set SWBST to 5.0V */
@@ -63,16 +168,20 @@ void pmic_init(void)
if( i2c_write(PFUZE100_I2C_ADDR, PFUZE100_SWBSTCTL, 1, &val, 1))
{
puts("i2c write failed\n");
- return;
}
+ return programmed;
}
-void pf0100_prog(void)
+int pf0100_prog(void)
{
unsigned char bus = 1;
unsigned char val;
unsigned i;
+ if(pmic_init() == 3) {
+ puts("PMIC already programmed, exiting\n");
+ return 1;
+ }
/* set up gpio to manipulate vprog, initially off */
imx_iomux_v3_setup_multiple_pads(pmic_prog_pads, ARRAY_SIZE(pmic_prog_pads));
gpio_direction_output(IMX_GPIO_NR(1, 2), 0);
@@ -80,7 +189,7 @@ void pf0100_prog(void)
if(!(0 == i2c_set_bus_num(bus) && (0 == i2c_probe(PFUZE100_I2C_ADDR))))
{
puts("i2c bus failed\n");
- return;
+ return 1;
}
for (i=0; i<ARRAY_SIZE(pmic_otp_prog); i++) {
@@ -92,7 +201,7 @@ void pf0100_prog(void)
{
printf("i2c write failed, reg 0x%2x, value0x%2x\n",
pmic_otp_prog[i].reg, val);
- return;
+ return 1;
}
break;
case pmic_delay:
@@ -106,15 +215,18 @@ void pf0100_prog(void)
break;
}
}
+ return 0;
}
-static int do_pf0100_prog(cmd_tbl_t *cmdtp, int flag, int argc,
+int do_pf0100_prog(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
puts("Programming PMIC OTP...");
- pf0100_prog();
- puts("done. Power cycle the board\n");
+ if(!pf0100_prog())
+ puts("done.\n");
+ else
+ puts("failed.\n");
return 0;
}
diff --git a/board/toradex/apalis_imx6/pf0100.h b/board/toradex/apalis_imx6/pf0100.h
index dabec3e121..b43744c47e 100644
--- a/board/toradex/apalis_imx6/pf0100.h
+++ b/board/toradex/apalis_imx6/pf0100.h
@@ -32,11 +32,24 @@
#define PFUZE100_SWBSTCTL (0x66)
#define PFUZE100_SWBST_VAL (0x40 + 0x08 + 0x00) /* Always ON, Auto Switching Mode, 5.0V */
-/* enables some rails on a not programmed PMIC */
-/* VGEN1 to 1.2V, set SWBST to 5.0V */
-void pmic_init(void);
+/* chooses the extended page (registers 0x80..0xff) */
+#define PFUZE100_PAGE_REGISTER 0x7f
+#define PFUZE100_PAGE_REGISTER_PAGE_M (0x1f << 0)
+#define PFUZE100_PAGE_REGISTER_PAGE1 (0x01 & PFUZE100_PAGE_REGISTER_PAGE_M)
+#define PFUZE100_PAGE_REGISTER_PAGE2 (0x02 & PFUZE100_PAGE_REGISTER_PAGE_M)
+
+/* extended page 1 */
+#define PFUZE100_FUSE_POR1 0xe4
+#define PFUZE100_FUSE_POR2 0xe5
+#define PFUZE100_FUSE_POR3 0xe6
+#define PFUZE100_FUSE_POR_M (0x1 << 1)
+
+
+/* output some informational messages, return the number FUSE_POR=1 */
+/* i.e. 0: unprogrammed, 3: programmed, other: undefined prog. state */
+unsigned pmic_init(void);
/* programmes OTP fuses to values required on a Toradex Apalis iMX6 */
-void pf0100_prog(void);
+int pf0100_prog(void);
#endif /* PF0100_H_ */