diff mbox series

[U-Boot,v1,23/23] board: apalis_imx6: check for and report ecc errors in fuses

Message ID 20190201162920.32067-24-marcel@ziswiler.com
State Superseded
Delegated to: Stefano Babic
Headers show
Series apalis imx6 fixes, device tree enablement and driver model conversion | expand

Commit Message

Marcel Ziswiler Feb. 1, 2019, 4:29 p.m. UTC
From: Gerard Salvatella <gerard.salvatella@toradex.com>

The PMIC on Apalis iMX6 may have ECC errors in fuses that will prevent
correct settings. Up to one bit error per fuse bank may be reported and
corrected by the ECC logic. Two bit errors can only be reported.

Signed-off-by: Gerard Salvatella <gerard.salvatella@toradex.com>
Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>

---

 board/toradex/apalis_imx6/pf0100.c | 51 ++++++++++++++++++++++++++
 board/toradex/apalis_imx6/pf0100.h | 57 +++++++++++++++++++++++++++++-
 2 files changed, 107 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/board/toradex/apalis_imx6/pf0100.c b/board/toradex/apalis_imx6/pf0100.c
index 030124c0ae..8fc08d39b2 100644
--- a/board/toradex/apalis_imx6/pf0100.c
+++ b/board/toradex/apalis_imx6/pf0100.c
@@ -22,6 +22,8 @@ 
 /* define for PMIC register dump */
 /*#define DEBUG */
 
+#define WARNBAR "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
+
 /* use Apalis GPIO1 to switch on VPGM, ON: 1 */
 static __maybe_unused iomux_v3_cfg_t const pmic_prog_pads[] = {
 	MX6_PAD_NANDF_D4__GPIO2_IO04 | MUX_PAD_CTRL(NO_PAD_CTRL),
@@ -43,6 +45,55 @@  unsigned pmic_init(void)
 		       PFUZE100_I2C_ADDR);
 		return 0;
 	}
