From 9d0ab35ab4e2b9edf022237e2592d999dfe54704 Mon Sep 17 00:00:00 2001
From: Anup Patel <anup.patel@wdc.com>
Date: Wed, 15 Sep 2021 10:11:24 +0530
Subject: lib: sbi: Add generic timer delay loop function

We now have frequency of the timer device provided by the platform
support so we can emulate desired delay using a loop where the number
loop iterations are based on timer frequency.

This patch provides sbi_timer_delay_loop() for above purpose.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Xiang W <wxjstz@126.com>
---
 lib/sbi/sbi_timer.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

(limited to 'lib')

diff --git a/lib/sbi/sbi_timer.c b/lib/sbi/sbi_timer.c
index 2759501..acdba92 100644
--- a/lib/sbi/sbi_timer.c
+++ b/lib/sbi/sbi_timer.c
@@ -8,7 +8,9 @@
  */
 
 #include <sbi/riscv_asm.h>
+#include <sbi/riscv_barrier.h>
 #include <sbi/riscv_encoding.h>
+#include <sbi/sbi_console.h>
 #include <sbi/sbi_error.h>
 #include <sbi/sbi_hart.h>
 #include <sbi/sbi_platform.h>
@@ -47,6 +49,38 @@ static u64 get_platform_ticks(void)
 	return timer_dev->timer_value();
 }
 
+static void nop_delay_fn(void *opaque)
+{
+	cpu_relax();
+}
+
+void sbi_timer_delay_loop(ulong units, u64 unit_freq,
+			  void (*delay_fn)(void *), void *opaque)
+{
+	u64 start_val, delta;
+
+	/* Do nothing if we don't have timer device */
+	if (!timer_dev || !get_time_val) {
+		sbi_printf("%s: called without timer device\n", __func__);
+		return;
+	}
+
+	/* Save starting timer value */
+	start_val = get_time_val();
+
+	/* Compute desired timer value delta */
+	delta = ((u64)timer_dev->timer_freq * (u64)units);
+	delta = delta / unit_freq;
+
+	/* Use NOP delay function if delay function not available */
+	if (!delay_fn)
+		delay_fn = nop_delay_fn;
+
+	/* Busy loop until desired timer value delta reached */
+	while ((get_time_val() - start_val) < delta)
+		delay_fn(opaque);
+}
+
 u64 sbi_timer_value(void)
 {
 	if (get_time_val)
-- 
cgit v1.2.3