drivers/pc80/tpm: Use stopwatch for timeout-loops

There are manual timeout-loops which use a fixed value and udelay().
In all cases there is a debug printk() inside this loop which, when
enabled, takes way longer than the counted microsecond delay. This
leads to the result that e.g. a 1 second delay takes nearly an eternity
if the debug messages are enabled due to the longer function execution
time.

This patch uses the stopwatch scheme for the timeout-loops which still
makes sure that the timeout period is maintained while it takes longer
function calls like printk() into account. In order to keep the minimum
delay between two register accesses on the TPM keep the udelay(1)-call.

TEST=Enable TPM debug messages on a board where the TPM hits a timeout
by failure and make sure that the debug messages occur in the log
just in the timeout period. It still works as expected if the debug
messages are disabled.

Change-Id: I8fd261c9d60a9a60509c847dbc4983bc05f41d48
Signed-off-by: Werner Zeh <werner.zeh@siemens.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/58240
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
diff --git a/src/drivers/pc80/tpm/tis.c b/src/drivers/pc80/tpm/tis.c
index 2b29acf..c209e5a 100644
--- a/src/drivers/pc80/tpm/tis.c
+++ b/src/drivers/pc80/tpm/tis.c
@@ -22,6 +22,7 @@
 #include <security/tpm/tis.h>
 #include <device/pnp.h>
 #include <drivers/tpm/tpm_ppi.h>
+#include <timer.h>
 #include "chip.h"
 
 #define PREFIX "lpc_tpm: "
@@ -84,7 +85,7 @@
 #define TPM_DRIVER_ERR		(~0)
 
  /* 1 second is plenty for anything TPM does.*/
-#define MAX_DELAY_US	(1000 * 1000)
+#define MAX_DELAY_US	USECS_PER_SEC
 
 /*
  * Structures defined below allow creating descriptions of TPM vendor/device
@@ -238,7 +239,7 @@
 /*
  * tis_wait_sts()
  *
- * Wait for at least a second for a status to change its state to match the
+ * Wait for at most a second for a status to change its state to match the
  * expected state. Normally the transition happens within microseconds.
  *
  * @locality - locality
@@ -249,14 +250,15 @@
  */
 static int tis_wait_sts(int locality, u8 mask, u8 expected)
 {
-	u32 time_us = MAX_DELAY_US;
-	while (time_us > 0) {
+	struct stopwatch sw;
+
+	stopwatch_init_usecs_expire(&sw, MAX_DELAY_US);
+	do {
 		u8 value = tpm_read_status(locality);
 		if ((value & mask) == expected)
 			return 0;
-		udelay(1); /* 1 us */
-		time_us--;
-	}
+		udelay(1);
+	} while (!stopwatch_expired(&sw));
 	return TPM_TIMEOUT_ERR;
 }
 
@@ -291,7 +293,7 @@
 /*
  * tis_wait_access()
  *
- * Wait for at least a second for a access to change its state to match the
+ * Wait for at most a second for a access to change its state to match the
  * expected state. Normally the transition happens within microseconds.
  *
  * @locality - locality
@@ -302,14 +304,15 @@
  */
 static int tis_wait_access(int locality, u8 mask, u8 expected)
 {
-	u32 time_us = MAX_DELAY_US;
-	while (time_us > 0) {
+	struct stopwatch sw;
+
+	stopwatch_init_usecs_expire(&sw, MAX_DELAY_US);
+	do {
 		u8 value = tpm_read_access(locality);
 		if ((value & mask) == expected)
 			return 0;
-		udelay(1); /* 1 us */
-		time_us--;
-	}
+		udelay(1);
+	} while (!stopwatch_expired(&sw));
 	return TPM_TIMEOUT_ERR;
 }
 
@@ -440,7 +443,6 @@
 {
 	u32 offset = 0;
 	u16 burst = 0;
-	u32 max_cycles = 0;
 	u8 locality = 0;
 
 	if (tis_wait_ready(locality)) {
@@ -452,10 +454,12 @@
 
 	while (1) {
 		unsigned int count;
+		struct stopwatch sw;
 
 		/* Wait till the device is ready to accept more data. */
+		stopwatch_init_usecs_expire(&sw, MAX_DELAY_US);
 		while (!burst) {
-			if (max_cycles++ == MAX_DELAY_US) {
+			if (stopwatch_expired(&sw)) {
 				printf("%s:%d failed to feed %d bytes of %d\n",
 				       __FILE__, __LINE__, len - offset, len);
 				return TPM_DRIVER_ERR;
@@ -464,8 +468,6 @@
 			burst = tpm_read_burst_count(locality);
 		}
 
-		max_cycles = 0;
-
 		/*
 		 * Calculate number of bytes the TPM is ready to accept in one
 		 * shot.