diff mbox series

[v3,1/1] riscv: Add timer_get_us() for tracing

Message ID 20201111101435.31455-2-pragnesh.patel@sifive.com
State Superseded
Delegated to: Andes
Headers show
Series RISC-V tracing support | expand

Commit Message

Pragnesh Patel Nov. 11, 2020, 10:14 a.m. UTC
Add timer_get_us() which is useful for tracing.
For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide
a timer ticks and For M-mode U-Boot, mtime register will
provide the same.

Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
---

Changes in v3:
- Added gd->arch.plmt in global data
- For timer_get_us(), use readq() instead of andes_plmt_get_count()
  and sifive_clint_get_count()

Changes in v2:
- Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
  and andes_plmt_timer.c.


 arch/riscv/include/asm/global_data.h |  3 +++
 drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
 drivers/timer/riscv_timer.c          | 14 +++++++++++++-
 drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
 4 files changed, 52 insertions(+), 3 deletions(-)

Comments

Heinrich Schuchardt Nov. 11, 2020, 11:21 a.m. UTC | #1
On 11.11.20 11:14, Pragnesh Patel wrote:
> Add timer_get_us() which is useful for tracing.
> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide
> a timer ticks and For M-mode U-Boot, mtime register will
> provide the same.
>
> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>

The default implementation of get_timer_us() in lib/time.c calls
get_ticks() which calls timer_get_count(). The get_count() operation is
implemented in drivers/timer/andes_plmt_timer.c,
drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.

Why do you need special timer_get_us() implementations?
Isn't it enough to supply the get_count() operation in the drivers?

Best regards

Heinrich

> ---
>
> Changes in v3:
> - Added gd->arch.plmt in global data
> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>   and sifive_clint_get_count()
>
> Changes in v2:
> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>   and andes_plmt_timer.c.
>
>
>  arch/riscv/include/asm/global_data.h |  3 +++
>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>  4 files changed, 52 insertions(+), 3 deletions(-)
>
> diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
> index d3a0b1d221..4e22ceb83f 100644
> --- a/arch/riscv/include/asm/global_data.h
> +++ b/arch/riscv/include/asm/global_data.h
> @@ -24,6 +24,9 @@ struct arch_global_data {
>  #ifdef CONFIG_ANDES_PLIC
>  	void __iomem *plic;	/* plic base address */
>  #endif
> +#ifdef CONFIG_ANDES_PLMT
> +	void __iomem *plmt;     /* plmt base address */
> +#endif
>  #if CONFIG_IS_ENABLED(SMP)
>  	struct ipi_data ipi[CONFIG_NR_CPUS];
>  #endif
> diff --git a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
> index cec86718c7..7c50c46d9e 100644
> --- a/drivers/timer/andes_plmt_timer.c
> +++ b/drivers/timer/andes_plmt_timer.c
> @@ -13,11 +13,12 @@
>  #include <timer.h>
>  #include <asm/io.h>
>  #include <linux/err.h>
> +#include <div64.h>
>
>  /* mtime register */
>  #define MTIME_REG(base)			((ulong)(base))
>
> -static u64 andes_plmt_get_count(struct udevice *dev)
> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>  {
>  	return readq((void __iomem *)MTIME_REG(dev->priv));
>  }
> @@ -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>  	.get_count = andes_plmt_get_count,
>  };
>
> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> +unsigned long notrace timer_get_us(void)
> +{
> +	u64 ticks;
> +
> +	/* FIXME: gd->arch.plmt should contain valid base address */
> +	if (gd->arch.plmt) {
> +		ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
> +		do_div(ticks, CONFIG_SYS_HZ);
> +	}
> +
> +	return ticks;
> +}
> +#endif
> +
>  static int andes_plmt_probe(struct udevice *dev)
>  {
>  	dev->priv = dev_read_addr_ptr(dev);
>  	if (!dev->priv)
>  		return -EINVAL;
>
> +	gd->arch.plmt = dev->priv;
>  	return timer_timebase_fallback(dev);
>  }
>
> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
> index 21ae184057..7fa8773da3 100644
> --- a/drivers/timer/riscv_timer.c
> +++ b/drivers/timer/riscv_timer.c
> @@ -15,8 +15,9 @@
>  #include <errno.h>
>  #include <timer.h>
>  #include <asm/csr.h>
> +#include <div64.h>
>
> -static u64 riscv_timer_get_count(struct udevice *dev)
> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>  {
>  	__maybe_unused u32 hi, lo;
>
> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>  	return ((u64)hi << 32) | lo;
>  }
>
> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
> +unsigned long notrace timer_get_us(void)
> +{
> +	u64 ticks;
> +
> +	ticks = riscv_timer_get_count(NULL);
> +	do_div(ticks, CONFIG_SYS_HZ);
> +	return ticks;
> +}
> +#endif
> +
>  static int riscv_timer_probe(struct udevice *dev)
>  {
>  	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c
> index 00ce0f08d6..c341f7789b 100644
> --- a/drivers/timer/sifive_clint_timer.c
> +++ b/drivers/timer/sifive_clint_timer.c
> @@ -10,11 +10,12 @@
>  #include <timer.h>
>  #include <asm/io.h>
>  #include <linux/err.h>
> +#include <div64.h>
>
>  /* mtime register */
>  #define MTIME_REG(base)			((ulong)(base) + 0xbff8)
>
> -static u64 sifive_clint_get_count(struct udevice *dev)
> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>  {
>  	return readq((void __iomem *)MTIME_REG(dev->priv));
>  }
> @@ -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>  	.get_count = sifive_clint_get_count,
>  };
>
> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> +unsigned long notrace timer_get_us(void)
> +{
> +	u64 ticks;
> +
> +	/* FIXME: gd->arch.clint should contain valid base address */
> +	if (gd->arch.clint) {
> +		ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
> +		do_div(ticks, CONFIG_SYS_HZ);
> +	}
> +
> +	return ticks;
> +}
> +#endif
> +
>  static int sifive_clint_probe(struct udevice *dev)
>  {
>  	dev->priv = dev_read_addr_ptr(dev);
>  	if (!dev->priv)
>  		return -EINVAL;
>
> +	gd->arch.clint = dev->priv;
>  	return timer_timebase_fallback(dev);
>  }
>
>
Pragnesh Patel Nov. 11, 2020, 11:56 a.m. UTC | #2
Hi Heinrich,

>-----Original Message-----
>From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>Sent: 11 November 2020 16:51
>To: Pragnesh Patel <pragnesh.patel@openfive.com>; u-boot@lists.denx.de
>Cc: atish.patra@wdc.com; palmerdabbelt@google.com; bmeng.cn@gmail.com;
>Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>; anup.patel@wdc.com;
>Sagar Kadam <sagar.kadam@openfive.com>; rick@andestech.com; Sean
>Anderson <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>On 11.11.20 11:14, Pragnesh Patel wrote:
>> Add timer_get_us() which is useful for tracing.
>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>> and For M-mode U-Boot, mtime register will provide the same.
>>
>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>
>The default implementation of get_timer_us() in lib/time.c calls
>get_ticks() which calls timer_get_count(). The get_count() operation is
>implemented in drivers/timer/andes_plmt_timer.c,
>drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>
>Why do you need special timer_get_us() implementations?
>Isn't it enough to supply the get_count() operation in the drivers?

get_ticks() is depend on gd->timer and there are 2 cases

1) if gd->timer== NULL then dm_timer_init() gets called and it will call functions
which are not marked with "notrace" so tracing got stuck.

2) if gd->timer is already initialized then still initr_dm() will make gd->timer = NULL;

initr_dm()
{
#ifdef CONFIG_TIMER
        gd->timer = NULL;
#endif
}

So again dm_timer_init() gets called and tracing got stuck.

So I thought better to implement timer_get_us().

>
>Best regards
>
>Heinrich
>
>> ---
>>
>> Changes in v3:
>> - Added gd->arch.plmt in global data
>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>   and sifive_clint_get_count()
>>
>> Changes in v2:
>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>   and andes_plmt_timer.c.
>>
>>
>>  arch/riscv/include/asm/global_data.h |  3 +++
>>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>  4 files changed, 52 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/riscv/include/asm/global_data.h
>> b/arch/riscv/include/asm/global_data.h
>> index d3a0b1d221..4e22ceb83f 100644
>> --- a/arch/riscv/include/asm/global_data.h
>> +++ b/arch/riscv/include/asm/global_data.h
>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>       void __iomem *plic;     /* plic base address */
>>  #endif
>> +#ifdef CONFIG_ANDES_PLMT
>> +     void __iomem *plmt;     /* plmt base address */
>> +#endif
>>  #if CONFIG_IS_ENABLED(SMP)
>>       struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>> a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
>> index cec86718c7..7c50c46d9e 100644
>> --- a/drivers/timer/andes_plmt_timer.c
>> +++ b/drivers/timer/andes_plmt_timer.c
>> @@ -13,11 +13,12 @@
>>  #include <timer.h>
>>  #include <asm/io.h>
>>  #include <linux/err.h>
>> +#include <div64.h>
>>
>>  /* mtime register */
>>  #define MTIME_REG(base)                      ((ulong)(base))
>>
>> -static u64 andes_plmt_get_count(struct udevice *dev)
>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>  {
>>       return readq((void __iomem *)MTIME_REG(dev->priv));  } @@ -26,12
>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>       .get_count = andes_plmt_get_count,  };
>>
>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +     u64 ticks;
>> +
>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>> +     if (gd->arch.plmt) {
>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>> +             do_div(ticks, CONFIG_SYS_HZ);
>> +     }
>> +
>> +     return ticks;
>> +}
>> +#endif
>> +
>>  static int andes_plmt_probe(struct udevice *dev)  {
>>       dev->priv = dev_read_addr_ptr(dev);
>>       if (!dev->priv)
>>               return -EINVAL;
>>
>> +     gd->arch.plmt = dev->priv;
>>       return timer_timebase_fallback(dev);  }
>>
>> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
>> index 21ae184057..7fa8773da3 100644
>> --- a/drivers/timer/riscv_timer.c
>> +++ b/drivers/timer/riscv_timer.c
>> @@ -15,8 +15,9 @@
>>  #include <errno.h>
>>  #include <timer.h>
>>  #include <asm/csr.h>
>> +#include <div64.h>
>>
>> -static u64 riscv_timer_get_count(struct udevice *dev)
>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>  {
>>       __maybe_unused u32 hi, lo;
>>
>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>       return ((u64)hi << 32) | lo;
>>  }
>>
>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +     u64 ticks;
>> +
>> +     ticks = riscv_timer_get_count(NULL);
>> +     do_div(ticks, CONFIG_SYS_HZ);
>> +     return ticks;
>> +}
>> +#endif
>> +
>>  static int riscv_timer_probe(struct udevice *dev)  {
>>       struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); diff
>> --git a/drivers/timer/sifive_clint_timer.c
>> b/drivers/timer/sifive_clint_timer.c
>> index 00ce0f08d6..c341f7789b 100644
>> --- a/drivers/timer/sifive_clint_timer.c
>> +++ b/drivers/timer/sifive_clint_timer.c
>> @@ -10,11 +10,12 @@
>>  #include <timer.h>
>>  #include <asm/io.h>
>>  #include <linux/err.h>
>> +#include <div64.h>
>>
>>  /* mtime register */
>>  #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>
>> -static u64 sifive_clint_get_count(struct udevice *dev)
>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>  {
>>       return readq((void __iomem *)MTIME_REG(dev->priv));  } @@ -23,12
>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>       .get_count = sifive_clint_get_count,  };
>>
>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +     u64 ticks;
>> +
>> +     /* FIXME: gd->arch.clint should contain valid base address */
>> +     if (gd->arch.clint) {
>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>> +             do_div(ticks, CONFIG_SYS_HZ);
>> +     }
>> +
>> +     return ticks;
>> +}
>> +#endif
>> +
>>  static int sifive_clint_probe(struct udevice *dev)  {
>>       dev->priv = dev_read_addr_ptr(dev);
>>       if (!dev->priv)
>>               return -EINVAL;
>>
>> +     gd->arch.clint = dev->priv;
>>       return timer_timebase_fallback(dev);  }
>>
>>
Heinrich Schuchardt Nov. 11, 2020, 1:48 p.m. UTC | #3
On 11/11/20 12:56 PM, Pragnesh Patel wrote:
> Hi Heinrich,
>
>> -----Original Message-----
>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>> Sent: 11 November 2020 16:51
>> To: Pragnesh Patel <pragnesh.patel@openfive.com>; u-boot@lists.denx.de
>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com; bmeng.cn@gmail.com;
>> Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>; anup.patel@wdc.com;
>> Sagar Kadam <sagar.kadam@openfive.com>; rick@andestech.com; Sean
>> Anderson <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>
>> [External Email] Do not click links or attachments unless you recognize the
>> sender and know the content is safe
>>
>> On 11.11.20 11:14, Pragnesh Patel wrote:
>>> Add timer_get_us() which is useful for tracing.
>>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>>> and For M-mode U-Boot, mtime register will provide the same.
>>>
>>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>>
>> The default implementation of get_timer_us() in lib/time.c calls
>> get_ticks() which calls timer_get_count(). The get_count() operation is
>> implemented in drivers/timer/andes_plmt_timer.c,
>> drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>>
>> Why do you need special timer_get_us() implementations?
>> Isn't it enough to supply the get_count() operation in the drivers?
>
> get_ticks() is depend on gd->timer and there are 2 cases
>
> 1) if gd->timer== NULL then dm_timer_init() gets called and it will call functions
> which are not marked with "notrace" so tracing got stuck.

Thanks for the background information.

Please, identify the existing functions that lack "notrace" and fix
them. This will give us a solution for all existing boards and not for a
small selection. Furthermore it will avoid code duplication.

In lib/trace.c consider replacing
"__attribute__((no_instrument_function))" by "notrace".

Best regards

Heinrich

>
> 2) if gd->timer is already initialized then still initr_dm() will make gd->timer = NULL;
>
> initr_dm()
> {
> #ifdef CONFIG_TIMER
>          gd->timer = NULL;
> #endif
> }
>
> So again dm_timer_init() gets called and tracing got stuck.
>
> So I thought better to implement timer_get_us().
>
>>
>> Best regards
>>
>> Heinrich
>>
>>> ---
>>>
>>> Changes in v3:
>>> - Added gd->arch.plmt in global data
>>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>>    and sifive_clint_get_count()
>>>
>>> Changes in v2:
>>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>>    and andes_plmt_timer.c.
>>>
>>>
>>>   arch/riscv/include/asm/global_data.h |  3 +++
>>>   drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>>   drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>>   drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>>   4 files changed, 52 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/riscv/include/asm/global_data.h
>>> b/arch/riscv/include/asm/global_data.h
>>> index d3a0b1d221..4e22ceb83f 100644
>>> --- a/arch/riscv/include/asm/global_data.h
>>> +++ b/arch/riscv/include/asm/global_data.h
>>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>>        void __iomem *plic;     /* plic base address */
>>>   #endif
>>> +#ifdef CONFIG_ANDES_PLMT
>>> +     void __iomem *plmt;     /* plmt base address */
>>> +#endif
>>>   #if CONFIG_IS_ENABLED(SMP)
>>>        struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>>> a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
>>> index cec86718c7..7c50c46d9e 100644
>>> --- a/drivers/timer/andes_plmt_timer.c
>>> +++ b/drivers/timer/andes_plmt_timer.c
>>> @@ -13,11 +13,12 @@
>>>   #include <timer.h>
>>>   #include <asm/io.h>
>>>   #include <linux/err.h>
>>> +#include <div64.h>
>>>
>>>   /* mtime register */
>>>   #define MTIME_REG(base)                      ((ulong)(base))
>>>
>>> -static u64 andes_plmt_get_count(struct udevice *dev)
>>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>>   {
>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@ -26,12
>>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>>        .get_count = andes_plmt_get_count,  };
>>>
>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>> +unsigned long notrace timer_get_us(void) {
>>> +     u64 ticks;
>>> +
>>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>>> +     if (gd->arch.plmt) {
>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>> +     }
>>> +
>>> +     return ticks;
>>> +}
>>> +#endif
>>> +
>>>   static int andes_plmt_probe(struct udevice *dev)  {
>>>        dev->priv = dev_read_addr_ptr(dev);
>>>        if (!dev->priv)
>>>                return -EINVAL;
>>>
>>> +     gd->arch.plmt = dev->priv;
>>>        return timer_timebase_fallback(dev);  }
>>>
>>> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
>>> index 21ae184057..7fa8773da3 100644
>>> --- a/drivers/timer/riscv_timer.c
>>> +++ b/drivers/timer/riscv_timer.c
>>> @@ -15,8 +15,9 @@
>>>   #include <errno.h>
>>>   #include <timer.h>
>>>   #include <asm/csr.h>
>>> +#include <div64.h>
>>>
>>> -static u64 riscv_timer_get_count(struct udevice *dev)
>>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>>   {
>>>        __maybe_unused u32 hi, lo;
>>>
>>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>>        return ((u64)hi << 32) | lo;
>>>   }
>>>
>>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>>> +unsigned long notrace timer_get_us(void) {
>>> +     u64 ticks;
>>> +
>>> +     ticks = riscv_timer_get_count(NULL);
>>> +     do_div(ticks, CONFIG_SYS_HZ);
>>> +     return ticks;
>>> +}
>>> +#endif
>>> +
>>>   static int riscv_timer_probe(struct udevice *dev)  {
>>>        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); diff
>>> --git a/drivers/timer/sifive_clint_timer.c
>>> b/drivers/timer/sifive_clint_timer.c
>>> index 00ce0f08d6..c341f7789b 100644
>>> --- a/drivers/timer/sifive_clint_timer.c
>>> +++ b/drivers/timer/sifive_clint_timer.c
>>> @@ -10,11 +10,12 @@
>>>   #include <timer.h>
>>>   #include <asm/io.h>
>>>   #include <linux/err.h>
>>> +#include <div64.h>
>>>
>>>   /* mtime register */
>>>   #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>>
>>> -static u64 sifive_clint_get_count(struct udevice *dev)
>>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>>   {
>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@ -23,12
>>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>>        .get_count = sifive_clint_get_count,  };
>>>
>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>> +unsigned long notrace timer_get_us(void) {
>>> +     u64 ticks;
>>> +
>>> +     /* FIXME: gd->arch.clint should contain valid base address */
>>> +     if (gd->arch.clint) {
>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>> +     }
>>> +
>>> +     return ticks;
>>> +}
>>> +#endif
>>> +
>>>   static int sifive_clint_probe(struct udevice *dev)  {
>>>        dev->priv = dev_read_addr_ptr(dev);
>>>        if (!dev->priv)
>>>                return -EINVAL;
>>>
>>> +     gd->arch.clint = dev->priv;
>>>        return timer_timebase_fallback(dev);  }
>>>
>>>
>
Pragnesh Patel Nov. 12, 2020, 6:34 a.m. UTC | #4
Hi Heinrich,

