aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic_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
commitba7eda4c60e1d070b2f6586d42719ec1d5302d3b (patch)
treea7d54b9748825334b48d32af0a4b338d8f5be479 /arch/x86/kernel/apic_64.c
parent02290683343391a50f45599710295dafa2ddd018 (diff)
x86_64: Add (not yet used) clock event functions
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/apic_64.c')
-rw-r--r--arch/x86/kernel/apic_64.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index 40938ef99dc2..2c2807abe1d4 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -25,6 +25,7 @@
25#include <linux/sysdev.h> 25#include <linux/sysdev.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/ioport.h> 27#include <linux/ioport.h>
28#include <linux/clockchips.h>
28 29
29#include <asm/atomic.h> 30#include <asm/atomic.h>
30#include <asm/smp.h> 31#include <asm/smp.h>
@@ -57,6 +58,77 @@ static struct resource lapic_resource = {
57 58
58static unsigned int calibration_result; 59static unsigned int calibration_result;
59 60
61static int lapic_next_event(unsigned long delta,
62 struct clock_event_device *evt);
63static void lapic_timer_setup(enum clock_event_mode mode,
64 struct clock_event_device *evt);
65
66static void lapic_timer_broadcast(cpumask_t mask);
67
68static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen);
69
70static struct clock_event_device lapic_clockevent = {
71 .name = "lapic",
72 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
73 | CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
74 .shift = 32,
75 .set_mode = lapic_timer_setup,
76 .set_next_event = lapic_next_event,
77 .broadcast = lapic_timer_broadcast,
78 .rating = 100,
79 .irq = -1,
80};
81static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
82
83static int lapic_next_event(unsigned long delta,
84 struct clock_event_device *evt)
85{
86 apic_write(APIC_TMICT, delta);
87 return 0;
88}
89
90static void lapic_timer_setup(enum clock_event_mode mode,
91 struct clock_event_device *evt)
92{
93 unsigned long flags;
94 unsigned int v;
95
96 /* Lapic used as dummy for broadcast ? */
97 if (evt->features & CLOCK_EVT_FEAT_DUMMY)
98 return;
99
100 local_irq_save(flags);
101
102 switch (mode) {
103 case CLOCK_EVT_MODE_PERIODIC:
104 case CLOCK_EVT_MODE_ONESHOT:
105 __setup_APIC_LVTT(calibration_result,
106 mode != CLOCK_EVT_MODE_PERIODIC, 1);
107 break;
108 case CLOCK_EVT_MODE_UNUSED:
109 case CLOCK_EVT_MODE_SHUTDOWN:
110 v = apic_read(APIC_LVTT);
111 v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
112 apic_write(APIC_LVTT, v);
113 break;
114 case CLOCK_EVT_MODE_RESUME:
115 /* Nothing to do here */
116 break;
117 }
118
119 local_irq_restore(flags);
120}
121
122/*
123 * Local APIC timer broadcast function
124 */
125static void lapic_timer_broadcast(cpumask_t mask)
126{
127#ifdef CONFIG_SMP
128 send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
129#endif
130}
131
60/* 132/*
61 * cpu_mask that denotes the CPUs that needs timer interrupt coming in as 133 * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
62 * IPIs in place of local APIC timers 134 * IPIs in place of local APIC timers
@@ -866,6 +938,13 @@ static void __init calibrate_APIC_clock(void)
866 printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n", 938 printk(KERN_INFO "Detected %d.%03d MHz APIC timer.\n",
867 result / 1000 / 1000, result / 1000 % 1000); 939 result / 1000 / 1000, result / 1000 % 1000);
868 940
941 /* Calculate the scaled math multiplication factor */
942 lapic_clockevent.mult = div_sc(result, NSEC_PER_SEC, 32);
943 lapic_clockevent.max_delta_ns =
944 clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
945 lapic_clockevent.min_delta_ns =
946 clockevent_delta2ns(0xF, &lapic_clockevent);
947
869 calibration_result = result / HZ; 948 calibration_result = result / HZ;
870} 949}
871 950