[U-Boot] [RFC][PATCH 5/5][Timer]Add x86 timer HAL
Graeme Russ
graeme.russ at gmail.com
Sun May 29 15:44:14 CEST 2011
---
arch/x86/cpu/sc520/sc520_timer.c | 46 ++++++++++++++++++++++++++---------
arch/x86/include/asm/global_data.h | 16 ++++++++++++
arch/x86/include/asm/ic/sc520.h | 3 ++
arch/x86/lib/board.c | 12 ++++++++-
arch/x86/lib/timer.c | 15 +-----------
board/eNET/eNET.c | 11 ++++----
board/eNET/eNET_start.S | 13 +++++++++-
board/eNET/eNET_start16.S | 9 +++++++
8 files changed, 90 insertions(+), 35 deletions(-)
diff --git a/arch/x86/cpu/sc520/sc520_timer.c b/arch/x86/cpu/sc520/sc520_timer.c
index 1bcfe67..92e0954 100644
--- a/arch/x86/cpu/sc520/sc520_timer.c
+++ b/arch/x86/cpu/sc520/sc520_timer.c
@@ -29,10 +29,13 @@
#include <asm/interrupt.h>
#include <asm/ic/sc520.h>
+DECLARE_GLOBAL_DATA_PTR;
+
void sc520_timer_isr(void)
{
/* Ack the GP Timer Interrupt */
writeb(0x02, &sc520_mmcr->gptmrsta);
+ sync_timers();
}
int timer_init(void)
@@ -70,21 +73,40 @@ int timer_init(void)
return 0;
}
-/* Allow boards to override udelay implementation */
void __udelay(unsigned long usec)
- __attribute__((weak, alias("sc520_udelay")));
+{
+ u32 start = get_us_timer(0);
+
+ while (get_us_timer(start) < usec)
+ ;
+}
+
+void sync_ticks(void)
+{
+ u16 milli;
+ u16 micro;
+
+ milli = readw(&sc520_mmcr->swtmrmilli);
+ micro = readw(&sc520_mmcr->swtmrmicro);
+
+ gd->ticks += (milli * 1000) + micro - gd->last_micro;
+ gd->last_micro = micro;
+}
+
+ulong usec2ticks(unsigned long usecs)
+{
+ return usecs;
+}
-void sc520_udelay(unsigned long usec)
+ulong ticks2usec(unsigned long ticks)
{
- int m = 0;
- long u;
- long temp;
+ return ticks;
+}
- temp = readw(&sc520_mmcr->swtmrmilli);
- temp = readw(&sc520_mmcr->swtmrmicro);
+int init_timebase(void)
+{
+ sync_timers();
- do {
- m += readw(&sc520_mmcr->swtmrmilli);
- u = readw(&sc520_mmcr->swtmrmicro) + (m * 1000);
- } while (u < usec);
+ return 0;
}
+
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
index f977dbe..6352f01 100644
--- a/arch/x86/include/asm/global_data.h
+++ b/arch/x86/include/asm/global_data.h
@@ -50,8 +50,24 @@ typedef struct global_data {
unsigned long start_addr_sp; /* start_addr_stackpointer */
phys_size_t ram_size; /* RAM size */
unsigned long reset_status; /* reset status register at boot */
+
+ /*
+ * Used by the sc520 timer routine to keep track of free running
+ * microsecond counter (which does not reset)
+ */
+ u16 last_micro; /* last value read from sc520 swtmrmicro */
+
+ /* Raw hardware tick counter maintained by sync_ticks() */
+ u64 ticks;
+
+ /* Timers maintained by sync_timers() */
+ u32 us_timer; /* microsecond timer */
+ u32 ms_timer; /* millisecond timer */
+ u32 us_accumulator;
+
void **jt; /* jump table */
char env_buf[32]; /* buffer for getenv() before reloc. */
+
} gd_t;
extern gd_t *gd;
diff --git a/arch/x86/include/asm/ic/sc520.h b/arch/x86/include/asm/ic/sc520.h
index 8b5f47c..bcf46ca 100644
--- a/arch/x86/include/asm/ic/sc520.h
+++ b/arch/x86/include/asm/ic/sc520.h
@@ -260,6 +260,9 @@ extern sc520_mmcr_t *sc520_mmcr;
#define SC520_MMCR_BASE 0xfffef000
/* MMCR Addresses (required for assembler code) */
+#define SC520_SWTMRMILLI (SC520_MMCR_BASE + 0xc60)
+#define SC520_SWTMRCFG (SC520_MMCR_BASE + 0xc64)
+
#define SC520_PAR0 (SC520_MMCR_BASE + 0x088)
#define SC520_PAR1 (SC520_PAR0 + (0x04 * 1))
#define SC520_PAR2 (SC520_PAR0 + (0x04 * 2))
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
index df54222..6b57bd3 100644
--- a/arch/x86/lib/board.c
+++ b/arch/x86/lib/board.c
@@ -159,6 +159,7 @@ static int do_elf_reloc_fixups(void);
init_fnc_t *init_sequence_f[] = {
cpu_init_f,
board_early_init_f,
+ init_timebase,
env_init,
init_baudrate,
serial_init,
@@ -275,6 +276,9 @@ void board_init_r(gd_t *id, ulong dest_addr)
static gd_t gd_data;
init_fnc_t **init_fnc_ptr;
+ u32 start_us = get_us_timer(0);
+ u32 start_ms = get_ms_timer(0);
+
show_boot_progress(0x21);
/* Global data pointer is now writable */
@@ -363,8 +367,6 @@ void board_init_r(gd_t *id, ulong dest_addr)
udelay(20);
- set_timer (0);
-
/* Initialize from environment */
if ((s = getenv ("loadaddr")) != NULL) {
load_addr = simple_strtoul (s, NULL, 16);
@@ -432,6 +434,12 @@ void board_init_r(gd_t *id, ulong dest_addr)
show_boot_progress(0x29);
+ printf("board_init_r () time = %u microseconds, %u milliseconds\n",
+ get_us_timer(start_us),
+ get_ms_timer(start_ms));
+
+ printf("Total Boot Time = %u microseconds\n", get_us_timer(0));
+
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop();
diff --git a/arch/x86/lib/timer.c b/arch/x86/lib/timer.c
index 8fc68cd..e382aab 100644
--- a/arch/x86/lib/timer.c
+++ b/arch/x86/lib/timer.c
@@ -36,7 +36,6 @@ struct timer_isr_function {
};
static struct timer_isr_function *first_timer_isr = NULL;
-static volatile unsigned long system_ticks = 0;
/*
* register_timer_isr() allows multiple architecture and board specific
@@ -85,8 +84,6 @@ void timer_isr(void *unused)
{
struct timer_isr_function *temp = first_timer_isr;
- system_ticks++;
-
/* Execute each registered function */
while (temp != NULL) {
temp->isr_func ();
@@ -94,17 +91,7 @@ void timer_isr(void *unused)
}
}
-void reset_timer (void)
-{
- system_ticks = 0;
-}
-
ulong get_timer (ulong base)
{
- return (system_ticks - base);
-}
-
-void set_timer (ulong t)
-{
- system_ticks = t;
+ return get_ms_timer(base);
}
diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c
index 2a5636c..226b68a 100644
--- a/board/eNET/eNET.c
+++ b/board/eNET/eNET.c
@@ -48,6 +48,9 @@ int board_early_init_f(void)
{
u16 pio_out_cfg = 0x0000;
+ /* 33.000 MHz xtal */
+ writeb(0x01, &sc520_mmcr->swtmrcfg);
+
/* Configure General Purpose Bus timing */
writeb(CONFIG_SYS_SC520_GPCSRT, &sc520_mmcr->gpcsrt);
writeb(CONFIG_SYS_SC520_GPCSPW, &sc520_mmcr->gpcspw);
@@ -252,16 +255,12 @@ void setup_pcat_compatibility()
void enet_timer_isr(void)
{
- static long enet_ticks = 0;
-
- enet_ticks++;
-
/* Toggle Watchdog every 100ms */
- if ((enet_ticks % 100) == 0)
+ if ((get_ms_timer(0) % 100) == 0)
hw_watchdog_reset();
/* Toggle Run LED every 500ms */
- if ((enet_ticks % 500) == 0)
+ if ((get_ms_timer(0) % 500) == 0)
enet_toggle_run_led();
}
diff --git a/board/eNET/eNET_start.S b/board/eNET/eNET_start.S
index 0dec7ea..bd35d7d 100644
--- a/board/eNET/eNET_start.S
+++ b/board/eNET/eNET_start.S
@@ -22,9 +22,20 @@
*/
#include "hardware.h"
+#include <asm/ic/sc520.h>
/* board early intialization */
.globl early_board_init
early_board_init:
- /* No 32-bit board specific initialisation */
+
+ /* Set xtal frequency (33.000MHz) */
+ movl $(SC520_SWTMRCFG), %edi
+ movb $0x01, %al
+ movb %al, (%di)
+
+ /* Reset millisecond software timer */
+ movl $(SC520_SWTMRMILLI), %edi
+ movl (%di), %eax
+
+ /* Done */
jmp early_board_init_ret
diff --git a/board/eNET/eNET_start16.S b/board/eNET/eNET_start16.S
index 77e5519..2fc032d 100644
--- a/board/eNET/eNET_start16.S
+++ b/board/eNET/eNET_start16.S
@@ -47,6 +47,15 @@ board_init16:
movw $0xdf00, %ax
movw %ax, %ds
+ /* Set xtal frequency (33.000MHz) */
+ movl $(SC520_SWTMRCFG - SC520_MMCR_BASE), %edi
+ movb $0x01, %al
+ movb %al, (%di)
+
+ /* Reset millisecond software timer */
+ movl $(SC520_SWTMRMILLI - SC520_MMCR_BASE), %edi
+ movl (%di), %eax
+
/* Map PAR for Boot Flash (BOOTCS, 512kB @ 0x380000000) */
movl $(SC520_PAR14 - SC520_MMCR_BASE), %edi
movl $CONFIG_SYS_SC520_BOOTCS_PAR, %eax
--
1.7.5.2.317.g391b14
More information about the U-Boot
mailing list