diff mbox

[U-Boot,RESEND,v2,2/5] Tegra2: Add microsecond timer functions

Message ID 1309884558-7700-3-git-send-email-sjg@chromium.org
State Superseded, archived
Delegated to: Albert ARIBAUD
Headers show

Commit Message

Simon Glass July 5, 2011, 4:49 p.m. UTC
These functions provide access to the high resolution microsecond timer
and tidy up a global variable in the code.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 arch/arm/cpu/armv7/tegra2/timer.c        |   27 +++++++++++++++++------
 arch/arm/include/asm/arch-tegra2/timer.h |   34 ++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-tegra2/timer.h

Comments

Albert ARIBAUD July 9, 2011, 1:58 p.m. UTC | #1
Hi Simon,

Le 05/07/2011 18:49, Simon Glass a écrit :
> These functions provide access to the high resolution microsecond timer
> and tidy up a global variable in the code.
>
> Signed-off-by: Simon Glass<sjg@chromium.org>
> ---
>   arch/arm/cpu/armv7/tegra2/timer.c        |   27 +++++++++++++++++------
>   arch/arm/include/asm/arch-tegra2/timer.h |   34 ++++++++++++++++++++++++++++++
>   2 files changed, 54 insertions(+), 7 deletions(-)
>   create mode 100644 arch/arm/include/asm/arch-tegra2/timer.h
>
> diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/armv7/tegra2/timer.c
> index fb061d0..b69c172 100644
> --- a/arch/arm/cpu/armv7/tegra2/timer.c
> +++ b/arch/arm/cpu/armv7/tegra2/timer.c
> @@ -38,13 +38,12 @@
>   #include<common.h>
>   #include<asm/io.h>
>   #include<asm/arch/tegra2.h>
> +#include<asm/arch/timer.h>
>
>   DECLARE_GLOBAL_DATA_PTR;
>
> -struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
> -
>   /* counter runs at 1MHz */
> -#define TIMER_CLK	(1000000)
> +#define TIMER_CLK	1000000
>   #define TIMER_LOAD_VAL	0xffffffff
>
>   /* timer without interrupts */
> @@ -67,10 +66,10 @@ void set_timer(ulong t)
>   void __udelay(unsigned long usec)
>   {
>   	long tmo = usec * (TIMER_CLK / 1000) / 1000;
> -	unsigned long now, last = readl(&timer_base->cntr_1us);
> +	unsigned long now, last = timer_get_us();
>
>   	while (tmo>  0) {
> -		now = readl(&timer_base->cntr_1us);
> +		now = timer_get_us();
>   		if (last>  now) /* count up timer overflow */
>   			tmo -= TIMER_LOAD_VAL - last + now;
>   		else
> @@ -82,7 +81,7 @@ void __udelay(unsigned long usec)
>   void reset_timer_masked(void)
>   {
>   	/* reset time, capture current incrementer value time */
> -	gd->lastinc = readl(&timer_base->cntr_1us) / (TIMER_CLK/CONFIG_SYS_HZ);
> +	gd->lastinc = timer_get_us() / (TIMER_CLK/CONFIG_SYS_HZ);
>   	gd->tbl = 0;		/* start "advancing" time stamp from 0 */
>   }
>
> @@ -91,7 +90,7 @@ ulong get_timer_masked(void)
>   	ulong now;
>
>   	/* current tick value */
> -	now = readl(&timer_base->cntr_1us) / (TIMER_CLK / CONFIG_SYS_HZ);
> +	now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
>
>   	if (now>= gd->lastinc)	/* normal mode (non roll) */
>   		/* move stamp forward with absolute diff ticks */
> @@ -120,3 +119,17 @@ ulong get_tbclk(void)
>   {
>   	return CONFIG_SYS_HZ;
>   }
> +
> +
> +unsigned long timer_get_us(void)
> +{
> +	struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
> +
> +	return readl(&timer_base->cntr_1us);
> +}
> +
> +unsigned long timer_get_future_us(u32 delay)
> +{
> +	return timer_get_us() + delay;
> +}

What is the added value in a function that just adds its argument to the 
return value of another function? Might as well do the addition directly 
instead of calling this 'future' function.

> +
> diff --git a/arch/arm/include/asm/arch-tegra2/timer.h b/arch/arm/include/asm/arch-tegra2/timer.h
> new file mode 100644
> index 0000000..5d5445e
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-tegra2/timer.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (c) 2011 The Chromium OS Authors.
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/* Tegra2 timer functions */
> +
> +#ifndef _TEGRA2_TIMER_H
> +#define _TEGRA2_TIMER_H
> +
> +/* returns the current monotonic timer value in microseconds */
> +unsigned long timer_get_us(void);
> +
> +/* returns what the time will likely be some microseconds into the future */
> +unsigned long timer_get_future_us(u32 delay);
> +
> +#endif
> +


Amicalement,
Graeme Russ July 10, 2011, 5:24 a.m. UTC | #2
Hi Simon,

On 06/07/11 02:49, Simon Glass wrote:
> These functions provide access to the high resolution microsecond timer
> and tidy up a global variable in the code.

Excellent - Good to see microsecond timers making their way in already

> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>  arch/arm/cpu/armv7/tegra2/timer.c        |   27 +++++++++++++++++------
>  arch/arm/include/asm/arch-tegra2/timer.h |   34 ++++++++++++++++++++++++++++++
>  2 files changed, 54 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm/include/asm/arch-tegra2/timer.h
> 
> diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/armv7/tegra2/timer.c
> index fb061d0..b69c172 100644
> --- a/arch/arm/cpu/armv7/tegra2/timer.c
> +++ b/arch/arm/cpu/armv7/tegra2/timer.c
> @@ -38,13 +38,12 @@
>  #include <common.h>
>  #include <asm/io.h>
>  #include <asm/arch/tegra2.h>
> +#include <asm/arch/timer.h>
>  
>  DECLARE_GLOBAL_DATA_PTR;
>  
> -struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
> -
>  /* counter runs at 1MHz */
> -#define TIMER_CLK	(1000000)
> +#define TIMER_CLK	1000000
>  #define TIMER_LOAD_VAL	0xffffffff
>  
>  /* timer without interrupts */
> @@ -67,10 +66,10 @@ void set_timer(ulong t)
>  void __udelay(unsigned long usec)
>  {
>  	long tmo = usec * (TIMER_CLK / 1000) / 1000;
> -	unsigned long now, last = readl(&timer_base->cntr_1us);
> +	unsigned long now, last = timer_get_us();
>  
>  	while (tmo > 0) {
> -		now = readl(&timer_base->cntr_1us);
> +		now = timer_get_us();
>  		if (last > now) /* count up timer overflow */
>  			tmo -= TIMER_LOAD_VAL - last + now;
>  		else
> @@ -82,7 +81,7 @@ void __udelay(unsigned long usec)
>  void reset_timer_masked(void)
>  {
>  	/* reset time, capture current incrementer value time */
> -	gd->lastinc = readl(&timer_base->cntr_1us) / (TIMER_CLK/CONFIG_SYS_HZ);
> +	gd->lastinc = timer_get_us() / (TIMER_CLK/CONFIG_SYS_HZ);

CONFIG_SYS_HZ is always supposed to be 1000 and in future I think it should
be removed entirely - Can you clean this up to not us CONFIG_SYS_HZ?

>  	gd->tbl = 0;		/* start "advancing" time stamp from 0 */
>  }
>  
> @@ -91,7 +90,7 @@ ulong get_timer_masked(void)
>  	ulong now;
>  
>  	/* current tick value */
> -	now = readl(&timer_base->cntr_1us) / (TIMER_CLK / CONFIG_SYS_HZ);
> +	now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);

And here

>  
>  	if (now >= gd->lastinc)	/* normal mode (non roll) */
>  		/* move stamp forward with absolute diff ticks */
> @@ -120,3 +119,17 @@ ulong get_tbclk(void)
>  {
>  	return CONFIG_SYS_HZ;
>  }

Hmmm, maybe all of the above should use get_tbclk()?

> +
> +
> +unsigned long timer_get_us(void)
> +{
> +	struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
> +
> +	return readl(&timer_base->cntr_1us);
> +}

timer_get_us needs to be u64 (unsigned long long). Also, the new timer API
will define this as time_now_us, would be great if you could use this
naming convention now to save me doing a mass of replaces later

> +
> +unsigned long timer_get_future_us(u32 delay)
> +{
> +	return timer_get_us() + delay;
> +}

C'mon - We've been here before - This is timer API stuff. Where are you
going to use this? Why can't the proposed API be used instead?

I know you don't like the 'time since' implementation, but this has been
discussed to death and it appears to me that the majority decision was to
go that route rather than the 'future time' route. It is a completely
pointless exercise and a complete waste of my time to re-write the timer
API just to have someone that doesn't like a particular aspect go off and
write a one-off function.

> +
> diff --git a/arch/arm/include/asm/arch-tegra2/timer.h b/arch/arm/include/asm/arch-tegra2/timer.h
> new file mode 100644
> index 0000000..5d5445e
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-tegra2/timer.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (c) 2011 The Chromium OS Authors.
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/* Tegra2 timer functions */
> +
> +#ifndef _TEGRA2_TIMER_H
> +#define _TEGRA2_TIMER_H
> +
> +/* returns the current monotonic timer value in microseconds */
> +unsigned long timer_get_us(void);
> +
> +/* returns what the time will likely be some microseconds into the future */
> +unsigned long timer_get_future_us(u32 delay);

'likely' meaning it may or may not - no guarantee though. The new timer API
is designed specifically designed to resolve this - 'At least x ms/us have
passed' or 'at most x ms/us have passed'. No more 'x ms/us _might_ have passed'

> +
> +#endif
> +

Regards,

Graeme
Simon Glass July 10, 2011, 6:14 a.m. UTC | #3
Hi Graeme,

On Sat, Jul 9, 2011 at 10:24 PM, Graeme Russ <graeme.russ@gmail.com> wrote:

> Hi Simon,
>
> On 06/07/11 02:49, Simon Glass wrote:
> > These functions provide access to the high resolution microsecond timer
> > and tidy up a global variable in the code.
>
> Excellent - Good to see microsecond timers making their way in already
>
> >
> >       /* reset time, capture current incrementer value time */
> > -     gd->lastinc = readl(&timer_base->cntr_1us) /
> (TIMER_CLK/CONFIG_SYS_HZ);
> > +     gd->lastinc = timer_get_us() / (TIMER_CLK/CONFIG_SYS_HZ);
>
> CONFIG_SYS_HZ is always supposed to be 1000 and in future I think it should
> be removed entirely - Can you clean this up to not us CONFIG_SYS_HZ?
>
> I will take a look.


> >       gd->tbl = 0;            /* start "advancing" time stamp from 0 */
> >  }
> >
> > @@ -91,7 +90,7 @@ ulong get_timer_masked(void)
> >       ulong now;
> >
> >       /* current tick value */
> > -     now = readl(&timer_base->cntr_1us) / (TIMER_CLK / CONFIG_SYS_HZ);
> > +     now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
>
> And here
>
> >
> >       if (now >= gd->lastinc) /* normal mode (non roll) */
> >               /* move stamp forward with absolute diff ticks */
> > @@ -120,3 +119,17 @@ ulong get_tbclk(void)
> >  {
> >       return CONFIG_SYS_HZ;
> >  }
>
> Hmmm, maybe all of the above should use get_tbclk()?
>
> > +
> > +
> > +unsigned long timer_get_us(void)
> > +{
> > +     struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
> > +
> > +     return readl(&timer_base->cntr_1us);
> > +}
>
> timer_get_us needs to be u64 (unsigned long long). Also, the new timer API
> will define this as time_now_us, would be great if you could use this
> naming convention now to save me doing a mass of replaces later
>

Yes will do.

>
> > +
> > +unsigned long timer_get_future_us(u32 delay)
> > +{
> > +     return timer_get_us() + delay;
> > +}
>
> C'mon - We've been here before - This is timer API stuff. Where are you
> going to use this? Why can't the proposed API be used instead?
>
> I know you don't like the 'time since' implementation, but this has been
> discussed to death and it appears to me that the majority decision was to
> go that route rather than the 'future time' route. It is a completely
> pointless exercise and a complete waste of my time to re-write the timer
> API just to have someone that doesn't like a particular aspect go off and
> write a one-off function.
>

Well this code pre-dates this and I haven't revised it. I will take another
look and sort this out. In fact from memory the return value isn't even
used!

>
> > +
> > diff --git a/arch/arm/include/asm/arch-tegra2/timer.h
> b/arch/arm/include/asm/arch-tegra2/timer.h
> > new file mode 100644
> > index 0000000..5d5445e
> > --- /dev/null
> > +++ b/arch/arm/include/asm/arch-tegra2/timer.h
> > @@ -0,0 +1,34 @@
> > +/*
> > + * Copyright (c) 2011 The Chromium OS Authors.
> > + * See file CREDITS for list of people who contributed to this
> > + * project.
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License as
> > + * published by the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> > + * MA 02111-1307 USA
> > + */
> > +
> > +/* Tegra2 timer functions */
> > +
> > +#ifndef _TEGRA2_TIMER_H
> > +#define _TEGRA2_TIMER_H
> > +
> > +/* returns the current monotonic timer value in microseconds */
> > +unsigned long timer_get_us(void);
> > +
> > +/* returns what the time will likely be some microseconds into the
> future */
> > +unsigned long timer_get_future_us(u32 delay);
>
> 'likely' meaning it may or may not - no guarantee though. The new timer API
> is designed specifically designed to resolve this - 'At least x ms/us have
> passed' or 'at most x ms/us have passed'. No more 'x ms/us _might_ have
> passed'
>

Yes, watch this space.

BTW I have come across another problem where initialization must be done
which has long delays in it (LCD display power-up sequence). It's starting
to feel like we should have a central place for registering a timer which
calls back when a time has expired. That way we can continue with other
tings while we wait for the time to elapse. Something like:


/* Move to the next state */
static int next_state(void *my_data)
{
/* do some things, and then if you want to be called again... */
timer_register(timer_now_ms() + 40, next_state, my_data)
}

void start_lcd_init()
{
// do first thing
...
// set a timer to do the next thing later
timer_register(timer_now_ms() + 200, next_state, my_data)
}

...

Every now and then code (or a timer wait function) can call

timer_check()

which will call any expired timers on the list and remove them. This allows
LCD init to continue while downloading the kernel, for example.


I haven't thought too hard about this, but apart from LCD I know that USB
has some big delays. Obviously we can't make U-Boot multi-threaded but we
can perhaps do something simple like the above. What do you think?

Also given that your timer API stuff seems to have a good reception and
people are very happy, is there any impediment to getting this in sooner
rather than later?

Regards,
Simon



> > +
> > +#endif
> > +
>
> Regards,
>
> Graeme
>
Graeme Russ July 10, 2011, 6:54 a.m. UTC | #4
Hi Simon,

On 10/07/11 16:14, Simon Glass wrote:
> Hi Graeme,

[snip]

> 
>     timer_get_us needs to be u64 (unsigned long long). Also, the new timer API
>     will define this as time_now_us, would be great if you could use this
>     naming convention now to save me doing a mass of replaces later
> 
> 
> Yes will do. 

Thanks

>     > +
>     > +unsigned long timer_get_future_us(u32 delay)
>     > +{
>     > +     return timer_get_us() + delay;
>     > +}
> 
>     C'mon - We've been here before - This is timer API stuff. Where are you
>     going to use this? Why can't the proposed API be used instead?
> 
>     I know you don't like the 'time since' implementation, but this has been
>     discussed to death and it appears to me that the majority decision was to
>     go that route rather than the 'future time' route. It is a completely
>     pointless exercise and a complete waste of my time to re-write the timer
>     API just to have someone that doesn't like a particular aspect go off and
>     write a one-off function.
> 
> 
> Well this code pre-dates this and I haven't revised it. I will take another
> look and sort this out. In fact from memory the return value isn't even used! 

Ah, OK then - Sorry for the tone, I didn't realise the history of this patch

[snip]

> 
>     'likely' meaning it may or may not - no guarantee though. The new timer API
>     is designed specifically designed to resolve this - 'At least x ms/us have
>     passed' or 'at most x ms/us have passed'. No more 'x ms/us _might_ have
>     passed'
> 
> 
> Yes, watch this space.

Maybe you could grab the timer functions for the new API from the patch
series I posted recently and create the micro-second equivalents in Tegra2.
I can the move them into common code later with no other code changes necessary

> 
> BTW I have come across another problem where initialization must be done
> which has long delays in it (LCD display power-up sequence). It's starting
> to feel like we should have a central place for registering a timer which
> calls back when a time has expired. That way we can continue with other
> tings while we wait for the time to elapse. Something like:
> 
> 
> /* Move to the next state */
> static int next_state(void *my_data)
> {
> /* do some things, and then if you want to be called again... */
> timer_register(timer_now_ms() + 40, next_state, my_data)
> }
> 
> void start_lcd_init()
> {
> // do first thing
> ...
> // set a timer to do the next thing later
> timer_register(timer_now_ms() + 200, next_state, my_data)
> }
> 
> ...
> 
> Every now and then code (or a timer wait function) can call
> 
> timer_check()
> 
> which will call any expired timers on the list and remove them. This allows
> LCD init to continue while downloading the kernel, for example.
> 
> 
> I haven't thought too hard about this, but apart from LCD I know that USB
> has some big delays. Obviously we can't make U-Boot multi-threaded but we
> can perhaps do something simple like the above. What do you think?

Well, this is a little beyond the scope of a simple boot loader ;) And
unless we start getting real fancy with task schedulers etc, the callback
will most likely be done in the context of an IRQ handler.

I do agree, however, that in some circumstances, it would be useful to be
able to 'background' some tasks such as doing a flash erase in the
background while calculating the environment CRC or letting a device
initialising itself while U-Boot moves on through the boot sequence. But
this can be done without callbacks anyway in the board init sequence:

	...low level init stuff...,
	start_lcd_init,
	...other stuff...,
	wait_lcd_init_complete,
	...more stuff needing LCD output...,

> Also given that your timer API stuff seems to have a good reception and
> people are very happy, is there any impediment to getting this in sooner
> rather than later?
> 

I hope so, but I'm really wanting feedback from Wolfgang and I fear the
merge window will close before it's ready :(

Regards,

Graeme
Wolfgang Denk July 11, 2011, 6:17 a.m. UTC | #5
Dear Graeme Russ,

In message <4E1937A6.7050808@gmail.com> you wrote:
> 
> On 06/07/11 02:49, Simon Glass wrote:
> > These functions provide access to the high resolution microsecond timer
> > and tidy up a global variable in the code.
> 
> Excellent - Good to see microsecond timers making their way in already

Sorry, but I disagree here.

I consider it just overhead and code bloat.

Best regards,

Wolfgang Denk
Wolfgang Denk July 11, 2011, 6:20 a.m. UTC | #6
Dear Graeme Russ,

In message <4E1937A6.7050808@gmail.com> you wrote:
> 
> timer_get_us needs to be u64 (unsigned long long). Also, the new timer API
> will define this as time_now_us, would be great if you could use this
> naming convention now to save me doing a mass of replaces later


Um... this sounds as if there was some confirmed agreement on a new
timer API?  I remember that we had such a discussion some time ago,
with some suggestions, but then the discussion faded, and I don't
remember that any specific agreement was made.

Am I missing something?

Best regards,

Wolfgang Denk
Graeme Russ July 11, 2011, 6:43 a.m. UTC | #7
Hi Wolfgang,

On 11/07/11 16:20, Wolfgang Denk wrote:
> Dear Graeme Russ,
> 
> In message <4E1937A6.7050808@gmail.com> you wrote:
>>
>> timer_get_us needs to be u64 (unsigned long long). Also, the new timer API
>> will define this as time_now_us, would be great if you could use this
>> naming convention now to save me doing a mass of replaces later
> 
> 
> Um... this sounds as if there was some confirmed agreement on a new
> timer API?  I remember that we had such a discussion some time ago,
> with some suggestions, but then the discussion faded, and I don't
> remember that any specific agreement was made.
> 
> Am I missing something?

Yes - A 16 part patch series:
 - In patchwork, filter by Graeme Russ as submitter
 - http://lists.denx.de/pipermail/u-boot/2011-June/094958.html is the
summary post

A request for you to look at it (plus a few questions):
 - http://lists.denx.de/pipermail/u-boot/2011-July/095693.html

The wiki:
 - http://www.denx.de/wiki/U-Boot/TaskTimerAPI

Regards,

Graeme
Wolfgang Denk July 11, 2011, 7:58 p.m. UTC | #8
Dear Graeme,

In message <4E1A9B9B.4030104@gmail.com> you wrote:
> 
> > Am I missing something?
> 
> Yes - A 16 part patch series:
>  - In patchwork, filter by Graeme Russ as submitter
>  - http://lists.denx.de/pipermail/u-boot/2011-June/094958.html is the
> summary post

I'm aware of this - it's on my list, but unfortunately this is a long
list :-(

> The wiki:
>  - http://www.denx.de/wiki/U-Boot/TaskTimerAPI

I see. Hm... assuming this is still under discussion, how do you
suggest to handle the wiki version?  For discussing things, it's
probably not really efficient if several people edit the pages.

Best regards,

Wolfgang Denk
Graeme Russ July 11, 2011, 10:52 p.m. UTC | #9
On 12/07/11 05:58, Wolfgang Denk wrote:
> Dear Graeme,
> 
> In message <4E1A9B9B.4030104@gmail.com> you wrote:
>>
>>> Am I missing something?
>>
>> Yes - A 16 part patch series:
>>  - In patchwork, filter by Graeme Russ as submitter
>>  - http://lists.denx.de/pipermail/u-boot/2011-June/094958.html is the
>> summary post
> 
> I'm aware of this - it's on my list, but unfortunately this is a long
> list :-(
> 
>> The wiki:
>>  - http://www.denx.de/wiki/U-Boot/TaskTimerAPI
> 
> I see. Hm... assuming this is still under discussion, how do you
> suggest to handle the wiki version?  For discussing things, it's
> probably not really efficient if several people edit the pages.

What about if I keep the wiki updated with links to the past and current
discussion threads and patches in patchwork? I can update the wiki based on
the ongoing discussion until we are happy that we have reached the right
solution?

Regards,

Graeme
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/armv7/tegra2/timer.c
index fb061d0..b69c172 100644
--- a/arch/arm/cpu/armv7/tegra2/timer.c
+++ b/arch/arm/cpu/armv7/tegra2/timer.c
@@ -38,13 +38,12 @@ 
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/tegra2.h>
+#include <asm/arch/timer.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
-
 /* counter runs at 1MHz */
-#define TIMER_CLK	(1000000)
+#define TIMER_CLK	1000000
 #define TIMER_LOAD_VAL	0xffffffff
 
 /* timer without interrupts */
@@ -67,10 +66,10 @@  void set_timer(ulong t)
 void __udelay(unsigned long usec)
 {
 	long tmo = usec * (TIMER_CLK / 1000) / 1000;
-	unsigned long now, last = readl(&timer_base->cntr_1us);
+	unsigned long now, last = timer_get_us();
 
 	while (tmo > 0) {
-		now = readl(&timer_base->cntr_1us);
+		now = timer_get_us();
 		if (last > now) /* count up timer overflow */
 			tmo -= TIMER_LOAD_VAL - last + now;
 		else
@@ -82,7 +81,7 @@  void __udelay(unsigned long usec)
 void reset_timer_masked(void)
 {
 	/* reset time, capture current incrementer value time */
-	gd->lastinc = readl(&timer_base->cntr_1us) / (TIMER_CLK/CONFIG_SYS_HZ);
+	gd->lastinc = timer_get_us() / (TIMER_CLK/CONFIG_SYS_HZ);
 	gd->tbl = 0;		/* start "advancing" time stamp from 0 */
 }
 
@@ -91,7 +90,7 @@  ulong get_timer_masked(void)
 	ulong now;
 
 	/* current tick value */
-	now = readl(&timer_base->cntr_1us) / (TIMER_CLK / CONFIG_SYS_HZ);
+	now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ);
 
 	if (now >= gd->lastinc)	/* normal mode (non roll) */
 		/* move stamp forward with absolute diff ticks */
@@ -120,3 +119,17 @@  ulong get_tbclk(void)
 {
 	return CONFIG_SYS_HZ;
 }
+
+
+unsigned long timer_get_us(void)
+{
+	struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE;
+
+	return readl(&timer_base->cntr_1us);
+}
+
+unsigned long timer_get_future_us(u32 delay)
+{
+	return timer_get_us() + delay;
+}
+
diff --git a/arch/arm/include/asm/arch-tegra2/timer.h b/arch/arm/include/asm/arch-tegra2/timer.h
new file mode 100644
index 0000000..5d5445e
--- /dev/null
+++ b/arch/arm/include/asm/arch-tegra2/timer.h
@@ -0,0 +1,34 @@ 
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* Tegra2 timer functions */
+
+#ifndef _TEGRA2_TIMER_H
+#define _TEGRA2_TIMER_H
+
+/* returns the current monotonic timer value in microseconds */
+unsigned long timer_get_us(void);
+
+/* returns what the time will likely be some microseconds into the future */
+unsigned long timer_get_future_us(u32 delay);
+
+#endif
+