diff mbox

[U-Boot,resend] armv7/ltimer: Add support for local timer on armv7 cpus

Message ID 48d6117c89a79895ac320d95d4deda4a690a585b.1354785761.git.vipin.kumar@st.com
State Rejected
Delegated to: Albert ARIBAUD
Headers show

Commit Message

Vipin Kumar Dec. 6, 2012, 9:22 a.m. UTC
Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer within the
CPU core itself.  This patch adds generic support for local timer.

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 arch/arm/cpu/armv7/Makefile       |  11 ++-
 arch/arm/cpu/armv7/ca9_ltimer.c   | 152 ++++++++++++++++++++++++++++++++++++++
 arch/arm/include/asm/ca9_ltimer.h |  40 ++++++++++
 3 files changed, 199 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/ca9_ltimer.c
 create mode 100644 arch/arm/include/asm/ca9_ltimer.h

Comments

Vipin Kumar Dec. 12, 2012, 10:01 a.m. UTC | #1
ping

On 12/6/2012 2:52 PM, Vipin KUMAR wrote:
> Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer within the
> CPU core itself.  This patch adds generic support for local timer.
>
> Signed-off-by: Vipin Kumar<vipin.kumar@st.com>
> ---
>   arch/arm/cpu/armv7/Makefile       |  11 ++-
>   arch/arm/cpu/armv7/ca9_ltimer.c   | 152 ++++++++++++++++++++++++++++++++++++++
>   arch/arm/include/asm/ca9_ltimer.h |  40 ++++++++++
>   3 files changed, 199 insertions(+), 4 deletions(-)
>   create mode 100644 arch/arm/cpu/armv7/ca9_ltimer.c
>   create mode 100644 arch/arm/include/asm/ca9_ltimer.h
>
> diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
> index 4fdbee4..3ef01f6 100644
> --- a/arch/arm/cpu/armv7/Makefile
> +++ b/arch/arm/cpu/armv7/Makefile
> @@ -27,15 +27,18 @@ LIB	= $(obj)lib$(CPU).o
>
>   START	:= start.o
>
> -COBJS	+= cache_v7.o
> +COBJS-y	+= cache_v7.o
>
> -COBJS	+= cpu.o
> -COBJS	+= syslib.o
> +COBJS-y	+= cpu.o
> +COBJS-y	+= syslib.o
> +COBJS-$(CONFIG_ARMV7_CA9LTIMER) += ca9_ltimer.o
>
>   ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
> -SOBJS	+= lowlevel_init.o
> +SOBJS-y	+= lowlevel_init.o
>   endif
>
> +COBJS	:= $(sort $(COBJS-y))
> +SOBJS	:= $(sort $(SOBJS-y))
>   SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
>   OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
>   START	:= $(addprefix $(obj),$(START))
> diff --git a/arch/arm/cpu/armv7/ca9_ltimer.c b/arch/arm/cpu/armv7/ca9_ltimer.c
> new file mode 100644
> index 0000000..cbf1552
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/ca9_ltimer.c
> @@ -0,0 +1,152 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#include<common.h>
> +#include<asm/io.h>
> +#include<asm/ca9_ltimer.h>
> +#include<asm/arch/hardware.h>
> +
> +#define READ_TIMER()	readl(&ca9_timer_p->count)
> +
> +static struct ca9_timer_regs *const ca9_timer_p =
> +	(struct ca9_timer_regs *)CONFIG_ARMV7_LTIMER_BASE;
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define timestamp	gd->tbl
> +#define lastdec		gd->lastinc
> +#define tickshz		gd->timer_rate_hz
> +#define ticksper10usec	gd->tbu
> +
> +int timer_init(void)
> +{
> +	u32 prescaler, timertickshz;
> +	/*
> +	 * Genrally, CortexA9 MPUs are operating from 500MHz to 1500MHz which
> +	 * means that CA9 local timer clock would be in the range of 250 MHz to
> +	 * 750MHz.
> +	 * Try to find a prescaler which can perfectly divide the local timer
> +	 * clock. Take prescaler as 200 if nothing is found
> +	 */
> +	for (prescaler = 255; prescaler>  1; prescaler--) {
> +		if (CONFIG_ARMV7_LTMR_CLK ==
> +				(CONFIG_ARMV7_LTMR_CLK / prescaler) * prescaler)
> +			break;
> +	}
> +
> +	if (prescaler == 1)
> +		prescaler = 200;
> +	timertickshz = CONFIG_ARMV7_LTMR_CLK / prescaler;
> +	ticksper10usec = timertickshz / (100 * 1000);
> +	tickshz = timertickshz / CONFIG_SYS_HZ;
> +
> +	/* disable timers */
> +	writel(((prescaler - 1)<<  8) | AUTO_RELOAD,&ca9_timer_p->control);
> +
> +	/* load value for free running */
> +	writel(FREE_RUNNING,&ca9_timer_p->load);
> +
> +	/* auto reload, start timer */
> +	setbits_le32(&ca9_timer_p->control, TIMER_ENABLE);
> +
> +	reset_timer_masked();
> +
> +	return 0;
> +}
> +
> +/*
> + * timer without interrupts
> + */
> +
> +void reset_timer(void)
> +{
> +	reset_timer_masked();
> +}
> +
> +ulong get_timer(ulong base)
> +{
> +	return (get_timer_masked() / tickshz) - base;
> +}
> +
> +void set_timer(ulong t)
> +{
> +	timestamp = t;
> +}
> +
> +void __udelay(unsigned long usec)
> +{
> +	ulong tmo;
> +	ulong start = get_timer_masked();
> +	ulong rndoff;
> +
> +	rndoff = (usec % 10) ? 1 : 0;
> +	tmo = ((usec / 10) + rndoff) * ticksper10usec;
> +
> +	while ((ulong) (get_timer_masked() - start)<  tmo);
> +}
> +
> +void reset_timer_masked(void)
> +{
> +	/* reset time */
> +	lastdec = READ_TIMER();
> +	timestamp = 0;
> +}
> +
> +ulong get_timer_masked(void)
> +{
> +	ulong now = READ_TIMER();
> +
> +	if (now<= lastdec) {
> +		/* normal mode */
> +		timestamp += lastdec - now;
> +	} else {
> +		/* we have an overflow ... */
> +		timestamp += lastdec + FREE_RUNNING - now;
> +	}
> +	lastdec = now;
> +
> +	return timestamp;
> +}
> +
> +void udelay_masked(unsigned long usec)
> +{
> +	return udelay(usec);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (read timebase as long long).
> + * On ARM it just returns the timer value.
> + */
> +unsigned long long get_ticks(void)
> +{
> +	return get_timer(0);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (timebase clock frequency).
> + * On ARM it returns the number of timer ticks per second.
> + */
> +ulong get_tbclk(void)
> +{
> +	return CONFIG_SYS_HZ;
> +}
> diff --git a/arch/arm/include/asm/ca9_ltimer.h b/arch/arm/include/asm/ca9_ltimer.h
> new file mode 100644
> index 0000000..8833853
> --- /dev/null
> +++ b/arch/arm/include/asm/ca9_ltimer.h
> @@ -0,0 +1,40 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#ifndef __ARCH_ARM_CA9TIMER_H
> +#define __ARCH_ARM_CA9TIMER_H
> +
> +struct ca9_timer_regs {
> +	u32 load;
> +	u32 count;
> +	u32 control;
> +};
> +
> +/* control related definitions */
> +#define AUTO_RELOAD		(1<<  1)
> +#define TIMER_ENABLE		(1<<  0)
> +
> +/* load related definitions */
> +#define FREE_RUNNING		(0xFFFFFFFF)
> +
> +#endif
Vipin Kumar Dec. 14, 2012, 9:26 a.m. UTC | #2
ping again

On 12/6/2012 2:52 PM, Vipin KUMAR wrote:
> Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer within the
> CPU core itself.  This patch adds generic support for local timer.
>
> Signed-off-by: Vipin Kumar<vipin.kumar@st.com>
> ---
>   arch/arm/cpu/armv7/Makefile       |  11 ++-
>   arch/arm/cpu/armv7/ca9_ltimer.c   | 152 ++++++++++++++++++++++++++++++++++++++
>   arch/arm/include/asm/ca9_ltimer.h |  40 ++++++++++
>   3 files changed, 199 insertions(+), 4 deletions(-)
>   create mode 100644 arch/arm/cpu/armv7/ca9_ltimer.c
>   create mode 100644 arch/arm/include/asm/ca9_ltimer.h
>
> diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
> index 4fdbee4..3ef01f6 100644
> --- a/arch/arm/cpu/armv7/Makefile
> +++ b/arch/arm/cpu/armv7/Makefile
> @@ -27,15 +27,18 @@ LIB	= $(obj)lib$(CPU).o
>
>   START	:= start.o
>
> -COBJS	+= cache_v7.o
> +COBJS-y	+= cache_v7.o
>
> -COBJS	+= cpu.o
> -COBJS	+= syslib.o
> +COBJS-y	+= cpu.o
> +COBJS-y	+= syslib.o
> +COBJS-$(CONFIG_ARMV7_CA9LTIMER) += ca9_ltimer.o
>
>   ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
> -SOBJS	+= lowlevel_init.o
> +SOBJS-y	+= lowlevel_init.o
>   endif
>
> +COBJS	:= $(sort $(COBJS-y))
> +SOBJS	:= $(sort $(SOBJS-y))
>   SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
>   OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
>   START	:= $(addprefix $(obj),$(START))
> diff --git a/arch/arm/cpu/armv7/ca9_ltimer.c b/arch/arm/cpu/armv7/ca9_ltimer.c
> new file mode 100644
> index 0000000..cbf1552
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/ca9_ltimer.c
> @@ -0,0 +1,152 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#include<common.h>
> +#include<asm/io.h>
> +#include<asm/ca9_ltimer.h>
> +#include<asm/arch/hardware.h>
> +
> +#define READ_TIMER()	readl(&ca9_timer_p->count)
> +
> +static struct ca9_timer_regs *const ca9_timer_p =
> +	(struct ca9_timer_regs *)CONFIG_ARMV7_LTIMER_BASE;
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define timestamp	gd->tbl
> +#define lastdec		gd->lastinc
> +#define tickshz		gd->timer_rate_hz
> +#define ticksper10usec	gd->tbu
> +
> +int timer_init(void)
> +{
> +	u32 prescaler, timertickshz;
> +	/*
> +	 * Genrally, CortexA9 MPUs are operating from 500MHz to 1500MHz which
> +	 * means that CA9 local timer clock would be in the range of 250 MHz to
> +	 * 750MHz.
> +	 * Try to find a prescaler which can perfectly divide the local timer
> +	 * clock. Take prescaler as 200 if nothing is found
> +	 */
> +	for (prescaler = 255; prescaler>  1; prescaler--) {
> +		if (CONFIG_ARMV7_LTMR_CLK ==
> +				(CONFIG_ARMV7_LTMR_CLK / prescaler) * prescaler)
> +			break;
> +	}
> +
> +	if (prescaler == 1)
> +		prescaler = 200;
> +	timertickshz = CONFIG_ARMV7_LTMR_CLK / prescaler;
> +	ticksper10usec = timertickshz / (100 * 1000);
> +	tickshz = timertickshz / CONFIG_SYS_HZ;
> +
> +	/* disable timers */
> +	writel(((prescaler - 1)<<  8) | AUTO_RELOAD,&ca9_timer_p->control);
> +
> +	/* load value for free running */
> +	writel(FREE_RUNNING,&ca9_timer_p->load);
> +
> +	/* auto reload, start timer */
> +	setbits_le32(&ca9_timer_p->control, TIMER_ENABLE);
> +
> +	reset_timer_masked();
> +
> +	return 0;
> +}
> +
> +/*
> + * timer without interrupts
> + */
> +
> +void reset_timer(void)
> +{
> +	reset_timer_masked();
> +}
> +
> +ulong get_timer(ulong base)
> +{
> +	return (get_timer_masked() / tickshz) - base;
> +}
> +
> +void set_timer(ulong t)
> +{
> +	timestamp = t;
> +}
> +
> +void __udelay(unsigned long usec)
> +{
> +	ulong tmo;
> +	ulong start = get_timer_masked();
> +	ulong rndoff;
> +
> +	rndoff = (usec % 10) ? 1 : 0;
> +	tmo = ((usec / 10) + rndoff) * ticksper10usec;
> +
> +	while ((ulong) (get_timer_masked() - start)<  tmo);
> +}
> +
> +void reset_timer_masked(void)
> +{
> +	/* reset time */
> +	lastdec = READ_TIMER();
> +	timestamp = 0;
> +}
> +
> +ulong get_timer_masked(void)
> +{
> +	ulong now = READ_TIMER();
> +
> +	if (now<= lastdec) {
> +		/* normal mode */
> +		timestamp += lastdec - now;
> +	} else {
> +		/* we have an overflow ... */
> +		timestamp += lastdec + FREE_RUNNING - now;
> +	}
> +	lastdec = now;
> +
> +	return timestamp;
> +}
> +
> +void udelay_masked(unsigned long usec)
> +{
> +	return udelay(usec);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (read timebase as long long).
> + * On ARM it just returns the timer value.
> + */
> +unsigned long long get_ticks(void)
> +{
> +	return get_timer(0);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (timebase clock frequency).
> + * On ARM it returns the number of timer ticks per second.
> + */
> +ulong get_tbclk(void)
> +{
> +	return CONFIG_SYS_HZ;
> +}
> diff --git a/arch/arm/include/asm/ca9_ltimer.h b/arch/arm/include/asm/ca9_ltimer.h
> new file mode 100644
> index 0000000..8833853
> --- /dev/null
> +++ b/arch/arm/include/asm/ca9_ltimer.h
> @@ -0,0 +1,40 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#ifndef __ARCH_ARM_CA9TIMER_H
> +#define __ARCH_ARM_CA9TIMER_H
> +
> +struct ca9_timer_regs {
> +	u32 load;
> +	u32 count;
> +	u32 control;
> +};
> +
> +/* control related definitions */
> +#define AUTO_RELOAD		(1<<  1)
> +#define TIMER_ENABLE		(1<<  0)
> +
> +/* load related definitions */
> +#define FREE_RUNNING		(0xFFFFFFFF)
> +
> +#endif
Wolfgang Denk Dec. 14, 2012, 10:20 p.m. UTC | #3
Dear Vipin Kumar,

In message <50CAF0CB.1050108@st.com> you wrote:
> ping again

pong ;-)

> On 12/6/2012 2:52 PM, Vipin KUMAR wrote:
> > Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer within the
> > CPU core itself.  This patch adds generic support for local timer.

What would be the use of such timer support?  Is there any code that
actually needs it, and why does it need anything beyond the existing
timer support we have?

Best regards,

Wolfgang Denk
Dennis Lan (dlan) Dec. 16, 2012, 7:44 a.m. UTC | #4
Hi


On Sat, Dec 15, 2012 at 6:20 AM, Wolfgang Denk <wd@denx.de> wrote:

> Dear Vipin Kumar,
>
> In message <50CAF0CB.1050108@st.com> you wrote:
> > ping again
>
> pong ;-)
>
> > On 12/6/2012 2:52 PM, Vipin KUMAR wrote:
> > > Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer
> within the
> > > CPU core itself.  This patch adds generic support for local timer.
>
> What would be the use of such timer support?  Is there any code that
> actually needs it, and why does it need anything beyond the existing
> timer support we have?
>
Hi wolfgang:
  I think vipin here is trying to provide a generic timer support for ARMV7
architecture,
which contains private(local) and global timer. It's general a good thing
which means we can maximize the code usage..
  Actually I was planing to test the code, but haven't find the time yet ;-)

Hi vipin:
  why you only support local timer(private)? shouldn't it different to
support global timer too?


> Best regards,
>
> Wolfgang Denk
>
> --
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
> There is a time in the tides of men, Which, taken at its flood, leads
> on to success. On the other hand, don't count on it.   - T. K. Lawson
> _______________________________________________
> U-Boot mailing list
> U-Boot@lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>
Vipin Kumar Dec. 17, 2012, 4:24 a.m. UTC | #5
On 12/16/2012 1:14 PM, Dennis Lan (dlan) wrote:
> Hi
>
>
> On Sat, Dec 15, 2012 at 6:20 AM, Wolfgang Denk <wd@denx.de
> <mailto:wd@denx.de>> wrote:
>
>     Dear Vipin Kumar,
>
>     In message <50CAF0CB.1050108@st.com
>     <mailto:50CAF0CB.1050108@st.com>> you wrote:
>      > ping again
>
>     pong ;-)
>
>      > On 12/6/2012 2:52 PM, Vipin KUMAR wrote:
>      > > Certain ARMV7 cpus eg. CortexA9 contains a local and a global
>     timer within the
>      > > CPU core itself.  This patch adds generic support for local timer.
>
>     What would be the use of such timer support?  Is there any code that
>     actually needs it, and why does it need anything beyond the existing
>     timer support we have?
>
> Hi wolfgang:
>    I think vipin here is trying to provide a generic timer support for
> ARMV7 architecture,
> which contains private(local) and global timer. It's general a good
> thing which means we can maximize the code usage..
>    Actually I was planing to test the code, but haven't find the time
> yet ;-)
>

