summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
authorFugang Duan <b38611@freescale.com>2014-08-11 15:14:50 +0800
committerYe Li <ye.li@nxp.com>2016-03-25 16:14:24 +0800
commitc5a44a2a0b2218221cb12645b10f0b34ecc6f79b (patch)
treea11fc6bb673bf81bb98517c206a15798d6033652 /arch/arm
parentdbe744de73c88f14e01f56a3258752ab5cd45b14 (diff)
downloadu-boot-imx-c5a44a2a0b2218221cb12645b10f0b34ecc6f79b.zip
u-boot-imx-c5a44a2a0b2218221cb12645b10f0b34ecc6f79b.tar.gz
u-boot-imx-c5a44a2a0b2218221cb12645b10f0b34ecc6f79b.tar.bz2
ENGR00328312 i2c: imx: Optimize the i2c device recovery solution
From i2c spec, if device pull down the SDA line that causes i2c bus dead, host can send out 9 clock to let device release SDA. But for some special device like pfuze100, it pull down SDA line and the solution cannot take effort. The patch just add NACK and STOP signal after 8 dummy clock, and pmic can release SDA line after the recovery. Test case catch 375 times of i2c hang, and all are recovered. Signed-off-by: Fugang Duan <B38611@freescale.com> (cherry picked from commit 53118db42d201d36ca9067b4bb0e2702399e100b) Signed-off-by: Peng Fan <Peng.Fan@freescale.com> (cherry picked from commit b8dcb812401026cb2189b24a4f6058830151c85a)
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/imx-common/i2c-mxv7.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/arch/arm/imx-common/i2c-mxv7.c b/arch/arm/imx-common/i2c-mxv7.c
index ff72b1a..d358d6c 100644
--- a/arch/arm/imx-common/i2c-mxv7.c
+++ b/arch/arm/imx-common/i2c-mxv7.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 Boundary Devices Inc.
+ * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -33,13 +34,36 @@ int force_idle_bus(void *priv)
printf("%s: sda=%d scl=%d sda.gp=0x%x scl.gp=0x%x\n", __func__,
sda, scl, p->sda.gp, p->scl.gp);
+ gpio_direction_output(p->scl.gp, 1);
+ udelay(1000);
/* Send high and low on the SCL line */
for (i = 0; i < 9; i++) {
- gpio_direction_output(p->scl.gp, 0);
+ gpio_direction_output(p->scl.gp, 1);
udelay(50);
- gpio_direction_input(p->scl.gp);
+ gpio_direction_output(p->scl.gp, 0);
udelay(50);
}
+
+ /* Simulate the NACK */
+ gpio_direction_output(p->sda.gp, 1);
+ udelay(50);
+ gpio_direction_output(p->scl.gp, 1);
+ udelay(50);
+ gpio_direction_output(p->scl.gp, 0);
+ udelay(50);
+
+ /* Simulate the STOP signal */
+ gpio_direction_output(p->sda.gp, 0);
+ udelay(50);
+ gpio_direction_output(p->scl.gp, 1);
+ udelay(50);
+ gpio_direction_output(p->sda.gp, 1);
+ udelay(50);
+
+ /* Get the bus status */
+ gpio_direction_input(p->sda.gp);
+ gpio_direction_input(p->scl.gp);
+
start_time = get_timer(0);
for (;;) {
sda = gpio_get_value(p->sda.gp);