Re: [U-Boot] [PATCH v2] armv7m: Add SysTick timer driver

2017-02-16 Thread Vikas MANOCHA
Hi Phil,

> -Original Message-
> From: Phil Edworthy [mailto:phil.edwor...@renesas.com]
> Sent: Wednesday, February 15, 2017 11:22 PM
> To: Vikas MANOCHA ; Albert Aribaud 
> 
> Cc: Tom Rini ; Kamil Lulko ; 
> Michael Kurz ; u-
> b...@lists.denx.de
> Subject: RE: [PATCH v2] armv7m: Add SysTick timer driver
> 
> Hi Vikas,
> 
> On 15 February 2017 23:50, Vikas MANOCHA wrote:
> > Hi Phil,
> >
> > > -Original Message-
> > > From: Phil Edworthy [mailto:phil.edwor...@renesas.com]
> > > Sent: Monday, February 13, 2017 11:48 PM
> > > To: Albert Aribaud 
> > > Cc: Tom Rini ; Vikas MANOCHA
> > ; Kamil Lulko ; Michael
> > > Kurz ; u-boot@lists.denx.de; Phil Edworthy
> > 
> > > Subject: [PATCH v2] armv7m: Add SysTick timer driver
> > >
> > > The SysTick is a 24-bit down counter that is found on all ARM Cortex
> > > M3, M4,
> > M7 devices and is always located at a fixed address.
> > >
> > > Signed-off-by: Phil Edworthy 
> > > ---
> > > v2:
> > >  - Variables & constant renamed.
> > >  - Use the calibration reg to determine if we use the cpu or ref clk
> > >  - Use the calibration reg to get the clk rate, unless specified
> > > ---
> > >  arch/arm/cpu/armv7m/Makefile|   2 +
> > >  arch/arm/cpu/armv7m/systick-timer.c | 107
> > 
> > >  2 files changed, 109 insertions(+)
> > >  create mode 100644 arch/arm/cpu/armv7m/systick-timer.c
> > >
> > > diff --git a/arch/arm/cpu/armv7m/Makefile
> > > b/arch/arm/cpu/armv7m/Makefile
> > index aff60e8..e1a6c40 100644
> > > --- a/arch/arm/cpu/armv7m/Makefile
> > > +++ b/arch/arm/cpu/armv7m/Makefile
> > > @@ -7,3 +7,5 @@
> > >
> > >  extra-y := start.o
> > >  obj-y += cpu.o
> > > +
> > > +obj-$(CONFIG_SYS_ARCH_TIMER) += systick-timer.o
> > > diff --git a/arch/arm/cpu/armv7m/systick-timer.c
> > b/arch/arm/cpu/armv7m/systick-timer.c
> > > new file mode 100644
> > > index 000..62308f9
> > > --- /dev/null
> > > +++ b/arch/arm/cpu/armv7m/systick-timer.c
> > > @@ -0,0 +1,107 @@
> > > +/*
> > > + * ARM Cortex M3/M4/M7 SysTick timer driver
> > > + * (C) Copyright 2017 Renesas Electronics Europe Ltd
> > > + *
> > > + * Based on arch/arm/mach-stm32/stm32f1/timer.c
> > > + * (C) Copyright 2015
> > > + * Kamil Lulko, 
> > > + *
> > > + * Copyright 2015 ATS Advanced Telematics Systems GmbH
> > > + * Copyright 2015 Konsulko Group, Matt Porter
> > > +
> > > + *
> > > + * SPDX-License-Identifier: GPL-2.0+
> > > + *
> > > + * The SysTick timer is a 24-bit count down timer. The clock can be
> > > +either the
> > > + * CPU clock or a reference clock. Since the timer will wrap around
> > > +very quickly
> > > + * when using the CPU clock, and we do not handle the timer
> > > +interrupts, it is
> > > + * expected that this driver is only ever used with a slow reference 
> > > clock.
> > > + */
> > > +
> > > +#include 
> > > +#include 
> > > +
> > > +DECLARE_GLOBAL_DATA_PTR;
> > > +
> > > +/* SysTick Base Address - fixed for all Cortex M3, M4 and M7 devices */
> > > +#define SYSTICK_BASE 0xE000E010
> > > +
> > > +struct cm3_systick {
> > > + uint32_t ctrl;
> > > + uint32_t reload_val;
> > > + uint32_t current_val;
> > > + uint32_t calibration;
> > > +};
> > > +
> > > +#define TIMER_MAX_VAL0x00FF
> > > +#define SYSTICK_CTRL_EN  BIT(0)
> > > +/* Clock source: 0 = Ref clock, 1 = CPU clock */
> > > +#define SYSTICK_CTRL_CPU_CLK BIT(2)
> > > +#define SYSTICK_CAL_NOREFBIT(31)
> > > +#define SYSTICK_CAL_SKEW BIT(30)
> > > +#define SYSTICK_CAL_TENMS_MASK   0x00FF
> > > +
> > > +/* read the 24-bit timer */
> > > +static ulong read_timer(void)
> > > +{
> > > + struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
> > > +
> > > + /* The timer counts down, therefore convert to an incrementing timer */
> > > + return TIMER_MAX_VAL - readl(>current_val); }
> > > +
> > > +int timer_init(void)
> > > +{
> > > + struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
> > > + u32 cal;
> > > +
> > > + writel(TIMER_MAX_VAL, >reload_val);
> > > + /* Any write to current_val reg clears it to 0 */
> > > + writel(0, >current_val);
> > > +
> > > + cal = readl(>calibration);
> > > + if (cal & SYSTICK_CAL_NOREF)
> >
> > Good.
> >
> > > + /* Use CPU clock, no interrupts */
> > > + writel(SYSTICK_CTRL_EN | SYSTICK_CTRL_CPU_CLK, 
> > >ctrl);
> > > + else
> > > + /* Use external clock, no interrupts */
> > > + writel(SYSTICK_CTRL_EN, >ctrl);
> > > +
> > > +#if defined(CONFIG_SYS_HZ_CLOCK)
> > > + gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK; #else
> > > + gd->arch.timer_rate_hz = (cal & SYSTICK_CAL_TENMS_MASK) * 100;
> >
> > This value is 

Re: [U-Boot] [PATCH v2] armv7m: Add SysTick timer driver

2017-02-15 Thread Phil Edworthy
Hi Vikas,

On 15 February 2017 23:50, Vikas MANOCHA wrote:
> Hi Phil,
> 
> > -Original Message-
> > From: Phil Edworthy [mailto:phil.edwor...@renesas.com]
> > Sent: Monday, February 13, 2017 11:48 PM
> > To: Albert Aribaud 
> > Cc: Tom Rini ; Vikas MANOCHA
> ; Kamil Lulko ; Michael
> > Kurz ; u-boot@lists.denx.de; Phil Edworthy
> 
> > Subject: [PATCH v2] armv7m: Add SysTick timer driver
> >
> > The SysTick is a 24-bit down counter that is found on all ARM Cortex M3, M4,
> M7 devices and is always located at a fixed address.
> >
> > Signed-off-by: Phil Edworthy 
> > ---
> > v2:
> >  - Variables & constant renamed.
> >  - Use the calibration reg to determine if we use the cpu or ref clk
> >  - Use the calibration reg to get the clk rate, unless specified
> > ---
> >  arch/arm/cpu/armv7m/Makefile|   2 +
> >  arch/arm/cpu/armv7m/systick-timer.c | 107
> 
> >  2 files changed, 109 insertions(+)
> >  create mode 100644 arch/arm/cpu/armv7m/systick-timer.c
> >
> > diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile
> index aff60e8..e1a6c40 100644
> > --- a/arch/arm/cpu/armv7m/Makefile
> > +++ b/arch/arm/cpu/armv7m/Makefile
> > @@ -7,3 +7,5 @@
> >
> >  extra-y := start.o
> >  obj-y += cpu.o
> > +
> > +obj-$(CONFIG_SYS_ARCH_TIMER) += systick-timer.o
> > diff --git a/arch/arm/cpu/armv7m/systick-timer.c
> b/arch/arm/cpu/armv7m/systick-timer.c
> > new file mode 100644
> > index 000..62308f9
> > --- /dev/null
> > +++ b/arch/arm/cpu/armv7m/systick-timer.c
> > @@ -0,0 +1,107 @@
> > +/*
> > + * ARM Cortex M3/M4/M7 SysTick timer driver
> > + * (C) Copyright 2017 Renesas Electronics Europe Ltd
> > + *
> > + * Based on arch/arm/mach-stm32/stm32f1/timer.c
> > + * (C) Copyright 2015
> > + * Kamil Lulko, 
> > + *
> > + * Copyright 2015 ATS Advanced Telematics Systems GmbH
> > + * Copyright 2015 Konsulko Group, Matt Porter 
> > + *
> > + * SPDX-License-Identifier: GPL-2.0+
> > + *
> > + * The SysTick timer is a 24-bit count down timer. The clock can be
> > +either the
> > + * CPU clock or a reference clock. Since the timer will wrap around
> > +very quickly
> > + * when using the CPU clock, and we do not handle the timer interrupts,
> > +it is
> > + * expected that this driver is only ever used with a slow reference clock.
> > + */
> > +
> > +#include 
> > +#include 
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +/* SysTick Base Address - fixed for all Cortex M3, M4 and M7 devices */
> > +#define SYSTICK_BASE   0xE000E010
> > +
> > +struct cm3_systick {
> > +   uint32_t ctrl;
> > +   uint32_t reload_val;
> > +   uint32_t current_val;
> > +   uint32_t calibration;
> > +};
> > +
> > +#define TIMER_MAX_VAL  0x00FF
> > +#define SYSTICK_CTRL_ENBIT(0)
> > +/* Clock source: 0 = Ref clock, 1 = CPU clock */
> > +#define SYSTICK_CTRL_CPU_CLK   BIT(2)
> > +#define SYSTICK_CAL_NOREF  BIT(31)
> > +#define SYSTICK_CAL_SKEW   BIT(30)
> > +#define SYSTICK_CAL_TENMS_MASK 0x00FF
> > +
> > +/* read the 24-bit timer */
> > +static ulong read_timer(void)
> > +{
> > +   struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
> > +
> > +   /* The timer counts down, therefore convert to an incrementing timer */
> > +   return TIMER_MAX_VAL - readl(>current_val); }
> > +
> > +int timer_init(void)
> > +{
> > +   struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
> > +   u32 cal;
> > +
> > +   writel(TIMER_MAX_VAL, >reload_val);
> > +   /* Any write to current_val reg clears it to 0 */
> > +   writel(0, >current_val);
> > +
> > +   cal = readl(>calibration);
> > +   if (cal & SYSTICK_CAL_NOREF)
> 
> Good.
> 
> > +   /* Use CPU clock, no interrupts */
> > +   writel(SYSTICK_CTRL_EN | SYSTICK_CTRL_CPU_CLK, 
> >ctrl);
> > +   else
> > +   /* Use external clock, no interrupts */
> > +   writel(SYSTICK_CTRL_EN, >ctrl);
> > +
> > +#if defined(CONFIG_SYS_HZ_CLOCK)
> > +   gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK; #else
> > +   gd->arch.timer_rate_hz = (cal & SYSTICK_CAL_TENMS_MASK) * 100;
> 
> This value is implementation dependent, it can't replace
> CONFIG_SYS_HZ_CLOCK.
> 
> Let me explain a bit,
> Here the assumption is  calibration value is always 1ms at any systick clock
> frequency which is not true. Different arm vendors
> write different values in this register to have timer value for 1 or 10 ms at 
> one
> particular clock frequency, on top of it this particular frequency
> is also different for all vendors.

Hmm, I think it's vendor defined because the clock rate can be different from
different vendors. The field is named TENMS for a reason and the ARM 
description says that it is the ticks for 10ms.

However, I also realise that sometimes this field is 

Re: [U-Boot] [PATCH v2] armv7m: Add SysTick timer driver

2017-02-15 Thread Vikas MANOCHA
Hi Phil,

> -Original Message-
> From: Phil Edworthy [mailto:phil.edwor...@renesas.com]
> Sent: Monday, February 13, 2017 11:48 PM
> To: Albert Aribaud 
> Cc: Tom Rini ; Vikas MANOCHA ; 
> Kamil Lulko ; Michael
> Kurz ; u-boot@lists.denx.de; Phil Edworthy 
> 
> Subject: [PATCH v2] armv7m: Add SysTick timer driver
> 
> The SysTick is a 24-bit down counter that is found on all ARM Cortex M3, M4, 
> M7 devices and is always located at a fixed address.
> 
> Signed-off-by: Phil Edworthy 
> ---
> v2:
>  - Variables & constant renamed.
>  - Use the calibration reg to determine if we use the cpu or ref clk
>  - Use the calibration reg to get the clk rate, unless specified
> ---
>  arch/arm/cpu/armv7m/Makefile|   2 +
>  arch/arm/cpu/armv7m/systick-timer.c | 107 
> 
>  2 files changed, 109 insertions(+)
>  create mode 100644 arch/arm/cpu/armv7m/systick-timer.c
> 
> diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile 
> index aff60e8..e1a6c40 100644
> --- a/arch/arm/cpu/armv7m/Makefile
> +++ b/arch/arm/cpu/armv7m/Makefile
> @@ -7,3 +7,5 @@
> 
>  extra-y := start.o
>  obj-y += cpu.o
> +
> +obj-$(CONFIG_SYS_ARCH_TIMER) += systick-timer.o
> diff --git a/arch/arm/cpu/armv7m/systick-timer.c 
> b/arch/arm/cpu/armv7m/systick-timer.c
> new file mode 100644
> index 000..62308f9
> --- /dev/null
> +++ b/arch/arm/cpu/armv7m/systick-timer.c
> @@ -0,0 +1,107 @@
> +/*
> + * ARM Cortex M3/M4/M7 SysTick timer driver
> + * (C) Copyright 2017 Renesas Electronics Europe Ltd
> + *
> + * Based on arch/arm/mach-stm32/stm32f1/timer.c
> + * (C) Copyright 2015
> + * Kamil Lulko, 
> + *
> + * Copyright 2015 ATS Advanced Telematics Systems GmbH
> + * Copyright 2015 Konsulko Group, Matt Porter 
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + *
> + * The SysTick timer is a 24-bit count down timer. The clock can be
> +either the
> + * CPU clock or a reference clock. Since the timer will wrap around
> +very quickly
> + * when using the CPU clock, and we do not handle the timer interrupts,
> +it is
> + * expected that this driver is only ever used with a slow reference clock.
> + */
> +
> +#include 
> +#include 
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* SysTick Base Address - fixed for all Cortex M3, M4 and M7 devices */
> +#define SYSTICK_BASE 0xE000E010
> +
> +struct cm3_systick {
> + uint32_t ctrl;
> + uint32_t reload_val;
> + uint32_t current_val;
> + uint32_t calibration;
> +};
> +
> +#define TIMER_MAX_VAL0x00FF
> +#define SYSTICK_CTRL_EN  BIT(0)
> +/* Clock source: 0 = Ref clock, 1 = CPU clock */
> +#define SYSTICK_CTRL_CPU_CLK BIT(2)
> +#define SYSTICK_CAL_NOREFBIT(31)
> +#define SYSTICK_CAL_SKEW BIT(30)
> +#define SYSTICK_CAL_TENMS_MASK   0x00FF
> +
> +/* read the 24-bit timer */
> +static ulong read_timer(void)
> +{
> + struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
> +
> + /* The timer counts down, therefore convert to an incrementing timer */
> + return TIMER_MAX_VAL - readl(>current_val); }
> +
> +int timer_init(void)
> +{
> + struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
> + u32 cal;
> +
> + writel(TIMER_MAX_VAL, >reload_val);
> + /* Any write to current_val reg clears it to 0 */
> + writel(0, >current_val);
> +
> + cal = readl(>calibration);
> + if (cal & SYSTICK_CAL_NOREF)

Good.

> + /* Use CPU clock, no interrupts */
> + writel(SYSTICK_CTRL_EN | SYSTICK_CTRL_CPU_CLK, >ctrl);
> + else
> + /* Use external clock, no interrupts */
> + writel(SYSTICK_CTRL_EN, >ctrl);
> +
> +#if defined(CONFIG_SYS_HZ_CLOCK)
> + gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK; #else
> + gd->arch.timer_rate_hz = (cal & SYSTICK_CAL_TENMS_MASK) * 100;

This value is implementation dependent, it can't replace CONFIG_SYS_HZ_CLOCK.

Let me explain a bit,
Here the assumption is  calibration value is always 1ms at any systick clock 
frequency which is not true. Different arm vendors
write different values in this register to have timer value for 1 or 10 ms at 
one particular clock frequency, on top of it this particular frequency
is also different for all vendors.

Otherwise,
Reviewed-by: Vikas MANOCHA 

Cheers,
Vikas

> #endif
> +
> + gd->arch.tbl = 0;
> + gd->arch.tbu = 0;
> + gd->arch.lastinc = read_timer();
> +
> + return 0;
> +}
> +
> +/* return milli-seconds timer value */
> +ulong get_timer(ulong base)
> +{
> + unsigned long long t = get_ticks() * 1000;
> +
> + return (ulong)((t / gd->arch.timer_rate_hz)) - base; }
> +
> +unsigned long long get_ticks(void)
> +{
> + u32 now = read_timer();
> +
> + if (now >= 

[U-Boot] [PATCH v2] armv7m: Add SysTick timer driver

2017-02-13 Thread Phil Edworthy
The SysTick is a 24-bit down counter that is found on all ARM Cortex
M3, M4, M7 devices and is always located at a fixed address.

Signed-off-by: Phil Edworthy 
---
v2:
 - Variables & constant renamed.
 - Use the calibration reg to determine if we use the cpu or ref clk
 - Use the calibration reg to get the clk rate, unless specified
---
 arch/arm/cpu/armv7m/Makefile|   2 +
 arch/arm/cpu/armv7m/systick-timer.c | 107 
 2 files changed, 109 insertions(+)
 create mode 100644 arch/arm/cpu/armv7m/systick-timer.c

diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile
index aff60e8..e1a6c40 100644
--- a/arch/arm/cpu/armv7m/Makefile
+++ b/arch/arm/cpu/armv7m/Makefile
@@ -7,3 +7,5 @@
 
 extra-y := start.o
 obj-y += cpu.o
+
+obj-$(CONFIG_SYS_ARCH_TIMER) += systick-timer.o
diff --git a/arch/arm/cpu/armv7m/systick-timer.c 
b/arch/arm/cpu/armv7m/systick-timer.c
new file mode 100644
index 000..62308f9
--- /dev/null
+++ b/arch/arm/cpu/armv7m/systick-timer.c
@@ -0,0 +1,107 @@
+/*
+ * ARM Cortex M3/M4/M7 SysTick timer driver
+ * (C) Copyright 2017 Renesas Electronics Europe Ltd
+ *
+ * Based on arch/arm/mach-stm32/stm32f1/timer.c
+ * (C) Copyright 2015
+ * Kamil Lulko, 
+ *
+ * Copyright 2015 ATS Advanced Telematics Systems GmbH
+ * Copyright 2015 Konsulko Group, Matt Porter 
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * The SysTick timer is a 24-bit count down timer. The clock can be either the
+ * CPU clock or a reference clock. Since the timer will wrap around very 
quickly
+ * when using the CPU clock, and we do not handle the timer interrupts, it is
+ * expected that this driver is only ever used with a slow reference clock.
+ */
+
+#include 
+#include 
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* SysTick Base Address - fixed for all Cortex M3, M4 and M7 devices */
+#define SYSTICK_BASE   0xE000E010
+
+struct cm3_systick {
+   uint32_t ctrl;
+   uint32_t reload_val;
+   uint32_t current_val;
+   uint32_t calibration;
+};
+
+#define TIMER_MAX_VAL  0x00FF
+#define SYSTICK_CTRL_ENBIT(0)
+/* Clock source: 0 = Ref clock, 1 = CPU clock */
+#define SYSTICK_CTRL_CPU_CLK   BIT(2)
+#define SYSTICK_CAL_NOREF  BIT(31)
+#define SYSTICK_CAL_SKEW   BIT(30)
+#define SYSTICK_CAL_TENMS_MASK 0x00FF
+
+/* read the 24-bit timer */
+static ulong read_timer(void)
+{
+   struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
+
+   /* The timer counts down, therefore convert to an incrementing timer */
+   return TIMER_MAX_VAL - readl(>current_val);
+}
+
+int timer_init(void)
+{
+   struct cm3_systick *systick = (struct cm3_systick *)SYSTICK_BASE;
+   u32 cal;
+
+   writel(TIMER_MAX_VAL, >reload_val);
+   /* Any write to current_val reg clears it to 0 */
+   writel(0, >current_val);
+
+   cal = readl(>calibration);
+   if (cal & SYSTICK_CAL_NOREF)
+   /* Use CPU clock, no interrupts */
+   writel(SYSTICK_CTRL_EN | SYSTICK_CTRL_CPU_CLK, >ctrl);
+   else
+   /* Use external clock, no interrupts */
+   writel(SYSTICK_CTRL_EN, >ctrl);
+
+#if defined(CONFIG_SYS_HZ_CLOCK)
+   gd->arch.timer_rate_hz = CONFIG_SYS_HZ_CLOCK;
+#else
+   gd->arch.timer_rate_hz = (cal & SYSTICK_CAL_TENMS_MASK) * 100;
+#endif
+
+   gd->arch.tbl = 0;
+   gd->arch.tbu = 0;
+   gd->arch.lastinc = read_timer();
+
+   return 0;
+}
+
+/* return milli-seconds timer value */
+ulong get_timer(ulong base)
+{
+   unsigned long long t = get_ticks() * 1000;
+
+   return (ulong)((t / gd->arch.timer_rate_hz)) - base;
+}
+
+unsigned long long get_ticks(void)
+{
+   u32 now = read_timer();
+
+   if (now >= gd->arch.lastinc)
+   gd->arch.tbl += (now - gd->arch.lastinc);
+   else
+   gd->arch.tbl += (TIMER_MAX_VAL - gd->arch.lastinc) + now;
+
+   gd->arch.lastinc = now;
+
+   return gd->arch.tbl;
+}
+
+ulong get_tbclk(void)
+{
+   return gd->arch.timer_rate_hz;
+}
-- 
2.7.4

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot