diff options
author | Wayne Zou <b36644@freescale.com> | 2011-09-06 13:43:00 +0800 |
---|---|---|
committer | Wayne Zou <b36644@freescale.com> | 2011-09-06 14:20:30 +0800 |
commit | 3022105ecdeec0c6b10199bd1e1bc7e0ba9f0cee (patch) | |
tree | daeb2f6ddf442b72d2681d40ecf8bb28f7eace6c /board/freescale/mx53_smd | |
parent | aac855885f336cb9a7ed570247901c0704570871 (diff) | |
download | u-boot-imx-3022105ecdeec0c6b10199bd1e1bc7e0ba9f0cee.zip u-boot-imx-3022105ecdeec0c6b10199bd1e1bc7e0ba9f0cee.tar.gz u-boot-imx-3022105ecdeec0c6b10199bd1e1bc7e0ba9f0cee.tar.bz2 |
ENGR00156098 mx53_smd/mx53_loco: DA9053 I2C SDA stuck low issue on bootup
For 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.
Signed-off-by: Wayne Zou <b36644@freescale.com>
Diffstat (limited to 'board/freescale/mx53_smd')
-rw-r--r-- | board/freescale/mx53_smd/mx53_smd.c | 103 |
1 files changed, 102 insertions, 1 deletions
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"); |