diff options
author | Stefan Reinauer <stepan@openbios.org> | 2006-04-26 15:08:19 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2006-04-26 15:08:19 +0000 |
commit | 5c9eb9b45ba7b3c0dc911328da6f0ccc703b8fff (patch) | |
tree | a43f9dc7f4a627a20c4d73b8791705f4df2752c4 /drivers/timer.c | |
download | openbios-5c9eb9b45ba7b3c0dc911328da6f0ccc703b8fff.zip openbios-5c9eb9b45ba7b3c0dc911328da6f0ccc703b8fff.tar.gz openbios-5c9eb9b45ba7b3c0dc911328da6f0ccc703b8fff.tar.bz2 |
initial import of openbios--main--1.0--patch-26
git-svn-id: svn://coreboot.org/openbios/openbios-devel@1 f158a5a8-5612-0410-a976-696ce0be7e32
Diffstat (limited to 'drivers/timer.c')
-rw-r--r-- | drivers/timer.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/drivers/timer.c b/drivers/timer.c new file mode 100644 index 0000000..6b58ea1 --- /dev/null +++ b/drivers/timer.c @@ -0,0 +1,104 @@ +/* + * OpenBIOS native timer driver + * + * (C) 2004 Stefan Reinauer <stepan@openbios.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "openbios/config.h" +#include "timer.h" +#include "asm/io.h" + +#if defined(CONFIG_X86) || defined(CONFIG_AMD64) + +void setup_timers(void) +{ + /* nothing to do */ +} + +static void load_timer2(unsigned int ticks) +{ + /* Set up the timer gate, turn off the speaker */ + outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB); + outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT, + TIMER_MODE_PORT); + outb(ticks & 0xFF, TIMER2_PORT); + outb(ticks >> 8, TIMER2_PORT); +} + +void udelay(unsigned int usecs) +{ + load_timer2((usecs * TICKS_PER_MS) / 1000); + while ((inb(PPC_PORTB) & PPCB_T2OUT) == 0); +} + +unsigned long currticks(void) +{ + static unsigned long totticks = 0UL; /* High resolution */ + unsigned long ticks = 0; + unsigned char portb = inb(PPC_PORTB); + + /* + * Read the timer, and hope it hasn't wrapped around + * (call this again within 54ms), then restart it + */ + outb(TIMER2_SEL | LATCH_COUNT, TIMER_MODE_PORT); + ticks = inb(TIMER2_PORT); + ticks |= inb(TIMER2_PORT) << 8; + outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT, + TIMER_MODE_PORT); + outb(0, TIMER2_PORT); + outb(0, TIMER2_PORT); + + /* + * Check if the timer was running. If not, + * result is rubbish and need to start it + */ + if (portb & PPCB_T2GATE) { + totticks += (0x10000 - ticks); + } else { + /* Set up the timer gate, turn off the speaker */ + outb((portb & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB); + } + return totticks / TICKS_PER_MS; +} +#endif + +#ifdef CONFIG_PPC + +void setup_timers(void) +{ + /* nothing to do */ +} + +/* + * TODO: pass via lb table + */ + +unsigned long get_timer_freq() +{ + return 100000000 / 4; +} + +void udelay(unsigned int usecs) +{ + extern void _wait_ticks(unsigned long); + unsigned long ticksperusec = get_timer_freq() / 1000000; + _wait_ticks(ticksperusec * usecs); +} + +#endif + +void ndelay(unsigned int nsecs) +{ + udelay((nsecs + 999) / 1000); +} + +void mdelay(unsigned int msecs) +{ + udelay(msecs * 1000); +} |