aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/time_64.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2007-10-12 17:04:07 -0400
committerThomas Gleixner <tglx@inhelltoy.tec.linutronix.de>2007-10-12 17:04:07 -0400
commitb8ce33590687888ebb900d09557b8807c4539022 (patch)
tree0e51543c7d4febff8ff6ad7660268bea2035f9ce /arch/x86/kernel/time_64.c
parentba7eda4c60e1d070b2f6586d42719ec1d5302d3b (diff)
x86_64: convert to clock events
Finally switch to the clockevents code. Share code with i386 for hpet and PIT. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Chris Wright <chrisw@sous-sol.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Diffstat (limited to 'arch/x86/kernel/time_64.c')
-rw-r--r--arch/x86/kernel/time_64.c107
1 files changed, 13 insertions, 94 deletions
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c
index d899216e01ca..7781df1d50e3 100644
--- a/arch/x86/kernel/time_64.c
+++ b/arch/x86/kernel/time_64.c
@@ -28,6 +28,8 @@
28#include <linux/cpu.h> 28#include <linux/cpu.h>
29#include <linux/kallsyms.h> 29#include <linux/kallsyms.h>
30#include <linux/acpi.h> 30#include <linux/acpi.h>
31#include <linux/clockchips.h>
32
31#ifdef CONFIG_ACPI 33#ifdef CONFIG_ACPI
32#include <acpi/achware.h> /* for PM timer frequency */ 34#include <acpi/achware.h> /* for PM timer frequency */
33#include <acpi/acpi_bus.h> 35#include <acpi/acpi_bus.h>
@@ -46,12 +48,8 @@
46#include <asm/nmi.h> 48#include <asm/nmi.h>
47#include <asm/vgtod.h> 49#include <asm/vgtod.h>
48 50
49static char *timename = NULL;
50
51DEFINE_SPINLOCK(rtc_lock); 51DEFINE_SPINLOCK(rtc_lock);
52EXPORT_SYMBOL(rtc_lock); 52EXPORT_SYMBOL(rtc_lock);
53DEFINE_SPINLOCK(i8253_lock);
54EXPORT_SYMBOL(i8253_lock);
55 53
56volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; 54volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
57 55
@@ -194,6 +192,13 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
194 return IRQ_HANDLED; 192 return IRQ_HANDLED;
195} 193}
196 194
195static irqreturn_t timer_event_interrupt(int irq, void *dev_id)
196{
197 global_clock_event->event_handler(global_clock_event);
198
199 return IRQ_HANDLED;
200}
201
197unsigned long read_persistent_clock(void) 202unsigned long read_persistent_clock(void)
198{ 203{
199 unsigned int year, mon, day, hour, min, sec; 204 unsigned int year, mon, day, hour, min, sec;
@@ -291,42 +296,8 @@ static unsigned int __init tsc_calibrate_cpu_khz(void)
291 return pmc_now * tsc_khz / (tsc_now - tsc_start); 296 return pmc_now * tsc_khz / (tsc_now - tsc_start);
292} 297}
293 298
294static void __pit_init(int val, u8 mode)
295{
296 unsigned long flags;
297
298 spin_lock_irqsave(&i8253_lock, flags);
299 outb_p(mode, PIT_MODE);
300 outb_p(val & 0xff, PIT_CH0); /* LSB */
301 outb_p(val >> 8, PIT_CH0); /* MSB */
302 spin_unlock_irqrestore(&i8253_lock, flags);
303}
304
305void __init pit_init(void)
306{
307 __pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
308}
309
310void pit_stop_interrupt(void)
311{
312 __pit_init(0, 0x30); /* mode 0 */
313}
314
315void stop_timer_interrupt(void)
316{
317 char *name;
318 if (hpet_address) {
319 name = "HPET";
320 hpet_timer_stop_set_go(0);
321 } else {
322 name = "PIT";
323 pit_stop_interrupt();
324 }
325 printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
326}
327
328static struct irqaction irq0 = { 299static struct irqaction irq0 = {
329 .handler = timer_interrupt, 300 .handler = timer_event_interrupt,
330 .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING, 301 .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
331 .mask = CPU_MASK_NONE, 302 .mask = CPU_MASK_NONE,
332 .name = "timer" 303 .name = "timer"
@@ -334,20 +305,10 @@ static struct irqaction irq0 = {
334 305
335void __init time_init(void) 306void __init time_init(void)
336{ 307{
337 if (nohpet) 308 if (!hpet_enable())
338 hpet_address = 0; 309 setup_pit_timer();
339
340 if (hpet_arch_init())
341 hpet_address = 0;
342 310
343 if (hpet_use_timer) { 311 setup_irq(0, &irq0);
344 /* set tick_nsec to use the proper rate for HPET */
345 tick_nsec = TICK_NSEC_HPET;
346 timename = "HPET";
347 } else {
348 pit_init();
349 timename = "PIT";
350 }
351 312
352 tsc_calibrate(); 313 tsc_calibrate();
353 314
@@ -369,46 +330,4 @@ void __init time_init(void)
369 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", 330 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
370 cpu_khz / 1000, cpu_khz % 1000); 331 cpu_khz / 1000, cpu_khz % 1000);
371 init_tsc_clocksource(); 332 init_tsc_clocksource();
372
373 setup_irq(0, &irq0);
374}
375
376/*
377 * sysfs support for the timer.
378 */
379
380static int timer_suspend(struct sys_device *dev, pm_message_t state)
381{
382 return 0;
383} 333}
384
385static int timer_resume(struct sys_device *dev)
386{
387 if (hpet_address)
388 hpet_reenable();
389 else
390 i8254_timer_resume();
391 return 0;
392}
393
394static struct sysdev_class timer_sysclass = {
395 .resume = timer_resume,
396 .suspend = timer_suspend,
397 set_kset_name("timer"),
398};
399
400/* XXX this sysfs stuff should probably go elsewhere later -john */
401static struct sys_device device_timer = {
402 .id = 0,
403 .cls = &timer_sysclass,
404};
405
406static int time_init_device(void)
407{
408 int error = sysdev_class_register(&timer_sysclass);
409 if (!error)
410 error = sysdev_register(&device_timer);
411 return error;
412}
413
414device_initcall(time_init_device);