diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-05-08 13:55:19 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-05-14 05:29:48 -0400 |
| commit | 82491451dd25a3abe8496ddbd04ddb3f77d285c2 (patch) | |
| tree | c9aa32c209fae4d664d2b7035271c65f1c79c142 | |
| parent | 8c414ff3f4dcdde228c6a668385218290d73a265 (diff) | |
clocksource: convert x86 to generic i8253 clocksource
Convert x86 i8253 clocksource code to use generic i8253 clocksource.
Acked-by: John Stultz <john.stultz@linaro.org>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
| -rw-r--r-- | arch/x86/Kconfig | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/i8253.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/i8253.c | 79 |
3 files changed, 4 insertions, 78 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index cc6c53a95bfd..01115d54c5be 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -8,6 +8,7 @@ config 64BIT | |||
| 8 | 8 | ||
| 9 | config X86_32 | 9 | config X86_32 |
| 10 | def_bool !64BIT | 10 | def_bool !64BIT |
| 11 | select CLKSRC_I8253 | ||
| 11 | 12 | ||
| 12 | config X86_64 | 13 | config X86_64 |
| 13 | def_bool 64BIT | 14 | def_bool 64BIT |
diff --git a/arch/x86/include/asm/i8253.h b/arch/x86/include/asm/i8253.h index fc1f579fb965..65aaa91d5850 100644 --- a/arch/x86/include/asm/i8253.h +++ b/arch/x86/include/asm/i8253.h | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | #define PIT_CH0 0x40 | 6 | #define PIT_CH0 0x40 |
| 7 | #define PIT_CH2 0x42 | 7 | #define PIT_CH2 0x42 |
| 8 | 8 | ||
| 9 | #define PIT_LATCH LATCH | ||
| 10 | |||
| 9 | extern raw_spinlock_t i8253_lock; | 11 | extern raw_spinlock_t i8253_lock; |
| 10 | 12 | ||
| 11 | extern struct clock_event_device *global_clock_event; | 13 | extern struct clock_event_device *global_clock_event; |
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 2dfd31597443..b904dfbf6dbc 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c | |||
| @@ -117,81 +117,6 @@ void __init setup_pit_timer(void) | |||
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #ifndef CONFIG_X86_64 | 119 | #ifndef CONFIG_X86_64 |
| 120 | /* | ||
| 121 | * Since the PIT overflows every tick, its not very useful | ||
| 122 | * to just read by itself. So use jiffies to emulate a free | ||
| 123 | * running counter: | ||
| 124 | */ | ||
| 125 | static cycle_t pit_read(struct clocksource *cs) | ||
| 126 | { | ||
| 127 | static int old_count; | ||
| 128 | static u32 old_jifs; | ||
| 129 | unsigned long flags; | ||
| 130 | int count; | ||
| 131 | u32 jifs; | ||
| 132 | |||
| 133 | raw_spin_lock_irqsave(&i8253_lock, flags); | ||
| 134 | /* | ||
| 135 | * Although our caller may have the read side of xtime_lock, | ||
| 136 | * this is now a seqlock, and we are cheating in this routine | ||
| 137 | * by having side effects on state that we cannot undo if | ||
| 138 | * there is a collision on the seqlock and our caller has to | ||
| 139 | * retry. (Namely, old_jifs and old_count.) So we must treat | ||
| 140 | * jiffies as volatile despite the lock. We read jiffies | ||
| 141 | * before latching the timer count to guarantee that although | ||
| 142 | * the jiffies value might be older than the count (that is, | ||
| 143 | * the counter may underflow between the last point where | ||
| 144 | * jiffies was incremented and the point where we latch the | ||
| 145 | * count), it cannot be newer. | ||
| 146 | */ | ||
| 147 | jifs = jiffies; | ||
| 148 | outb_pit(0x00, PIT_MODE); /* latch the count ASAP */ | ||
| 149 | count = inb_pit(PIT_CH0); /* read the latched count */ | ||
| 150 | count |= inb_pit(PIT_CH0) << 8; | ||
| 151 | |||
| 152 | /* VIA686a test code... reset the latch if count > max + 1 */ | ||
| 153 | if (count > LATCH) { | ||
| 154 | outb_pit(0x34, PIT_MODE); | ||
| 155 | outb_pit(LATCH & 0xff, PIT_CH0); | ||
| 156 | outb_pit(LATCH >> 8, PIT_CH0); | ||
| 157 | count = LATCH - 1; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* | ||
| 161 | * It's possible for count to appear to go the wrong way for a | ||
| 162 | * couple of reasons: | ||
| 163 | * | ||
| 164 | * 1. The timer counter underflows, but we haven't handled the | ||
| 165 | * resulting interrupt and incremented jiffies yet. | ||
| 166 | * 2. Hardware problem with the timer, not giving us continuous time, | ||
| 167 | * the counter does small "jumps" upwards on some Pentium systems, | ||
| 168 | * (see c't 95/10 page 335 for Neptun bug.) | ||
| 169 | * | ||
| 170 | * Previous attempts to handle these cases intelligently were | ||
| 171 | * buggy, so we just do the simple thing now. | ||
| 172 | */ | ||
| 173 | if (count > old_count && jifs == old_jifs) | ||
| 174 | count = old_count; | ||
| 175 | |||
| 176 | old_count = count; | ||
| 177 | old_jifs = jifs; | ||
| 178 | |||
| 179 | raw_spin_unlock_irqrestore(&i8253_lock, flags); | ||
| 180 | |||
| 181 | count = (LATCH - 1) - count; | ||
| 182 | |||
| 183 | return (cycle_t)(jifs * LATCH) + count; | ||
| 184 | } | ||
| 185 | |||
| 186 | static struct clocksource pit_cs = { | ||
| 187 | .name = "pit", | ||
| 188 | .rating = 110, | ||
| 189 | .read = pit_read, | ||
| 190 | .mask = CLOCKSOURCE_MASK(32), | ||
| 191 | .mult = 0, | ||
| 192 | .shift = 20, | ||
| 193 | }; | ||
| 194 | |||
| 195 | static int __init init_pit_clocksource(void) | 120 | static int __init init_pit_clocksource(void) |
| 196 | { | 121 | { |
| 197 | /* | 122 | /* |
| @@ -205,9 +130,7 @@ static int __init init_pit_clocksource(void) | |||
| 205 | pit_ce.mode != CLOCK_EVT_MODE_PERIODIC) | 130 | pit_ce.mode != CLOCK_EVT_MODE_PERIODIC) |
| 206 | return 0; | 131 | return 0; |
| 207 | 132 | ||
| 208 | pit_cs.mult = clocksource_hz2mult(CLOCK_TICK_RATE, pit_cs.shift); | 133 | return clocksource_i8253_init(); |
| 209 | |||
| 210 | return clocksource_register(&pit_cs); | ||
| 211 | } | 134 | } |
| 212 | arch_initcall(init_pit_clocksource); | 135 | arch_initcall(init_pit_clocksource); |
| 213 | 136 | ||
