From 51c4d9fbfd9611978627ce6111b1083379a4b829 Mon Sep 17 00:00:00 2001
From: Rob Barnes <robbarnes@google.com>
Date: Wed, 24 Mar 2021 12:25:26 -0600
Subject: chromeec: Fix google_chromeec_status_check timeout

Rewrite google_chromeec_status_check to use stopwatch instead of a
delay in a while loop. In practice the while loop ends up taking
much longer than one second to timeout. Using stopwatch library will
accurately timeout after one second.

BUG=b:183524609
TEST=Build and run on guybrush
BRANCH=None

Change-Id: I363ff7453bcf81581884f92797629a6f96d42580
Signed-off-by: Rob Barnes <robbarnes@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/51775
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
---
 src/ec/google/chromeec/ec_lpc.c | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

(limited to 'src')

diff --git a/src/ec/google/chromeec/ec_lpc.c b/src/ec/google/chromeec/ec_lpc.c
index b9c972834b..3b2a7465a3 100644
--- a/src/ec/google/chromeec/ec_lpc.c
+++ b/src/ec/google/chromeec/ec_lpc.c
@@ -7,6 +7,7 @@
 #include <device/pnp.h>
 #include <ec/google/common/mec.h>
 #include <stdint.h>
+#include <timer.h>
 
 #include "chip.h"
 #include "ec.h"
@@ -92,23 +93,19 @@ static inline u8 write_byte(u8 val, u16 port)
 
 static int google_chromeec_status_check(u16 port, u8 mask, u8 cond)
 {
-	u8 ec_status = read_byte(port);
-	u32 time_count = 0;
-
-	/*
-	 * One second is more than plenty for any EC operation to complete
-	 * (and the bus accessing/code execution) overhead will make the
-	 * timeout even longer.
-	 */
-#define MAX_EC_TIMEOUT_US 1000000
-
-	while ((ec_status & mask) != cond) {
-		udelay(1);
-		if (time_count++ == MAX_EC_TIMEOUT_US)
-			return -1;
-		ec_status = read_byte(port);
-	}
-	return 0;
+	struct stopwatch timeout_sw;
+	/* One second is more than plenty for any EC operation to complete */
+	const uint64_t ec_status_timeout_us = 1 * USECS_PER_SEC;
+	/* Wait 1 usec between read attempts  */
+	const uint64_t ec_status_read_period_us = 1;
+
+	stopwatch_init_usecs_expire(&timeout_sw, ec_status_timeout_us);
+	do {
+		if ((read_byte(port) & mask) == cond)
+			return 0;
+		udelay(ec_status_read_period_us);
+	} while (!stopwatch_expired(&timeout_sw));
+	return -1;
 }
 
 static int google_chromeec_wait_ready(u16 port)
-- 
cgit v1.2.3