From 1ca196841ac4db46d8d9c3c55004c3e9ee3c8844 Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Wed, 7 Sep 2016 10:52:12 -0700 Subject: drivers/i2c/tpm: Fix early TPM probe The early TPM probe was done directly in tis.c ignoring the lower layer that provides appropriate access to the chip. Move this into a tpm_vendor_probe() function so it can use iic_tpm_read() with all of the built-in delays and semantics instead of calling i2c_readb() directly from the wrong layer. This fixes early init failures that were seen with the cr50 i2c tpm on the reef mainboard. Change-Id: I9bb3b820d10f6e2ea24c57b90cf0edc813cdc7e0 Signed-off-by: Duncan Laurie Reviewed-on: https://review.coreboot.org/16527 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin Reviewed-by: Furquan Shaikh Reviewed-by: Paul Menzel --- src/drivers/i2c/tpm/tis.c | 35 ++--------------------------------- src/drivers/i2c/tpm/tpm.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/drivers/i2c/tpm/tpm.h | 2 ++ 3 files changed, 46 insertions(+), 33 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/i2c/tpm/tis.c b/src/drivers/i2c/tpm/tis.c index ce0de8953b..fea5145ad2 100644 --- a/src/drivers/i2c/tpm/tis.c +++ b/src/drivers/i2c/tpm/tis.c @@ -31,7 +31,6 @@ static struct tpm_chip g_chip CAR_GLOBAL; #define TPM_CMD_COUNT_BYTE 2 #define TPM_CMD_ORDINAL_BYTE 6 -#define TPM_VALID_STATUS (1 << 7) int tis_open(void) { @@ -69,38 +68,8 @@ int tis_close(void) int tis_init(void) { - int bus = CONFIG_DRIVER_TPM_I2C_BUS; - int chip = CONFIG_DRIVER_TPM_I2C_ADDR; - struct stopwatch sw; - uint8_t buf = 0; - int ret; - long sw_run_duration = 750; - - /* - * Probe TPM. Check if the TPM_ACCESS register's ValidSts bit is set(1) - * If the bit remains clear(0) then claim that init has failed. - */ - stopwatch_init_msecs_expire(&sw, sw_run_duration); - do { - ret = i2c_readb(bus, chip, 0, &buf); - if (!ret && (buf & TPM_VALID_STATUS)) { - sw_run_duration = stopwatch_duration_msecs(&sw); - break; - } - } while (!stopwatch_expired(&sw)); - - printk(BIOS_INFO, - "%s: ValidSts bit %s(%d) in TPM_ACCESS register after %ld ms\n", - __func__, (buf & TPM_VALID_STATUS) ? "set" : "clear", - (buf & TPM_VALID_STATUS) >> 7, sw_run_duration); - - /* - * Claim failure if the ValidSts (bit 7) is clear. - */ - if (!(buf & TPM_VALID_STATUS)) - return -1; - - return 0; + return tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS, + CONFIG_DRIVER_TPM_I2C_ADDR); } static ssize_t tpm_transmit(const uint8_t *buf, size_t bufsiz) diff --git a/src/drivers/i2c/tpm/tpm.c b/src/drivers/i2c/tpm/tpm.c index 5e3c0c1bc8..f0f5ca8d6c 100644 --- a/src/drivers/i2c/tpm/tpm.c +++ b/src/drivers/i2c/tpm/tpm.c @@ -46,6 +46,7 @@ #define SLEEP_DURATION 60 /* in usec */ #define SLEEP_DURATION_LONG 210 /* in usec */ #define SLEEP_DURATION_SAFE 750 /* in usec */ +#define SLEEP_DURATION_PROBE_MS 1000 /* in msec */ /* max. number of iterations after I2C NAK for 'long' commands * we need this especially for sending TPM_READY, since the cleanup after the @@ -695,6 +696,47 @@ out: /* Initialization of I2C TPM */ +int tpm_vendor_probe(unsigned bus, uint32_t addr) +{ + struct tpm_inf_dev *tpm_dev = car_get_var_ptr(&g_tpm_dev); + struct stopwatch sw; + uint8_t buf = 0; + int ret; + long sw_run_duration = SLEEP_DURATION_PROBE_MS; + + tpm_dev->chip_type = UNKNOWN; + tpm_dev->bus = bus; + tpm_dev->addr = addr; + tpm_dev->sleep_short = SLEEP_DURATION_SAFE; + tpm_dev->sleep_long = SLEEP_DURATION_SAFE * 2; + + /* + * Probe TPM. Check if the TPM_ACCESS register's ValidSts bit is set(1) + * If the bit remains clear(0) then claim that init has failed. + */ + stopwatch_init_msecs_expire(&sw, sw_run_duration); + do { + ret = iic_tpm_read(TPM_ACCESS(0), &buf, 1); + if (!ret && (buf & TPM_STS_VALID)) { + sw_run_duration = stopwatch_duration_msecs(&sw); + break; + } + } while (!stopwatch_expired(&sw)); + + printk(BIOS_INFO, + "%s: ValidSts bit %s(%d) in TPM_ACCESS register after %ld ms\n", + __func__, (buf & TPM_STS_VALID) ? "set" : "clear", + (buf & TPM_STS_VALID) >> 7, sw_run_duration); + + /* + * Claim failure if the ValidSts (bit 7) is clear. + */ + if (!(buf & TPM_STS_VALID)) + return -1; + + return 0; +} + int tpm_vendor_init(struct tpm_chip *chip, unsigned bus, uint32_t dev_addr) { struct tpm_inf_dev *tpm_dev = car_get_var_ptr(&g_tpm_dev); diff --git a/src/drivers/i2c/tpm/tpm.h b/src/drivers/i2c/tpm/tpm.h index 7dfd59481d..ddf12a9e98 100644 --- a/src/drivers/i2c/tpm/tpm.h +++ b/src/drivers/i2c/tpm/tpm.h @@ -121,6 +121,8 @@ struct tpm_cmd_t { /* ---------- Interface for TPM vendor ------------ */ +int tpm_vendor_probe(unsigned bus, uint32_t addr); + int tpm_vendor_init(struct tpm_chip *chip, unsigned bus, uint32_t dev_addr); void tpm_vendor_cleanup(struct tpm_chip *chip); -- cgit v1.2.3