aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2007-02-16 04:28:04 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:13:59 -0500
commite9e2cdb412412326c4827fc78ba27f410d837e6e (patch)
treecd4ca03e6bdc3691619024492fb9414427b2f813 /include
parent79bf2bb335b85db25d27421c798595a2fa2a0e82 (diff)
[PATCH] clockevents: i386 drivers
Add clockevent drivers for i386: lapic (local) and PIT/HPET (global). Update the timer IRQ to call into the PIT/HPET driver's event handler and the lapic-timer IRQ to call into the lapic clockevent driver. The assignement of timer functionality is delegated to the core framework code and replaces the compile and runtime evalution in do_timer_interrupt_hook() Use the clockevents broadcast support and implement the lapic_broadcast function for ACPI. No changes to existing functionality. [ kdump fix from Vivek Goyal <vgoyal@in.ibm.com> ] [ fixes based on review feedback from Arjan van de Ven <arjan@infradead.org> ] Cleanups-from: Adrian Bunk <bunk@stusta.de> Build-fixes-from: Andrew Morton <akpm@osdl.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: john stultz <johnstul@us.ibm.com> Cc: Roman Zippel <zippel@linux-m68k.org> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/asm-i386/apic.h5
-rw-r--r--include/asm-i386/hpet.h16
-rw-r--r--include/asm-i386/i8253.h15
-rw-r--r--include/asm-i386/mach-default/do_timer.h78
-rw-r--r--include/asm-i386/mach-voyager/do_timer.h27
-rw-r--r--include/asm-i386/mpspec.h1
6 files changed, 41 insertions, 101 deletions
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index ccf64fa7b935..a595fe054272 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -113,14 +113,9 @@ extern void smp_local_timer_interrupt (void);
113extern void setup_boot_APIC_clock (void); 113extern void setup_boot_APIC_clock (void);
114extern void setup_secondary_APIC_clock (void); 114extern void setup_secondary_APIC_clock (void);
115extern int APIC_init_uniprocessor (void); 115extern int APIC_init_uniprocessor (void);
116extern void disable_APIC_timer(void);
117extern void enable_APIC_timer(void);
118 116
119extern void enable_NMI_through_LVT0 (void * dummy); 117extern void enable_NMI_through_LVT0 (void * dummy);
120 118
121void smp_send_timer_broadcast_ipi(void);
122void switch_APIC_timer_to_ipi(void *cpumask);
123void switch_ipi_to_APIC_timer(void *cpumask);
124#define ARCH_APICTIMER_STOPS_ON_C3 1 119#define ARCH_APICTIMER_STOPS_ON_C3 1
125 120
126extern int timer_over_8254; 121extern int timer_over_8254;
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index e47be9a56cc2..fc03cf9de5c4 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -90,16 +90,19 @@
90#define HPET_MIN_PERIOD (100000UL) 90#define HPET_MIN_PERIOD (100000UL)
91#define HPET_TICK_RATE (HZ * 100000UL) 91#define HPET_TICK_RATE (HZ * 100000UL)
92 92
93extern unsigned long hpet_tick; /* hpet clks count per tick */
94extern unsigned long hpet_address; /* hpet memory map physical address */ 93extern unsigned long hpet_address; /* hpet memory map physical address */
95extern int hpet_use_timer; 94extern int is_hpet_enabled(void);
96 95
96#ifdef CONFIG_X86_64
97extern unsigned long hpet_tick; /* hpet clks count per tick */
98extern int hpet_use_timer;
97extern int hpet_rtc_timer_init(void); 99extern int hpet_rtc_timer_init(void);
98extern int hpet_enable(void); 100extern int hpet_enable(void);
99extern int hpet_reenable(void);
100extern int is_hpet_enabled(void);
101extern int is_hpet_capable(void); 101extern int is_hpet_capable(void);
102extern int hpet_readl(unsigned long a); 102extern int hpet_readl(unsigned long a);
103#else
104extern int hpet_enable(void);
105#endif
103 106
104#ifdef CONFIG_HPET_EMULATE_RTC 107#ifdef CONFIG_HPET_EMULATE_RTC
105extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask); 108extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
@@ -110,5 +113,10 @@ extern int hpet_rtc_dropped_irq(void);
110extern int hpet_rtc_timer_init(void); 113extern int hpet_rtc_timer_init(void);
111extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); 114extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id);
112#endif /* CONFIG_HPET_EMULATE_RTC */ 115#endif /* CONFIG_HPET_EMULATE_RTC */
116
117#else
118
119static inline int hpet_enable(void) { return 0; }
120
113#endif /* CONFIG_HPET_TIMER */ 121#endif /* CONFIG_HPET_TIMER */
114#endif /* _I386_HPET_H */ 122#endif /* _I386_HPET_H */
diff --git a/include/asm-i386/i8253.h b/include/asm-i386/i8253.h
index 015d8df07690..6cb0dd4dcdde 100644
--- a/include/asm-i386/i8253.h
+++ b/include/asm-i386/i8253.h
@@ -1,6 +1,21 @@
1#ifndef __ASM_I8253_H__ 1#ifndef __ASM_I8253_H__
2#define __ASM_I8253_H__ 2#define __ASM_I8253_H__
3 3
4#include <linux/clockchips.h>
5
4extern spinlock_t i8253_lock; 6extern spinlock_t i8253_lock;
5 7
8extern struct clock_event_device *global_clock_event;
9
10/**
11 * pit_interrupt_hook - hook into timer tick
12 * @regs: standard registers from interrupt
13 *
14 * Call the global clock event handler.
15 **/
16static inline void pit_interrupt_hook(void)
17{
18 global_clock_event->event_handler(global_clock_event);
19}
20
6#endif /* __ASM_I8253_H__ */ 21#endif /* __ASM_I8253_H__ */
diff --git a/include/asm-i386/mach-default/do_timer.h b/include/asm-i386/mach-default/do_timer.h
index 7d606e3364ae..56e5689863ae 100644
--- a/include/asm-i386/mach-default/do_timer.h
+++ b/include/asm-i386/mach-default/do_timer.h
@@ -1,86 +1,16 @@
1/* defines for inline arch setup functions */ 1/* defines for inline arch setup functions */
2#include <linux/clockchips.h>
2 3
3#include <asm/apic.h>
4#include <asm/i8259.h> 4#include <asm/i8259.h>
5#include <asm/i8253.h>
5 6
6/** 7/**
7 * do_timer_interrupt_hook - hook into timer tick 8 * do_timer_interrupt_hook - hook into timer tick
8 * @regs: standard registers from interrupt
9 * 9 *
10 * Description: 10 * Call the pit clock event handler. see asm/i8253.h
11 * This hook is called immediately after the timer interrupt is ack'd.
12 * It's primary purpose is to allow architectures that don't possess
13 * individual per CPU clocks (like the CPU APICs supply) to broadcast the
14 * timer interrupt as a means of triggering reschedules etc.
15 **/ 11 **/
16 12
17static inline void do_timer_interrupt_hook(void) 13static inline void do_timer_interrupt_hook(void)
18{ 14{
19 do_timer(1); 15 pit_interrupt_hook();
20#ifndef CONFIG_SMP
21 update_process_times(user_mode_vm(get_irq_regs()));
22#endif
23/*
24 * In the SMP case we use the local APIC timer interrupt to do the
25 * profiling, except when we simulate SMP mode on a uniprocessor
26 * system, in that case we have to call the local interrupt handler.
27 */
28#ifndef CONFIG_X86_LOCAL_APIC
29 profile_tick(CPU_PROFILING);
30#else
31 if (!using_apic_timer)
32 smp_local_timer_interrupt();
33#endif
34}
35
36
37/* you can safely undefine this if you don't have the Neptune chipset */
38
39#define BUGGY_NEPTUN_TIMER
40
41/**
42 * do_timer_overflow - process a detected timer overflow condition
43 * @count: hardware timer interrupt count on overflow
44 *
45 * Description:
46 * This call is invoked when the jiffies count has not incremented but
47 * the hardware timer interrupt has. It means that a timer tick interrupt
48 * came along while the previous one was pending, thus a tick was missed
49 **/
50static inline int do_timer_overflow(int count)
51{
52 int i;
53
54 spin_lock(&i8259A_lock);
55 /*
56 * This is tricky when I/O APICs are used;
57 * see do_timer_interrupt().
58 */
59 i = inb(0x20);
60 spin_unlock(&i8259A_lock);
61
62 /* assumption about timer being IRQ0 */
63 if (i & 0x01) {
64 /*
65 * We cannot detect lost timer interrupts ...
66 * well, that's why we call them lost, don't we? :)
67 * [hmm, on the Pentium and Alpha we can ... sort of]
68 */
69 count -= LATCH;
70 } else {
71#ifdef BUGGY_NEPTUN_TIMER
72 /*
73 * for the Neptun bug we know that the 'latch'
74 * command doesn't latch the high and low value
75 * of the counter atomically. Thus we have to
76 * substract 256 from the counter
77 * ... funny, isnt it? :)
78 */
79
80 count -= 256;
81#else
82 printk("do_slow_gettimeoffset(): hardware timer problem?\n");
83#endif
84 }
85 return count;
86} 16}
diff --git a/include/asm-i386/mach-voyager/do_timer.h b/include/asm-i386/mach-voyager/do_timer.h
index 04e69c104a74..60f9dcc15d54 100644
--- a/include/asm-i386/mach-voyager/do_timer.h
+++ b/include/asm-i386/mach-voyager/do_timer.h
@@ -1,25 +1,18 @@
1/* defines for inline arch setup functions */ 1/* defines for inline arch setup functions */
2#include <linux/clockchips.h>
3
2#include <asm/voyager.h> 4#include <asm/voyager.h>
5#include <asm/i8253.h>
3 6
7/**
8 * do_timer_interrupt_hook - hook into timer tick
9 * @regs: standard registers from interrupt
10 *
11 * Call the pit clock event handler. see asm/i8253.h
12 **/
4static inline void do_timer_interrupt_hook(void) 13static inline void do_timer_interrupt_hook(void)
5{ 14{
6 do_timer(1); 15 pit_interrupt_hook();
7#ifndef CONFIG_SMP
8 update_process_times(user_mode_vm(irq_regs));
9#endif
10
11 voyager_timer_interrupt(); 16 voyager_timer_interrupt();
12} 17}
13 18
14static inline int do_timer_overflow(int count)
15{
16 /* can't read the ISR, just assume 1 tick
17 overflow */
18 if(count > LATCH || count < 0) {
19 printk(KERN_ERR "VOYAGER PROBLEM: count is %d, latch is %d\n", count, LATCH);
20 count = LATCH;
21 }
22 count -= LATCH;
23
24 return count;
25}
diff --git a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
index 770bf6da8c3d..f21349399d14 100644
--- a/include/asm-i386/mpspec.h
+++ b/include/asm-i386/mpspec.h
@@ -23,7 +23,6 @@ extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
23extern int mpc_default_type; 23extern int mpc_default_type;
24extern unsigned long mp_lapic_addr; 24extern unsigned long mp_lapic_addr;
25extern int pic_mode; 25extern int pic_mode;
26extern int using_apic_timer;
27 26
28#ifdef CONFIG_ACPI 27#ifdef CONFIG_ACPI
29extern void mp_register_lapic (u8 id, u8 enabled); 28extern void mp_register_lapic (u8 id, u8 enabled);