summaryrefslogtreecommitdiff
path: root/src/include/timer.h
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2018-11-02 14:48:24 -0700
committerJulius Werner <jwerner@chromium.org>2018-11-07 06:17:37 +0000
commit5132570845443767539fc00b502f6eafbfa37ba2 (patch)
tree5955e1e6a9a69df23e81b70c264c30a44d1e86dc /src/include/timer.h
parent55a972236ee93d36bd3df4e8e5680ba447242bd7 (diff)
timer: Add wait_us/wait_ms helper macros to wait for conditions
A very common pattern in drivers is that we need to wait for a condition to become true (e.g. for a lock bit in a PLL status register to become set), but we still want to have a maximum timeout before we treat it as an error. coreboot uses the stopwatch API for this, but it's still a little verbose for the most simple cases. This patch introduces two new helper macros that wrap this common application of the stopwatch API in a single line: wait_ms(XXX, YYY) waits for up to XXX milliseconds to see if the C condition 'if (YYY)' becomes true. The return value is 0 on failure (i.e. timeout expires without the condition becoming true) and the amount of elapsed time on success, so it can be used both in a boolean context and to log the amount of time waited. Replace the custom version used in an MTK ADC driver with this new generic version. Change-Id: I6de38ee00673c46332ae92b8a11099485de5327a Signed-off-by: Tristan Shieh <tristan.shieh@mediatek.com> Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://review.coreboot.org/29315 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/include/timer.h')
-rw-r--r--src/include/timer.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/include/timer.h b/src/include/timer.h
index 49eae5ec40..d3afb19646 100644
--- a/src/include/timer.h
+++ b/src/include/timer.h
@@ -15,6 +15,8 @@
#ifndef TIMER_H
#define TIMER_H
+#include <types.h>
+
#define NSECS_PER_SEC 1000000000
#define USECS_PER_SEC 1000000
#define MSECS_PER_SEC 1000
@@ -195,4 +197,36 @@ static inline long stopwatch_duration_msecs(struct stopwatch *sw)
return stopwatch_duration_usecs(sw) / USECS_PER_MSEC;
}
+/*
+ * Helper macro to wait until a condition becomes true or a timeout elapses.
+ *
+ * condition: a C expression to wait for
+ * timeout: timeout, in microseconds
+ *
+ * Returns:
+ * 0 if the condition still evaluates to false after the timeout elapsed,
+ * >0 if the condition evaluates to true. The return value is the amount of
+ * microseconds waited (at least 1).
+ */
+#define wait_us(timeout_us, condition) \
+({ \
+ long __ret = 0; \
+ struct stopwatch __sw; \
+ stopwatch_init_usecs_expire(&__sw, timeout_us); \
+ do { \
+ if (condition) { \
+ stopwatch_tick(&__sw); \
+ __ret = stopwatch_duration_usecs(&__sw); \
+ if (!__ret) /* make sure it evaluates to true */\
+ __ret = 1; \
+ break; \
+ } \
+ } while (!stopwatch_expired(&__sw)); \
+ __ret; \
+})
+
+#define wait_ms(timeout_ms, condition) \
+ DIV_ROUND_UP(wait_us((timeout_ms) * USECS_PER_MSEC, condition), \
+ USECS_PER_MSEC)
+
#endif /* TIMER_H */