board: apalis_imx6: check for and report ecc errors in fuses
authorGerard Salvatella <gerard.salvatella@toradex.com>
Fri, 8 Feb 2019 17:12:26 +0000 (18:12 +0100)
committerStefano Babic <sbabic@denx.de>
Sat, 13 Apr 2019 18:30:08 +0000 (20:30 +0200)
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
board/toradex/apalis_imx6/pf0100.h

index 8106abf89acb256d77bb4c13c896eb9b3a8c19d1..ebd6418fd472c2cc1ebefb2d90e0f3552225cb80 100644 (file)
@@ -21,6 +21,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),
@@ -42,6 +44,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");
index b854fe8c541d3d1adc0969274c490a8f26a79786..925762051104b828f689d477db809cc182ac8592 100644 (file)
 #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 */
 #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);