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>
This commit is contained in:
parent
b70a140bd0
commit
bd09dbe330
|
@ -6,6 +6,7 @@ if CPU_ALLWINNER_A10
|
|||
|
||||
config CPU_SPECIFIC_OPTIONS
|
||||
def_bool y
|
||||
select HAVE_INIT_TIMER
|
||||
select HAVE_MONOTONIC_TIMER
|
||||
select HAVE_UART_SPECIAL
|
||||
select HAVE_UART_MEMORY_MAPPED
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Definitions for timer control on Allwinner CPUs
|
||||
*
|
||||
* Copyright (C) 2007-2011 Allwinner Technology Co., Ltd.
|
||||
* Tom Cubie <tangliang@allwinnertech.com>
|
||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
* Subject to the GNU GPL v2, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef CPU_ALLWINNER_A10_TIMER_H
|
||||
#define CPU_ALLWINNER_A10_TIMER_H
|
||||
|
||||
#include "memmap.h"
|
||||
#include <types.h>
|
||||
|
||||
/* TMRx_CTRL values */
|
||||
#define TIMER_CTRL_MODE_SINGLE (1 << 7)
|
||||
#define TIMER_CTRL_PRESC_MASK (0x7 << 4)
|
||||
#define TIMER_CTRL_PRESC_DIV_EXP(ep) ((ep << 4) & TIMER_CTRL_PRESC_MASK)
|
||||
#define TIMER_CTRL_CLK_SRC_MASK (0x3 << 2)
|
||||
#define TIMER_CTRL_CLK_SRC_LOSC (0x0 << 2)
|
||||
#define TIMER_CTRL_CLK_SRC_OSC24M (0x1 << 2)
|
||||
#define TIMER_CTRL_CLK_SRC_PLL6 (0x2 << 2)
|
||||
#define TIMER_CTRL_RELOAD (1 << 1)
|
||||
#define TIMER_CTRL_TMR_EN (1 << 0)
|
||||
|
||||
/* General purpose timer */
|
||||
struct a1x_timer {
|
||||
u32 ctrl;
|
||||
u32 interval;
|
||||
u32 val;
|
||||
u8 res[4];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Audio video sync*/
|
||||
struct a1x_avs {
|
||||
u32 ctrl; /* 0x80 */
|
||||
u32 cnt0; /* 0x84 */
|
||||
u32 cnt1; /* 0x88 */
|
||||
u32 div; /* 0x8c */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Watchdog */
|
||||
struct a1x_wdog {
|
||||
u32 ctrl; /* 0x90 */
|
||||
u32 mode; /* 0x94 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* 64 bit counter */
|
||||
struct a1x_64cnt {
|
||||
u32 ctrl; /* 0xa0 */
|
||||
u32 lo; /* 0xa4 */
|
||||
u32 hi; /* 0xa8 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Rtc */
|
||||
struct a1x_rtc {
|
||||
u32 ctrl; /* 0x100 */
|
||||
u32 yymmdd; /* 0x104 */
|
||||
u32 hhmmss; /* 0x108 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Alarm */
|
||||
struct a1x_alarm {
|
||||
u32 ddhhmmss; /* 0x10c */
|
||||
u32 hhmmss; /* 0x110 */
|
||||
u32 en; /* 0x114 */
|
||||
u32 irq_en; /* 0x118 */
|
||||
u32 irq_sta; /* 0x11c */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct a1x_timer_module {
|
||||
u32 irq_en; /* 0x00 */
|
||||
u32 irq_sta; /* 0x04 */
|
||||
u8 res1[8];
|
||||
struct a1x_timer timer[6]; /* We have 6 timers */
|
||||
u8 res2[16];
|
||||
struct a1x_avs avs;
|
||||
struct a1x_wdog wdog;
|
||||
u8 res3[8];
|
||||
struct a1x_64cnt cnt64;
|
||||
u8 res4[0x58];
|
||||
struct a1x_rtc rtc;
|
||||
struct a1x_alarm alarm;
|
||||
u32 gp_data[4];
|
||||
u8 res5[8];
|
||||
u32 cpu_cfg;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif /* CPU_ALLWINNER_A10_TIMER_H */
|
Loading…
Reference in New Issue