From 672ea89dba35644d5a6b056c5e6a6ffa37dfca11 Mon Sep 17 00:00:00 2001 From: Scott Date: Wed, 21 Sep 2016 14:34:01 -0700 Subject: Cr50: I2CS TPM: Prevent sleep when I2CS is active Similar to the TPM SPI interface, added code to disable sleep an I2CS interrupt is received. Enabling sleep follwoing a 1 second delay when the TPM fifo register has been read by the host. The I2CS TPM layer doesn't know when a command has finished, but the one second delay is more than enough delay since sleep will be disabled again when the next I2CS interrupt is received. BRANCH=none BUG=chrome-os-partner:40397 TEST=manual Tested without these changes first. Shortened sleep delay to 30 seconds, and disconnected suzyq. Waited 30 seconds then issued the command on the AP console: tpmc read 0x1007 0xa [ 59.796813] tpm tpm0: tpm_transmit: tpm_send: error -16 ERROR: write failure to TPM device: Device or resource busy In addition, using logic analyzer verifed that there was activity on SDA/SCL but no response from Cr50. With this CL in place, ran the test and got the following: tpmc read 0x1007 0xa 2 0 1 0 1 0 0 0 0 4f With the logic analyzer I was able to confirm that there was no activity from the host on the I2CS bus until the command was issued. Change-Id: If07573ae8f72b983bca57979d53c22660b91b95e Signed-off-by: Scott Reviewed-on: https://chromium-review.googlesource.com/387910 Commit-Ready: Scott Collyer Tested-by: Scott Collyer Reviewed-by: Bill Richardson Reviewed-by: Mary Ruthven --- common/i2cs_tpm.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'common/i2cs_tpm.c') diff --git a/common/i2cs_tpm.c b/common/i2cs_tpm.c index b9ab003b16..7700fd8373 100644 --- a/common/i2cs_tpm.c +++ b/common/i2cs_tpm.c @@ -9,6 +9,7 @@ #include "hooks.h" #include "i2cs.h" #include "registers.h" +#include "system.h" #include "tpm_registers.h" /* @@ -129,6 +130,14 @@ static void process_read_access(uint16_t reg_size, tpm_register_get(tpm_reg, data, reg_size); /* Transfer TPM fifo data to the I2CS HW fifo */ i2cs_post_read_fill_fifo(data, reg_size); + + /* + * Could be the end of a TPM trasaction. Set sleep to be reenabled in 1 + * second. If this is not the end of a TPM response, then sleep will be + * disabled again in the next I2CS interrupt. + */ + delay_sleep_by(1 * SECOND); + enable_sleep(SLEEP_MASK_I2C_SLAVE); } static void process_write_access(uint16_t reg_size, uint16_t tpm_reg, -- cgit v1.2.1