[coreboot-gerrit] New patch to review for coreboot: drivers/i2c/tpm: Fix early TPM probe

Duncan Laurie (dlaurie@chromium.org) gerrit at coreboot.org
Wed Sep 7 19:57:15 CEST 2016


Duncan Laurie (dlaurie at chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16527

-gerrit

commit 57f948d4cf6bdbdff8d4a7e280e3e6288a8b237a
Author: Duncan Laurie <dlaurie at chromium.org>
Date:   Wed Sep 7 10:52:12 2016 -0700

    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 <dlaurie at chromium.org>
---
 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(-)

diff --git a/src/drivers/i2c/tpm/tis.c b/src/drivers/i2c/tpm/tis.c
index ce0de89..fea5145 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 5e3c0c1..f0f5ca8 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 7dfd594..ddf12a9 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);



More information about the coreboot-gerrit mailing list