>-----Original Message-----
>From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>Sent: 11 November 2020 19:18
>To: Pragnesh Patel <pragnesh.patel@openfive.com>
>Cc: atish.patra@wdc.com; palmerdabbelt@google.com; u-boot@lists.denx.de;
>bmeng.cn@gmail.com; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
>anup.patel@wdc.com; Sagar Kadam <sagar.kadam@openfive.com>;
>rick@andestech.com; Sean Anderson <seanga2@gmail.com>; Simon Glass
><sjg@chromium.org>
>Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>On 11/11/20 12:56 PM, Pragnesh Patel wrote:
>> Hi Heinrich,
>>
>>> -----Original Message-----
>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>> Sent: 11 November 2020 16:51
>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>;
>>> u-boot@lists.denx.de
>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>> bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>>> <paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>>> <sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>>> <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>
>>> [External Email] Do not click links or attachments unless you
>>> recognize the sender and know the content is safe
>>>
>>> On 11.11.20 11:14, Pragnesh Patel wrote:
>>>> Add timer_get_us() which is useful for tracing.
>>>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>>>> and For M-mode U-Boot, mtime register will provide the same.
>>>>
>>>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>>>
>>> The default implementation of get_timer_us() in lib/time.c calls
>>> get_ticks() which calls timer_get_count(). The get_count() operation
>>> is implemented in drivers/timer/andes_plmt_timer.c,
>>> drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>>>
>>> Why do you need special timer_get_us() implementations?
>>> Isn't it enough to supply the get_count() operation in the drivers?
>>
>> get_ticks() is depend on gd->timer and there are 2 cases
>>
>> 1) if gd->timer== NULL then dm_timer_init() gets called and it will
>> call functions which are not marked with "notrace" so tracing got stuck.
>
>Thanks for the background information.
>
>Please, identify the existing functions that lack "notrace" and fix them. This will
>give us a solution for all existing boards and not for a small selection.
>Furthermore it will avoid code duplication.

I tried but There are so many functions which need "notrace".

Why don’t we consider removing gd->timer=NULL in initr_dm()
initr_dm()
{
#ifdef CONFIG_TIMER
         gd->timer = NULL;
#endif
}

Or I can use TIMER_EARLY and return ticks and rate  by adding timer_early_get_count()
and timer_early_get_rate() repectively.

Suggestions are welcome

>
>In lib/trace.c consider replacing
>"__attribute__((no_instrument_function))" by "notrace".
>
>Best regards
>
>Heinrich
>
>>
>> 2) if gd->timer is already initialized then still initr_dm() will make
>> gd->timer = NULL;
>>
>> initr_dm()
>> {
>> #ifdef CONFIG_TIMER
>>          gd->timer = NULL;
>> #endif
>> }
>>
>> So again dm_timer_init() gets called and tracing got stuck.
>>
>> So I thought better to implement timer_get_us().
>>
>>>
>>> Best regards
>>>
>>> Heinrich
>>>
>>>> ---
>>>>
>>>> Changes in v3:
>>>> - Added gd->arch.plmt in global data
>>>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>>>    and sifive_clint_get_count()
>>>>
>>>> Changes in v2:
>>>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>>>    and andes_plmt_timer.c.
>>>>
>>>>
>>>>   arch/riscv/include/asm/global_data.h |  3 +++
>>>>   drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>>>   drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>>>   drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>>>   4 files changed, 52 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/riscv/include/asm/global_data.h
>>>> b/arch/riscv/include/asm/global_data.h
>>>> index d3a0b1d221..4e22ceb83f 100644
>>>> --- a/arch/riscv/include/asm/global_data.h
>>>> +++ b/arch/riscv/include/asm/global_data.h
>>>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>>>        void __iomem *plic;     /* plic base address */
>>>>   #endif
>>>> +#ifdef CONFIG_ANDES_PLMT
>>>> +     void __iomem *plmt;     /* plmt base address */
>>>> +#endif
>>>>   #if CONFIG_IS_ENABLED(SMP)
>>>>        struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>>>> a/drivers/timer/andes_plmt_timer.c
>>>> b/drivers/timer/andes_plmt_timer.c
>>>> index cec86718c7..7c50c46d9e 100644
>>>> --- a/drivers/timer/andes_plmt_timer.c
>>>> +++ b/drivers/timer/andes_plmt_timer.c
>>>> @@ -13,11 +13,12 @@
>>>>   #include <timer.h>
>>>>   #include <asm/io.h>
>>>>   #include <linux/err.h>
>>>> +#include <div64.h>
>>>>
>>>>   /* mtime register */
>>>>   #define MTIME_REG(base)                      ((ulong)(base))
>>>>
>>>> -static u64 andes_plmt_get_count(struct udevice *dev)
>>>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>>>   {
>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>> -26,12
>>>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>>>        .get_count = andes_plmt_get_count,  };
>>>>
>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>>> +unsigned long notrace timer_get_us(void) {
>>>> +     u64 ticks;
>>>> +
>>>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>>>> +     if (gd->arch.plmt) {
>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>> +     }
>>>> +
>>>> +     return ticks;
>>>> +}
>>>> +#endif
>>>> +
>>>>   static int andes_plmt_probe(struct udevice *dev)  {
>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>        if (!dev->priv)
>>>>                return -EINVAL;
>>>>
>>>> +     gd->arch.plmt = dev->priv;
>>>>        return timer_timebase_fallback(dev);  }
>>>>
>>>> diff --git a/drivers/timer/riscv_timer.c
>>>> b/drivers/timer/riscv_timer.c index 21ae184057..7fa8773da3 100644
>>>> --- a/drivers/timer/riscv_timer.c
>>>> +++ b/drivers/timer/riscv_timer.c
>>>> @@ -15,8 +15,9 @@
>>>>   #include <errno.h>
>>>>   #include <timer.h>
>>>>   #include <asm/csr.h>
>>>> +#include <div64.h>
>>>>
>>>> -static u64 riscv_timer_get_count(struct udevice *dev)
>>>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>>>   {
>>>>        __maybe_unused u32 hi, lo;
>>>>
>>>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>>>        return ((u64)hi << 32) | lo;
>>>>   }
>>>>
>>>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>>>> +unsigned long notrace timer_get_us(void) {
>>>> +     u64 ticks;
>>>> +
>>>> +     ticks = riscv_timer_get_count(NULL);
>>>> +     do_div(ticks, CONFIG_SYS_HZ);
>>>> +     return ticks;
>>>> +}
>>>> +#endif
>>>> +
>>>>   static int riscv_timer_probe(struct udevice *dev)  {
>>>>        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>>>> diff --git a/drivers/timer/sifive_clint_timer.c
>>>> b/drivers/timer/sifive_clint_timer.c
>>>> index 00ce0f08d6..c341f7789b 100644
>>>> --- a/drivers/timer/sifive_clint_timer.c
>>>> +++ b/drivers/timer/sifive_clint_timer.c
>>>> @@ -10,11 +10,12 @@
>>>>   #include <timer.h>
>>>>   #include <asm/io.h>
>>>>   #include <linux/err.h>
>>>> +#include <div64.h>
>>>>
>>>>   /* mtime register */
>>>>   #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>>>
>>>> -static u64 sifive_clint_get_count(struct udevice *dev)
>>>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>>>   {
>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>> -23,12
>>>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>>>        .get_count = sifive_clint_get_count,  };
>>>>
>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>>> +unsigned long notrace timer_get_us(void) {
>>>> +     u64 ticks;
>>>> +
>>>> +     /* FIXME: gd->arch.clint should contain valid base address */
>>>> +     if (gd->arch.clint) {
>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>> +     }
>>>> +
>>>> +     return ticks;
>>>> +}
>>>> +#endif
>>>> +
>>>>   static int sifive_clint_probe(struct udevice *dev)  {
>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>        if (!dev->priv)
>>>>                return -EINVAL;
>>>>
>>>> +     gd->arch.clint = dev->priv;
>>>>        return timer_timebase_fallback(dev);  }
>>>>
>>>>
>>
Heinrich Schuchardt Nov. 12, 2020, 7:09 a.m. UTC | #5
On 11/12/20 7:34 AM, Pragnesh Patel wrote:
> Hi Heinrich,
>
>> -----Original Message-----
>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>> Sent: 11 November 2020 19:18
>> To: Pragnesh Patel <pragnesh.patel@openfive.com>
>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com; u-boot@lists.denx.de;
>> bmeng.cn@gmail.com; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
>> anup.patel@wdc.com; Sagar Kadam <sagar.kadam@openfive.com>;
>> rick@andestech.com; Sean Anderson <seanga2@gmail.com>; Simon Glass
>> <sjg@chromium.org>
>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>
>> [External Email] Do not click links or attachments unless you recognize the
>> sender and know the content is safe
>>
>> On 11/11/20 12:56 PM, Pragnesh Patel wrote:
>>> Hi Heinrich,
>>>
>>>> -----Original Message-----
>>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>>> Sent: 11 November 2020 16:51
>>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>;
>>>> u-boot@lists.denx.de
>>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>>> bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>>>> <paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>>>> <sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>>>> <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>>
>>>> [External Email] Do not click links or attachments unless you
>>>> recognize the sender and know the content is safe
>>>>
>>>> On 11.11.20 11:14, Pragnesh Patel wrote:
>>>>> Add timer_get_us() which is useful for tracing.
>>>>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>>>>> and For M-mode U-Boot, mtime register will provide the same.
>>>>>
>>>>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>>>>
>>>> The default implementation of get_timer_us() in lib/time.c calls
>>>> get_ticks() which calls timer_get_count(). The get_count() operation
>>>> is implemented in drivers/timer/andes_plmt_timer.c,
>>>> drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>>>>
>>>> Why do you need special timer_get_us() implementations?
>>>> Isn't it enough to supply the get_count() operation in the drivers?
>>>
>>> get_ticks() is depend on gd->timer and there are 2 cases
>>>
>>> 1) if gd->timer== NULL then dm_timer_init() gets called and it will
>>> call functions which are not marked with "notrace" so tracing got stuck.
>>
>> Thanks for the background information.
>>
>> Please, identify the existing functions that lack "notrace" and fix them. This will
>> give us a solution for all existing boards and not for a small selection.
>> Furthermore it will avoid code duplication.
>
> I tried but There are so many functions which need "notrace".

Let's start with the problem statement:

When tracing functions is enabled this adds calls to
__cyg_profile_func_enter() and __cyg_profile_func_exit() to the traced
functions.

__cyg_profile_func_exit() and __cyg_profile_func_exit() invoke
timer_get_us() to record the entry and exit time.

If timer_get_us() or any function used to implement does not carry
__attribute__((no_instrument_function)) this will lead to an indefinite
recursion.

We have to change __cyg_profile_func_enter() and
__cyg_profile_func_exit() such that during their execution no function
is traced. We can do so by temporarily setting trace_enabled to false.

Does this match your observation?

Best regards

Heinrich

>
> Why don’t we consider removing gd->timer=NULL in initr_dm()
> initr_dm()
> {
> #ifdef CONFIG_TIMER
>          gd->timer = NULL;
> #endif
> }
>
> Or I can use TIMER_EARLY and return ticks and rate  by adding timer_early_get_count()
> and timer_early_get_rate() repectively.
>
> Suggestions are welcome
>
>>
>> In lib/trace.c consider replacing
>> "__attribute__((no_instrument_function))" by "notrace".
>>
>> Best regards
>>
>> Heinrich
>>
>>>
>>> 2) if gd->timer is already initialized then still initr_dm() will make
>>> gd->timer = NULL;
>>>
>>> initr_dm()
>>> {
>>> #ifdef CONFIG_TIMER
>>>          gd->timer = NULL;
>>> #endif
>>> }
>>>
>>> So again dm_timer_init() gets called and tracing got stuck.
>>>
>>> So I thought better to implement timer_get_us().
>>>
>>>>
>>>> Best regards
>>>>
>>>> Heinrich
>>>>
>>>>> ---
>>>>>
>>>>> Changes in v3:
>>>>> - Added gd->arch.plmt in global data
>>>>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>>>>    and sifive_clint_get_count()
>>>>>
>>>>> Changes in v2:
>>>>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>>>>    and andes_plmt_timer.c.
>>>>>
>>>>>
>>>>>   arch/riscv/include/asm/global_data.h |  3 +++
>>>>>   drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>>>>   drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>>>>   drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>>>>   4 files changed, 52 insertions(+), 3 deletions(-)
>>>>>
>>>>> diff --git a/arch/riscv/include/asm/global_data.h
>>>>> b/arch/riscv/include/asm/global_data.h
>>>>> index d3a0b1d221..4e22ceb83f 100644
>>>>> --- a/arch/riscv/include/asm/global_data.h
>>>>> +++ b/arch/riscv/include/asm/global_data.h
>>>>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>>>>        void __iomem *plic;     /* plic base address */
>>>>>   #endif
>>>>> +#ifdef CONFIG_ANDES_PLMT
>>>>> +     void __iomem *plmt;     /* plmt base address */
>>>>> +#endif
>>>>>   #if CONFIG_IS_ENABLED(SMP)
>>>>>        struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>>>>> a/drivers/timer/andes_plmt_timer.c
>>>>> b/drivers/timer/andes_plmt_timer.c
>>>>> index cec86718c7..7c50c46d9e 100644
>>>>> --- a/drivers/timer/andes_plmt_timer.c
>>>>> +++ b/drivers/timer/andes_plmt_timer.c
>>>>> @@ -13,11 +13,12 @@
>>>>>   #include <timer.h>
>>>>>   #include <asm/io.h>
>>>>>   #include <linux/err.h>
>>>>> +#include <div64.h>
>>>>>
>>>>>   /* mtime register */
>>>>>   #define MTIME_REG(base)                      ((ulong)(base))
>>>>>
>>>>> -static u64 andes_plmt_get_count(struct udevice *dev)
>>>>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>>>>   {
>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>> -26,12
>>>>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>>>>        .get_count = andes_plmt_get_count,  };
>>>>>
>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>>>> +unsigned long notrace timer_get_us(void) {
>>>>> +     u64 ticks;
>>>>> +
>>>>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>>>>> +     if (gd->arch.plmt) {
>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>> +     }
>>>>> +
>>>>> +     return ticks;
>>>>> +}
>>>>> +#endif
>>>>> +
>>>>>   static int andes_plmt_probe(struct udevice *dev)  {
>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>        if (!dev->priv)
>>>>>                return -EINVAL;
>>>>>
>>>>> +     gd->arch.plmt = dev->priv;
>>>>>        return timer_timebase_fallback(dev);  }
>>>>>
>>>>> diff --git a/drivers/timer/riscv_timer.c
>>>>> b/drivers/timer/riscv_timer.c index 21ae184057..7fa8773da3 100644
>>>>> --- a/drivers/timer/riscv_timer.c
>>>>> +++ b/drivers/timer/riscv_timer.c
>>>>> @@ -15,8 +15,9 @@
>>>>>   #include <errno.h>
>>>>>   #include <timer.h>
>>>>>   #include <asm/csr.h>
>>>>> +#include <div64.h>
>>>>>
>>>>> -static u64 riscv_timer_get_count(struct udevice *dev)
>>>>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>>>>   {
>>>>>        __maybe_unused u32 hi, lo;
>>>>>
>>>>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>>>>        return ((u64)hi << 32) | lo;
>>>>>   }
>>>>>
>>>>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>>>>> +unsigned long notrace timer_get_us(void) {
>>>>> +     u64 ticks;
>>>>> +
>>>>> +     ticks = riscv_timer_get_count(NULL);
>>>>> +     do_div(ticks, CONFIG_SYS_HZ);
>>>>> +     return ticks;
>>>>> +}
>>>>> +#endif
>>>>> +
>>>>>   static int riscv_timer_probe(struct udevice *dev)  {
>>>>>        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>>>>> diff --git a/drivers/timer/sifive_clint_timer.c
>>>>> b/drivers/timer/sifive_clint_timer.c
>>>>> index 00ce0f08d6..c341f7789b 100644
>>>>> --- a/drivers/timer/sifive_clint_timer.c
>>>>> +++ b/drivers/timer/sifive_clint_timer.c
>>>>> @@ -10,11 +10,12 @@
>>>>>   #include <timer.h>
>>>>>   #include <asm/io.h>
>>>>>   #include <linux/err.h>
>>>>> +#include <div64.h>
>>>>>
>>>>>   /* mtime register */
>>>>>   #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>>>>
>>>>> -static u64 sifive_clint_get_count(struct udevice *dev)
>>>>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>>>>   {
>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>> -23,12
>>>>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>>>>        .get_count = sifive_clint_get_count,  };
>>>>>
>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>>>> +unsigned long notrace timer_get_us(void) {
>>>>> +     u64 ticks;
>>>>> +
>>>>> +     /* FIXME: gd->arch.clint should contain valid base address */
>>>>> +     if (gd->arch.clint) {
>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>> +     }
>>>>> +
>>>>> +     return ticks;
>>>>> +}
>>>>> +#endif
>>>>> +
>>>>>   static int sifive_clint_probe(struct udevice *dev)  {
>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>        if (!dev->priv)
>>>>>                return -EINVAL;
>>>>>
>>>>> +     gd->arch.clint = dev->priv;
>>>>>        return timer_timebase_fallback(dev);  }
>>>>>
>>>>>
>>>
>
Heinrich Schuchardt Nov. 12, 2020, 7:19 a.m. UTC | #6
On 11/12/20 8:09 AM, Heinrich Schuchardt wrote:
> On 11/12/20 7:34 AM, Pragnesh Patel wrote:
>> Hi Heinrich,
>>
>>> -----Original Message-----
>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>> Sent: 11 November 2020 19:18
>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>
>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com; u-boot@lists.denx.de;
>>> bmeng.cn@gmail.com; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
>>> anup.patel@wdc.com; Sagar Kadam <sagar.kadam@openfive.com>;
>>> rick@andestech.com; Sean Anderson <seanga2@gmail.com>; Simon Glass
>>> <sjg@chromium.org>
>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>
>>> [External Email] Do not click links or attachments unless you recognize the
>>> sender and know the content is safe
>>>
>>> On 11/11/20 12:56 PM, Pragnesh Patel wrote:
>>>> Hi Heinrich,
>>>>
>>>>> -----Original Message-----
>>>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>>>> Sent: 11 November 2020 16:51
>>>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>;
>>>>> u-boot@lists.denx.de
>>>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>>>> bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>>>>> <paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>>>>> <sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>>>>> <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>>>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>>>
>>>>> [External Email] Do not click links or attachments unless you
>>>>> recognize the sender and know the content is safe
>>>>>
>>>>> On 11.11.20 11:14, Pragnesh Patel wrote:
>>>>>> Add timer_get_us() which is useful for tracing.
>>>>>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>>>>>> and For M-mode U-Boot, mtime register will provide the same.
>>>>>>
>>>>>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>>>>>
>>>>> The default implementation of get_timer_us() in lib/time.c calls
>>>>> get_ticks() which calls timer_get_count(). The get_count() operation
>>>>> is implemented in drivers/timer/andes_plmt_timer.c,
>>>>> drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>>>>>
>>>>> Why do you need special timer_get_us() implementations?
>>>>> Isn't it enough to supply the get_count() operation in the drivers?
>>>>
>>>> get_ticks() is depend on gd->timer and there are 2 cases
>>>>
>>>> 1) if gd->timer== NULL then dm_timer_init() gets called and it will
>>>> call functions which are not marked with "notrace" so tracing got stuck.
>>>
>>> Thanks for the background information.
>>>
>>> Please, identify the existing functions that lack "notrace" and fix them. This will
>>> give us a solution for all existing boards and not for a small selection.
>>> Furthermore it will avoid code duplication.
>>
>> I tried but There are so many functions which need "notrace".
>
> Let's start with the problem statement:
>
> When tracing functions is enabled this adds calls to
> __cyg_profile_func_enter() and __cyg_profile_func_exit() to the traced
> functions.
>
> __cyg_profile_func_exit() and __cyg_profile_func_exit() invoke
> timer_get_us() to record the entry and exit time.
>
> If timer_get_us() or any function used to implement does not carry
> __attribute__((no_instrument_function)) this will lead to an indefinite
> recursion.
>
> We have to change __cyg_profile_func_enter() and
> __cyg_profile_func_exit() such that during their execution no function
> is traced. We can do so by temporarily setting trace_enabled to false.
>
> Does this match your observation?

