Patchwork [U-Boot,RFC,5/5,Timer] Add x86 timer HAL

login
register
mail settings
Submitter Graeme Russ
Date May 29, 2011, 1:44 p.m.
Message ID <1306676654-6276-6-git-send-email-graeme.russ@gmail.com>
Download mbox | patch
Permalink /patch/97840/
State RFC
Headers show

Comments

Graeme Russ - May 29, 2011, 1:44 p.m.
---
 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(-)

--
1.7.5.2.317.g391b14

Patch

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