From 9d0ab35ab4e2b9edf022237e2592d999dfe54704 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Wed, 15 Sep 2021 10:11:24 +0530 Subject: [PATCH] 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 Reviewed-by: Bin Meng Reviewed-by: Xiang W --- include/sbi/sbi_timer.h | 16 ++++++++++++++++ lib/sbi/sbi_timer.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/sbi/sbi_timer.h b/include/sbi/sbi_timer.h index 211e83d..63ef1af 100644 --- a/include/sbi/sbi_timer.h +++ b/include/sbi/sbi_timer.h @@ -32,6 +32,22 @@ struct sbi_timer_device { struct sbi_scratch; +/** Generic delay loop of desired granularity */ +void sbi_timer_delay_loop(ulong units, u64 unit_freq, + void (*delay_fn)(void *), void *opaque); + +/** Provide delay in terms of milliseconds */ +static inline void sbi_timer_mdelay(ulong msecs) +{ + sbi_timer_delay_loop(msecs, 1000, NULL, NULL); +} + +/** Provide delay in terms of microseconds */ +static inline void sbi_timer_udelay(ulong usecs) +{ + sbi_timer_delay_loop(usecs, 1000000, NULL, NULL); +} + /** Get timer value for current HART */ u64 sbi_timer_value(void); 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 +#include #include +#include #include #include #include @@ -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) -- 2.7.4