Hello Wolfgang

Dennis is right. I am trying to provide the armv7 local timer support.

> Hi vipin:
>    why you only support local timer(private)? shouldn't it different to
> support global timer too?
>

Well, actually the local timer was used in the spear13xx support which 
is to be added later on. The global timer was not used and hence the 
driver was not needed (at least by us). but I agree that such a driver 
would be useful for a lot of people using armv7 cores and CPU timers

The global timer support, even if it is added, would be added as a 
separate driver so this is infact complete in its own

Regards
Vipin
Armando Visconti Dec. 17, 2012, 10:39 a.m. UTC | #6
Ciao Vipin,

Yes, I agree about the need to have the generic
local_timer support in u-boot.

Internally I was not able to give comment about this
part. So, see my comments now.

On 12/06/2012 10:22 AM, Vipin KUMAR wrote:
> Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer within the
> CPU core itself.  This patch adds generic support for local timer.
>
> Signed-off-by: Vipin Kumar<vipin.kumar@st.com>
> ---
>   arch/arm/cpu/armv7/Makefile       |  11 ++-
>   arch/arm/cpu/armv7/ca9_ltimer.c   | 152 ++++++++++++++++++++++++++++++++++++++
>   arch/arm/include/asm/ca9_ltimer.h |  40 ++++++++++
>   3 files changed, 199 insertions(+), 4 deletions(-)
>   create mode 100644 arch/arm/cpu/armv7/ca9_ltimer.c
>   create mode 100644 arch/arm/include/asm/ca9_ltimer.h
>
> diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
> index 4fdbee4..3ef01f6 100644
> --- a/arch/arm/cpu/armv7/Makefile
> +++ b/arch/arm/cpu/armv7/Makefile
> @@ -27,15 +27,18 @@ LIB	= $(obj)lib$(CPU).o
>
>   START	:= start.o
>
> -COBJS	+= cache_v7.o
> +COBJS-y	+= cache_v7.o
>
> -COBJS	+= cpu.o
> -COBJS	+= syslib.o
> +COBJS-y	+= cpu.o
> +COBJS-y	+= syslib.o
> +COBJS-$(CONFIG_ARMV7_CA9LTIMER) += ca9_ltimer.o
>

