From: Matthias Kaehlcke <matthias@kaehlcke.net>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] ep93xx timer: Fix get_ticks() and usecs_to_ticks()
Date: Fri, 26 Feb 2010 18:26:38 +0100 [thread overview]
Message-ID: <20100226172637.GK3628@darwin> (raw)
ep93xx timer: Make get_ticks() consistent with get_tbclk(), returning
a value with CONFIG_SYS_HZ resolution. This fix obsoletes the function
clk_to_systicks(), leading to a simplification of the timer code. Further
a variable in usecs_to_ticks() is promoted to a 64-bit value, to avoid
overflows of intermediate values.
Signed-off-by: Matthias Kaehlcke <matthias@kaehlcke.net>
Tested-by: Alessandro Rubini <rubini-list@gnudd.com>
---
cpu/arm920t/ep93xx/timer.c | 83 +++++++++++++++++++------------------------
1 files changed, 37 insertions(+), 46 deletions(-)
diff --git a/cpu/arm920t/ep93xx/timer.c b/cpu/arm920t/ep93xx/timer.c
index b1a01a0..c4c1fb0 100644
--- a/cpu/arm920t/ep93xx/timer.c
+++ b/cpu/arm920t/ep93xx/timer.c
@@ -1,8 +1,7 @@
/*
* Cirrus Logic EP93xx timer support.
*
- * Copyright (C) 2009, 2010
- * Matthias Kaehlcke <matthias@kaehlcke.net>
+ * Copyright (C) 2009, 2010 Matthias Kaehlcke <matthias@kaehlcke.net>
*
* Copyright (C) 2004, 2005
* Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
@@ -36,67 +35,55 @@
#define TIMER_CLKSEL (1 << 3)
#define TIMER_ENABLE (1 << 7)
-#define TIMER_FREQ 508469
+#define TIMER_FREQ 508469 /* ticks / second */
#define TIMER_MAX_VAL 0xFFFFFFFF
static struct ep93xx_timer
{
unsigned long long ticks;
- unsigned long last_update;
+ unsigned long last_read;
} timer;
-static inline unsigned long clk_to_systicks(unsigned long long clk_ticks)
+static inline unsigned long long usecs_to_ticks(unsigned long usecs)
{
- unsigned long long sys_ticks = (clk_ticks * CONFIG_SYS_HZ);
- do_div(sys_ticks, TIMER_FREQ);
-
- return (unsigned long)sys_ticks;
-}
-
-static inline unsigned long usecs_to_ticks(unsigned long usecs)
-{
- unsigned long ticks;
-
- if (usecs >= 1000) {
- ticks = usecs / 1000;
- ticks *= TIMER_FREQ;
- ticks /= 1000;
- } else {
- ticks = usecs * TIMER_FREQ;
- ticks /= (1000 * 1000);
- }
+ unsigned long long ticks = usecs * TIMER_FREQ;
+ do_div(ticks, 1000 * 1000);
return ticks;
}
-static inline unsigned long read_timer(void)
+static inline void read_timer(void)
{
- struct timer_regs *timer = (struct timer_regs *)TIMER_BASE;
+ struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE;
+ const unsigned long now = TIMER_MAX_VAL - readl(&timer_regs->timer3.value);
+
+ if (now >= timer.last_read)
+ timer.ticks += now - timer.last_read;
+ else
+ /* an overflow occurred */
+ timer.ticks += TIMER_MAX_VAL - timer.last_read + now;
- return TIMER_MAX_VAL - readl(&timer->timer3.value);
+ timer.last_read = now;
}
/*
- * timer without interrupts
+ * Get the number of ticks (in CONFIG_SYS_HZ resolution)
*/
unsigned long long get_ticks(void)
{
- const unsigned long now = read_timer();
+ unsigned long long sys_ticks;
- if (now >= timer.last_update)
- timer.ticks += now - timer.last_update;
- else
- /* an overflow occurred */
- timer.ticks += TIMER_MAX_VAL - timer.last_update + now;
+ read_timer();
- timer.last_update = now;
+ sys_ticks = timer.ticks * CONFIG_SYS_HZ;
+ do_div(sys_ticks, TIMER_FREQ);
- return timer.ticks;
+ return sys_ticks;
}
unsigned long get_timer_masked(void)
{
- return clk_to_systicks(get_ticks());
+ return get_ticks();
}
unsigned long get_timer(unsigned long base)
@@ -106,7 +93,7 @@ unsigned long get_timer(unsigned long base)
void reset_timer_masked(void)
{
- timer.last_update = read_timer();
+ read_timer();
timer.ticks = 0;
}
@@ -117,25 +104,29 @@ void reset_timer(void)
void __udelay(unsigned long usec)
{
- const unsigned long target = get_ticks() + usecs_to_ticks(usec);
+ unsigned long long target;
+
+ read_timer();
+
+ target = timer.ticks + usecs_to_ticks(usec);
- while (get_ticks() < target)
- /* noop */;
+ while (timer.ticks < target)
+ read_timer();
}
int timer_init(void)
{
- struct timer_regs *timer = (struct timer_regs *)TIMER_BASE;
+ struct timer_regs *timer_regs = (struct timer_regs *)TIMER_BASE;
- /* use timer 3 with 508KHz and free running */
- writel(TIMER_CLKSEL, &timer->timer3.control);
+ /* use timer 3 with 508KHz and free running, not enabled now */
+ writel(TIMER_CLKSEL, &timer_regs->timer3.control);
- /* set initial timer value 3 */
- writel(TIMER_MAX_VAL, &timer->timer3.load);
+ /* set initial timer value */
+ writel(TIMER_MAX_VAL, &timer_regs->timer3.load);
/* Enable the timer */
writel(TIMER_ENABLE | TIMER_CLKSEL,
- &timer->timer3.control);
+ &timer_regs->timer3.control);
reset_timer_masked();
--
1.6.5
next reply other threads:[~2010-02-26 17:26 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-26 17:26 Matthias Kaehlcke [this message]
2010-02-27 23:41 ` [U-Boot] [PATCH] ep93xx timer: Fix get_ticks() and usecs_to_ticks() Tom
2010-02-27 23:58 ` Matthias Kaehlcke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100226172637.GK3628@darwin \
--to=matthias@kaehlcke.net \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.