I just tried to put this into a patch

[PATCH 1/1] trace: avoid infinite recursion
https://lists.denx.de/pipermail/u-boot/2020-November/432589.html
https://patchwork.ozlabs.org/project/uboot/patch/20201112071411.4202-1-xypron.glpk@gmx.de/

Does this solve you problem?

Best regards

Heinrich
>
>>
>> Why don’t we consider removing gd->timer=NULL in initr_dm()
>> initr_dm()
>> {
>> #ifdef CONFIG_TIMER
>>          gd->timer = NULL;
>> #endif
>> }
>>
>> Or I can use TIMER_EARLY and return ticks and rate  by adding timer_early_get_count()
>> and timer_early_get_rate() repectively.
>>
>> Suggestions are welcome
>>
>>>
>>> In lib/trace.c consider replacing
>>> "__attribute__((no_instrument_function))" by "notrace".
>>>
>>> Best regards
>>>
>>> Heinrich
>>>
>>>>
>>>> 2) if gd->timer is already initialized then still initr_dm() will make
>>>> gd->timer = NULL;
>>>>
>>>> initr_dm()
>>>> {
>>>> #ifdef CONFIG_TIMER
>>>>          gd->timer = NULL;
>>>> #endif
>>>> }
>>>>
>>>> So again dm_timer_init() gets called and tracing got stuck.
>>>>
>>>> So I thought better to implement timer_get_us().
>>>>
>>>>>
>>>>> Best regards
>>>>>
>>>>> Heinrich
>>>>>
>>>>>> ---
>>>>>>
>>>>>> Changes in v3:
>>>>>> - Added gd->arch.plmt in global data
>>>>>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>>>>>    and sifive_clint_get_count()
>>>>>>
>>>>>> Changes in v2:
>>>>>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>>>>>    and andes_plmt_timer.c.
>>>>>>
>>>>>>
>>>>>>   arch/riscv/include/asm/global_data.h |  3 +++
>>>>>>   drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>>>>>   drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>>>>>   drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>>>>>   4 files changed, 52 insertions(+), 3 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/riscv/include/asm/global_data.h
>>>>>> b/arch/riscv/include/asm/global_data.h
>>>>>> index d3a0b1d221..4e22ceb83f 100644
>>>>>> --- a/arch/riscv/include/asm/global_data.h
>>>>>> +++ b/arch/riscv/include/asm/global_data.h
>>>>>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>>>>>        void __iomem *plic;     /* plic base address */
>>>>>>   #endif
>>>>>> +#ifdef CONFIG_ANDES_PLMT
>>>>>> +     void __iomem *plmt;     /* plmt base address */
>>>>>> +#endif
>>>>>>   #if CONFIG_IS_ENABLED(SMP)
>>>>>>        struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>>>>>> a/drivers/timer/andes_plmt_timer.c
>>>>>> b/drivers/timer/andes_plmt_timer.c
>>>>>> index cec86718c7..7c50c46d9e 100644
>>>>>> --- a/drivers/timer/andes_plmt_timer.c
>>>>>> +++ b/drivers/timer/andes_plmt_timer.c
>>>>>> @@ -13,11 +13,12 @@
>>>>>>   #include <timer.h>
>>>>>>   #include <asm/io.h>
>>>>>>   #include <linux/err.h>
>>>>>> +#include <div64.h>
>>>>>>
>>>>>>   /* mtime register */
>>>>>>   #define MTIME_REG(base)                      ((ulong)(base))
>>>>>>
>>>>>> -static u64 andes_plmt_get_count(struct udevice *dev)
>>>>>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>>>>>   {
>>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>>> -26,12
>>>>>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>>>>>        .get_count = andes_plmt_get_count,  };
>>>>>>
>>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>>>>> +unsigned long notrace timer_get_us(void) {
>>>>>> +     u64 ticks;
>>>>>> +
>>>>>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>>>>>> +     if (gd->arch.plmt) {
>>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>>> +     }
>>>>>> +
>>>>>> +     return ticks;
>>>>>> +}
>>>>>> +#endif
>>>>>> +
>>>>>>   static int andes_plmt_probe(struct udevice *dev)  {
>>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>>        if (!dev->priv)
>>>>>>                return -EINVAL;
>>>>>>
>>>>>> +     gd->arch.plmt = dev->priv;
>>>>>>        return timer_timebase_fallback(dev);  }
>>>>>>
>>>>>> diff --git a/drivers/timer/riscv_timer.c
>>>>>> b/drivers/timer/riscv_timer.c index 21ae184057..7fa8773da3 100644
>>>>>> --- a/drivers/timer/riscv_timer.c
>>>>>> +++ b/drivers/timer/riscv_timer.c
>>>>>> @@ -15,8 +15,9 @@
>>>>>>   #include <errno.h>
>>>>>>   #include <timer.h>
>>>>>>   #include <asm/csr.h>
>>>>>> +#include <div64.h>
>>>>>>
>>>>>> -static u64 riscv_timer_get_count(struct udevice *dev)
>>>>>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>>>>>   {
>>>>>>        __maybe_unused u32 hi, lo;
>>>>>>
>>>>>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>>>>>        return ((u64)hi << 32) | lo;
>>>>>>   }
>>>>>>
>>>>>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>>>>>> +unsigned long notrace timer_get_us(void) {
>>>>>> +     u64 ticks;
>>>>>> +
>>>>>> +     ticks = riscv_timer_get_count(NULL);
>>>>>> +     do_div(ticks, CONFIG_SYS_HZ);
>>>>>> +     return ticks;
>>>>>> +}
>>>>>> +#endif
>>>>>> +
>>>>>>   static int riscv_timer_probe(struct udevice *dev)  {
>>>>>>        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>>>>>> diff --git a/drivers/timer/sifive_clint_timer.c
>>>>>> b/drivers/timer/sifive_clint_timer.c
>>>>>> index 00ce0f08d6..c341f7789b 100644
>>>>>> --- a/drivers/timer/sifive_clint_timer.c
>>>>>> +++ b/drivers/timer/sifive_clint_timer.c
>>>>>> @@ -10,11 +10,12 @@
>>>>>>   #include <timer.h>
>>>>>>   #include <asm/io.h>
>>>>>>   #include <linux/err.h>
>>>>>> +#include <div64.h>
>>>>>>
>>>>>>   /* mtime register */
>>>>>>   #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>>>>>
>>>>>> -static u64 sifive_clint_get_count(struct udevice *dev)
>>>>>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>>>>>   {
>>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>>> -23,12
>>>>>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>>>>>        .get_count = sifive_clint_get_count,  };
>>>>>>
>>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>>>>>> +unsigned long notrace timer_get_us(void) {
>>>>>> +     u64 ticks;
>>>>>> +
>>>>>> +     /* FIXME: gd->arch.clint should contain valid base address */
>>>>>> +     if (gd->arch.clint) {
>>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>>> +     }
>>>>>> +
>>>>>> +     return ticks;
>>>>>> +}
>>>>>> +#endif
>>>>>> +
>>>>>>   static int sifive_clint_probe(struct udevice *dev)  {
>>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>>        if (!dev->priv)
>>>>>>                return -EINVAL;
>>>>>>
>>>>>> +     gd->arch.clint = dev->priv;
>>>>>>        return timer_timebase_fallback(dev);  }
>>>>>>
>>>>>>
>>>>
>>
>
Pragnesh Patel Nov. 12, 2020, 7:35 a.m. UTC | #7
Hi Heinrich,

>-----Original Message-----
>From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>Sent: 12 November 2020 12:49
>To: Pragnesh Patel <pragnesh.patel@openfive.com>; Simon Glass
><sjg@chromium.org>
>Cc: atish.patra@wdc.com; palmerdabbelt@google.com; u-boot@lists.denx.de;
>bmeng.cn@gmail.com; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
>anup.patel@wdc.com; Sagar Kadam <sagar.kadam@openfive.com>;
>rick@andestech.com; Sean Anderson <seanga2@gmail.com>
>Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>On 11/12/20 8:09 AM, Heinrich Schuchardt wrote:
>> On 11/12/20 7:34 AM, Pragnesh Patel wrote:
>>> Hi Heinrich,
>>>
>>>> -----Original Message-----
>>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>>> Sent: 11 November 2020 19:18
>>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>
>>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>>> u-boot@lists.denx.de; bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>>>> <paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>>>> <sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>>>> <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>>
>>>> [External Email] Do not click links or attachments unless you
>>>> recognize the sender and know the content is safe
>>>>
>>>> On 11/11/20 12:56 PM, Pragnesh Patel wrote:
>>>>> Hi Heinrich,
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>>>>> Sent: 11 November 2020 16:51
>>>>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>;
>>>>>> u-boot@lists.denx.de
>>>>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>>>>> bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>>>>>> <paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>>>>>> <sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>>>>>> <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>>>>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>>>>
>>>>>> [External Email] Do not click links or attachments unless you
>>>>>> recognize the sender and know the content is safe
>>>>>>
>>>>>> On 11.11.20 11:14, Pragnesh Patel wrote:
>>>>>>> Add timer_get_us() which is useful for tracing.
>>>>>>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer
>>>>>>> ticks and For M-mode U-Boot, mtime register will provide the same.
>>>>>>>
>>>>>>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>>>>>>
>>>>>> The default implementation of get_timer_us() in lib/time.c calls
>>>>>> get_ticks() which calls timer_get_count(). The get_count()
>>>>>> operation is implemented in drivers/timer/andes_plmt_timer.c,
>>>>>> drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>>>>>>
>>>>>> Why do you need special timer_get_us() implementations?
>>>>>> Isn't it enough to supply the get_count() operation in the drivers?
>>>>>
>>>>> get_ticks() is depend on gd->timer and there are 2 cases
>>>>>
>>>>> 1) if gd->timer== NULL then dm_timer_init() gets called and it will
>>>>> call functions which are not marked with "notrace" so tracing got stuck.
>>>>
>>>> Thanks for the background information.
>>>>
>>>> Please, identify the existing functions that lack "notrace" and fix
>>>> them. This will give us a solution for all existing boards and not for a small
>selection.
>>>> Furthermore it will avoid code duplication.
>>>
>>> I tried but There are so many functions which need "notrace".
>>
>> Let's start with the problem statement:
>>
>> When tracing functions is enabled this adds calls to
>> __cyg_profile_func_enter() and __cyg_profile_func_exit() to the traced
>> functions.
>>
>> __cyg_profile_func_exit() and __cyg_profile_func_exit() invoke
>> timer_get_us() to record the entry and exit time.
>>
>> If timer_get_us() or any function used to implement does not carry
>> __attribute__((no_instrument_function)) this will lead to an
>> indefinite recursion.
>>
>> We have to change __cyg_profile_func_enter() and
>> __cyg_profile_func_exit() such that during their execution no function
>> is traced. We can do so by temporarily setting trace_enabled to false.
>>
>> Does this match your observation?
>
>I just tried to put this into a patch
>
>[PATCH 1/1] trace: avoid infinite recursion https://lists.denx.de/pipermail/u-
>boot/2020-November/432589.html
>https://patchwork.ozlabs.org/project/uboot/patch/20201112071411.4202-1-
>xypron.glpk@gmx.de/
>
>Does this solve you problem?

Getting error, "Could not initialize timer (err -11)" from get_ticks() function.

Below are my boot logs,

U-Boot 2021.01-rc1-00244-g794c155581-dirty (Nov 12 2020 - 12:56:27 +0530)

CPU:   rv64imafdc
Model: SiFive HiFive Unleashed A00
DRAM:  8 GiB
trace: enabled
Could not initialize timer (err -11)

Could not initialize timer (err -11)

Could not initialize timer (err -11)

Could not initialize timer (err -11)


