diff options
Diffstat (limited to 'arch/i386/kernel/i8253.c')
-rw-r--r-- | arch/i386/kernel/i8253.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c index 29cb2eb34363..a276bceade68 100644 --- a/arch/i386/kernel/i8253.c +++ b/arch/i386/kernel/i8253.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * i8253.c 8253/PIT functions | 2 | * i8253.c 8253/PIT functions |
3 | * | 3 | * |
4 | */ | 4 | */ |
5 | #include <linux/clocksource.h> | ||
5 | #include <linux/spinlock.h> | 6 | #include <linux/spinlock.h> |
6 | #include <linux/jiffies.h> | 7 | #include <linux/jiffies.h> |
7 | #include <linux/sysdev.h> | 8 | #include <linux/sysdev.h> |
@@ -30,3 +31,55 @@ void setup_pit_timer(void) | |||
30 | outb(LATCH >> 8 , PIT_CH0); /* MSB */ | 31 | outb(LATCH >> 8 , PIT_CH0); /* MSB */ |
31 | spin_unlock_irqrestore(&i8253_lock, flags); | 32 | spin_unlock_irqrestore(&i8253_lock, flags); |
32 | } | 33 | } |
34 | |||
35 | /* | ||
36 | * Since the PIT overflows every tick, its not very useful | ||
37 | * to just read by itself. So use jiffies to emulate a free | ||
38 | * running counter: | ||
39 | */ | ||
40 | static cycle_t pit_read(void) | ||
41 | { | ||
42 | unsigned long flags; | ||
43 | int count; | ||
44 | u64 jifs; | ||
45 | |||
46 | spin_lock_irqsave(&i8253_lock, flags); | ||
47 | outb_p(0x00, PIT_MODE); /* latch the count ASAP */ | ||
48 | count = inb_p(PIT_CH0); /* read the latched count */ | ||
49 | count |= inb_p(PIT_CH0) << 8; | ||
50 | |||
51 | /* VIA686a test code... reset the latch if count > max + 1 */ | ||
52 | if (count > LATCH) { | ||
53 | outb_p(0x34, PIT_MODE); | ||
54 | outb_p(LATCH & 0xff, PIT_CH0); | ||
55 | outb(LATCH >> 8, PIT_CH0); | ||
56 | count = LATCH - 1; | ||
57 | } | ||
58 | spin_unlock_irqrestore(&i8253_lock, flags); | ||
59 | |||
60 | jifs = jiffies_64; | ||
61 | |||
62 | jifs -= INITIAL_JIFFIES; | ||
63 | count = (LATCH-1) - count; | ||
64 | |||
65 | return (cycle_t)(jifs * LATCH) + count; | ||
66 | } | ||
67 | |||
68 | static struct clocksource clocksource_pit = { | ||
69 | .name = "pit", | ||
70 | .rating = 110, | ||
71 | .read = pit_read, | ||
72 | .mask = (cycle_t)-1, | ||
73 | .mult = 0, | ||
74 | .shift = 20, | ||
75 | }; | ||
76 | |||
77 | static int __init init_pit_clocksource(void) | ||
78 | { | ||
79 | if (num_possible_cpus() > 4) /* PIT does not scale! */ | ||
80 | return 0; | ||
81 | |||
82 | clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20); | ||
83 | return register_clocksource(&clocksource_pit); | ||
84 | } | ||
85 | module_init(init_pit_clocksource); | ||