summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/board.c2
-rw-r--r--board/cr50/board.h3
-rw-r--r--common/tpm_registers.c48
-rw-r--r--core/cortex-m/ec.lds.S10
-rw-r--r--include/tpm_registers.h11
5 files changed, 63 insertions, 11 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index 31a8d2fef1..c967871c8e 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -395,7 +395,7 @@ void sys_rst_asserted(enum gpio_signal signal)
return;
/* Re-initialize the TPM software state */
- task_set_event(TASK_ID_TPM, TPM_EVENT_RESET, 0);
+ tpm_reset();
}
void assert_sys_rst(void)
diff --git a/board/cr50/board.h b/board/cr50/board.h
index cc7589e750..7d11abd60d 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -136,9 +136,6 @@ void assert_ec_rst(void);
void deassert_ec_rst(void);
int is_ec_rst_asserted(void);
-/* Event to request a reset/re-initialization of the TPM task */
-#define TPM_EVENT_RESET (TASK_EVENT_CUSTOM(1))
-
#endif /* !__ASSEMBLER__ */
/* USB interface indexes (use define rather than enum to expand them) */
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index 6fcd6eb839..5728dc6f92 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -570,7 +570,39 @@ static void call_extension_command(struct tpm_cmd_header *tpmh,
}
#endif
-static void tpm_reset(void)
+/* Event (to TPM task) to request reset, or (from TPM task) on completion. */
+#define TPM_EVENT_RESET (TASK_EVENT_CUSTOM(1))
+
+/* Calling task to notify when the TPM reset has completed. */
+static task_id_t waiting_for_reset
+/* This must not be affected by the reset, or we'll forget who to tell. */
+__attribute__((section(".data.noreinit"))) = TASK_ID_INVALID;
+
+int tpm_reset(void)
+{
+ uint32_t evt;
+
+ cprints(CC_TASK, "%s", __func__);
+
+ task_set_event(TASK_ID_TPM, TPM_EVENT_RESET, 0);
+
+ if (in_interrupt_context() ||
+ task_get_current() == TASK_ID_TPM)
+ return 0; /* Can't sleep. Clown'll eat me. */
+
+ /* Try to wait until the TPM is reset, but timeout eventually */
+ waiting_for_reset = task_get_current();
+ evt = task_wait_event_mask(TPM_EVENT_RESET, SECOND);
+
+ /* Timeout is bad */
+ if (evt & TASK_EVENT_TIMER)
+ return -1;
+
+ /* Otherwise, good */
+ return 1;
+}
+
+static void tpm_reset_now(void)
{
/* This is more related to TPM task activity than TPM transactions */
cprints(CC_TASK, "%s", __func__);
@@ -585,16 +617,20 @@ static void tpm_reset(void)
memset(__bss_libtpm2_start, __bss_libtpm2_end - __bss_libtpm2_start, 0);
/*
- * TPM reset currently only clears BSS for the TPM library. It does
- * not reset any initialized variables in data. So, make sure there
- * aren't any.
+ * NOTE: Any initialized variables in this file must be placed in a
+ * separate section (NOT .data). If they need resetting, do so here.
*/
- ASSERT(__data_libtpm2_start == __data_libtpm2_end);
/* Re-initialize our registers */
tpm_init();
sps_tpm_enable();
+
+ if (waiting_for_reset != TASK_ID_INVALID) {
+ /* Wake the waiting task, if any */
+ task_set_event(waiting_for_reset, TPM_EVENT_RESET, 0);
+ waiting_for_reset = TASK_ID_INVALID;
+ }
}
void tpm_task(void)
@@ -614,7 +650,7 @@ void tpm_task(void)
/* Wait for the next command event */
evt = task_wait_event(-1);
if (evt & TPM_EVENT_RESET) {
- tpm_reset();
+ tpm_reset_now();
continue;
}
tpmh = (struct tpm_cmd_header *)tpm_.regs.data_fifo;
diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S
index 5b756cec58..9e791f0380 100644
--- a/core/cortex-m/ec.lds.S
+++ b/core/cortex-m/ec.lds.S
@@ -300,7 +300,15 @@ SECTIONS
STRINGIFY(OUTDIR/common/tpm_registers.o*)(.data)
__data_libtpm2_end = .;
- *(.data)
+ /*
+ * TPM reset currently only clears BSS for the TPM library. It does
+ * not reset any initialized variables in data. So, make sure there
+ * aren't any.
+ */
+ ASSERT(__data_libtpm2_start == __data_libtpm2_end,
+ "libtpm2 .data section is nonzero");
+
+ *(.data*)
#ifdef CONFIG_MPU
/* It has to be aligned by 32 bytes to be a valid MPU region. */
. = ALIGN(32);
diff --git a/include/tpm_registers.h b/include/tpm_registers.h
index 35f6dff471..037fc73441 100644
--- a/include/tpm_registers.h
+++ b/include/tpm_registers.h
@@ -32,6 +32,17 @@ void sps_tpm_disable(void);
size_t tpm_get_burst_size(void);
/*
+ * Reset the TPM. This sends a request to the TPM task, so that the reset can
+ * happen when the TPM task finishes whatever it's doing at the moment.
+ *
+ * Returns 0 if the request was made, but we can't wait for it to complete
+ * because we're in interrupt context or something similar. Otherwise, it
+ * blocks and returns 1 after the TPM has been cleared, or returns -1 if the
+ * request timed out.
+ */
+int tpm_reset(void);
+
+/*
* This structure describes the header of all commands and responses sent and
* received over TPM FIFO.
*