diff options
-rw-r--r-- | board/freescale/mx53_loco/mx53_loco.c | 103 | ||||
-rw-r--r-- | board/freescale/mx53_smd/mx53_smd.c | 103 |
2 files changed, 204 insertions, 2 deletions
diff --git a/board/freescale/mx53_loco/mx53_loco.c b/board/freescale/mx53_loco/mx53_loco.c index a96c417..963c11e 100644 --- a/board/freescale/mx53_loco/mx53_loco.c +++ b/board/freescale/mx53_loco/mx53_loco.c @@ -322,6 +322,107 @@ static void setup_i2c(unsigned int module_base) void setup_pmic_voltages(void) { } + +/* DA9053 I2C SDA stuck low issue: the I2C block in DA9053 may not correctly + * receive a Power On Reset and device is in unknown state during start-up. + * The only way to get the chip into known state before any communication + * with the Chip via I2C is to dummy clock the I2C and bring it in a state + * where I2C can communicate. Dialog suggested to provide 9 clock on SCL. + * Dialog don't know the exact reason for the fault and assume it is because + * some random noise or spurious behaviour. + * This has to been done in host platform specific I2C driver during + * start-up when the I2C is being configured at platform level to supply with + * dummy 9 clock on SCL. Dialog I2C driver has no control to provide dummy 9 + * clock on SCL. + */ +#define I2C1_SDA_GPIO5_26_BIT_MASK (1 << 26) +#define I2C1_SCL_GPIO5_27_BIT_MASK (1 << 27) +void i2c_failed_handle(void) +{ + unsigned int reg, i, retry = 10; + + do { + /* set I2C1_SDA as GPIO input */ + mxc_request_iomux(MX53_PIN_CSI0_D8, IOMUX_CONFIG_ALT1); + reg = readl(GPIO5_BASE_ADDR + 0x4); + reg &= ~I2C1_SDA_GPIO5_26_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x4); + + /* set I2C1_SCL as GPIO output */ + mxc_request_iomux(MX53_PIN_CSI0_D9, IOMUX_CONFIG_ALT1); + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + + reg = readl(GPIO5_BASE_ADDR + 0x4); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x4); + udelay(10000); + + for (i = 0; i < 10; i++) { + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + udelay(5000); + + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg &= ~I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + udelay(5000); + } + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + udelay(1000); + + reg = readl(GPIO5_BASE_ADDR + 0x8); + if (reg & I2C1_SDA_GPIO5_26_BIT_MASK) { + printf("***I2C1_SDA = hight***\n"); + return; + } else { + printf("***I2C1_SDA = low***\n"); + } + } while (retry--); +} + +int i2c_read_check(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret = 0; + + ret = i2c_read(chip, addr, alen, buf, len); + if (ret == 0) { + return 0; + } else { + i2c_failed_handle(); + setup_i2c(CONFIG_SYS_I2C_PORT); + ret = i2c_read(chip, addr, alen, buf, len); + if (ret != 0) { + printf("[I2C-DA9053]read i2c fail\n"); + return -1; + } + return 0; + } +} + +int i2c_write_check(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret = 0; + + ret = i2c_write(chip, addr, alen, buf, len); + if (ret == 0) { + return 0; + } else { + i2c_failed_handle(); + setup_i2c(CONFIG_SYS_I2C_PORT); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + ret = i2c_write(chip, addr, alen, buf, len); + if (ret != 0) { + printf("[I2C-DA9053]write i2c fail\n"); + return -1; + } + return 0; + } +} #endif #if defined(CONFIG_DWC_AHSATA) @@ -752,7 +853,7 @@ int board_late_init(void) /* increase VDDGP as 1.25V for 1GHZ */ value = 0x5e; do { - if (0 != i2c_write(0x48, 0x2e, 1, &value, 1)) { + if (0 != i2c_write_check(0x48, 0x2e, 1, &value, 1)) { printf("da9052_i2c_is_connected - i2c write failed.....\n"); } else { printf("da9052_i2c_is_connected - i2c write success....\n"); diff --git a/board/freescale/mx53_smd/mx53_smd.c b/board/freescale/mx53_smd/mx53_smd.c index aa8568b..af69a2d 100644 --- a/board/freescale/mx53_smd/mx53_smd.c +++ b/board/freescale/mx53_smd/mx53_smd.c @@ -400,6 +400,107 @@ static void setup_i2c(unsigned int module_base) } } +/* DA9053 I2C SDA stuck low issue: the I2C block in DA9053 may not correctly + * receive a Power On Reset and device is in unknown state during start-up. + * The only way to get the chip into known state before any communication + * with the Chip via I2C is to dummy clock the I2C and bring it in a state + * where I2C can communicate. Dialog suggested to provide 9 clock on SCL. + * Dialog don't know the exact reason for the fault and assume it is because + * some random noise or spurious behaviour. + * This has to been done in host platform specific I2C driver during + * start-up when the I2C is being configured at platform level to supply with + * dummy 9 clock on SCL. Dialog I2C driver has no control to provide dummy 9 + * clock on SCL. + */ +#define I2C1_SDA_GPIO5_26_BIT_MASK (1 << 26) +#define I2C1_SCL_GPIO5_27_BIT_MASK (1 << 27) +void i2c_failed_handle(void) +{ + unsigned int reg, i, retry = 10; + + do { + /* set I2C1_SDA as GPIO input */ + mxc_request_iomux(MX53_PIN_CSI0_D8, IOMUX_CONFIG_ALT1); + reg = readl(GPIO5_BASE_ADDR + 0x4); + reg &= ~I2C1_SDA_GPIO5_26_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x4); + + /* set I2C1_SCL as GPIO output */ + mxc_request_iomux(MX53_PIN_CSI0_D9, IOMUX_CONFIG_ALT1); + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + + reg = readl(GPIO5_BASE_ADDR + 0x4); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x4); + udelay(10000); + + for (i = 0; i < 10; i++) { + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + udelay(5000); + + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg &= ~I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + udelay(5000); + } + reg = readl(GPIO5_BASE_ADDR + 0x0); + reg |= I2C1_SCL_GPIO5_27_BIT_MASK; + writel(reg, GPIO5_BASE_ADDR + 0x0); + udelay(1000); + + reg = readl(GPIO5_BASE_ADDR + 0x8); + if (reg & I2C1_SDA_GPIO5_26_BIT_MASK) { + printf("***I2C1_SDA = hight***\n"); + return; + } else { + printf("***I2C1_SDA = low***\n"); + } + } while (retry--); +} + +int i2c_read_check(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret = 0; + + ret = i2c_read(chip, addr, alen, buf, len); + if (ret == 0) { + return 0; + } else { + i2c_failed_handle(); + setup_i2c(CONFIG_SYS_I2C_PORT); + ret = i2c_read(chip, addr, alen, buf, len); + if (ret != 0) { + printf("[I2C-DA9053]read i2c fail\n"); + return -1; + } + return 0; + } +} + +int i2c_write_check(uchar chip, uint addr, int alen, uchar *buf, int len) +{ + int ret = 0; + + ret = i2c_write(chip, addr, alen, buf, len); + if (ret == 0) { + return 0; + } else { + i2c_failed_handle(); + setup_i2c(CONFIG_SYS_I2C_PORT); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + ret = i2c_write(chip, addr, alen, buf, len); + if (ret != 0) { + printf("[I2C-DA9053]write i2c fail\n"); + return -1; + } + return 0; + } +} + /* restore VUSB 2V5 active after suspend */ #define BUCKPERI_RESTORE_SW_STEP (0x55) /* restore VUSB 2V5 power supply after suspend */ @@ -415,7 +516,7 @@ void setup_pmic_voltages(void) /* increase VDDGP as 1.25V for 1GHZ */ value = 0x5e; do { - if (0 != i2c_write(0x48, 0x2e, 1, &value, 1)) { + if (0 != i2c_write_check(0x48, 0x2e, 1, &value, 1)) { printf("da9052_i2c_is_connected - i2c write failed.....\n"); } else { printf("da9052_i2c_is_connected - i2c write success....\n"); |