Is it really necessary to have the 'ca9' prefix here?
I think it  would be better to stay more generic here,
like: 'CONFIG_ARMV7_LTIMER' and 'ltimer.o'.

In linux as well is kept generic, even across architectures...

If accepted, apply globally...

>   ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
> -SOBJS	+= lowlevel_init.o
> +SOBJS-y	+= lowlevel_init.o
>   endif
>
> +COBJS	:= $(sort $(COBJS-y))
> +SOBJS	:= $(sort $(SOBJS-y))
>   SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
>   OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
>   START	:= $(addprefix $(obj),$(START))
> diff --git a/arch/arm/cpu/armv7/ca9_ltimer.c b/arch/arm/cpu/armv7/ca9_ltimer.c
> new file mode 100644
> index 0000000..cbf1552
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/ca9_ltimer.c
> @@ -0,0 +1,152 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#include<common.h>
> +#include<asm/io.h>
> +#include<asm/ca9_ltimer.h>
> +#include<asm/arch/hardware.h>
> +
> +#define READ_TIMER()	readl(&ca9_timer_p->count)
> +
> +static struct ca9_timer_regs *const ca9_timer_p =
> +	(struct ca9_timer_regs *)CONFIG_ARMV7_LTIMER_BASE;
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define timestamp	gd->tbl
> +#define lastdec		gd->lastinc
> +#define tickshz		gd->timer_rate_hz
> +#define ticksper10usec	gd->tbu
> +
> +int timer_init(void)
> +{
> +	u32 prescaler, timertickshz;
> +	/*
> +	 * Genrally, CortexA9 MPUs are operating from 500MHz to 1500MHz which
> +	 * means that CA9 local timer clock would be in the range of 250 MHz to
> +	 * 750MHz.
> +	 * Try to find a prescaler which can perfectly divide the local timer
> +	 * clock. Take prescaler as 200 if nothing is found
> +	 */
> +	for (prescaler = 255; prescaler>  1; prescaler--) {
> +		if (CONFIG_ARMV7_LTMR_CLK ==
> +				(CONFIG_ARMV7_LTMR_CLK / prescaler) * prescaler)
> +			break;
> +	}
> +
> +	if (prescaler == 1)
> +		prescaler = 200;

Where the default '200' prescaler selection come from?
Shouldn't it be a configurable option (i.e. CONFIG_)?
Or passed as an argument to this function?

> +	timertickshz = CONFIG_ARMV7_LTMR_CLK / prescaler;
> +	ticksper10usec = timertickshz / (100 * 1000);
> +	tickshz = timertickshz / CONFIG_SYS_HZ;
> +
> +	/* disable timers */
> +	writel(((prescaler - 1)<<  8) | AUTO_RELOAD,&ca9_timer_p->control);
> +

Why can't single-shot be selectable?
Shouldn't it be passed as an argument to timer_init()?

> +	/* load value for free running */
> +	writel(FREE_RUNNING,&ca9_timer_p->load);
> +
> +	/* auto reload, start timer */
> +	setbits_le32(&ca9_timer_p->control, TIMER_ENABLE);
> +
> +	reset_timer_masked();
> +
> +	return 0;
> +}
> +
> +/*
> + * timer without interrupts
> + */
> +
> +void reset_timer(void)
> +{
> +	reset_timer_masked();
> +}
> +
> +ulong get_timer(ulong base)
> +{
> +	return (get_timer_masked() / tickshz) - base;
> +}
> +
> +void set_timer(ulong t)
> +{
> +	timestamp = t;
> +}
> +
> +void __udelay(unsigned long usec)
> +{
> +	ulong tmo;
> +	ulong start = get_timer_masked();
> +	ulong rndoff;
> +
> +	rndoff = (usec % 10) ? 1 : 0;
> +	tmo = ((usec / 10) + rndoff) * ticksper10usec;
> +
> +	while ((ulong) (get_timer_masked() - start)<  tmo);
> +}
> +
> +void reset_timer_masked(void)
> +{
> +	/* reset time */
> +	lastdec = READ_TIMER();
> +	timestamp = 0;
> +}
> +
> +ulong get_timer_masked(void)
> +{
> +	ulong now = READ_TIMER();
> +
> +	if (now<= lastdec) {
> +		/* normal mode */
> +		timestamp += lastdec - now;
> +	} else {
> +		/* we have an overflow ... */
> +		timestamp += lastdec + FREE_RUNNING - now;
> +	}
> +	lastdec = now;
> +
> +	return timestamp;
> +}
> +
> +void udelay_masked(unsigned long usec)
> +{
> +	return udelay(usec);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (read timebase as long long).
> + * On ARM it just returns the timer value.
> + */
> +unsigned long long get_ticks(void)
> +{
> +	return get_timer(0);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (timebase clock frequency).
> + * On ARM it returns the number of timer ticks per second.
> + */
> +ulong get_tbclk(void)
> +{
> +	return CONFIG_SYS_HZ;
> +}
> diff --git a/arch/arm/include/asm/ca9_ltimer.h b/arch/arm/include/asm/ca9_ltimer.h
> new file mode 100644
> index 0000000..8833853
> --- /dev/null
> +++ b/arch/arm/include/asm/ca9_ltimer.h
> @@ -0,0 +1,40 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#ifndef __ARCH_ARM_CA9TIMER_H
> +#define __ARCH_ARM_CA9TIMER_H
> +
> +struct ca9_timer_regs {
> +	u32 load;
> +	u32 count;
> +	u32 control;
> +};
> +
> +/* control related definitions */
> +#define AUTO_RELOAD		(1<<  1)
> +#define TIMER_ENABLE		(1<<  0)
> +
> +/* load related definitions */
> +#define FREE_RUNNING		(0xFFFFFFFF)
> +
> +#endif

Seems good otherwise.
Reveiewed-by:armando.visconti@st.com
Wolfgang Denk Dec. 17, 2012, 5:50 p.m. UTC | #7
Dear "Dennis Lan (dlan)",

In message <CAF1ZMEcVWc3DNdcb7gQ60D-8Nx-MHOpkLs=eY0ph2w_Lgcozaw@mail.gmail.com> you wrote:
>
> > What would be the use of such timer support?  Is there any code that
> > actually needs it, and why does it need anything beyond the existing
> > timer support we have?

>   I think vipin here is trying to provide a generic timer support for ARMV7
> architecture,
> which contains private(local) and global timer. It's general a good thing
> which means we can maximize the code usage..

Sorry, I don't get it.  Why would we need separate global and local
timers?  And what exactly is "local" here - local to what?

We don't need anything like that on other architectures - so why here?

"general a good thing" sounds like "nice to have", and this is usually
something we don't really need, especially not in a boot loader.

Best regards,

Wolfgang Denk
Wolfgang Denk Dec. 17, 2012, 5:53 p.m. UTC | #8
Dear Vipin Kumar,

In message <50CE9E90.1090406@st.com> you wrote:
>
> Dennis is right. I am trying to provide the armv7 local timer support.

Why would we need such?  And how is the term "local" defined here?
Local to what?

> Well, actually the local timer was used in the spear13xx support which 
> is to be added later on. The global timer was not used and hence the 
> driver was not needed (at least by us). but I agree that such a driver 
> would be useful for a lot of people using armv7 cores and CPU timers

Please explain why?  We do have timer support on armv7, right?

Why are you adding something new, then?  If you are tring to replace
existing code with some better implementation, I would expect to see
code being removed, too?

> The global timer support, even if it is added, would be added as a 
> separate driver so this is infact complete in its own

Please understand that completeness has never been any goal for
U-Boot, on contrary.

Quote:

Perfection is reached, not when there is no longer anything  to  add,
but when there is no longer anything to take away.
                                           - Antoine de Saint-Exupery


Best regards,

Wolfgang Denk
Vipin Kumar Dec. 18, 2012, 4:39 a.m. UTC | #9
On 12/17/2012 11:20 PM, Wolfgang Denk wrote:
> Dear "Dennis Lan (dlan)",
>
> In message<CAF1ZMEcVWc3DNdcb7gQ60D-8Nx-MHOpkLs=eY0ph2w_Lgcozaw@mail.gmail.com>  you wrote:
>>
>>> What would be the use of such timer support?  Is there any code that
>>> actually needs it, and why does it need anything beyond the existing
>>> timer support we have?
>
>>    I think vipin here is trying to provide a generic timer support for ARMV7
>> architecture,
>> which contains private(local) and global timer. It's general a good thing
>> which means we can maximize the code usage..
>
> Sorry, I don't get it.  Why would we need separate global and local
> timers?  And what exactly is "local" here - local to what?
>
> We don't need anything like that on other architectures - so why here?
>

Let me start afresh. There are two timer peripherals (called as local 
and global) built into armv7 cores. The local timer is specific to each 
processor while the global timer is common for all cores. These timers 
may be initialized and used for timer operations in armv7 based SoCs

> "general a good thing" sounds like "nice to have", and this is usually
> something we don't really need, especially not in a boot loader.
>

This is nothing but a timer peripheral driver. The timer is a part of 
armv7 core so it is kept in arch/arm/cpu/armv7

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0407i/index.html

Regards
Vipin

> Best regards,
>
> Wolfgang Denk
>
Albert ARIBAUD Feb. 3, 2013, 1:58 p.m. UTC | #10
Hi Vipin,

On Thu, 6 Dec 2012 14:52:55 +0530, Vipin Kumar <vipin.kumar@st.com>
wrote:

> Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer within the
> CPU core itself.  This patch adds generic support for local timer.
> 
> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
> ---
>  arch/arm/cpu/armv7/Makefile       |  11 ++-
>  arch/arm/cpu/armv7/ca9_ltimer.c   | 152 ++++++++++++++++++++++++++++++++++++++
>  arch/arm/include/asm/ca9_ltimer.h |  40 ++++++++++
>  3 files changed, 199 insertions(+), 4 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/ca9_ltimer.c
>  create mode 100644 arch/arm/include/asm/ca9_ltimer.h
> 
> diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
> index 4fdbee4..3ef01f6 100644
> --- a/arch/arm/cpu/armv7/Makefile
> +++ b/arch/arm/cpu/armv7/Makefile
> @@ -27,15 +27,18 @@ LIB	= $(obj)lib$(CPU).o
>  
>  START	:= start.o
>  
> -COBJS	+= cache_v7.o
> +COBJS-y	+= cache_v7.o
>  
> -COBJS	+= cpu.o
> -COBJS	+= syslib.o
> +COBJS-y	+= cpu.o
> +COBJS-y	+= syslib.o
> +COBJS-$(CONFIG_ARMV7_CA9LTIMER) += ca9_ltimer.o
>  
>  ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
> -SOBJS	+= lowlevel_init.o
> +SOBJS-y	+= lowlevel_init.o
>  endif
>  
> +COBJS	:= $(sort $(COBJS-y))
> +SOBJS	:= $(sort $(SOBJS-y))
>  SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
>  OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
>  START	:= $(addprefix $(obj),$(START))
> diff --git a/arch/arm/cpu/armv7/ca9_ltimer.c b/arch/arm/cpu/armv7/ca9_ltimer.c
> new file mode 100644
> index 0000000..cbf1552
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/ca9_ltimer.c
> @@ -0,0 +1,152 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/ca9_ltimer.h>
> +#include <asm/arch/hardware.h>
> +
> +#define READ_TIMER()	readl(&ca9_timer_p->count)
> +
> +static struct ca9_timer_regs *const ca9_timer_p =
> +	(struct ca9_timer_regs *)CONFIG_ARMV7_LTIMER_BASE;
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define timestamp	gd->tbl
> +#define lastdec		gd->lastinc
> +#define tickshz		gd->timer_rate_hz
> +#define ticksper10usec	gd->tbu
> +
> +int timer_init(void)
> +{
> +	u32 prescaler, timertickshz;
> +	/*
> +	 * Genrally, CortexA9 MPUs are operating from 500MHz to 1500MHz which
> +	 * means that CA9 local timer clock would be in the range of 250 MHz to
> +	 * 750MHz.
> +	 * Try to find a prescaler which can perfectly divide the local timer
> +	 * clock. Take prescaler as 200 if nothing is found
> +	 */
> +	for (prescaler = 255; prescaler > 1; prescaler--) {
> +		if (CONFIG_ARMV7_LTMR_CLK ==
> +				(CONFIG_ARMV7_LTMR_CLK / prescaler) * prescaler)
> +			break;
> +	}
> +
> +	if (prescaler == 1)
> +		prescaler = 200;
> +	timertickshz = CONFIG_ARMV7_LTMR_CLK / prescaler;
> +	ticksper10usec = timertickshz / (100 * 1000);
> +	tickshz = timertickshz / CONFIG_SYS_HZ;
> +
> +	/* disable timers */
> +	writel(((prescaler - 1) << 8) | AUTO_RELOAD, &ca9_timer_p->control);
> +
> +	/* load value for free running */
> +	writel(FREE_RUNNING, &ca9_timer_p->load);
> +
> +	/* auto reload, start timer */
> +	setbits_le32(&ca9_timer_p->control, TIMER_ENABLE);
> +
> +	reset_timer_masked();
> +
> +	return 0;
> +}
> +
> +/*
> + * timer without interrupts
> + */
> +
> +void reset_timer(void)
> +{
> +	reset_timer_masked();
> +}
> +
> +ulong get_timer(ulong base)
> +{
> +	return (get_timer_masked() / tickshz) - base;
> +}
> +
> +void set_timer(ulong t)
> +{
> +	timestamp = t;
> +}
> +
> +void __udelay(unsigned long usec)
> +{
> +	ulong tmo;
> +	ulong start = get_timer_masked();
> +	ulong rndoff;
> +
> +	rndoff = (usec % 10) ? 1 : 0;
> +	tmo = ((usec / 10) + rndoff) * ticksper10usec;
> +
> +	while ((ulong) (get_timer_masked() - start) < tmo);
> +}
> +
> +void reset_timer_masked(void)
> +{
> +	/* reset time */
> +	lastdec = READ_TIMER();
> +	timestamp = 0;
> +}
> +
> +ulong get_timer_masked(void)
> +{
> +	ulong now = READ_TIMER();
> +
> +	if (now <= lastdec) {
> +		/* normal mode */
> +		timestamp += lastdec - now;
> +	} else {
> +		/* we have an overflow ... */
> +		timestamp += lastdec + FREE_RUNNING - now;
> +	}
> +	lastdec = now;
> +
> +	return timestamp;
> +}
> +
> +void udelay_masked(unsigned long usec)
> +{
> +	return udelay(usec);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (read timebase as long long).
> + * On ARM it just returns the timer value.
> + */
> +unsigned long long get_ticks(void)
> +{
> +	return get_timer(0);
> +}
> +
> +/*
> + * This function is derived from PowerPC code (timebase clock frequency).
> + * On ARM it returns the number of timer ticks per second.
> + */
> +ulong get_tbclk(void)
> +{
> +	return CONFIG_SYS_HZ;
> +}
> diff --git a/arch/arm/include/asm/ca9_ltimer.h b/arch/arm/include/asm/ca9_ltimer.h
> new file mode 100644
> index 0000000..8833853
> --- /dev/null
> +++ b/arch/arm/include/asm/ca9_ltimer.h
> @@ -0,0 +1,40 @@
> +/*
> + * (C) Copyright 2012
> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
> + *
> + * 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
> + */
> +
> +#ifndef __ARCH_ARM_CA9TIMER_H
> +#define __ARCH_ARM_CA9TIMER_H
> +
> +struct ca9_timer_regs {
> +	u32 load;
> +	u32 count;
> +	u32 control;
> +};
> +
> +/* control related definitions */
> +#define AUTO_RELOAD		(1 << 1)
> +#define TIMER_ENABLE		(1 << 0)
> +
> +/* load related definitions */
> +#define FREE_RUNNING		(0xFFFFFFFF)
> +
> +#endif

Rejected on the grounds that it is basically dead code. Feel free to
resubmit within a series where it is needed, for instance in support of
a new target where current timer implementation would not be useable, or
at least, where using the core-local timer module brings benefits
with respect to the current implementation.

Amicalement,
Vipin Kumar Feb. 6, 2013, 6:46 a.m. UTC | #11
On 2/3/2013 7:28 PM, Albert ARIBAUD wrote:
> Hi Vipin,
>
> On Thu, 6 Dec 2012 14:52:55 +0530, Vipin Kumar<vipin.kumar@st.com>
> wrote:
>
>> Certain ARMV7 cpus eg. CortexA9 contains a local and a global timer within the
>> CPU core itself.  This patch adds generic support for local timer.
>>
>> Signed-off-by: Vipin Kumar<vipin.kumar@st.com>
>> ---
>>   arch/arm/cpu/armv7/Makefile       |  11 ++-
>>   arch/arm/cpu/armv7/ca9_ltimer.c   | 152 ++++++++++++++++++++++++++++++++++++++
>>   arch/arm/include/asm/ca9_ltimer.h |  40 ++++++++++
>>   3 files changed, 199 insertions(+), 4 deletions(-)
>>   create mode 100644 arch/arm/cpu/armv7/ca9_ltimer.c
>>   create mode 100644 arch/arm/include/asm/ca9_ltimer.h
>>
>> diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
>> index 4fdbee4..3ef01f6 100644
>> --- a/arch/arm/cpu/armv7/Makefile
>> +++ b/arch/arm/cpu/armv7/Makefile
>> @@ -27,15 +27,18 @@ LIB	= $(obj)lib$(CPU).o
>>
>>   START	:= start.o
>>
>> -COBJS	+= cache_v7.o
>> +COBJS-y	+= cache_v7.o
>>
>> -COBJS	+= cpu.o
>> -COBJS	+= syslib.o
>> +COBJS-y	+= cpu.o
>> +COBJS-y	+= syslib.o
>> +COBJS-$(CONFIG_ARMV7_CA9LTIMER) += ca9_ltimer.o
>>
>>   ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
>> -SOBJS	+= lowlevel_init.o
>> +SOBJS-y	+= lowlevel_init.o
>>   endif
>>
>> +COBJS	:= $(sort $(COBJS-y))
>> +SOBJS	:= $(sort $(SOBJS-y))
>>   SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
>>   OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
>>   START	:= $(addprefix $(obj),$(START))
>> diff --git a/arch/arm/cpu/armv7/ca9_ltimer.c b/arch/arm/cpu/armv7/ca9_ltimer.c
>> new file mode 100644
>> index 0000000..cbf1552
>> --- /dev/null
>> +++ b/arch/arm/cpu/armv7/ca9_ltimer.c
>> @@ -0,0 +1,152 @@
>> +/*
>> + * (C) Copyright 2012
>> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
>> + *
>> + * 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
>> + */
>> +
>> +#include<common.h>
>> +#include<asm/io.h>
>> +#include<asm/ca9_ltimer.h>
>> +#include<asm/arch/hardware.h>
>> +
>> +#define READ_TIMER()	readl(&ca9_timer_p->count)
>> +
>> +static struct ca9_timer_regs *const ca9_timer_p =
>> +	(struct ca9_timer_regs *)CONFIG_ARMV7_LTIMER_BASE;
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#define timestamp	gd->tbl
>> +#define lastdec		gd->lastinc
>> +#define tickshz		gd->timer_rate_hz
>> +#define ticksper10usec	gd->tbu
>> +
>> +int timer_init(void)
>> +{
>> +	u32 prescaler, timertickshz;
>> +	/*
>> +	 * Genrally, CortexA9 MPUs are operating from 500MHz to 1500MHz which
>> +	 * means that CA9 local timer clock would be in the range of 250 MHz to
>> +	 * 750MHz.
>> +	 * Try to find a prescaler which can perfectly divide the local timer
>> +	 * clock. Take prescaler as 200 if nothing is found
>> +	 */
>> +	for (prescaler = 255; prescaler>  1; prescaler--) {
>> +		if (CONFIG_ARMV7_LTMR_CLK ==
>> +				(CONFIG_ARMV7_LTMR_CLK / prescaler) * prescaler)
>> +			break;
>> +	}
>> +
>> +	if (prescaler == 1)
>> +		prescaler = 200;
>> +	timertickshz = CONFIG_ARMV7_LTMR_CLK / prescaler;
>> +	ticksper10usec = timertickshz / (100 * 1000);
>> +	tickshz = timertickshz / CONFIG_SYS_HZ;
>> +
>> +	/* disable timers */
>> +	writel(((prescaler - 1)<<  8) | AUTO_RELOAD,&ca9_timer_p->control);
>> +
>> +	/* load value for free running */
>> +	writel(FREE_RUNNING,&ca9_timer_p->load);
>> +
>> +	/* auto reload, start timer */
>> +	setbits_le32(&ca9_timer_p->control, TIMER_ENABLE);
>> +
>> +	reset_timer_masked();
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * timer without interrupts
>> + */
>> +
>> +void reset_timer(void)
>> +{
>> +	reset_timer_masked();
>> +}
>> +
>> +ulong get_timer(ulong base)
>> +{
>> +	return (get_timer_masked() / tickshz) - base;
>> +}
>> +
>> +void set_timer(ulong t)
>> +{
>> +	timestamp = t;
>> +}
>> +
>> +void __udelay(unsigned long usec)
>> +{
>> +	ulong tmo;
>> +	ulong start = get_timer_masked();
>> +	ulong rndoff;
>> +
>> +	rndoff = (usec % 10) ? 1 : 0;
>> +	tmo = ((usec / 10) + rndoff) * ticksper10usec;
>> +
>> +	while ((ulong) (get_timer_masked() - start)<  tmo);
>> +}
>> +
>> +void reset_timer_masked(void)
>> +{
>> +	/* reset time */
>> +	lastdec = READ_TIMER();
>> +	timestamp = 0;
>> +}
>> +
>> +ulong get_timer_masked(void)
>> +{
>> +	ulong now = READ_TIMER();
>> +
>> +	if (now<= lastdec) {
>> +		/* normal mode */
>> +		timestamp += lastdec - now;
>> +	} else {
>> +		/* we have an overflow ... */
>> +		timestamp += lastdec + FREE_RUNNING - now;
>> +	}
>> +	lastdec = now;
>> +
>> +	return timestamp;
>> +}
>> +
>> +void udelay_masked(unsigned long usec)
>> +{
>> +	return udelay(usec);
>> +}
>> +
>> +/*
>> + * This function is derived from PowerPC code (read timebase as long long).
>> + * On ARM it just returns the timer value.
>> + */
>> +unsigned long long get_ticks(void)
>> +{
>> +	return get_timer(0);
>> +}
>> +
>> +/*
>> + * This function is derived from PowerPC code (timebase clock frequency).
>> + * On ARM it returns the number of timer ticks per second.
>> + */
>> +ulong get_tbclk(void)
>> +{
>> +	return CONFIG_SYS_HZ;
>> +}
>> diff --git a/arch/arm/include/asm/ca9_ltimer.h b/arch/arm/include/asm/ca9_ltimer.h
>> new file mode 100644
>> index 0000000..8833853
>> --- /dev/null
>> +++ b/arch/arm/include/asm/ca9_ltimer.h
>> @@ -0,0 +1,40 @@
>> +/*
>> + * (C) Copyright 2012
>> + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
>> + *
>> + * 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
>> + */
>> +
>> +#ifndef __ARCH_ARM_CA9TIMER_H
>> +#define __ARCH_ARM_CA9TIMER_H
>> +
>> +struct ca9_timer_regs {
>> +	u32 load;
>> +	u32 count;
>> +	u32 control;
>> +};
>> +
>> +/* control related definitions */
>> +#define AUTO_RELOAD		(1<<  1)
>> +#define TIMER_ENABLE		(1<<  0)
>> +
>> +/* load related definitions */
>> +#define FREE_RUNNING		(0xFFFFFFFF)
>> +
>> +#endif
>
> Rejected on the grounds that it is basically dead code. Feel free to
> resubmit within a series where it is needed, for instance in support of
> a new target where current timer implementation would not be useable, or
> at least, where using the core-local timer module brings benefits
> with respect to the current implementation.
>

OK. I thought this driver can be used by anyone using a CA9. Infact, I 
remember that someone showed interest to use it

Anyways, I would resubmit with its user

Vipin

> Amicalement,
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index 4fdbee4..3ef01f6 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -27,15 +27,18 @@  LIB	= $(obj)lib$(CPU).o
 
 START	:= start.o
 
-COBJS	+= cache_v7.o
+COBJS-y	+= cache_v7.o
 
-COBJS	+= cpu.o
-COBJS	+= syslib.o
+COBJS-y	+= cpu.o
+COBJS-y	+= syslib.o
+COBJS-$(CONFIG_ARMV7_CA9LTIMER) += ca9_ltimer.o
 
 ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),)
-SOBJS	+= lowlevel_init.o
+SOBJS-y	+= lowlevel_init.o
 endif
 
+COBJS	:= $(sort $(COBJS-y))
+SOBJS	:= $(sort $(SOBJS-y))
 SRCS	:= $(START:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS) $(SOBJS))
 START	:= $(addprefix $(obj),$(START))
diff --git a/arch/arm/cpu/armv7/ca9_ltimer.c b/arch/arm/cpu/armv7/ca9_ltimer.c
new file mode 100644
index 0000000..cbf1552
--- /dev/null
+++ b/arch/arm/cpu/armv7/ca9_ltimer.c
@@ -0,0 +1,152 @@ 
+/*
+ * (C) Copyright 2012
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ca9_ltimer.h>
+#include <asm/arch/hardware.h>
+
+#define READ_TIMER()	readl(&ca9_timer_p->count)
+
+static struct ca9_timer_regs *const ca9_timer_p =
+	(struct ca9_timer_regs *)CONFIG_ARMV7_LTIMER_BASE;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define timestamp	gd->tbl
+#define lastdec		gd->lastinc
+#define tickshz		gd->timer_rate_hz
+#define ticksper10usec	gd->tbu
+
+int timer_init(void)
+{
+	u32 prescaler, timertickshz;
+	/*
+	 * Genrally, CortexA9 MPUs are operating from 500MHz to 1500MHz which
+	 * means that CA9 local timer clock would be in the range of 250 MHz to
+	 * 750MHz.
+	 * Try to find a prescaler which can perfectly divide the local timer
+	 * clock. Take prescaler as 200 if nothing is found
+	 */
+	for (prescaler = 255; prescaler > 1; prescaler--) {
+		if (CONFIG_ARMV7_LTMR_CLK ==
+				(CONFIG_ARMV7_LTMR_CLK / prescaler) * prescaler)
+			break;
+	}
+
+	if (prescaler == 1)
+		prescaler = 200;
+	timertickshz = CONFIG_ARMV7_LTMR_CLK / prescaler;
+	ticksper10usec = timertickshz / (100 * 1000);
+	tickshz = timertickshz / CONFIG_SYS_HZ;
+
+	/* disable timers */
+	writel(((prescaler - 1) << 8) | AUTO_RELOAD, &ca9_timer_p->control);
+
+	/* load value for free running */
+	writel(FREE_RUNNING, &ca9_timer_p->load);
+
+	/* auto reload, start timer */
+	setbits_le32(&ca9_timer_p->control, TIMER_ENABLE);
+
+	reset_timer_masked();
+
+	return 0;
+}
+
+/*
+ * timer without interrupts
+ */
+
+void reset_timer(void)
+{
+	reset_timer_masked();
+}
+
+ulong get_timer(ulong base)
+{
+	return (get_timer_masked() / tickshz) - base;
+}
+
+void set_timer(ulong t)
+{
+	timestamp = t;
+}
+
+void __udelay(unsigned long usec)
+{
+	ulong tmo;
+	ulong start = get_timer_masked();
+	ulong rndoff;
+
+	rndoff = (usec % 10) ? 1 : 0;
+	tmo = ((usec / 10) + rndoff) * ticksper10usec;
+
+	while ((ulong) (get_timer_masked() - start) < tmo);
+}
+
+void reset_timer_masked(void)
+{
+	/* reset time */
+	lastdec = READ_TIMER();
+	timestamp = 0;
+}
+
+ulong get_timer_masked(void)
+{
+	ulong now = READ_TIMER();
+
+	if (now <= lastdec) {
+		/* normal mode */
+		timestamp += lastdec - now;
+	} else {
+		/* we have an overflow ... */
+		timestamp += lastdec + FREE_RUNNING - now;
+	}
+	lastdec = now;
+
+	return timestamp;
+}
+
+void udelay_masked(unsigned long usec)
+{
+	return udelay(usec);
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/include/asm/ca9_ltimer.h b/arch/arm/include/asm/ca9_ltimer.h
new file mode 100644
index 0000000..8833853
--- /dev/null
+++ b/arch/arm/include/asm/ca9_ltimer.h
@@ -0,0 +1,40 @@ 
+/*
+ * (C) Copyright 2012
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ *
+ * 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
+ */
+
+#ifndef __ARCH_ARM_CA9TIMER_H
+#define __ARCH_ARM_CA9TIMER_H
+
+struct ca9_timer_regs {
+	u32 load;
+	u32 count;
+	u32 control;
+};
+
+/* control related definitions */
+#define AUTO_RELOAD		(1 << 1)
+#define TIMER_ENABLE		(1 << 0)
+
+/* load related definitions */
+#define FREE_RUNNING		(0xFFFFFFFF)
+
+#endif