summaryrefslogtreecommitdiff
path: root/board/freescale/mx53_loco
diff options
context:
space:
mode:
authorWayne Zou <b36644@freescale.com>2011-09-06 13:43:00 +0800
committerWayne Zou <b36644@freescale.com>2011-09-06 14:20:30 +0800
commit3022105ecdeec0c6b10199bd1e1bc7e0ba9f0cee (patch)
treedaeb2f6ddf442b72d2681d40ecf8bb28f7eace6c /board/freescale/mx53_loco
parentaac855885f336cb9a7ed570247901c0704570871 (diff)
downloadu-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_loco')
-rw-r--r--board/freescale/mx53_loco/mx53_loco.c103
1 files changed, 102 insertions, 1 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");