Message ID | 20210925043735.686518-5-anup.patel@wdc.com |
---|---|
State | Accepted |
Headers | show |
Series | Timer based delay loop | expand |
在 2021-09-25星期六的 10:07 +0530,Anup Patel写道: > 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> > --- > 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 <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) > -- > 2.25.1 > >
On Sat, Sep 25, 2021 at 12:59 PM Xiang W <wxjstz@126.com> wrote: > > 在 2021-09-25星期六的 10:07 +0530,Anup Patel写道: > > 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> Applied this patch to the riscv/opensbi repo Regards, Anup > > --- > > 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 <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) > > -- > > 2.25.1 > > > > > >
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 <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)