summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-10-30 18:29:03 -0700
committerVadim Bendebury <vbendeb@chromium.org>2017-11-28 18:35:28 +0000
commit3b62d6b40a12ed1a882266ea725471ee0edc437c (patch)
treed0ef75535328b30aadb770925de2205fa11eeae4 /src
parenteb72207fee10986c81d04c445c0d04cb7f130637 (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')
-rw-r--r--src/drivers/spi/tpm/tpm.c38
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