MIPS port has two problems in timer routines. One is now we assume CFG_HZ == CP0 counter frequency, but this is wrong. CFG_HZ has to be 1000 in the U-Boot system.
The other is we don't have a proper time management counter like timestamp other ARCHs have. We need the 32-bit millisecond clock that U-Boot wants. This patch adds 3 global variables; timestamp, cycles_per_jiffy, expirelo. timestamp is a 32-bit non-overflowing CFG_HZ counter. cycles_per_jiffy is calculated counter cycles in a CFG_HZ. And expirelo holds the count value for next CPU timer expiration. With these variables, fix each functions. Notably, * timer_init: Initialize cycles_per_jiffy, timestamp, and expirelo. Note that we don't have to initialize CP0 count/compare registers here. They have been already cleared on the system reset. Leave them as they are. * get_timer: Calculate how many timestamps have been passed, then return (relative) timestamp. I'm afraid we might suffer from a big catch up loop if this function is called after a long delay. * get_ticks: Return the current timestamp, that is get_timer(0). Most parts are from good old Linux v2.6.16 kernel. Signed-off-by: Shinya Kuribayashi <[EMAIL PROTECTED]> --- lib_mips/time.c | 44 ++++++++++++++++++++++++++++++++++++++------ 1 files changed, 38 insertions(+), 6 deletions(-) diff --git a/lib_mips/time.c b/lib_mips/time.c index 154d792..4b47e41 100644 --- a/lib_mips/time.c +++ b/lib_mips/time.c @@ -24,31 +24,63 @@ #include <common.h> #include <asm/mipsregs.h> +static unsigned long timestamp; + +/* how many counter cycles in a jiffy */ +static unsigned long cycles_per_jiffy; + +/* expirelo is the count value for next CPU timer interrupt */ +static unsigned int expirelo; + /* * timer without interrupts */ int timer_init(void) { - write_32bit_cp0_register(CP0_COMPARE, 0); - write_32bit_cp0_register(CP0_COUNT, 0); + /* Calculate cache parameters. */ + cycles_per_jiffy = (CONFIG_MIPS_TIMER_FREQ + CFG_HZ / 2) / CFG_HZ; + + /* Report the high precision timer rate for a reference. */ + printf("Using %u.%03u MHz high precision timer.\n", + ((CONFIG_MIPS_TIMER_FREQ + 500) / 1000) / 1000, + ((CONFIG_MIPS_TIMER_FREQ + 500) / 1000) % 1000); + + /* Set up the timer for the first expiration. */ + timestamp = 0; + expirelo = read_32bit_cp0_register(CP0_COUNT) + cycles_per_jiffy; return 0; } void reset_timer(void) { - write_32bit_cp0_register(CP0_COUNT, 0); + timestamp = 0; + expirelo = read_32bit_cp0_register(CP0_COUNT) + cycles_per_jiffy; } ulong get_timer(ulong base) { - return read_32bit_cp0_register(CP0_COUNT) - base; + unsigned int count; + + /* Check to see if we have missed any timestamps. */ + count = read_32bit_cp0_register(CP0_COUNT); + while ((count - expirelo) < 0x7fffffff) { + /* + * FIXME: We might suffer from a big catch up loop + * if called after a long delay. + */ + expirelo += cycles_per_jiffy; + timestamp++; + } + + return (timestamp - base); } void set_timer(ulong t) { - write_32bit_cp0_register(CP0_COUNT, t); + timestamp = t; + expirelo = read_32bit_cp0_register(CP0_COUNT) + cycles_per_jiffy; } void udelay(unsigned long usec) @@ -67,7 +99,7 @@ void udelay(unsigned long usec) */ unsigned long long get_ticks(void) { - return read_32bit_cp0_register(CP0_COUNT); + return get_timer(0); } /* ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ U-Boot-Users mailing list U-Boot-Users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/u-boot-users