Duncan Laurie (dlaurie@chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16395
-gerrit
commit ec81e0c553374f5a4f3d531bfe13c93bb6de3db1 Author: Duncan Laurie dlaurie@chromium.org Date: Wed Aug 31 14:48:12 2016 -0700
drivers/i2c/tpm: Allow sleep durations to be set by the chip
Allow the sleep durations used by the driver to be set by the specific chip so they can be tuned appropriately.
Since we need to read the chip id to know the values use very conservative defaults for the first command and then set it to the current values by default.
Change-Id: Ic64159328b18a1471eb06fa8b52b589eec1e1ca2 Signed-off-by: Duncan Laurie dlaurie@chromium.org --- src/drivers/i2c/tpm/tpm.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-)
diff --git a/src/drivers/i2c/tpm/tpm.c b/src/drivers/i2c/tpm/tpm.c index 426bc7c..c447001 100644 --- a/src/drivers/i2c/tpm/tpm.c +++ b/src/drivers/i2c/tpm/tpm.c @@ -45,6 +45,8 @@ #define MAX_COUNT 3
#define SLEEP_DURATION 60 /* in usec */ +#define SLEEP_DURATION_LONG 210 /* in usec */ +#define SLEEP_DURATION_SAFE 750 /* in usec */
/* max. number of iterations after I2C NAK for 'long' commands * we need this especially for sending TPM_READY, since the cleanup after the @@ -53,8 +55,6 @@ */ #define MAX_COUNT_LONG 50
-#define SLEEP_DURATION_LONG 210 /* in usec */ - /* expected value for DIDVID register */ #define TPM_TIS_I2C_DID_VID_9635 0x000b15d1L #define TPM_TIS_I2C_DID_VID_9645 0x001a15d1L @@ -75,6 +75,8 @@ static const char * const chip_name[] = { struct tpm_inf_dev { int bus; unsigned int addr; + unsigned int sleep_short; /* Short sleep duration in usec */ + unsigned int sleep_long; /* Long sleep duration in usec */ uint8_t buf[TPM_BUFSIZE + sizeof(uint8_t)]; // max. buffer size + addr enum i2c_chip_type chip_type; }; @@ -112,7 +114,7 @@ static int iic_tpm_read(uint8_t addr, uint8_t *buffer, size_t len) if (rc == 0) break; /* success, break to skip sleep */
- udelay(SLEEP_DURATION); + udelay(tpm_dev->sleep_short); }
if (rc) @@ -123,7 +125,7 @@ static int iic_tpm_read(uint8_t addr, uint8_t *buffer, size_t len) * retrieving the data */ for (count = 0; count < MAX_COUNT; count++) { - udelay(SLEEP_DURATION); + udelay(tpm_dev->sleep_short); rc = i2c_read_raw(tpm_dev->bus, tpm_dev->addr, buffer, len); if (rc == 0) @@ -146,12 +148,12 @@ static int iic_tpm_read(uint8_t addr, uint8_t *buffer, size_t len) i2c_transfer(tpm_dev->bus, &dseg, 1); if (rc == 0) break; /* break here to skip sleep */ - udelay(SLEEP_DURATION); + udelay(tpm_dev->sleep_short); } }
/* take care of 'guard time' */ - udelay(SLEEP_DURATION); + udelay(tpm_dev->sleep_short); if (rc) return -1;
@@ -187,7 +189,7 @@ static int iic_tpm_write_generic(uint8_t addr, uint8_t *buffer, size_t len, }
/* take care of 'guard time' */ - udelay(SLEEP_DURATION); + udelay(tpm_dev->sleep_short); if (rc) return -1;
@@ -212,7 +214,8 @@ static int iic_tpm_write_generic(uint8_t addr, uint8_t *buffer, size_t len, */ static int iic_tpm_write(uint8_t addr, uint8_t *buffer, size_t len) { - return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION, + struct tpm_inf_dev *tpm_dev = car_get_var_ptr(&g_tpm_dev); + return iic_tpm_write_generic(addr, buffer, len, tpm_dev->sleep_short, MAX_COUNT); }
@@ -222,7 +225,8 @@ static int iic_tpm_write(uint8_t addr, uint8_t *buffer, size_t len) * */ static int iic_tpm_write_long(uint8_t addr, uint8_t *buffer, size_t len) { - return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG, + struct tpm_inf_dev *tpm_dev = car_get_var_ptr(&g_tpm_dev); + return iic_tpm_write_generic(addr, buffer, len, tpm_dev->sleep_long, MAX_COUNT_LONG); }
@@ -495,6 +499,10 @@ int tpm_vendor_init(struct tpm_chip *chip, unsigned bus, uint32_t dev_addr) tpm_dev->addr = dev_addr; tpm_dev->bus = bus;
+ /* Use conservative values to read chip id */ + tpm_dev->sleep_short = SLEEP_DURATION_SAFE; + tpm_dev->sleep_long = SLEEP_DURATION_SAFE * 2; + memset(&chip->vendor, 0, sizeof(struct tpm_vendor_specific)); chip->is_open = 1;
@@ -525,6 +533,9 @@ int tpm_vendor_init(struct tpm_chip *chip, unsigned bus, uint32_t dev_addr) goto out_release; }
+ tpm_dev->sleep_short = SLEEP_DURATION; + tpm_dev->sleep_long = SLEEP_DURATION_LONG; + printk(BIOS_DEBUG, "1.2 TPM (chip type %s device-id 0x%X)\n", chip_name[tpm_dev->chip_type], vendor >> 16);