diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2017-10-30 18:29:03 -0700 |
---|---|---|
committer | Vadim Bendebury <vbendeb@chromium.org> | 2017-11-28 18:35:28 +0000 |
commit | 3b62d6b40a12ed1a882266ea725471ee0edc437c (patch) | |
tree | d0ef75535328b30aadb770925de2205fa11eeae4 /src/drivers/spi | |
parent | eb72207fee10986c81d04c445c0d04cb7f130637 (diff) |
spi/tpm.c do not waste time on wake pulses unless necessary
The Cr50 secure chip implementation is guaranteed not to fall asleep
for 1 second after any SPI slave activity.
Let's not waste time on the wake up ping when it is not necessary.
BRANCH=cr50
BUG=b:68012381
TEST=using a protocol analyzer verified that the wake pulses are
generated only when the new coreboot stage or depthcharge start,
not on every SPI slave transaction.
Change-Id: Id8def1470ba3eab533075b9e7180f8a58e0b00b6
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://review.coreboot.org/22321
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/drivers/spi')
-rw-r--r-- | src/drivers/spi/tpm/tpm.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/src/drivers/spi/tpm/tpm.c b/src/drivers/spi/tpm/tpm.c index 356c0fe3f7..e1fec28a41 100644 --- a/src/drivers/spi/tpm/tpm.c +++ b/src/drivers/spi/tpm/tpm.c @@ -110,19 +110,43 @@ static int start_transaction(int read_write, size_t bytes, unsigned addr) int i; struct stopwatch sw; static int tpm_sync_needed CAR_GLOBAL; + static struct stopwatch wake_up_sw CAR_GLOBAL; struct spi_slave *spi_slave = car_get_var_ptr(&g_spi_slave); + /* + * First Cr50 access in each coreboot stage where TPM is used will be + * prepended by a wake up pulse on the CS line. + */ + int wakeup_needed = 1; /* Wait for tpm to finish previous transaction if needed */ - if (car_get_var(tpm_sync_needed)) + if (car_get_var(tpm_sync_needed)) { tpm_sync(); - else + /* + * During the first invocation of this function on each stage + * this if () clause code does not run (as tpm_sync_needed + * value is zero), during all following invocations the + * stopwatch below is guaranteed to be started. + */ + if (!stopwatch_expired(car_get_var_ptr(&wake_up_sw))) + wakeup_needed = 0; + } else { car_set_var(tpm_sync_needed, 1); + } - /* Try to wake cr50 if it is asleep. */ - spi_claim_bus(spi_slave); - udelay(1); - spi_release_bus(spi_slave); - udelay(100); + if (wakeup_needed) { + /* Just in case Cr50 is asleep. */ + spi_claim_bus(spi_slave); + udelay(1); + spi_release_bus(spi_slave); + udelay(100); + } + + /* + * The Cr50 on H1 does not go to sleep for 1 second after any + * SPI slave activity, let's be conservative and limit the + * window to 900 ms. + */ + stopwatch_init_msecs_expire(car_get_var_ptr(&wake_up_sw), 900); /* * The first byte of the frame header encodes the transaction type |