summaryrefslogtreecommitdiff
path: root/common/i2cs_tpm.c
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-06-29 17:59:44 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-08-17 20:41:57 -0700
commit430d55879dc0ce9567b4ee2eefed200e604091ee (patch)
tree5b87eb9e7c63db7c8fbe51d712cabe5441dc739c /common/i2cs_tpm.c
parenta0c2fa80cd5e3c8dec89189d5c40075d6d210259 (diff)
downloadchrome-ec-430d55879dc0ce9567b4ee2eefed200e604091ee.tar.gz
g: add 'recover hosed slave' i2cs capability
A common failure condition on the i2c bus is when the master unexpectedly stops clocking the bus while the slave is driving the SDA line low. In this case the master is not able to issue Stop or Start sequences, which makes the bus unusable. Good slave controllers are able to detect this condition and recover from it by removing the pull down from the SDA line. This patch adds this capability to the g chip i2c slave controller. A new timer function is created which samples the SDA line twice a second. If it detects that SDA is low in two consecutive invocations and the number of i2cs read interrupts has not advanced, it decides that the "hosed slave" condition is happening and reinitializes the i2c driver, which removes the hold from the SDA line. Even though the state of the SDA line is supposed to be accessible through the I2CS_READVAL register, it in fact is not, reads always return zero in the SDA bit. To work around this a GPIO (port 0, bit 14) is being allocated to allow to monitor the state of the line, it is multiplexed to the same pin the SDA line uses. When the AP is in low power modes the SDA line is held low, this state should not trigger i2c reinitializations. CQ-DEPEND=CL:616300 BRANCH=none BUG=b:35648537 TEST=connected H1 on the test board to an I2c master capable of stopping clocking mid byte. Observed that the existing code would just sit in the "hosed" state indefinitely. The code with the fix recovers from the condition (drives the SDA line high) 500ms to 1s after the failure condition is created. Change-Id: Iafc7433bbae9e49975a72ef032a923274f8aab3b Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/614391 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
Diffstat (limited to 'common/i2cs_tpm.c')
-rw-r--r--common/i2cs_tpm.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/common/i2cs_tpm.c b/common/i2cs_tpm.c
index e649be1675..42089681dd 100644
--- a/common/i2cs_tpm.c
+++ b/common/i2cs_tpm.c
@@ -229,14 +229,22 @@ DECLARE_HOOK(HOOK_INIT, i2cs_if_register, HOOK_PRIO_LAST);
static int command_i2cs(int argc, char **argv)
{
+ static uint16_t base_read_recovery_count;
+ struct i2cs_status status;
+
+ i2cs_get_status(&status);
+
ccprintf("rd fifo adjust cnt = %d\n", i2cs_fifo_adjust_count);
ccprintf("wr mismatch cnt = %d\n", i2cs_write_error_count);
+ ccprintf("read recovered cnt = %d\n", status.read_recovery_count
+ - base_read_recovery_count);
if (argc < 2)
return EC_SUCCESS;
if (!strcasecmp(argv[1], "reset")) {
i2cs_fifo_adjust_count = 0;
i2cs_write_error_count = 0;
+ base_read_recovery_count = status.read_recovery_count;
ccprintf("i2cs error counts reset\n");
} else
return EC_ERROR_PARAM1;