>
>Best regards
>
>Heinrich
>>
>>>
>>> Why don’t we consider removing gd->timer=NULL in initr_dm()
>>> initr_dm()
>>> {
>>> #ifdef CONFIG_TIMER
>>>          gd->timer = NULL;
>>> #endif
>>> }
>>>
>>> Or I can use TIMER_EARLY and return ticks and rate  by adding
>>> timer_early_get_count() and timer_early_get_rate() repectively.
>>>
>>> Suggestions are welcome
>>>
>>>>
>>>> In lib/trace.c consider replacing
>>>> "__attribute__((no_instrument_function))" by "notrace".
>>>>
>>>> Best regards
>>>>
>>>> Heinrich
>>>>
>>>>>
>>>>> 2) if gd->timer is already initialized then still initr_dm() will
>>>>> make
>>>>> gd->timer = NULL;
>>>>>
>>>>> initr_dm()
>>>>> {
>>>>> #ifdef CONFIG_TIMER
>>>>>          gd->timer = NULL;
>>>>> #endif
>>>>> }
>>>>>
>>>>> So again dm_timer_init() gets called and tracing got stuck.
>>>>>
>>>>> So I thought better to implement timer_get_us().
>>>>>
>>>>>>
>>>>>> Best regards
>>>>>>
>>>>>> Heinrich
>>>>>>
>>>>>>> ---
>>>>>>>
>>>>>>> Changes in v3:
>>>>>>> - Added gd->arch.plmt in global data
>>>>>>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>>>>>>    and sifive_clint_get_count()
>>>>>>>
>>>>>>> Changes in v2:
>>>>>>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>>>>>>    and andes_plmt_timer.c.
>>>>>>>
>>>>>>>
>>>>>>>   arch/riscv/include/asm/global_data.h |  3 +++
>>>>>>>   drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>>>>>>   drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>>>>>>   drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>>>>>>   4 files changed, 52 insertions(+), 3 deletions(-)
>>>>>>>
>>>>>>> diff --git a/arch/riscv/include/asm/global_data.h
>>>>>>> b/arch/riscv/include/asm/global_data.h
>>>>>>> index d3a0b1d221..4e22ceb83f 100644
>>>>>>> --- a/arch/riscv/include/asm/global_data.h
>>>>>>> +++ b/arch/riscv/include/asm/global_data.h
>>>>>>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef
>CONFIG_ANDES_PLIC
>>>>>>>        void __iomem *plic;     /* plic base address */
>>>>>>>   #endif
>>>>>>> +#ifdef CONFIG_ANDES_PLMT
>>>>>>> +     void __iomem *plmt;     /* plmt base address */
>>>>>>> +#endif
>>>>>>>   #if CONFIG_IS_ENABLED(SMP)
>>>>>>>        struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>>>>>>> a/drivers/timer/andes_plmt_timer.c
>>>>>>> b/drivers/timer/andes_plmt_timer.c
>>>>>>> index cec86718c7..7c50c46d9e 100644
>>>>>>> --- a/drivers/timer/andes_plmt_timer.c
>>>>>>> +++ b/drivers/timer/andes_plmt_timer.c
>>>>>>> @@ -13,11 +13,12 @@
>>>>>>>   #include <timer.h>
>>>>>>>   #include <asm/io.h>
>>>>>>>   #include <linux/err.h>
>>>>>>> +#include <div64.h>
>>>>>>>
>>>>>>>   /* mtime register */
>>>>>>>   #define MTIME_REG(base)                      ((ulong)(base))
>>>>>>>
>>>>>>> -static u64 andes_plmt_get_count(struct udevice *dev)
>>>>>>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>>>>>>   {
>>>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>>>> -26,12
>>>>>>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>>>>>>        .get_count = andes_plmt_get_count,  };
>>>>>>>
>>>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
>>>>>>> +timer_get_us(void) {
>>>>>>> +     u64 ticks;
>>>>>>> +
>>>>>>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>>>>>>> +     if (gd->arch.plmt) {
>>>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>>>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     return ticks;
>>>>>>> +}
>>>>>>> +#endif
>>>>>>> +
>>>>>>>   static int andes_plmt_probe(struct udevice *dev)  {
>>>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>>>        if (!dev->priv)
>>>>>>>                return -EINVAL;
>>>>>>>
>>>>>>> +     gd->arch.plmt = dev->priv;
>>>>>>>        return timer_timebase_fallback(dev);  }
>>>>>>>
>>>>>>> diff --git a/drivers/timer/riscv_timer.c
>>>>>>> b/drivers/timer/riscv_timer.c index 21ae184057..7fa8773da3 100644
>>>>>>> --- a/drivers/timer/riscv_timer.c
>>>>>>> +++ b/drivers/timer/riscv_timer.c
>>>>>>> @@ -15,8 +15,9 @@
>>>>>>>   #include <errno.h>
>>>>>>>   #include <timer.h>
>>>>>>>   #include <asm/csr.h>
>>>>>>> +#include <div64.h>
>>>>>>>
>>>>>>> -static u64 riscv_timer_get_count(struct udevice *dev)
>>>>>>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>>>>>>   {
>>>>>>>        __maybe_unused u32 hi, lo;
>>>>>>>
>>>>>>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice
>*dev)
>>>>>>>        return ((u64)hi << 32) | lo;
>>>>>>>   }
>>>>>>>
>>>>>>> +#if CONFIG_IS_ENABLED(RISCV_SMODE) unsigned long notrace
>>>>>>> +timer_get_us(void) {
>>>>>>> +     u64 ticks;
>>>>>>> +
>>>>>>> +     ticks = riscv_timer_get_count(NULL);
>>>>>>> +     do_div(ticks, CONFIG_SYS_HZ);
>>>>>>> +     return ticks;
>>>>>>> +}
>>>>>>> +#endif
>>>>>>> +
>>>>>>>   static int riscv_timer_probe(struct udevice *dev)  {
>>>>>>>        struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>>>>>>> diff --git a/drivers/timer/sifive_clint_timer.c
>>>>>>> b/drivers/timer/sifive_clint_timer.c
>>>>>>> index 00ce0f08d6..c341f7789b 100644
>>>>>>> --- a/drivers/timer/sifive_clint_timer.c
>>>>>>> +++ b/drivers/timer/sifive_clint_timer.c
>>>>>>> @@ -10,11 +10,12 @@
>>>>>>>   #include <timer.h>
>>>>>>>   #include <asm/io.h>
>>>>>>>   #include <linux/err.h>
>>>>>>> +#include <div64.h>
>>>>>>>
>>>>>>>   /* mtime register */
>>>>>>>   #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>>>>>>
>>>>>>> -static u64 sifive_clint_get_count(struct udevice *dev)
>>>>>>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>>>>>>   {
>>>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>>>> -23,12
>>>>>>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>>>>>>        .get_count = sifive_clint_get_count,  };
>>>>>>>
>>>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
>>>>>>> +timer_get_us(void) {
>>>>>>> +     u64 ticks;
>>>>>>> +
>>>>>>> +     /* FIXME: gd->arch.clint should contain valid base address */
>>>>>>> +     if (gd->arch.clint) {
>>>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>>>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>>>> +     }
>>>>>>> +
>>>>>>> +     return ticks;
>>>>>>> +}
>>>>>>> +#endif
>>>>>>> +
>>>>>>>   static int sifive_clint_probe(struct udevice *dev)  {
>>>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>>>        if (!dev->priv)
>>>>>>>                return -EINVAL;
>>>>>>>
>>>>>>> +     gd->arch.clint = dev->priv;
>>>>>>>        return timer_timebase_fallback(dev);  }
>>>>>>>
>>>>>>>
>>>>>
>>>
>>
Pragnesh Patel Nov. 12, 2020, 11:51 a.m. UTC | #8
>-----Original Message-----
>From: U-Boot <u-boot-bounces@lists.denx.de> On Behalf Of Pragnesh Patel
>Sent: 12 November 2020 13:06
>To: Heinrich Schuchardt <xypron.glpk@gmx.de>; Simon Glass
><sjg@chromium.org>
>Cc: atish.patra@wdc.com; palmerdabbelt@google.com; u-boot@lists.denx.de;
>bmeng.cn@gmail.com; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
>anup.patel@wdc.com; Sagar Kadam <sagar.kadam@openfive.com>;
>rick@andestech.com; Sean Anderson <seanga2@gmail.com>
>Subject: RE: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
>Hi Heinrich,
>
>>-----Original Message-----
>>From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>Sent: 12 November 2020 12:49
>>To: Pragnesh Patel <pragnesh.patel@openfive.com>; Simon Glass
>><sjg@chromium.org>
>>Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>u-boot@lists.denx.de; bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>><paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>><sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>><seanga2@gmail.com>
>>Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>
>>[External Email] Do not click links or attachments unless you recognize
>>the sender and know the content is safe
>>
>>On 11/12/20 8:09 AM, Heinrich Schuchardt wrote:
>>> On 11/12/20 7:34 AM, Pragnesh Patel wrote:
>>>> Hi Heinrich,
>>>>
>>>>> -----Original Message-----
>>>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>>>> Sent: 11 November 2020 19:18
>>>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>
>>>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>>>> u-boot@lists.denx.de; bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>>>>> <paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>>>>> <sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>>>>> <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>>>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>>>
>>>>> [External Email] Do not click links or attachments unless you
>>>>> recognize the sender and know the content is safe
>>>>>
>>>>> On 11/11/20 12:56 PM, Pragnesh Patel wrote:
>>>>>> Hi Heinrich,
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Heinrich Schuchardt <xypron.glpk@gmx.de>
>>>>>>> Sent: 11 November 2020 16:51
>>>>>>> To: Pragnesh Patel <pragnesh.patel@openfive.com>;
>>>>>>> u-boot@lists.denx.de
>>>>>>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>>>>>>> bmeng.cn@gmail.com; Paul Walmsley ( Sifive)
>>>>>>> <paul.walmsley@sifive.com>; anup.patel@wdc.com; Sagar Kadam
>>>>>>> <sagar.kadam@openfive.com>; rick@andestech.com; Sean Anderson
>>>>>>> <seanga2@gmail.com>; Simon Glass <sjg@chromium.org>
>>>>>>> Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>>>>>>
>>>>>>> [External Email] Do not click links or attachments unless you
>>>>>>> recognize the sender and know the content is safe
>>>>>>>
>>>>>>> On 11.11.20 11:14, Pragnesh Patel wrote:
>>>>>>>> Add timer_get_us() which is useful for tracing.
>>>>>>>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer
>>>>>>>> ticks and For M-mode U-Boot, mtime register will provide the same.
>>>>>>>>
>>>>>>>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>>>>>>>
>>>>>>> The default implementation of get_timer_us() in lib/time.c calls
>>>>>>> get_ticks() which calls timer_get_count(). The get_count()
>>>>>>> operation is implemented in drivers/timer/andes_plmt_timer.c,
>>>>>>> drivers/timer/sifive_clint_timer.c, drivers/timer/riscv_timer.c.
>>>>>>>
>>>>>>> Why do you need special timer_get_us() implementations?
>>>>>>> Isn't it enough to supply the get_count() operation in the drivers?
>>>>>>
>>>>>> get_ticks() is depend on gd->timer and there are 2 cases
>>>>>>
>>>>>> 1) if gd->timer== NULL then dm_timer_init() gets called and it
>>>>>> will call functions which are not marked with "notrace" so tracing got
>stuck.
>>>>>
>>>>> Thanks for the background information.
>>>>>
>>>>> Please, identify the existing functions that lack "notrace" and fix
>>>>> them. This will give us a solution for all existing boards and not
>>>>> for a small
>>selection.
>>>>> Furthermore it will avoid code duplication.
>>>>
>>>> I tried but There are so many functions which need "notrace".
>>>
>>> Let's start with the problem statement:
>>>
>>> When tracing functions is enabled this adds calls to
>>> __cyg_profile_func_enter() and __cyg_profile_func_exit() to the
>>> traced functions.
>>>
>>> __cyg_profile_func_exit() and __cyg_profile_func_exit() invoke
>>> timer_get_us() to record the entry and exit time.
>>>
>>> If timer_get_us() or any function used to implement does not carry
>>> __attribute__((no_instrument_function)) this will lead to an
>>> indefinite recursion.
>>>
>>> We have to change __cyg_profile_func_enter() and
>>> __cyg_profile_func_exit() such that during their execution no
>>> function is traced. We can do so by temporarily setting trace_enabled to false.
>>>
>>> Does this match your observation?
>>
>>I just tried to put this into a patch
>>
>>[PATCH 1/1] trace: avoid infinite recursion
>>https://lists.denx.de/pipermail/u-
>>boot/2020-November/432589.html
>>https://patchwork.ozlabs.org/project/uboot/patch/20201112071411.4202-1-
>>xypron.glpk@gmx.de/
>>
>>Does this solve you problem?
>
>Getting error, "Could not initialize timer (err -11)" from get_ticks() function.
>
>Below are my boot logs,
>
>U-Boot 2021.01-rc1-00244-g794c155581-dirty (Nov 12 2020 - 12:56:27 +0530)
>
>CPU:   rv64imafdc
>Model: SiFive HiFive Unleashed A00
>DRAM:  8 GiB
>trace: enabled
>Could not initialize timer (err -11)
>
>Could not initialize timer (err -11)
>
>Could not initialize timer (err -11)
>
>Could not initialize timer (err -11)

With Further debugging, this is because gd->dm_root is equal to NULL by initr_dm().
dm_timer_init() will fail if gd->dm_root == NULL.

int notrace dm_timer_init(void)
{
        if (gd->dm_root == NULL)
                return -EAGAIN;
}

So the solution is to call initr_dm() before initr_trace() so that gd->dm_root will become available. I will send a patch
to do the same.