+
+	/* check for errors in PMIC fuses */
+	if (dm_i2c_read(dev, PFUZE100_INTSTAT3, &val, 1) < 0) {
+		puts("i2c pmic INTSTAT3 register read failed\n");
+		return 0;
+	}
+	if (val & PFUZE100_BIT_OTP_ECCI) {
+		puts("\n" WARNBAR);
+		puts("WARNING: ecc errors found in pmic fuse banks\n");
+		puts(WARNBAR);
+	}
+	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_SE1, &val, 1) < 0) {
+		puts("i2c pmic ECC_SE1 register read failed\n");
+		return 0;
+	}
+	if (val & PFUZE100_BITS_ECC_SE1) {
+		puts(WARNBAR);
+		puts("WARNING: ecc has made bit corrections in banks 1 to 5\n");
+		puts(WARNBAR);
+	}
+	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_SE2, &val, 1) < 0) {
+		puts("i2c pmic ECC_SE2 register read failed\n");
+		return 0;
+	}
+	if (val & PFUZE100_BITS_ECC_SE2) {
+		puts(WARNBAR);
+		puts("WARNING: ecc has made bit corrections in banks 6 to 10\n"
+		    );
+		puts(WARNBAR);
+	}
+	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_DE1, &val, 1) < 0) {
+		puts("i2c pmic ECC_DE register read failed\n");
+		return 0;
+	}
+	if (val & PFUZE100_BITS_ECC_DE1) {
+		puts(WARNBAR);
+		puts("ERROR: banks 1 to 5 have uncorrectable bits\n");
+		puts(WARNBAR);
+	}
+	if (dm_i2c_read(dev, PFUZE100_OTP_ECC_DE2, &val, 1) < 0) {
+		puts("i2c pmic ECC_DE register read failed\n");
+		return 0;
+	}
+	if (val & PFUZE100_BITS_ECC_DE2) {
+		puts(WARNBAR);
+		puts("ERROR: banks 6 to 10 have uncorrectable bits\n");
+		puts(WARNBAR);
+	}
+
 	/* get device ident */
 	if (dm_i2c_read(dev, PFUZE100_DEVICEID, &devid, 1) < 0) {
 		puts("i2c pmic devid read failed\n");
diff --git a/board/toradex/apalis_imx6/pf0100.h b/board/toradex/apalis_imx6/pf0100.h
index c0efb79bbc..e4eb2bd542 100644
--- a/board/toradex/apalis_imx6/pf0100.h
+++ b/board/toradex/apalis_imx6/pf0100.h
@@ -10,11 +10,23 @@ 
 #ifndef PF0100_H_
 #define PF0100_H_
 
+/* bit definitions */
+#define PFUZE100_BIT_0			(0x01 << 0)
+#define PFUZE100_BIT_1			(0x01 << 1)
+#define PFUZE100_BIT_2			(0x01 << 2)
+#define PFUZE100_BIT_3			(0x01 << 3)
+#define PFUZE100_BIT_4			(0x01 << 4)
+#define PFUZE100_BIT_5			(0x01 << 5)
+#define PFUZE100_BIT_6			(0x01 << 6)
+#define PFUZE100_BIT_7			(0x01 << 7)
+
 /* 7-bit I2C bus slave address */
 #define PFUZE100_I2C_ADDR		(0x08)
 /* Register Addresses */
 #define PFUZE100_DEVICEID		(0x0)
 #define PFUZE100_REVID			(0x3)
+#define PFUZE100_INTSTAT3		(0xe)
+#define PFUZE100_BIT_OTP_ECCI		PFUZE100_BIT_7
 #define PFUZE100_SW1AMODE		(0x23)
 #define PFUZE100_SW1ACON		36
 #define PFUZE100_SW1ACON_SPEED_VAL	(0x1<<6)	/*default */
@@ -39,12 +51,55 @@ 
 #define PFUZE100_PAGE_REGISTER_PAGE2	(0x02 & PFUZE100_PAGE_REGISTER_PAGE_M)
 
 /* extended page 1 */
+#define PFUZE100_OTP_ECC_SE1		0x8a
+#define PFUZE100_BIT_ECC1_SE		PFUZE100_BIT_0
+#define PFUZE100_BIT_ECC2_SE		PFUZE100_BIT_1
+#define PFUZE100_BIT_ECC3_SE		PFUZE100_BIT_2
+#define PFUZE100_BIT_ECC4_SE		PFUZE100_BIT_3
+#define PFUZE100_BIT_ECC5_SE		PFUZE100_BIT_4
+#define PFUZE100_BITS_ECC_SE1		((PFUZE100_BIT_ECC1_SE) | \
+					(PFUZE100_BIT_ECC2_SE) | \
+					(PFUZE100_BIT_ECC3_SE) | \
+					(PFUZE100_BIT_ECC4_SE) | \
+					(PFUZE100_BIT_ECC5_SE))
+#define PFUZE100_OTP_ECC_SE2		0x8b
+#define PFUZE100_BIT_ECC6_SE		PFUZE100_BIT_0
+#define PFUZE100_BIT_ECC7_SE		PFUZE100_BIT_1
+#define PFUZE100_BIT_ECC8_SE		PFUZE100_BIT_2
+#define PFUZE100_BIT_ECC9_SE		PFUZE100_BIT_3
+#define PFUZE100_BIT_ECC10_SE		PFUZE100_BIT_4
+#define PFUZE100_BITS_ECC_SE2		((PFUZE100_BIT_ECC6_SE) | \
+					(PFUZE100_BIT_ECC7_SE) | \
+					(PFUZE100_BIT_ECC8_SE) | \
+					(PFUZE100_BIT_ECC9_SE) | \
+					(PFUZE100_BIT_ECC10_SE))
+#define PFUZE100_OTP_ECC_DE1		0x8c
+#define PFUZE100_BIT_ECC1_DE		PFUZE100_BIT_0
+#define PFUZE100_BIT_ECC2_DE		PFUZE100_BIT_1
+#define PFUZE100_BIT_ECC3_DE		PFUZE100_BIT_2
+#define PFUZE100_BIT_ECC4_DE		PFUZE100_BIT_3
+#define PFUZE100_BIT_ECC5_DE		PFUZE100_BIT_4
+#define PFUZE100_BITS_ECC_DE1		((PFUZE100_BIT_ECC1_DE) | \
+					(PFUZE100_BIT_ECC2_DE) | \
+					(PFUZE100_BIT_ECC3_DE) | \
+					(PFUZE100_BIT_ECC4_DE) | \
+					(PFUZE100_BIT_ECC5_DE))
+#define PFUZE100_OTP_ECC_DE2		0x8d
+#define PFUZE100_BIT_ECC6_DE		PFUZE100_BIT_0
+#define PFUZE100_BIT_ECC7_DE		PFUZE100_BIT_1
+#define PFUZE100_BIT_ECC8_DE		PFUZE100_BIT_2
+#define PFUZE100_BIT_ECC9_DE		PFUZE100_BIT_3
+#define PFUZE100_BIT_ECC10_DE		PFUZE100_BIT_4
+#define PFUZE100_BITS_ECC_DE2		((PFUZE100_BIT_ECC6_DE) | \
+					(PFUZE100_BIT_ECC7_DE) | \
+					(PFUZE100_BIT_ECC8_DE) | \
+					(PFUZE100_BIT_ECC9_DE) | \
+					(PFUZE100_BIT_ECC10_DE))
 #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);