mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
This patches copies all needed ppc files to qemu and modifies them. The generated OpenBIOS image must be loaded at adresse 0xfff00000 by Qemu. It is able to load Yaboot from disk and Yaboot is able to load Linux, but Linux hangs somewhere... of course it needs more work (but this cleans up my patch queue). Thank you to Blue Swirl and Aurelien Jarno for their help. Signed-off-by: Laurent Vivier <Laurent@lvivier.info> git-svn-id: svn://coreboot.org/openbios/openbios-devel@301 f158a5a8-5612-0410-a976-696ce0be7e32
105 lines
2.1 KiB
C
105 lines
2.1 KiB
C
/*
|
|
* 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(void)
|
|
{
|
|
return 10000000 / 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);
|
|
}
|