Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / drivers / timer.c
1 /*
2  *   OpenBIOS native timer driver
3  *
4  *   (C) 2004 Stefan Reinauer <stepan@openbios.org>
5  *
6  *   This program is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU General Public License
8  *   version 2
9  *
10  */
11
12 #include "config.h"
13 #include "drivers/drivers.h"
14 #include "timer.h"
15 #include "asm/io.h"
16
17 #if defined(CONFIG_X86) || defined(CONFIG_AMD64)
18
19 void setup_timers(void)
20 {
21         /* nothing to do */
22 }
23
24 static void load_timer2(unsigned int ticks)
25 {
26         /* Set up the timer gate, turn off the speaker */
27         outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
28         outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT,
29              TIMER_MODE_PORT);
30         outb(ticks & 0xFF, TIMER2_PORT);
31         outb(ticks >> 8, TIMER2_PORT);
32 }
33
34 void udelay(unsigned int usecs)
35 {
36         load_timer2((usecs * TICKS_PER_MS) / 1000);
37         while ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
38 }
39
40 unsigned long currticks(void)
41 {
42         static unsigned long totticks = 0UL;    /* High resolution */
43         unsigned long ticks = 0;
44         unsigned char portb = inb(PPC_PORTB);
45
46         /*
47          * Read the timer, and hope it hasn't wrapped around
48          * (call this again within 54ms), then restart it
49          */
50         outb(TIMER2_SEL | LATCH_COUNT, TIMER_MODE_PORT);
51         ticks = inb(TIMER2_PORT);
52         ticks |= inb(TIMER2_PORT) << 8;
53         outb(TIMER2_SEL | WORD_ACCESS | MODE0 | BINARY_COUNT,
54              TIMER_MODE_PORT);
55         outb(0, TIMER2_PORT);
56         outb(0, TIMER2_PORT);
57
58         /*
59          * Check if the timer was running. If not,
60          * result is rubbish and need to start it
61          */
62         if (portb & PPCB_T2GATE) {
63                 totticks += (0x10000 - ticks);
64         } else {
65                 /* Set up the timer gate, turn off the speaker */
66                 outb((portb & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
67         }
68         return totticks / TICKS_PER_MS;
69 }
70 #endif
71
72 #ifdef CONFIG_PPC
73
74 void setup_timers(void)
75 {
76         /* nothing to do */
77 }
78
79 /*
80  * TODO: pass via lb table
81  */
82 unsigned long timer_freq = 10000000 / 4;
83
84 void udelay(unsigned int usecs)
85 {
86         unsigned long ticksperusec = timer_freq / 1000000;
87         _wait_ticks(ticksperusec * usecs);
88 }
89
90 #endif
91
92 void ndelay(unsigned int nsecs)
93 {
94         udelay((nsecs + 999) / 1000);
95 }
96
97 void mdelay(unsigned int msecs)
98 {
99         udelay(msecs * 1000);
100 }