>
>
>>
>>Best regards
>>
>>Heinrich
>>>
>>>>
>>>> Why don’t we consider removing gd->timer=NULL in initr_dm()
>>>> initr_dm()
>>>> {
>>>> #ifdef CONFIG_TIMER
>>>>          gd->timer = NULL;
>>>> #endif
>>>> }
>>>>
>>>> Or I can use TIMER_EARLY and return ticks and rate  by adding
>>>> timer_early_get_count() and timer_early_get_rate() repectively.
>>>>
>>>> Suggestions are welcome
>>>>
>>>>>
>>>>> In lib/trace.c consider replacing
>>>>> "__attribute__((no_instrument_function))" by "notrace".
>>>>>
>>>>> Best regards
>>>>>
>>>>> Heinrich
>>>>>
>>>>>>
>>>>>> 2) if gd->timer is already initialized then still initr_dm() will
>>>>>> make
>>>>>> gd->timer = NULL;
>>>>>>
>>>>>> initr_dm()
>>>>>> {
>>>>>> #ifdef CONFIG_TIMER
>>>>>>          gd->timer = NULL;
>>>>>> #endif
>>>>>> }
>>>>>>
>>>>>> So again dm_timer_init() gets called and tracing got stuck.
>>>>>>
>>>>>> So I thought better to implement timer_get_us().
>>>>>>
>>>>>>>
>>>>>>> Best regards
>>>>>>>
>>>>>>> Heinrich
>>>>>>>
>>>>>>>> ---
>>>>>>>>
>>>>>>>> Changes in v3:
>>>>>>>> - Added gd->arch.plmt in global data
>>>>>>>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>>>>>>>    and sifive_clint_get_count()
>>>>>>>>
>>>>>>>> Changes in v2:
>>>>>>>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>>>>>>>    and andes_plmt_timer.c.
>>>>>>>>
>>>>>>>>
>>>>>>>>   arch/riscv/include/asm/global_data.h |  3 +++
>>>>>>>>   drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>>>>>>>   drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>>>>>>>   drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>>>>>>>   4 files changed, 52 insertions(+), 3 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/arch/riscv/include/asm/global_data.h
>>>>>>>> b/arch/riscv/include/asm/global_data.h
>>>>>>>> index d3a0b1d221..4e22ceb83f 100644
>>>>>>>> --- a/arch/riscv/include/asm/global_data.h
>>>>>>>> +++ b/arch/riscv/include/asm/global_data.h
>>>>>>>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef
>>CONFIG_ANDES_PLIC
>>>>>>>>        void __iomem *plic;     /* plic base address */
>>>>>>>>   #endif
>>>>>>>> +#ifdef CONFIG_ANDES_PLMT
>>>>>>>> +     void __iomem *plmt;     /* plmt base address */
>>>>>>>> +#endif
>>>>>>>>   #if CONFIG_IS_ENABLED(SMP)
>>>>>>>>        struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>>>>>>>> a/drivers/timer/andes_plmt_timer.c
>>>>>>>> b/drivers/timer/andes_plmt_timer.c
>>>>>>>> index cec86718c7..7c50c46d9e 100644
>>>>>>>> --- a/drivers/timer/andes_plmt_timer.c
>>>>>>>> +++ b/drivers/timer/andes_plmt_timer.c
>>>>>>>> @@ -13,11 +13,12 @@
>>>>>>>>   #include <timer.h>
>>>>>>>>   #include <asm/io.h>
>>>>>>>>   #include <linux/err.h>
>>>>>>>> +#include <div64.h>
>>>>>>>>
>>>>>>>>   /* mtime register */
>>>>>>>>   #define MTIME_REG(base)                      ((ulong)(base))
>>>>>>>>
>>>>>>>> -static u64 andes_plmt_get_count(struct udevice *dev)
>>>>>>>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>>>>>>>   {
>>>>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>>>>> -26,12
>>>>>>>> +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>>>>>>>        .get_count = andes_plmt_get_count,  };
>>>>>>>>
>>>>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
>>>>>>>> +timer_get_us(void) {
>>>>>>>> +     u64 ticks;
>>>>>>>> +
>>>>>>>> +     /* FIXME: gd->arch.plmt should contain valid base address */
>>>>>>>> +     if (gd->arch.plmt) {
>>>>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>>>>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>>>>> +     }
>>>>>>>> +
>>>>>>>> +     return ticks;
>>>>>>>> +}
>>>>>>>> +#endif
>>>>>>>> +
>>>>>>>>   static int andes_plmt_probe(struct udevice *dev)  {
>>>>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>>>>        if (!dev->priv)
>>>>>>>>                return -EINVAL;
>>>>>>>>
>>>>>>>> +     gd->arch.plmt = dev->priv;
>>>>>>>>        return timer_timebase_fallback(dev);  }
>>>>>>>>
>>>>>>>> diff --git a/drivers/timer/riscv_timer.c
>>>>>>>> b/drivers/timer/riscv_timer.c index 21ae184057..7fa8773da3
>>>>>>>> 100644
>>>>>>>> --- a/drivers/timer/riscv_timer.c
>>>>>>>> +++ b/drivers/timer/riscv_timer.c
>>>>>>>> @@ -15,8 +15,9 @@
>>>>>>>>   #include <errno.h>
>>>>>>>>   #include <timer.h>
>>>>>>>>   #include <asm/csr.h>
>>>>>>>> +#include <div64.h>
>>>>>>>>
>>>>>>>> -static u64 riscv_timer_get_count(struct udevice *dev)
>>>>>>>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>>>>>>>   {
>>>>>>>>        __maybe_unused u32 hi, lo;
>>>>>>>>
>>>>>>>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct
>>>>>>>> udevice
>>*dev)
>>>>>>>>        return ((u64)hi << 32) | lo;
>>>>>>>>   }
>>>>>>>>
>>>>>>>> +#if CONFIG_IS_ENABLED(RISCV_SMODE) unsigned long notrace
>>>>>>>> +timer_get_us(void) {
>>>>>>>> +     u64 ticks;
>>>>>>>> +
>>>>>>>> +     ticks = riscv_timer_get_count(NULL);
>>>>>>>> +     do_div(ticks, CONFIG_SYS_HZ);
>>>>>>>> +     return ticks;
>>>>>>>> +}
>>>>>>>> +#endif
>>>>>>>> +
>>>>>>>>   static int riscv_timer_probe(struct udevice *dev)  {
>>>>>>>>        struct timer_dev_priv *uc_priv =
>>>>>>>> dev_get_uclass_priv(dev); diff --git
>>>>>>>> a/drivers/timer/sifive_clint_timer.c
>>>>>>>> b/drivers/timer/sifive_clint_timer.c
>>>>>>>> index 00ce0f08d6..c341f7789b 100644
>>>>>>>> --- a/drivers/timer/sifive_clint_timer.c
>>>>>>>> +++ b/drivers/timer/sifive_clint_timer.c
>>>>>>>> @@ -10,11 +10,12 @@
>>>>>>>>   #include <timer.h>
>>>>>>>>   #include <asm/io.h>
>>>>>>>>   #include <linux/err.h>
>>>>>>>> +#include <div64.h>
>>>>>>>>
>>>>>>>>   /* mtime register */
>>>>>>>>   #define MTIME_REG(base)                      ((ulong)(base) + 0xbff8)
>>>>>>>>
>>>>>>>> -static u64 sifive_clint_get_count(struct udevice *dev)
>>>>>>>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>>>>>>>   {
>>>>>>>>        return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>>>>>>>> -23,12
>>>>>>>> +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>>>>>>>        .get_count = sifive_clint_get_count,  };
>>>>>>>>
>>>>>>>> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
>>>>>>>> +timer_get_us(void) {
>>>>>>>> +     u64 ticks;
>>>>>>>> +
>>>>>>>> +     /* FIXME: gd->arch.clint should contain valid base address */
>>>>>>>> +     if (gd->arch.clint) {
>>>>>>>> +             ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>>>>>>>> +             do_div(ticks, CONFIG_SYS_HZ);
>>>>>>>> +     }
>>>>>>>> +
>>>>>>>> +     return ticks;
>>>>>>>> +}
>>>>>>>> +#endif
>>>>>>>> +
>>>>>>>>   static int sifive_clint_probe(struct udevice *dev)  {
>>>>>>>>        dev->priv = dev_read_addr_ptr(dev);
>>>>>>>>        if (!dev->priv)
>>>>>>>>                return -EINVAL;
>>>>>>>>
>>>>>>>> +     gd->arch.clint = dev->priv;
>>>>>>>>        return timer_timebase_fallback(dev);  }
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>
>>>
Rick Chen Nov. 13, 2020, 8:07 a.m. UTC | #9
Hi Pragnesh

> From: Pragnesh Patel [mailto:pragnesh.patel@sifive.com]
> Sent: Wednesday, November 11, 2020 6:15 PM
> To: u-boot@lists.denx.de
> Cc: atish.patra@wdc.com; palmerdabbelt@google.com; bmeng.cn@gmail.com; paul.walmsley@sifive.com; anup.patel@wdc.com; sagar.kadam@sifive.com; Rick Jian-Zhi Chen(陳建志); Pragnesh Patel; Sean Anderson; Heinrich Schuchardt; Simon Glass
> Subject: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
> Add timer_get_us() which is useful for tracing.
> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide
> a timer ticks and For M-mode U-Boot, mtime register will
> provide the same.
>
> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
> ---
>
> Changes in v3:
> - Added gd->arch.plmt in global data
> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>   and sifive_clint_get_count()
>
> Changes in v2:
> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>   and andes_plmt_timer.c.
>
>
>  arch/riscv/include/asm/global_data.h |  3 +++
>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>  4 files changed, 52 insertions(+), 3 deletions(-)
>
> diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
> index d3a0b1d221..4e22ceb83f 100644
> --- a/arch/riscv/include/asm/global_data.h
> +++ b/arch/riscv/include/asm/global_data.h
> @@ -24,6 +24,9 @@ struct arch_global_data {
>  #ifdef CONFIG_ANDES_PLIC
>         void __iomem *plic;     /* plic base address */
>  #endif
> +#ifdef CONFIG_ANDES_PLMT

It shall be CONFIG_ANDES_PLMT, or it will compile fail as below:

drivers/timer/andes_plmt_timer.c: In function 'timer_get_us':
drivers/timer/andes_plmt_timer.c:36:15: error: 'struct
arch_global_data' has no member named 'plmt'; did you mean 'plic'?
  if (gd->arch.plmt) {
               ^~~~
               plic
drivers/timer/andes_plmt_timer.c:37:52: error: 'struct
arch_global_data' has no member named 'plmt'; did you mean 'plic'?
   ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));

And it is not proper to have dependency of data structure between
/arch/riscv/include/asm/* and /drivers/timer/*
Maybe enable TIMER_EARLY and use timer_get_us() of /lib/time.c will be better.
I also found that without dm_timer_init() in initf_dm(),
andes_plmt_get_count() will be executed ahead of andes_plmt_probe().

Thanks,
Rick


> +       void __iomem *plmt;     /* plmt base address */
> +#endif
>  #if CONFIG_IS_ENABLED(SMP)
>         struct ipi_data ipi[CONFIG_NR_CPUS];
>  #endif
> diff --git a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
> index cec86718c7..7c50c46d9e 100644
> --- a/drivers/timer/andes_plmt_timer.c
> +++ b/drivers/timer/andes_plmt_timer.c
> @@ -13,11 +13,12 @@
>  #include <timer.h>
>  #include <asm/io.h>
>  #include <linux/err.h>
> +#include <div64.h>
>
>  /* mtime register */
>  #define MTIME_REG(base)                        ((ulong)(base))
>
> -static u64 andes_plmt_get_count(struct udevice *dev)
> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>  {
>         return readq((void __iomem *)MTIME_REG(dev->priv));
>  }
> @@ -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>         .get_count = andes_plmt_get_count,
>  };
>
> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> +unsigned long notrace timer_get_us(void)
> +{
> +       u64 ticks;
> +
> +       /* FIXME: gd->arch.plmt should contain valid base address */
> +       if (gd->arch.plmt) {
> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
> +               do_div(ticks, CONFIG_SYS_HZ);
> +       }
> +
> +       return ticks;
> +}
> +#endif
> +
>  static int andes_plmt_probe(struct udevice *dev)
>  {
>         dev->priv = dev_read_addr_ptr(dev);
>         if (!dev->priv)
>                 return -EINVAL;
>
> +       gd->arch.plmt = dev->priv;
>         return timer_timebase_fallback(dev);
>  }
>
> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
> index 21ae184057..7fa8773da3 100644
> --- a/drivers/timer/riscv_timer.c
> +++ b/drivers/timer/riscv_timer.c
> @@ -15,8 +15,9 @@
>  #include <errno.h>
>  #include <timer.h>
>  #include <asm/csr.h>
> +#include <div64.h>
>
> -static u64 riscv_timer_get_count(struct udevice *dev)
> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>  {
>         __maybe_unused u32 hi, lo;
>
> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>         return ((u64)hi << 32) | lo;
>  }
>
> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
> +unsigned long notrace timer_get_us(void)
> +{
> +       u64 ticks;
> +
> +       ticks = riscv_timer_get_count(NULL);
> +       do_div(ticks, CONFIG_SYS_HZ);
> +       return ticks;
> +}
> +#endif
> +
>  static int riscv_timer_probe(struct udevice *dev)
>  {
>         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c
> index 00ce0f08d6..c341f7789b 100644
> --- a/drivers/timer/sifive_clint_timer.c
> +++ b/drivers/timer/sifive_clint_timer.c
> @@ -10,11 +10,12 @@
>  #include <timer.h>
>  #include <asm/io.h>
>  #include <linux/err.h>
> +#include <div64.h>
>
>  /* mtime register */
>  #define MTIME_REG(base)                        ((ulong)(base) + 0xbff8)
>
> -static u64 sifive_clint_get_count(struct udevice *dev)
> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>  {
>         return readq((void __iomem *)MTIME_REG(dev->priv));
>  }
> @@ -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>         .get_count = sifive_clint_get_count,
>  };
>
> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> +unsigned long notrace timer_get_us(void)
> +{
> +       u64 ticks;
> +
> +       /* FIXME: gd->arch.clint should contain valid base address */
> +       if (gd->arch.clint) {
> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
> +               do_div(ticks, CONFIG_SYS_HZ);
> +       }
> +
> +       return ticks;
> +}
> +#endif
> +
>  static int sifive_clint_probe(struct udevice *dev)
>  {
>         dev->priv = dev_read_addr_ptr(dev);
>         if (!dev->priv)
>                 return -EINVAL;
>
> +       gd->arch.clint = dev->priv;
>         return timer_timebase_fallback(dev);
>  }
>
> --
> 2.17.1
Pragnesh Patel Nov. 15, 2020, 11:28 a.m. UTC | #10
Hi Rick,

>-----Original Message-----
>From: Rick Chen <rickchen36@gmail.com>
>Sent: 13 November 2020 13:37
>To: Pragnesh Patel <pragnesh.patel@openfive.com>
>Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Atish Patra
><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng
><bmeng.cn@gmail.com>; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
>Anup Patel <anup.patel@wdc.com>; Sagar Kadam
><sagar.kadam@openfive.com>; Sean Anderson <seanga2@gmail.com>; rick
><rick@andestech.com>; Alan Kao <alankao@andestech.com>; Leo Liang
><ycliang@andestech.com>
>Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>Hi Pragnesh
>
>> From: Pragnesh Patel [mailto:pragnesh.patel@sifive.com]
>> Sent: Wednesday, November 11, 2020 6:15 PM
>> To: u-boot@lists.denx.de
>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>bmeng.cn@gmail.com;
>> paul.walmsley@sifive.com; anup.patel@wdc.com; sagar.kadam@sifive.com;
>> Rick Jian-Zhi Chen(陳建志); Pragnesh Patel; Sean Anderson; Heinrich
>> Schuchardt; Simon Glass
>> Subject: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>
>> Add timer_get_us() which is useful for tracing.
>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>> and For M-mode U-Boot, mtime register will provide the same.
>>
>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>> ---
>>
>> Changes in v3:
>> - Added gd->arch.plmt in global data
>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>   and sifive_clint_get_count()
>>
>> Changes in v2:
>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>   and andes_plmt_timer.c.
>>
>>
>>  arch/riscv/include/asm/global_data.h |  3 +++
>>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>  4 files changed, 52 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/riscv/include/asm/global_data.h
>> b/arch/riscv/include/asm/global_data.h
>> index d3a0b1d221..4e22ceb83f 100644
>> --- a/arch/riscv/include/asm/global_data.h
>> +++ b/arch/riscv/include/asm/global_data.h
>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>         void __iomem *plic;     /* plic base address */
>>  #endif
>> +#ifdef CONFIG_ANDES_PLMT
>
>It shall be CONFIG_ANDES_PLMT, or it will compile fail as below:
>
>drivers/timer/andes_plmt_timer.c: In function 'timer_get_us':
>drivers/timer/andes_plmt_timer.c:36:15: error: 'struct arch_global_data' has no
>member named 'plmt'; did you mean 'plic'?
>  if (gd->arch.plmt) {
>               ^~~~
>               plic
>drivers/timer/andes_plmt_timer.c:37:52: error: 'struct arch_global_data' has no
>member named 'plmt'; did you mean 'plic'?
>   ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));

No I did not get this. Why are you getting this error because plmt is already defined ?

>
>And it is not proper to have dependency of data structure between
>/arch/riscv/include/asm/* and /drivers/timer/* Maybe enable TIMER_EARLY and
>use timer_get_us() of /lib/time.c will be better.
>I also found that without dm_timer_init() in initf_dm(),
>andes_plmt_get_count() will be executed ahead of andes_plmt_probe().

Thanks Rick but me and Heinrich are working on different approach to use existing dm_timer_init() from lib/time.c

https://patchwork.ozlabs.org/project/uboot/patch/20201112071411.4202-1-xypron.glpk@gmx.de/

>
>Thanks,
>Rick
>
>
>> +       void __iomem *plmt;     /* plmt base address */
>> +#endif
>>  #if CONFIG_IS_ENABLED(SMP)
>>         struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>> a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
>> index cec86718c7..7c50c46d9e 100644
>> --- a/drivers/timer/andes_plmt_timer.c
>> +++ b/drivers/timer/andes_plmt_timer.c
>> @@ -13,11 +13,12 @@
>>  #include <timer.h>
>>  #include <asm/io.h>
>>  #include <linux/err.h>
>> +#include <div64.h>
>>
>>  /* mtime register */
>>  #define MTIME_REG(base)                        ((ulong)(base))
>>
>> -static u64 andes_plmt_get_count(struct udevice *dev)
>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>  {
>>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>> -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>         .get_count = andes_plmt_get_count,  };
>>
>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +       u64 ticks;
>> +
>> +       /* FIXME: gd->arch.plmt should contain valid base address */
>> +       if (gd->arch.plmt) {
>> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>> +               do_div(ticks, CONFIG_SYS_HZ);
>> +       }
>> +
>> +       return ticks;
>> +}
>> +#endif
>> +
>>  static int andes_plmt_probe(struct udevice *dev)  {
>>         dev->priv = dev_read_addr_ptr(dev);
>>         if (!dev->priv)
>>                 return -EINVAL;
>>
>> +       gd->arch.plmt = dev->priv;
>>         return timer_timebase_fallback(dev);  }
>>
>> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
>> index 21ae184057..7fa8773da3 100644
>> --- a/drivers/timer/riscv_timer.c
>> +++ b/drivers/timer/riscv_timer.c
>> @@ -15,8 +15,9 @@
>>  #include <errno.h>
>>  #include <timer.h>
>>  #include <asm/csr.h>
>> +#include <div64.h>
>>
>> -static u64 riscv_timer_get_count(struct udevice *dev)
>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>  {
>>         __maybe_unused u32 hi, lo;
>>
>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>         return ((u64)hi << 32) | lo;
>>  }
>>
>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +       u64 ticks;
>> +
>> +       ticks = riscv_timer_get_count(NULL);
>> +       do_div(ticks, CONFIG_SYS_HZ);
>> +       return ticks;
>> +}
>> +#endif
>> +
>>  static int riscv_timer_probe(struct udevice *dev)  {
>>         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>> diff --git a/drivers/timer/sifive_clint_timer.c
>> b/drivers/timer/sifive_clint_timer.c
>> index 00ce0f08d6..c341f7789b 100644
>> --- a/drivers/timer/sifive_clint_timer.c
>> +++ b/drivers/timer/sifive_clint_timer.c
>> @@ -10,11 +10,12 @@
>>  #include <timer.h>
>>  #include <asm/io.h>
>>  #include <linux/err.h>
>> +#include <div64.h>
>>
>>  /* mtime register */
>>  #define MTIME_REG(base)                        ((ulong)(base) + 0xbff8)
>>
>> -static u64 sifive_clint_get_count(struct udevice *dev)
>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>  {
>>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>> -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>         .get_count = sifive_clint_get_count,  };
>>
>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +       u64 ticks;
>> +
>> +       /* FIXME: gd->arch.clint should contain valid base address */
>> +       if (gd->arch.clint) {
>> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>> +               do_div(ticks, CONFIG_SYS_HZ);
>> +       }
>> +
>> +       return ticks;
>> +}
>> +#endif
>> +
>>  static int sifive_clint_probe(struct udevice *dev)  {
>>         dev->priv = dev_read_addr_ptr(dev);
>>         if (!dev->priv)
>>                 return -EINVAL;
>>
>> +       gd->arch.clint = dev->priv;
>>         return timer_timebase_fallback(dev);  }
>>
>> --
>> 2.17.1
Rick Chen Nov. 16, 2020, 5:47 a.m. UTC | #11
Hi Pragnesh

> Hi Rick,
>
> >-----Original Message-----
> >From: Rick Chen <rickchen36@gmail.com>
> >Sent: 13 November 2020 13:37
> >To: Pragnesh Patel <pragnesh.patel@openfive.com>
> >Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Atish Patra
> ><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng
> ><bmeng.cn@gmail.com>; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
> >Anup Patel <anup.patel@wdc.com>; Sagar Kadam
> ><sagar.kadam@openfive.com>; Sean Anderson <seanga2@gmail.com>; rick
> ><rick@andestech.com>; Alan Kao <alankao@andestech.com>; Leo Liang
> ><ycliang@andestech.com>
> >Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
> >
> >[External Email] Do not click links or attachments unless you recognize the
> >sender and know the content is safe
> >
> >Hi Pragnesh
> >
> >> From: Pragnesh Patel [mailto:pragnesh.patel@sifive.com]
> >> Sent: Wednesday, November 11, 2020 6:15 PM
> >> To: u-boot@lists.denx.de
> >> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
> >bmeng.cn@gmail.com;
> >> paul.walmsley@sifive.com; anup.patel@wdc.com; sagar.kadam@sifive.com;
> >> Rick Jian-Zhi Chen(陳建志); Pragnesh Patel; Sean Anderson; Heinrich
> >> Schuchardt; Simon Glass
> >> Subject: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
> >>
> >> Add timer_get_us() which is useful for tracing.
> >> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
> >> and For M-mode U-Boot, mtime register will provide the same.
> >>
> >> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
> >> ---
> >>
> >> Changes in v3:
> >> - Added gd->arch.plmt in global data
> >> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
> >>   and sifive_clint_get_count()
> >>
> >> Changes in v2:
> >> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
> >>   and andes_plmt_timer.c.
> >>
> >>
> >>  arch/riscv/include/asm/global_data.h |  3 +++
> >>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
> >>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
> >>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
> >>  4 files changed, 52 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/riscv/include/asm/global_data.h
> >> b/arch/riscv/include/asm/global_data.h
> >> index d3a0b1d221..4e22ceb83f 100644
> >> --- a/arch/riscv/include/asm/global_data.h
> >> +++ b/arch/riscv/include/asm/global_data.h
> >> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
> >>         void __iomem *plic;     /* plic base address */
> >>  #endif
> >> +#ifdef CONFIG_ANDES_PLMT
> >
> >It shall be CONFIG_ANDES_PLMT, or it will compile fail as below:

