[coreboot-gerrit] Patch set updated for coreboot: 8a339f4 tegra: i2c: Add a timeout to I2C bit clear recovery mechanism

Marc Jones (marc.jones@se-eng.com) gerrit at coreboot.org
Sun Dec 28 20:26:33 CET 2014


Marc Jones (marc.jones at se-eng.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/7948

-gerrit

commit 8a339f41de910fa85005fc959be9d6052a5888c0
Author: Julius Werner <jwerner at chromium.org>
Date:   Fri May 16 11:27:46 2014 -0700

    tegra: i2c: Add a timeout to I2C bit clear recovery mechanism
    
    Our tests with the I2C bit clear mechanism (recovering from "lost
    arbitration" errors) show that the bit clear hardware does not work
    correctly in some situations. When a wedged slave device tries to send
    more than one 0-to-1-to-0 transition to the host (e.g. leftover bits
    from an aborted read), the controller never transitions the BC_ENABLE
    bit back to zero.
    
    This patch adds a long timeout to the bit clear code that waits for
    register transitions as a safeguard. This way, We will still eventually
    exit the function (probably followed by a reboot). Our tests show that
    this will recover from all conditions after at most a few reboots.
    
    BRANCH=nyan
    BUG=chrome-os-partner:28323
    TEST=Ran wedge_ack and wedge_read tests with software_i2c patch, system
    recovered as expected in all cases.
    
    Original-Change-Id: I6c37119130e1240e1ef3a5944582abbcd2e39ff0
    Original-Signed-off-by: Julius Werner <jwerner at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/200265
    Original-Reviewed-by: Tom Warren <twarren at nvidia.com>
    Original-Reviewed-by: Gabe Black <gabeblack at chromium.org>
    (cherry picked from commit 4c8d0af25cf107a38c856b38067b8f2f74384f22)
    Signed-off-by: Marc Jones <marc.jones at se-eng.com>
    
    Change-Id: I600d5c9a8e68719cf8795c083c5fac63f626f5bf
---
 src/soc/nvidia/tegra/i2c.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/soc/nvidia/tegra/i2c.c b/src/soc/nvidia/tegra/i2c.c
index 555d031..26c2559 100644
--- a/src/soc/nvidia/tegra/i2c.c
+++ b/src/soc/nvidia/tegra/i2c.c
@@ -19,6 +19,7 @@
 
 #include <arch/io.h>
 #include <console/console.h>
+#include <delay.h>
 #include <device/i2c.h>
 #include <stdlib.h>
 #include <string.h>
@@ -30,6 +31,7 @@ static void do_bus_clear(int bus)
 	struct tegra_i2c_bus_info *info = &tegra_i2c_info[bus];
 	struct tegra_i2c_regs * const regs = info->base;
 	uint32_t bc;
+	int i, timeout_ms = 10;
 
 	// BUS CLEAR regs (from TRM):
 	// 1. Reset the I2C controller (already done)
@@ -41,16 +43,20 @@ static void do_bus_clear(int bus)
 	write32(bc, &regs->bus_clear_config);
 	// 4.1 Set MSTR_CONFIG_LOAD and wait for clear
 	write32(I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE, &regs->config_load);
-	do {
+	for (i = 0; i < timeout_ms * 10 && (read32(&regs->config_load) &
+			I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE); i++) {
 		printk(BIOS_DEBUG, "%s: wait for MSTR_CONFIG_LOAD to clear\n",
 			__func__);
-	} while (read32(&regs->config_load) & I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD_ENABLE);
+		udelay(100);
+	}
 	// 5. Set ENABLE to start the bus clear op
 	write32(bc | I2C_BUS_CLEAR_CONFIG_BC_ENABLE, &regs->bus_clear_config);
-	do {
+	for (i = 0; i < timeout_ms * 10 && (read32(&regs->bus_clear_config) &
+			I2C_BUS_CLEAR_CONFIG_BC_ENABLE); i++) {
 		printk(BIOS_DEBUG, "%s: wait for bus clear completion\n",
 			__func__);
-	} while (read32(&regs->bus_clear_config) & I2C_BUS_CLEAR_CONFIG_BC_ENABLE);
+		udelay(100);
+	}
 }
 
 static int tegra_i2c_send_recv(int bus, int read,



More information about the coreboot-gerrit mailing list