forked from Mirrors/opensbi
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>
This commit is contained in:
@@ -32,6 +32,22 @@ struct sbi_timer_device {
|
|||||||
|
|
||||||
struct sbi_scratch;
|
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 */
|
/** Get timer value for current HART */
|
||||||
u64 sbi_timer_value(void);
|
u64 sbi_timer_value(void);
|
||||||
|
|
||||||
|
@@ -8,7 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sbi/riscv_asm.h>
|
#include <sbi/riscv_asm.h>
|
||||||
|
#include <sbi/riscv_barrier.h>
|
||||||
#include <sbi/riscv_encoding.h>
|
#include <sbi/riscv_encoding.h>
|
||||||
|
#include <sbi/sbi_console.h>
|
||||||
#include <sbi/sbi_error.h>
|
#include <sbi/sbi_error.h>
|
||||||
#include <sbi/sbi_hart.h>
|
#include <sbi/sbi_hart.h>
|
||||||
#include <sbi/sbi_platform.h>
|
#include <sbi/sbi_platform.h>
|
||||||
@@ -47,6 +49,38 @@ static u64 get_platform_ticks(void)
|
|||||||
return timer_dev->timer_value();
|
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)
|
u64 sbi_timer_value(void)
|
||||||
{
|
{
|
||||||
if (get_time_val)
|
if (get_time_val)
|
||||||
|
Reference in New Issue
Block a user