summaryrefslogtreecommitdiff
path: root/src/cpu/allwinner/a10/timer.c
diff options
context:
space:
mode:
authorAlexandru Gagniuc <mr.nuke.me@gmail.com>2013-12-31 00:17:19 -0500
committerAlexandru Gagniuc <mr.nuke.me@gmail.com>2014-01-09 01:02:47 +0100
commitbd09dbe3300eca302b84a8fe64cb302889089ab2 (patch)
treee3365a8dced52e265a8ca3004e33878e88ebda03 /src/cpu/allwinner/a10/timer.c
parentb70a140bd02ef5320c094f555b42dc1875dab2d5 (diff)
cpu/allwinner/a10: Implement udelay using timer 0
Change-Id: I4825f0d57696cd28751c59ae133b7e3315fb78e5 Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Reviewed-on: http://review.coreboot.org/4595 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net> Reviewed-by: David Hendricks <dhendrix@chromium.org>
Diffstat (limited to 'src/cpu/allwinner/a10/timer.c')
-rw-r--r--src/cpu/allwinner/a10/timer.c42
1 files changed, 39 insertions, 3 deletions
diff --git a/src/cpu/allwinner/a10/timer.c b/src/cpu/allwinner/a10/timer.c
index e156398be3..60cc60c4d1 100644
--- a/src/cpu/allwinner/a10/timer.c
+++ b/src/cpu/allwinner/a10/timer.c
@@ -1,19 +1,55 @@
/*
- * Placeholder for code to come(needed to complete build)
+ * Timer control and delays for Allwinner CPUs
*
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
* Subject to the GNU GPL v2, or (at your option) any later version.
*/
+#include "timer.h"
+
+#include <arch/io.h>
#include <delay.h>
#include <timer.h>
+struct a1x_timer *const tmr0 =
+ &((struct a1x_timer_module *)A1X_TIMER_BASE)->timer[0];
+
+static inline u32 read_timer(void)
+{
+ return read32(&tmr0->val);
+}
+
void init_timer(void)
{
- /* Stub */
+ u32 reg32;
+ /* Load the timer rollover value */
+ write32(0xffffffff, &tmr0->interval);
+ /* Configure the timer to run from 24MHz oscillator, no prescaler */
+ reg32 = TIMER_CTRL_PRESC_DIV_EXP(0);
+ reg32 |= TIMER_CTRL_CLK_SRC_OSC24M;
+ reg32 |= TIMER_CTRL_RELOAD;
+ reg32 |= TIMER_CTRL_TMR_EN;
+ write32(reg32, &tmr0->ctrl);
}
void udelay(unsigned usec)
{
- /* Stub */
+ u32 curr_tick, last_tick;
+ s32 ticks_left;
+
+ last_tick = read_timer();
+ /* 24 timer ticks per microsecond (24 MHz, divided by 1) */
+ ticks_left = usec * 24;
+
+ /* FIXME: Should we consider timer rollover?
+ * From when we start the timer, we have almost three minutes before it
+ * rolls over, so we should be long into having booted our payload.
+ */
+ while (ticks_left > 0) {
+ curr_tick = read_timer();
+ /* Timer value decreases with each tick */
+ ticks_left -= last_tick - curr_tick;
+ last_tick = curr_tick;
+ }
+
}