Sorry, it's shall be CONFIG_ANDES_PLMT_TIMER here // because of
obj-$(CONFIG_ANDES_PLMT_TIMER) += andes_plmt_timer.o
Or it will have a compiling error.

> >
> >drivers/timer/andes_plmt_timer.c: In function 'timer_get_us':
> >drivers/timer/andes_plmt_timer.c:36:15: error: 'struct arch_global_data' has no
> >member named 'plmt'; did you mean 'plic'?
> >  if (gd->arch.plmt) {
> >               ^~~~
> >               plic
> >drivers/timer/andes_plmt_timer.c:37:52: error: 'struct arch_global_data' has no
> >member named 'plmt'; did you mean 'plic'?
> >   ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>
> No I did not get this. Why are you getting this error because plmt is already defined ?
>
> >
> >And it is not proper to have dependency of data structure between
> >/arch/riscv/include/asm/* and /drivers/timer/* Maybe enable TIMER_EARLY and
> >use timer_get_us() of /lib/time.c will be better.
> >I also found that without dm_timer_init() in initf_dm(),
> >andes_plmt_get_count() will be executed ahead of andes_plmt_probe().
>
> Thanks Rick but me and Heinrich are working on different approach to use existing dm_timer_init() from lib/time.c
>
> https://patchwork.ozlabs.org/project/uboot/patch/20201112071411.4202-1-xypron.glpk@gmx.de/

OK

Thanks,
Rick

>
> >
> >Thanks,
> >Rick
> >
> >
> >> +       void __iomem *plmt;     /* plmt base address */
> >> +#endif
> >>  #if CONFIG_IS_ENABLED(SMP)
> >>         struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
> >> a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
> >> index cec86718c7..7c50c46d9e 100644
> >> --- a/drivers/timer/andes_plmt_timer.c
> >> +++ b/drivers/timer/andes_plmt_timer.c
> >> @@ -13,11 +13,12 @@
> >>  #include <timer.h>
> >>  #include <asm/io.h>
> >>  #include <linux/err.h>
> >> +#include <div64.h>
> >>
> >>  /* mtime register */
> >>  #define MTIME_REG(base)                        ((ulong)(base))
> >>
> >> -static u64 andes_plmt_get_count(struct udevice *dev)
> >> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
> >>  {
> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
> >> -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
> >>         .get_count = andes_plmt_get_count,  };
> >>
> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> >> +unsigned long notrace timer_get_us(void) {
> >> +       u64 ticks;
> >> +
> >> +       /* FIXME: gd->arch.plmt should contain valid base address */
> >> +       if (gd->arch.plmt) {
> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
> >> +               do_div(ticks, CONFIG_SYS_HZ);
> >> +       }
> >> +
> >> +       return ticks;
> >> +}
> >> +#endif
> >> +
> >>  static int andes_plmt_probe(struct udevice *dev)  {
> >>         dev->priv = dev_read_addr_ptr(dev);
> >>         if (!dev->priv)
> >>                 return -EINVAL;
> >>
> >> +       gd->arch.plmt = dev->priv;
> >>         return timer_timebase_fallback(dev);  }
> >>
> >> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
> >> index 21ae184057..7fa8773da3 100644
> >> --- a/drivers/timer/riscv_timer.c
> >> +++ b/drivers/timer/riscv_timer.c
> >> @@ -15,8 +15,9 @@
> >>  #include <errno.h>
> >>  #include <timer.h>
> >>  #include <asm/csr.h>
> >> +#include <div64.h>
> >>
> >> -static u64 riscv_timer_get_count(struct udevice *dev)
> >> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
> >>  {
> >>         __maybe_unused u32 hi, lo;
> >>
> >> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
> >>         return ((u64)hi << 32) | lo;
> >>  }
> >>
> >> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
> >> +unsigned long notrace timer_get_us(void) {
> >> +       u64 ticks;
> >> +
> >> +       ticks = riscv_timer_get_count(NULL);
> >> +       do_div(ticks, CONFIG_SYS_HZ);
> >> +       return ticks;
> >> +}
> >> +#endif
> >> +
> >>  static int riscv_timer_probe(struct udevice *dev)  {
> >>         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> >> diff --git a/drivers/timer/sifive_clint_timer.c
> >> b/drivers/timer/sifive_clint_timer.c
> >> index 00ce0f08d6..c341f7789b 100644
> >> --- a/drivers/timer/sifive_clint_timer.c
> >> +++ b/drivers/timer/sifive_clint_timer.c
> >> @@ -10,11 +10,12 @@
> >>  #include <timer.h>
> >>  #include <asm/io.h>
> >>  #include <linux/err.h>
> >> +#include <div64.h>
> >>
> >>  /* mtime register */
> >>  #define MTIME_REG(base)                        ((ulong)(base) + 0xbff8)
> >>
> >> -static u64 sifive_clint_get_count(struct udevice *dev)
> >> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
> >>  {
> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
> >> -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
> >>         .get_count = sifive_clint_get_count,  };
> >>
> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> >> +unsigned long notrace timer_get_us(void) {
> >> +       u64 ticks;
> >> +
> >> +       /* FIXME: gd->arch.clint should contain valid base address */
> >> +       if (gd->arch.clint) {
> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
> >> +               do_div(ticks, CONFIG_SYS_HZ);
> >> +       }
> >> +
> >> +       return ticks;
> >> +}
> >> +#endif
> >> +
> >>  static int sifive_clint_probe(struct udevice *dev)  {
> >>         dev->priv = dev_read_addr_ptr(dev);
> >>         if (!dev->priv)
> >>                 return -EINVAL;
> >>
> >> +       gd->arch.clint = dev->priv;
> >>         return timer_timebase_fallback(dev);  }
> >>
> >> --
> >> 2.17.1
Pragnesh Patel Nov. 17, 2020, 8:30 a.m. UTC | #12
Hi Rick,

>-----Original Message-----
>From: Rick Chen <rickchen36@gmail.com>
>Sent: 13 November 2020 13:37
>To: Pragnesh Patel <pragnesh.patel@openfive.com>
>Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Atish Patra
><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng
><bmeng.cn@gmail.com>; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
>Anup Patel <anup.patel@wdc.com>; Sagar Kadam
><sagar.kadam@openfive.com>; Sean Anderson <seanga2@gmail.com>; rick
><rick@andestech.com>; Alan Kao <alankao@andestech.com>; Leo Liang
><ycliang@andestech.com>
>Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>Hi Pragnesh
>
>> From: Pragnesh Patel [mailto:pragnesh.patel@sifive.com]
>> Sent: Wednesday, November 11, 2020 6:15 PM
>> To: u-boot@lists.denx.de
>> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>bmeng.cn@gmail.com;
>> paul.walmsley@sifive.com; anup.patel@wdc.com; sagar.kadam@sifive.com;
>> Rick Jian-Zhi Chen(陳建志); Pragnesh Patel; Sean Anderson; Heinrich
>> Schuchardt; Simon Glass
>> Subject: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>>
>> Add timer_get_us() which is useful for tracing.
>> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
>> and For M-mode U-Boot, mtime register will provide the same.
>>
>> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>> ---
>>
>> Changes in v3:
>> - Added gd->arch.plmt in global data
>> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>>   and sifive_clint_get_count()
>>
>> Changes in v2:
>> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>>   and andes_plmt_timer.c.
>>
>>
>>  arch/riscv/include/asm/global_data.h |  3 +++
>>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>>  4 files changed, 52 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/riscv/include/asm/global_data.h
>> b/arch/riscv/include/asm/global_data.h
>> index d3a0b1d221..4e22ceb83f 100644
>> --- a/arch/riscv/include/asm/global_data.h
>> +++ b/arch/riscv/include/asm/global_data.h
>> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>>         void __iomem *plic;     /* plic base address */
>>  #endif
>> +#ifdef CONFIG_ANDES_PLMT
>
>It shall be CONFIG_ANDES_PLMT, or it will compile fail as below:
>
>drivers/timer/andes_plmt_timer.c: In function 'timer_get_us':
>drivers/timer/andes_plmt_timer.c:36:15: error: 'struct arch_global_data' has no
>member named 'plmt'; did you mean 'plic'?
>  if (gd->arch.plmt) {
>               ^~~~
>               plic
>drivers/timer/andes_plmt_timer.c:37:52: error: 'struct arch_global_data' has no
>member named 'plmt'; did you mean 'plic'?
>   ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>
>And it is not proper to have dependency of data structure between
>/arch/riscv/include/asm/* and /drivers/timer/* Maybe enable TIMER_EARLY and
>use timer_get_us() of /lib/time.c will be better.

I am planning to use TIMER_EARLY for tracing.

With TIMER_EARLY, I need to implement timer_early_get_rate() and timer_early_get_count()

For timer_early_get_count(), I need PLMT or CLINT base address to read mtime register.
So I think it's better to save base address in gd->arch.clint or gd->arch.plmt.

Let me know if you have any other idea to save PLM or CLINT base address.

For timer_early_get_rate(), I will add new variable in global data (gd)
Like, gd->arch.clock_rate;       /* Clock rate of timer in Hz */
This will return Timer frequency in Hz.

Tracing is only useful in U-Boot not in U-Boot SPL so I am doing this for M mode U-boot and
S mode U-Boot.

>I also found that without dm_timer_init() in initf_dm(),
>andes_plmt_get_count() will be executed ahead of andes_plmt_probe().

If andes_plmt_get_count() executed before andes_plmt_probe() then how did it will get
PLMT base address ?

>
>Thanks,
>Rick
>
>
>> +       void __iomem *plmt;     /* plmt base address */
>> +#endif
>>  #if CONFIG_IS_ENABLED(SMP)
>>         struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>> a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
>> index cec86718c7..7c50c46d9e 100644
>> --- a/drivers/timer/andes_plmt_timer.c
>> +++ b/drivers/timer/andes_plmt_timer.c
>> @@ -13,11 +13,12 @@
>>  #include <timer.h>
>>  #include <asm/io.h>
>>  #include <linux/err.h>
>> +#include <div64.h>
>>
>>  /* mtime register */
>>  #define MTIME_REG(base)                        ((ulong)(base))
>>
>> -static u64 andes_plmt_get_count(struct udevice *dev)
>> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>>  {
>>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>> -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>>         .get_count = andes_plmt_get_count,  };
>>
>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +       u64 ticks;
>> +
>> +       /* FIXME: gd->arch.plmt should contain valid base address */
>> +       if (gd->arch.plmt) {
>> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>> +               do_div(ticks, CONFIG_SYS_HZ);
>> +       }
>> +
>> +       return ticks;
>> +}
>> +#endif
>> +
>>  static int andes_plmt_probe(struct udevice *dev)  {
>>         dev->priv = dev_read_addr_ptr(dev);
>>         if (!dev->priv)
>>                 return -EINVAL;
>>
>> +       gd->arch.plmt = dev->priv;
>>         return timer_timebase_fallback(dev);  }
>>
>> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
>> index 21ae184057..7fa8773da3 100644
>> --- a/drivers/timer/riscv_timer.c
>> +++ b/drivers/timer/riscv_timer.c
>> @@ -15,8 +15,9 @@
>>  #include <errno.h>
>>  #include <timer.h>
>>  #include <asm/csr.h>
>> +#include <div64.h>
>>
>> -static u64 riscv_timer_get_count(struct udevice *dev)
>> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>>  {
>>         __maybe_unused u32 hi, lo;
>>
>> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
>>         return ((u64)hi << 32) | lo;
>>  }
>>
>> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +       u64 ticks;
>> +
>> +       ticks = riscv_timer_get_count(NULL);
>> +       do_div(ticks, CONFIG_SYS_HZ);
>> +       return ticks;
>> +}
>> +#endif
>> +
>>  static int riscv_timer_probe(struct udevice *dev)  {
>>         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>> diff --git a/drivers/timer/sifive_clint_timer.c
>> b/drivers/timer/sifive_clint_timer.c
>> index 00ce0f08d6..c341f7789b 100644
>> --- a/drivers/timer/sifive_clint_timer.c
>> +++ b/drivers/timer/sifive_clint_timer.c
>> @@ -10,11 +10,12 @@
>>  #include <timer.h>
>>  #include <asm/io.h>
>>  #include <linux/err.h>
>> +#include <div64.h>
>>
>>  /* mtime register */
>>  #define MTIME_REG(base)                        ((ulong)(base) + 0xbff8)
>>
>> -static u64 sifive_clint_get_count(struct udevice *dev)
>> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>>  {
>>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>> -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>>         .get_count = sifive_clint_get_count,  };
>>
>> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
>> +unsigned long notrace timer_get_us(void) {
>> +       u64 ticks;
>> +
>> +       /* FIXME: gd->arch.clint should contain valid base address */
>> +       if (gd->arch.clint) {
>> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>> +               do_div(ticks, CONFIG_SYS_HZ);
>> +       }
>> +
>> +       return ticks;
>> +}
>> +#endif
>> +
>>  static int sifive_clint_probe(struct udevice *dev)  {
>>         dev->priv = dev_read_addr_ptr(dev);
>>         if (!dev->priv)
>>                 return -EINVAL;
>>
>> +       gd->arch.clint = dev->priv;
>>         return timer_timebase_fallback(dev);  }
>>
>> --
>> 2.17.1
Leo Liang Nov. 23, 2020, 5:57 a.m. UTC | #13
On Tue, Nov 17, 2020 at 08:30:21AM +0000, Pragnesh Patel wrote:

Hi Pragnesh,

> Hi Rick,
> 
> >-----Original Message-----
> >From: Rick Chen <rickchen36@gmail.com>
> >Sent: 13 November 2020 13:37
> >To: Pragnesh Patel <pragnesh.patel@openfive.com>
> >Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Atish Patra
> ><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng
> ><bmeng.cn@gmail.com>; Paul Walmsley ( Sifive) <paul.walmsley@sifive.com>;
> >Anup Patel <anup.patel@wdc.com>; Sagar Kadam
> ><sagar.kadam@openfive.com>; Sean Anderson <seanga2@gmail.com>; rick
> ><rick@andestech.com>; Alan Kao <alankao@andestech.com>; Leo Liang
> ><ycliang@andestech.com>
> >Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
> >
> >[External Email] Do not click links or attachments unless you recognize the
> >sender and know the content is safe
> >
> >Hi Pragnesh
> >
> >> From: Pragnesh Patel [mailto:pragnesh.patel@sifive.com]
> >> Sent: Wednesday, November 11, 2020 6:15 PM
> >> To: u-boot@lists.denx.de
> >> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
> >bmeng.cn@gmail.com;
> >> paul.walmsley@sifive.com; anup.patel@wdc.com; sagar.kadam@sifive.com;
> >> Rick Jian-Zhi Chen(陳建志); Pragnesh Patel; Sean Anderson; Heinrich
> >> Schuchardt; Simon Glass
> >> Subject: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
> >>
> >> Add timer_get_us() which is useful for tracing.
> >> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer ticks
> >> and For M-mode U-Boot, mtime register will provide the same.
> >>
> >> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
> >> ---
> >>
> >> Changes in v3:
> >> - Added gd->arch.plmt in global data
> >> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
> >>   and sifive_clint_get_count()
> >>
> >> Changes in v2:
> >> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
> >>   and andes_plmt_timer.c.
> >>
> >>
> >>  arch/riscv/include/asm/global_data.h |  3 +++
> >>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
> >>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
> >>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
> >>  4 files changed, 52 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/riscv/include/asm/global_data.h
> >> b/arch/riscv/include/asm/global_data.h
> >> index d3a0b1d221..4e22ceb83f 100644
> >> --- a/arch/riscv/include/asm/global_data.h
> >> +++ b/arch/riscv/include/asm/global_data.h
> >> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
> >>         void __iomem *plic;     /* plic base address */
> >>  #endif
> >> +#ifdef CONFIG_ANDES_PLMT
> >
> >It shall be CONFIG_ANDES_PLMT, or it will compile fail as below:
> >
> >drivers/timer/andes_plmt_timer.c: In function 'timer_get_us':
> >drivers/timer/andes_plmt_timer.c:36:15: error: 'struct arch_global_data' has no
> >member named 'plmt'; did you mean 'plic'?
> >  if (gd->arch.plmt) {
> >               ^~~~
> >               plic
> >drivers/timer/andes_plmt_timer.c:37:52: error: 'struct arch_global_data' has no
> >member named 'plmt'; did you mean 'plic'?
> >   ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
> >

This patch will cause compile error with ae350 defconfig.

${uboot}/drivers/timer/Makefile is articulated in this way,
"obj-$(CONFIG_ANDES_PLMT_TIMER) += andes_plmt_timer.o",
so the #ifdef indicator in ${uboot}/arch/riscv/include/asm/global_data.h should use CONFIG_ANDES_PLMT_TIMER.

Best regards,
Leo

> >And it is not proper to have dependency of data structure between
> >/arch/riscv/include/asm/* and /drivers/timer/* Maybe enable TIMER_EARLY and
> >use timer_get_us() of /lib/time.c will be better.
> 
> I am planning to use TIMER_EARLY for tracing.
> 
> With TIMER_EARLY, I need to implement timer_early_get_rate() and timer_early_get_count()
> 
> For timer_early_get_count(), I need PLMT or CLINT base address to read mtime register.
> So I think it's better to save base address in gd->arch.clint or gd->arch.plmt.
> 
> Let me know if you have any other idea to save PLM or CLINT base address.
> 
> For timer_early_get_rate(), I will add new variable in global data (gd)
> Like, gd->arch.clock_rate;       /* Clock rate of timer in Hz */
> This will return Timer frequency in Hz.
> 
> Tracing is only useful in U-Boot not in U-Boot SPL so I am doing this for M mode U-boot and
> S mode U-Boot.
> 
> >I also found that without dm_timer_init() in initf_dm(),
> >andes_plmt_get_count() will be executed ahead of andes_plmt_probe().
> 
> If andes_plmt_get_count() executed before andes_plmt_probe() then how did it will get
> PLMT base address ?
> 
> >
> >Thanks,
> >Rick
> >
> >
> >> +       void __iomem *plmt;     /* plmt base address */
> >> +#endif
> >>  #if CONFIG_IS_ENABLED(SMP)
> >>         struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
> >> a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
> >> index cec86718c7..7c50c46d9e 100644
> >> --- a/drivers/timer/andes_plmt_timer.c
> >> +++ b/drivers/timer/andes_plmt_timer.c
> >> @@ -13,11 +13,12 @@
> >>  #include <timer.h>
> >>  #include <asm/io.h>
> >>  #include <linux/err.h>
> >> +#include <div64.h>
> >>
> >>  /* mtime register */
> >>  #define MTIME_REG(base)                        ((ulong)(base))
> >>
> >> -static u64 andes_plmt_get_count(struct udevice *dev)
> >> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
> >>  {
> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
> >> -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
> >>         .get_count = andes_plmt_get_count,  };
> >>
> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> >> +unsigned long notrace timer_get_us(void) {
> >> +       u64 ticks;
> >> +
> >> +       /* FIXME: gd->arch.plmt should contain valid base address */
> >> +       if (gd->arch.plmt) {
> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
> >> +               do_div(ticks, CONFIG_SYS_HZ);
> >> +       }
> >> +
> >> +       return ticks;
> >> +}
> >> +#endif
> >> +
> >>  static int andes_plmt_probe(struct udevice *dev)  {
> >>         dev->priv = dev_read_addr_ptr(dev);
> >>         if (!dev->priv)
> >>                 return -EINVAL;
> >>
> >> +       gd->arch.plmt = dev->priv;
> >>         return timer_timebase_fallback(dev);  }
> >>
> >> diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
> >> index 21ae184057..7fa8773da3 100644
> >> --- a/drivers/timer/riscv_timer.c
> >> +++ b/drivers/timer/riscv_timer.c
> >> @@ -15,8 +15,9 @@
> >>  #include <errno.h>
> >>  #include <timer.h>
> >>  #include <asm/csr.h>
> >> +#include <div64.h>
> >>
> >> -static u64 riscv_timer_get_count(struct udevice *dev)
> >> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
> >>  {
> >>         __maybe_unused u32 hi, lo;
> >>
> >> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice *dev)
> >>         return ((u64)hi << 32) | lo;
> >>  }
> >>
> >> +#if CONFIG_IS_ENABLED(RISCV_SMODE)
> >> +unsigned long notrace timer_get_us(void) {
> >> +       u64 ticks;
> >> +
> >> +       ticks = riscv_timer_get_count(NULL);
> >> +       do_div(ticks, CONFIG_SYS_HZ);
> >> +       return ticks;
> >> +}
> >> +#endif
> >> +
> >>  static int riscv_timer_probe(struct udevice *dev)  {
> >>         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> >> diff --git a/drivers/timer/sifive_clint_timer.c
> >> b/drivers/timer/sifive_clint_timer.c
> >> index 00ce0f08d6..c341f7789b 100644
> >> --- a/drivers/timer/sifive_clint_timer.c
> >> +++ b/drivers/timer/sifive_clint_timer.c
> >> @@ -10,11 +10,12 @@
> >>  #include <timer.h>
> >>  #include <asm/io.h>
> >>  #include <linux/err.h>
> >> +#include <div64.h>
> >>
> >>  /* mtime register */
> >>  #define MTIME_REG(base)                        ((ulong)(base) + 0xbff8)
> >>
> >> -static u64 sifive_clint_get_count(struct udevice *dev)
> >> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
> >>  {
> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
> >> -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
> >>         .get_count = sifive_clint_get_count,  };
> >>
> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE)
> >> +unsigned long notrace timer_get_us(void) {
> >> +       u64 ticks;
> >> +
> >> +       /* FIXME: gd->arch.clint should contain valid base address */
> >> +       if (gd->arch.clint) {
> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
> >> +               do_div(ticks, CONFIG_SYS_HZ);
> >> +       }
> >> +
> >> +       return ticks;
> >> +}
> >> +#endif
> >> +
> >>  static int sifive_clint_probe(struct udevice *dev)  {
> >>         dev->priv = dev_read_addr_ptr(dev);
> >>         if (!dev->priv)
> >>                 return -EINVAL;
> >>
> >> +       gd->arch.clint = dev->priv;
> >>         return timer_timebase_fallback(dev);  }
> >>
> >> --
> >> 2.17.1
Pragnesh Patel Nov. 23, 2020, 6:19 a.m. UTC | #14
Hi Leo,

>-----Original Message-----
>From: Leo Liang <ycliang@andestech.com>
>Sent: 23 November 2020 11:28
>To: Pragnesh Patel <pragnesh.patel@openfive.com>
>Cc: Rick Chen <rickchen36@gmail.com>; U-Boot Mailing List <u-
>boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>;
>palmerdabbelt@google.com; Bin Meng <bmeng.cn@gmail.com>; Paul Walmsley
>( Sifive) <paul.walmsley@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar
>Kadam <sagar.kadam@openfive.com>; Sean Anderson <seanga2@gmail.com>;
>rick <rick@andestech.com>; Alan Kao <alankao@andestech.com>
>Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>
>[External Email] Do not click links or attachments unless you recognize the
>sender and know the content is safe
>
>On Tue, Nov 17, 2020 at 08:30:21AM +0000, Pragnesh Patel wrote:
>
>Hi Pragnesh,
>
>> Hi Rick,
>>
>> >-----Original Message-----
>> >From: Rick Chen <rickchen36@gmail.com>
>> >Sent: 13 November 2020 13:37
>> >To: Pragnesh Patel <pragnesh.patel@openfive.com>
>> >Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Atish Patra
>> ><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng
>> ><bmeng.cn@gmail.com>; Paul Walmsley ( Sifive)
>> ><paul.walmsley@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar
>> >Kadam <sagar.kadam@openfive.com>; Sean Anderson
><seanga2@gmail.com>;
>> >rick <rick@andestech.com>; Alan Kao <alankao@andestech.com>; Leo
>> >Liang <ycliang@andestech.com>
>> >Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>> >
>> >[External Email] Do not click links or attachments unless you
>> >recognize the sender and know the content is safe
>> >
>> >Hi Pragnesh
>> >
>> >> From: Pragnesh Patel [mailto:pragnesh.patel@sifive.com]
>> >> Sent: Wednesday, November 11, 2020 6:15 PM
>> >> To: u-boot@lists.denx.de
>> >> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
>> >bmeng.cn@gmail.com;
>> >> paul.walmsley@sifive.com; anup.patel@wdc.com;
>> >> sagar.kadam@sifive.com; Rick Jian-Zhi Chen(陳建志); Pragnesh Patel;
>> >> Sean Anderson; Heinrich Schuchardt; Simon Glass
>> >> Subject: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
>> >>
>> >> Add timer_get_us() which is useful for tracing.
>> >> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer
>> >> ticks and For M-mode U-Boot, mtime register will provide the same.
>> >>
>> >> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
>> >> ---
>> >>
>> >> Changes in v3:
>> >> - Added gd->arch.plmt in global data
>> >> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
>> >>   and sifive_clint_get_count()
>> >>
>> >> Changes in v2:
>> >> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
>> >>   and andes_plmt_timer.c.
>> >>
>> >>
>> >>  arch/riscv/include/asm/global_data.h |  3 +++
>> >>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
>> >>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
>> >>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
>> >>  4 files changed, 52 insertions(+), 3 deletions(-)
>> >>
>> >> diff --git a/arch/riscv/include/asm/global_data.h
>> >> b/arch/riscv/include/asm/global_data.h
>> >> index d3a0b1d221..4e22ceb83f 100644
>> >> --- a/arch/riscv/include/asm/global_data.h
>> >> +++ b/arch/riscv/include/asm/global_data.h
>> >> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
>> >>         void __iomem *plic;     /* plic base address */
>> >>  #endif
>> >> +#ifdef CONFIG_ANDES_PLMT
>> >
>> >It shall be CONFIG_ANDES_PLMT, or it will compile fail as below:
>> >
>> >drivers/timer/andes_plmt_timer.c: In function 'timer_get_us':
>> >drivers/timer/andes_plmt_timer.c:36:15: error: 'struct
>> >arch_global_data' has no member named 'plmt'; did you mean 'plic'?
>> >  if (gd->arch.plmt) {
>> >               ^~~~
>> >               plic
>> >drivers/timer/andes_plmt_timer.c:37:52: error: 'struct
>> >arch_global_data' has no member named 'plmt'; did you mean 'plic'?
>> >   ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>> >
>
>This patch will cause compile error with ae350 defconfig.
>
>${uboot}/drivers/timer/Makefile is articulated in this way,
>"obj-$(CONFIG_ANDES_PLMT_TIMER) += andes_plmt_timer.o", so the #ifdef
>indicator in ${uboot}/arch/riscv/include/asm/global_data.h should use
>CONFIG_ANDES_PLMT_TIMER.

Thanks Leo but Rick has already informed about this error.

I have discarded this series and added a new patch for Tracing which uses TIMER_EARLY
https://patchwork.ozlabs.org/project/uboot/patch/20201117110508.25819-1-pragnesh.patel@sifive.com/

>
>Best regards,
>Leo
>
>> >And it is not proper to have dependency of data structure between
>> >/arch/riscv/include/asm/* and /drivers/timer/* Maybe enable
>> >TIMER_EARLY and use timer_get_us() of /lib/time.c will be better.
>>
>> I am planning to use TIMER_EARLY for tracing.
>>
>> With TIMER_EARLY, I need to implement timer_early_get_rate() and
>> timer_early_get_count()
>>
>> For timer_early_get_count(), I need PLMT or CLINT base address to read mtime
>register.
>> So I think it's better to save base address in gd->arch.clint or gd->arch.plmt.
>>
>> Let me know if you have any other idea to save PLM or CLINT base address.
>>
>> For timer_early_get_rate(), I will add new variable in global data (gd)
>> Like, gd->arch.clock_rate;       /* Clock rate of timer in Hz */
>> This will return Timer frequency in Hz.
>>
>> Tracing is only useful in U-Boot not in U-Boot SPL so I am doing this
>> for M mode U-boot and S mode U-Boot.
>>
>> >I also found that without dm_timer_init() in initf_dm(),
>> >andes_plmt_get_count() will be executed ahead of andes_plmt_probe().
>>
>> If andes_plmt_get_count() executed before andes_plmt_probe() then how
>> did it will get PLMT base address ?
>>
>> >
>> >Thanks,
>> >Rick
>> >
>> >
>> >> +       void __iomem *plmt;     /* plmt base address */
>> >> +#endif
>> >>  #if CONFIG_IS_ENABLED(SMP)
>> >>         struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
>> >> a/drivers/timer/andes_plmt_timer.c
>> >> b/drivers/timer/andes_plmt_timer.c
>> >> index cec86718c7..7c50c46d9e 100644
>> >> --- a/drivers/timer/andes_plmt_timer.c
>> >> +++ b/drivers/timer/andes_plmt_timer.c
>> >> @@ -13,11 +13,12 @@
>> >>  #include <timer.h>
>> >>  #include <asm/io.h>
>> >>  #include <linux/err.h>
>> >> +#include <div64.h>
>> >>
>> >>  /* mtime register */
>> >>  #define MTIME_REG(base)                        ((ulong)(base))
>> >>
>> >> -static u64 andes_plmt_get_count(struct udevice *dev)
>> >> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
>> >>  {
>> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>> >> -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
>> >>         .get_count = andes_plmt_get_count,  };
>> >>
>> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
>> >> +timer_get_us(void) {
>> >> +       u64 ticks;
>> >> +
>> >> +       /* FIXME: gd->arch.plmt should contain valid base address */
>> >> +       if (gd->arch.plmt) {
>> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
>> >> +               do_div(ticks, CONFIG_SYS_HZ);
>> >> +       }
>> >> +
>> >> +       return ticks;
>> >> +}
>> >> +#endif
>> >> +
>> >>  static int andes_plmt_probe(struct udevice *dev)  {
>> >>         dev->priv = dev_read_addr_ptr(dev);
>> >>         if (!dev->priv)
>> >>                 return -EINVAL;
>> >>
>> >> +       gd->arch.plmt = dev->priv;
>> >>         return timer_timebase_fallback(dev);  }
>> >>
>> >> diff --git a/drivers/timer/riscv_timer.c
>> >> b/drivers/timer/riscv_timer.c index 21ae184057..7fa8773da3 100644
>> >> --- a/drivers/timer/riscv_timer.c
>> >> +++ b/drivers/timer/riscv_timer.c
>> >> @@ -15,8 +15,9 @@
>> >>  #include <errno.h>
>> >>  #include <timer.h>
>> >>  #include <asm/csr.h>
>> >> +#include <div64.h>
>> >>
>> >> -static u64 riscv_timer_get_count(struct udevice *dev)
>> >> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
>> >>  {
>> >>         __maybe_unused u32 hi, lo;
>> >>
>> >> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice
>*dev)
>> >>         return ((u64)hi << 32) | lo;  }
>> >>
>> >> +#if CONFIG_IS_ENABLED(RISCV_SMODE) unsigned long notrace
>> >> +timer_get_us(void) {
>> >> +       u64 ticks;
>> >> +
>> >> +       ticks = riscv_timer_get_count(NULL);
>> >> +       do_div(ticks, CONFIG_SYS_HZ);
>> >> +       return ticks;
>> >> +}
>> >> +#endif
>> >> +
>> >>  static int riscv_timer_probe(struct udevice *dev)  {
>> >>         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
>> >> diff --git a/drivers/timer/sifive_clint_timer.c
>> >> b/drivers/timer/sifive_clint_timer.c
>> >> index 00ce0f08d6..c341f7789b 100644
>> >> --- a/drivers/timer/sifive_clint_timer.c
>> >> +++ b/drivers/timer/sifive_clint_timer.c
>> >> @@ -10,11 +10,12 @@
>> >>  #include <timer.h>
>> >>  #include <asm/io.h>
>> >>  #include <linux/err.h>
>> >> +#include <div64.h>
>> >>
>> >>  /* mtime register */
>> >>  #define MTIME_REG(base)                        ((ulong)(base) + 0xbff8)
>> >>
>> >> -static u64 sifive_clint_get_count(struct udevice *dev)
>> >> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
>> >>  {
>> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
>> >> -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
>> >>         .get_count = sifive_clint_get_count,  };
>> >>
>> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
>> >> +timer_get_us(void) {
>> >> +       u64 ticks;
>> >> +
>> >> +       /* FIXME: gd->arch.clint should contain valid base address */
>> >> +       if (gd->arch.clint) {
>> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
>> >> +               do_div(ticks, CONFIG_SYS_HZ);
>> >> +       }
>> >> +
>> >> +       return ticks;
>> >> +}
>> >> +#endif
>> >> +
>> >>  static int sifive_clint_probe(struct udevice *dev)  {
>> >>         dev->priv = dev_read_addr_ptr(dev);
>> >>         if (!dev->priv)
>> >>                 return -EINVAL;
>> >>
>> >> +       gd->arch.clint = dev->priv;
>> >>         return timer_timebase_fallback(dev);  }
>> >>
>> >> --
>> >> 2.17.1
Leo Liang Nov. 23, 2020, 6:22 a.m. UTC | #15
Hi Pragnesh,

On Mon, Nov 23, 2020 at 06:19:06AM +0000, Pragnesh Patel wrote:
> Hi Leo,
> 
> >-----Original Message-----
> >From: Leo Liang <ycliang@andestech.com>
> >Sent: 23 November 2020 11:28
> >To: Pragnesh Patel <pragnesh.patel@openfive.com>
> >Cc: Rick Chen <rickchen36@gmail.com>; U-Boot Mailing List <u-
> >boot@lists.denx.de>; Atish Patra <atish.patra@wdc.com>;
> >palmerdabbelt@google.com; Bin Meng <bmeng.cn@gmail.com>; Paul Walmsley
> >( Sifive) <paul.walmsley@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar
> >Kadam <sagar.kadam@openfive.com>; Sean Anderson <seanga2@gmail.com>;
> >rick <rick@andestech.com>; Alan Kao <alankao@andestech.com>
> >Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
> >
> >[External Email] Do not click links or attachments unless you recognize the
> >sender and know the content is safe
> >
> >On Tue, Nov 17, 2020 at 08:30:21AM +0000, Pragnesh Patel wrote:
> >
> >Hi Pragnesh,
> >
> >> Hi Rick,
> >>
> >> >-----Original Message-----
> >> >From: Rick Chen <rickchen36@gmail.com>
> >> >Sent: 13 November 2020 13:37
> >> >To: Pragnesh Patel <pragnesh.patel@openfive.com>
> >> >Cc: U-Boot Mailing List <u-boot@lists.denx.de>; Atish Patra
> >> ><atish.patra@wdc.com>; palmerdabbelt@google.com; Bin Meng
> >> ><bmeng.cn@gmail.com>; Paul Walmsley ( Sifive)
> >> ><paul.walmsley@sifive.com>; Anup Patel <anup.patel@wdc.com>; Sagar
> >> >Kadam <sagar.kadam@openfive.com>; Sean Anderson
> ><seanga2@gmail.com>;
> >> >rick <rick@andestech.com>; Alan Kao <alankao@andestech.com>; Leo
> >> >Liang <ycliang@andestech.com>
> >> >Subject: Re: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
> >> >
> >> >[External Email] Do not click links or attachments unless you
> >> >recognize the sender and know the content is safe
> >> >
> >> >Hi Pragnesh
> >> >
> >> >> From: Pragnesh Patel [mailto:pragnesh.patel@sifive.com]
> >> >> Sent: Wednesday, November 11, 2020 6:15 PM
> >> >> To: u-boot@lists.denx.de
> >> >> Cc: atish.patra@wdc.com; palmerdabbelt@google.com;
> >> >bmeng.cn@gmail.com;
> >> >> paul.walmsley@sifive.com; anup.patel@wdc.com;
> >> >> sagar.kadam@sifive.com; Rick Jian-Zhi Chen(陳建志); Pragnesh Patel;
> >> >> Sean Anderson; Heinrich Schuchardt; Simon Glass
> >> >> Subject: [PATCH v3 1/1] riscv: Add timer_get_us() for tracing
> >> >>
> >> >> Add timer_get_us() which is useful for tracing.
> >> >> For S-mode U-Boot, CSR_TIMEH and CSR_TIME will provide a timer
> >> >> ticks and For M-mode U-Boot, mtime register will provide the same.
> >> >>
> >> >> Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
> >> >> ---
> >> >>
> >> >> Changes in v3:
> >> >> - Added gd->arch.plmt in global data
> >> >> - For timer_get_us(), use readq() instead of andes_plmt_get_count()
> >> >>   and sifive_clint_get_count()
> >> >>
> >> >> Changes in v2:
> >> >> - Added timer_get_us() in riscv_timer.c, sifive_clint_timer.c
> >> >>   and andes_plmt_timer.c.
> >> >>
> >> >>
> >> >>  arch/riscv/include/asm/global_data.h |  3 +++
> >> >>  drivers/timer/andes_plmt_timer.c     | 19 ++++++++++++++++++-
> >> >>  drivers/timer/riscv_timer.c          | 14 +++++++++++++-
> >> >>  drivers/timer/sifive_clint_timer.c   | 19 ++++++++++++++++++-
> >> >>  4 files changed, 52 insertions(+), 3 deletions(-)
> >> >>
> >> >> diff --git a/arch/riscv/include/asm/global_data.h
> >> >> b/arch/riscv/include/asm/global_data.h
> >> >> index d3a0b1d221..4e22ceb83f 100644
> >> >> --- a/arch/riscv/include/asm/global_data.h
> >> >> +++ b/arch/riscv/include/asm/global_data.h
> >> >> @@ -24,6 +24,9 @@ struct arch_global_data {  #ifdef CONFIG_ANDES_PLIC
> >> >>         void __iomem *plic;     /* plic base address */
> >> >>  #endif
> >> >> +#ifdef CONFIG_ANDES_PLMT
> >> >
> >> >It shall be CONFIG_ANDES_PLMT, or it will compile fail as below:
> >> >
> >> >drivers/timer/andes_plmt_timer.c: In function 'timer_get_us':
> >> >drivers/timer/andes_plmt_timer.c:36:15: error: 'struct
> >> >arch_global_data' has no member named 'plmt'; did you mean 'plic'?
> >> >  if (gd->arch.plmt) {
> >> >               ^~~~
> >> >               plic
> >> >drivers/timer/andes_plmt_timer.c:37:52: error: 'struct
> >> >arch_global_data' has no member named 'plmt'; did you mean 'plic'?
> >> >   ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
> >> >
> >
> >This patch will cause compile error with ae350 defconfig.
> >
> >${uboot}/drivers/timer/Makefile is articulated in this way,
> >"obj-$(CONFIG_ANDES_PLMT_TIMER) += andes_plmt_timer.o", so the #ifdef
> >indicator in ${uboot}/arch/riscv/include/asm/global_data.h should use
> >CONFIG_ANDES_PLMT_TIMER.
> 
> Thanks Leo but Rick has already informed about this error.
> 
> I have discarded this series and added a new patch for Tracing which uses TIMER_EARLY
> https://patchwork.ozlabs.org/project/uboot/patch/20201117110508.25819-1-pragnesh.patel@sifive.com/
> 

Got it! Thanks for the explanation,

Best regards,
Leo

> >
> >Best regards,
> >Leo
> >
> >> >And it is not proper to have dependency of data structure between
> >> >/arch/riscv/include/asm/* and /drivers/timer/* Maybe enable
> >> >TIMER_EARLY and use timer_get_us() of /lib/time.c will be better.
> >>
> >> I am planning to use TIMER_EARLY for tracing.
> >>
> >> With TIMER_EARLY, I need to implement timer_early_get_rate() and
> >> timer_early_get_count()
> >>
> >> For timer_early_get_count(), I need PLMT or CLINT base address to read mtime
> >register.
> >> So I think it's better to save base address in gd->arch.clint or gd->arch.plmt.
> >>
> >> Let me know if you have any other idea to save PLM or CLINT base address.
> >>
> >> For timer_early_get_rate(), I will add new variable in global data (gd)
> >> Like, gd->arch.clock_rate;       /* Clock rate of timer in Hz */
> >> This will return Timer frequency in Hz.
> >>
> >> Tracing is only useful in U-Boot not in U-Boot SPL so I am doing this
> >> for M mode U-boot and S mode U-Boot.
> >>
> >> >I also found that without dm_timer_init() in initf_dm(),
> >> >andes_plmt_get_count() will be executed ahead of andes_plmt_probe().
> >>
> >> If andes_plmt_get_count() executed before andes_plmt_probe() then how
> >> did it will get PLMT base address ?
> >>
> >> >
> >> >Thanks,
> >> >Rick
> >> >
> >> >
> >> >> +       void __iomem *plmt;     /* plmt base address */
> >> >> +#endif
> >> >>  #if CONFIG_IS_ENABLED(SMP)
> >> >>         struct ipi_data ipi[CONFIG_NR_CPUS];  #endif diff --git
> >> >> a/drivers/timer/andes_plmt_timer.c
> >> >> b/drivers/timer/andes_plmt_timer.c
> >> >> index cec86718c7..7c50c46d9e 100644
> >> >> --- a/drivers/timer/andes_plmt_timer.c
> >> >> +++ b/drivers/timer/andes_plmt_timer.c
> >> >> @@ -13,11 +13,12 @@
> >> >>  #include <timer.h>
> >> >>  #include <asm/io.h>
> >> >>  #include <linux/err.h>
> >> >> +#include <div64.h>
> >> >>
> >> >>  /* mtime register */
> >> >>  #define MTIME_REG(base)                        ((ulong)(base))
> >> >>
> >> >> -static u64 andes_plmt_get_count(struct udevice *dev)
> >> >> +static u64 notrace andes_plmt_get_count(struct udevice *dev)
> >> >>  {
> >> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
> >> >> -26,12 +27,28 @@ static const struct timer_ops andes_plmt_ops = {
> >> >>         .get_count = andes_plmt_get_count,  };
> >> >>
> >> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
> >> >> +timer_get_us(void) {
> >> >> +       u64 ticks;
> >> >> +
> >> >> +       /* FIXME: gd->arch.plmt should contain valid base address */
> >> >> +       if (gd->arch.plmt) {
> >> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
> >> >> +               do_div(ticks, CONFIG_SYS_HZ);
> >> >> +       }
> >> >> +
> >> >> +       return ticks;
> >> >> +}
> >> >> +#endif
> >> >> +
> >> >>  static int andes_plmt_probe(struct udevice *dev)  {
> >> >>         dev->priv = dev_read_addr_ptr(dev);
> >> >>         if (!dev->priv)
> >> >>                 return -EINVAL;
> >> >>
> >> >> +       gd->arch.plmt = dev->priv;
> >> >>         return timer_timebase_fallback(dev);  }
> >> >>
> >> >> diff --git a/drivers/timer/riscv_timer.c
> >> >> b/drivers/timer/riscv_timer.c index 21ae184057..7fa8773da3 100644
> >> >> --- a/drivers/timer/riscv_timer.c
> >> >> +++ b/drivers/timer/riscv_timer.c
> >> >> @@ -15,8 +15,9 @@
> >> >>  #include <errno.h>
> >> >>  #include <timer.h>
> >> >>  #include <asm/csr.h>
> >> >> +#include <div64.h>
> >> >>
> >> >> -static u64 riscv_timer_get_count(struct udevice *dev)
> >> >> +static u64 notrace riscv_timer_get_count(struct udevice *dev)
> >> >>  {
> >> >>         __maybe_unused u32 hi, lo;
> >> >>
> >> >> @@ -31,6 +32,17 @@ static u64 riscv_timer_get_count(struct udevice
> >*dev)
> >> >>         return ((u64)hi << 32) | lo;  }
> >> >>
> >> >> +#if CONFIG_IS_ENABLED(RISCV_SMODE) unsigned long notrace
> >> >> +timer_get_us(void) {
> >> >> +       u64 ticks;
> >> >> +
> >> >> +       ticks = riscv_timer_get_count(NULL);
> >> >> +       do_div(ticks, CONFIG_SYS_HZ);
> >> >> +       return ticks;
> >> >> +}
> >> >> +#endif
> >> >> +
> >> >>  static int riscv_timer_probe(struct udevice *dev)  {
> >> >>         struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
> >> >> diff --git a/drivers/timer/sifive_clint_timer.c
> >> >> b/drivers/timer/sifive_clint_timer.c
> >> >> index 00ce0f08d6..c341f7789b 100644
> >> >> --- a/drivers/timer/sifive_clint_timer.c
> >> >> +++ b/drivers/timer/sifive_clint_timer.c
> >> >> @@ -10,11 +10,12 @@
> >> >>  #include <timer.h>
> >> >>  #include <asm/io.h>
> >> >>  #include <linux/err.h>
> >> >> +#include <div64.h>
> >> >>
> >> >>  /* mtime register */
> >> >>  #define MTIME_REG(base)                        ((ulong)(base) + 0xbff8)
> >> >>
> >> >> -static u64 sifive_clint_get_count(struct udevice *dev)
> >> >> +static u64 notrace sifive_clint_get_count(struct udevice *dev)
> >> >>  {
> >> >>         return readq((void __iomem *)MTIME_REG(dev->priv));  } @@
> >> >> -23,12 +24,28 @@ static const struct timer_ops sifive_clint_ops = {
> >> >>         .get_count = sifive_clint_get_count,  };
> >> >>
> >> >> +#if CONFIG_IS_ENABLED(RISCV_MMODE) unsigned long notrace
> >> >> +timer_get_us(void) {
> >> >> +       u64 ticks;
> >> >> +
> >> >> +       /* FIXME: gd->arch.clint should contain valid base address */
> >> >> +       if (gd->arch.clint) {
> >> >> +               ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
> >> >> +               do_div(ticks, CONFIG_SYS_HZ);
> >> >> +       }
> >> >> +
> >> >> +       return ticks;
> >> >> +}
> >> >> +#endif
> >> >> +
> >> >>  static int sifive_clint_probe(struct udevice *dev)  {
> >> >>         dev->priv = dev_read_addr_ptr(dev);
> >> >>         if (!dev->priv)
> >> >>                 return -EINVAL;
> >> >>
> >> >> +       gd->arch.clint = dev->priv;
> >> >>         return timer_timebase_fallback(dev);  }
> >> >>
> >> >> --
> >> >> 2.17.1
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/global_data.h b/arch/riscv/include/asm/global_data.h
index d3a0b1d221..4e22ceb83f 100644
--- a/arch/riscv/include/asm/global_data.h
+++ b/arch/riscv/include/asm/global_data.h
@@ -24,6 +24,9 @@  struct arch_global_data {
 #ifdef CONFIG_ANDES_PLIC
 	void __iomem *plic;	/* plic base address */
 #endif
+#ifdef CONFIG_ANDES_PLMT
+	void __iomem *plmt;     /* plmt base address */
+#endif
 #if CONFIG_IS_ENABLED(SMP)
 	struct ipi_data ipi[CONFIG_NR_CPUS];
 #endif
diff --git a/drivers/timer/andes_plmt_timer.c b/drivers/timer/andes_plmt_timer.c
index cec86718c7..7c50c46d9e 100644
--- a/drivers/timer/andes_plmt_timer.c
+++ b/drivers/timer/andes_plmt_timer.c
@@ -13,11 +13,12 @@ 
 #include <timer.h>
 #include <asm/io.h>
 #include <linux/err.h>
+#include <div64.h>
 
 /* mtime register */
 #define MTIME_REG(base)			((ulong)(base))
 
-static u64 andes_plmt_get_count(struct udevice *dev)
+static u64 notrace andes_plmt_get_count(struct udevice *dev)
 {
 	return readq((void __iomem *)MTIME_REG(dev->priv));
 }
@@ -26,12 +27,28 @@  static const struct timer_ops andes_plmt_ops = {
 	.get_count = andes_plmt_get_count,
 };
 
+#if CONFIG_IS_ENABLED(RISCV_MMODE)
+unsigned long notrace timer_get_us(void)
+{
+	u64 ticks;
+
+	/* FIXME: gd->arch.plmt should contain valid base address */
+	if (gd->arch.plmt) {
+		ticks = readq((void __iomem *)MTIME_REG(gd->arch.plmt));
+		do_div(ticks, CONFIG_SYS_HZ);
+	}
+
+	return ticks;
+}
+#endif
+
 static int andes_plmt_probe(struct udevice *dev)
 {
 	dev->priv = dev_read_addr_ptr(dev);
 	if (!dev->priv)
 		return -EINVAL;
 
+	gd->arch.plmt = dev->priv;
 	return timer_timebase_fallback(dev);
 }
 
diff --git a/drivers/timer/riscv_timer.c b/drivers/timer/riscv_timer.c
index 21ae184057..7fa8773da3 100644
--- a/drivers/timer/riscv_timer.c
+++ b/drivers/timer/riscv_timer.c
@@ -15,8 +15,9 @@ 
 #include <errno.h>
 #include <timer.h>
 #include <asm/csr.h>
+#include <div64.h>
 
-static u64 riscv_timer_get_count(struct udevice *dev)
+static u64 notrace riscv_timer_get_count(struct udevice *dev)
 {
 	__maybe_unused u32 hi, lo;
 
@@ -31,6 +32,17 @@  static u64 riscv_timer_get_count(struct udevice *dev)
 	return ((u64)hi << 32) | lo;
 }
 
+#if CONFIG_IS_ENABLED(RISCV_SMODE)
+unsigned long notrace timer_get_us(void)
+{
+	u64 ticks;
+
+	ticks = riscv_timer_get_count(NULL);
+	do_div(ticks, CONFIG_SYS_HZ);
+	return ticks;
+}
+#endif
+
 static int riscv_timer_probe(struct udevice *dev)
 {
 	struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
diff --git a/drivers/timer/sifive_clint_timer.c b/drivers/timer/sifive_clint_timer.c
index 00ce0f08d6..c341f7789b 100644
--- a/drivers/timer/sifive_clint_timer.c
+++ b/drivers/timer/sifive_clint_timer.c
@@ -10,11 +10,12 @@ 
 #include <timer.h>
 #include <asm/io.h>
 #include <linux/err.h>
+#include <div64.h>
 
 /* mtime register */
 #define MTIME_REG(base)			((ulong)(base) + 0xbff8)
 
-static u64 sifive_clint_get_count(struct udevice *dev)
+static u64 notrace sifive_clint_get_count(struct udevice *dev)
 {
 	return readq((void __iomem *)MTIME_REG(dev->priv));
 }
@@ -23,12 +24,28 @@  static const struct timer_ops sifive_clint_ops = {
 	.get_count = sifive_clint_get_count,
 };
 
+#if CONFIG_IS_ENABLED(RISCV_MMODE)
+unsigned long notrace timer_get_us(void)
+{
+	u64 ticks;
+
+	/* FIXME: gd->arch.clint should contain valid base address */
+	if (gd->arch.clint) {
+		ticks = readq((void __iomem *)MTIME_REG(gd->arch.clint));
+		do_div(ticks, CONFIG_SYS_HZ);
+	}
+
+	return ticks;
+}
+#endif
+
 static int sifive_clint_probe(struct udevice *dev)
 {
 	dev->priv = dev_read_addr_ptr(dev);
 	if (!dev->priv)
 		return -EINVAL;
 
+	gd->arch.clint = dev->priv;
 	return timer_timebase_fallback(dev);
 }