From 19e3d335bddb480a53e30242e72195dd5ae8e056 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Fri, 3 Mar 2017 18:24:02 +0800 Subject: drivers/spi/tpm: using tpm irq to sync tpm transaction BUG=b:35647967 TEST=boot from bob Change-Id: Ib64107b17fb6e93dbe626ce92f3bc9da8b84784e Signed-off-by: Jeffy Chen Reviewed-on: https://chromium-review.googlesource.com/452284 Commit-Ready: Caesar Wang Tested-by: Caesar Wang Reviewed-by: Julius Werner Reviewed-on: https://review.coreboot.org/19113 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/drivers/spi/tpm/tpm.c | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'src/drivers/spi/tpm') diff --git a/src/drivers/spi/tpm/tpm.c b/src/drivers/spi/tpm/tpm.c index 29b85c4716a2..cd1fbdf73bee 100644 --- a/src/drivers/spi/tpm/tpm.c +++ b/src/drivers/spi/tpm/tpm.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "tpm.h" @@ -102,6 +103,39 @@ void tpm2_get_info(struct tpm2_info *info) *info = tpm_info; } +__attribute__((weak)) int tis_plat_irq_status(void) +{ + static int warning_displayed; + + if (!warning_displayed) { + printk(BIOS_WARNING, "WARNING: tis_plat_irq_status() not implemented, wasting 10ms to wait on Cr50!\n"); + warning_displayed = 1; + } + mdelay(10); + + return 1; +} + +/* + * TPM may trigger a irq after finish processing previous transfer. + * Waiting for this irq to sync tpm status. + * + * Returns 1 on success, 0 on failure (timeout). + */ +static int tpm_sync(void) +{ + struct stopwatch sw; + + stopwatch_init_usecs_expire(&sw, 10 * 1000); + while (!tis_plat_irq_status()) { + if (stopwatch_expired(&sw)) { + printk(BIOS_ERR, "Timeout wait for tpm irq!\n"); + return 0; + } + } + return 1; +} + /* * Each TPM2 SPI transaction starts the same: CS is asserted, the 4 byte * header is sent to the TPM, the master waits til TPM is ready to continue. @@ -114,12 +148,13 @@ static int start_transaction(int read_write, size_t bytes, unsigned addr) uint8_t byte; int i; struct stopwatch sw; + static int tpm_sync_needed; - /* - * Give it 10 ms. TODO(vbendeb): remove this once cr50 SPS TPM driver - * performance is fixed. - */ - mdelay(10); + /* Wait for tpm to finish previous transaction if needed */ + if (tpm_sync_needed) + tpm_sync(); + else + tpm_sync_needed = 1; /* Try to wake cr50 if it is asleep. */ tpm_if.cs_assert(&tpm_if.slave); -- cgit v1.2.3