diff mbox series

[v3,4/5] lib: sbi: Add generic timer delay loop function

Message ID 20210925043735.686518-5-anup.patel@wdc.com
State Accepted
Headers show
Series Timer based delay loop | expand

Commit Message

Anup Patel Sept. 25, 2021, 4:37 a.m. UTC
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>
---
 include/sbi/sbi_timer.h | 16 ++++++++++++++++
 lib/sbi/sbi_timer.c     | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

Comments

Xiang W Sept. 25, 2021, 7:28 a.m. UTC | #1
在 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
> 
>
Anup Patel Sept. 27, 2021, 3:58 a.m. UTC | #2
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 mbox series

Patch

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)