diff options
Diffstat (limited to 'arch/x86/kernel/i8253.c')
-rw-r--r-- | arch/x86/kernel/i8253.c | 93 |
1 files changed, 3 insertions, 90 deletions
diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 5783e6de2079..f2b96de3c7c1 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c | |||
@@ -3,15 +3,9 @@ | |||
3 | * | 3 | * |
4 | */ | 4 | */ |
5 | #include <linux/clockchips.h> | 5 | #include <linux/clockchips.h> |
6 | #include <linux/interrupt.h> | ||
7 | #include <linux/spinlock.h> | ||
8 | #include <linux/jiffies.h> | ||
9 | #include <linux/module.h> | 6 | #include <linux/module.h> |
10 | #include <linux/timex.h> | 7 | #include <linux/timex.h> |
11 | #include <linux/delay.h> | ||
12 | #include <linux/i8253.h> | 8 | #include <linux/i8253.h> |
13 | #include <linux/init.h> | ||
14 | #include <linux/io.h> | ||
15 | 9 | ||
16 | #include <asm/hpet.h> | 10 | #include <asm/hpet.h> |
17 | #include <asm/time.h> | 11 | #include <asm/time.h> |
@@ -23,91 +17,10 @@ | |||
23 | */ | 17 | */ |
24 | struct clock_event_device *global_clock_event; | 18 | struct clock_event_device *global_clock_event; |
25 | 19 | ||
26 | /* | ||
27 | * Initialize the PIT timer. | ||
28 | * | ||
29 | * This is also called after resume to bring the PIT into operation again. | ||
30 | */ | ||
31 | static void init_pit_timer(enum clock_event_mode mode, | ||
32 | struct clock_event_device *evt) | ||
33 | { | ||
34 | raw_spin_lock(&i8253_lock); | ||
35 | |||
36 | switch (mode) { | ||
37 | case CLOCK_EVT_MODE_PERIODIC: | ||
38 | /* binary, mode 2, LSB/MSB, ch 0 */ | ||
39 | outb_pit(0x34, PIT_MODE); | ||
40 | outb_pit(LATCH & 0xff , PIT_CH0); /* LSB */ | ||
41 | outb_pit(LATCH >> 8 , PIT_CH0); /* MSB */ | ||
42 | break; | ||
43 | |||
44 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
45 | case CLOCK_EVT_MODE_UNUSED: | ||
46 | if (evt->mode == CLOCK_EVT_MODE_PERIODIC || | ||
47 | evt->mode == CLOCK_EVT_MODE_ONESHOT) { | ||
48 | outb_pit(0x30, PIT_MODE); | ||
49 | outb_pit(0, PIT_CH0); | ||
50 | outb_pit(0, PIT_CH0); | ||
51 | } | ||
52 | break; | ||
53 | |||
54 | case CLOCK_EVT_MODE_ONESHOT: | ||
55 | /* One shot setup */ | ||
56 | outb_pit(0x38, PIT_MODE); | ||
57 | break; | ||
58 | |||
59 | case CLOCK_EVT_MODE_RESUME: | ||
60 | /* Nothing to do here */ | ||
61 | break; | ||
62 | } | ||
63 | raw_spin_unlock(&i8253_lock); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Program the next event in oneshot mode | ||
68 | * | ||
69 | * Delta is given in PIT ticks | ||
70 | */ | ||
71 | static int pit_next_event(unsigned long delta, struct clock_event_device *evt) | ||
72 | { | ||
73 | raw_spin_lock(&i8253_lock); | ||
74 | outb_pit(delta & 0xff , PIT_CH0); /* LSB */ | ||
75 | outb_pit(delta >> 8 , PIT_CH0); /* MSB */ | ||
76 | raw_spin_unlock(&i8253_lock); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * On UP the PIT can serve all of the possible timer functions. On SMP systems | ||
83 | * it can be solely used for the global tick. | ||
84 | * | ||
85 | * The profiling and update capabilities are switched off once the local apic is | ||
86 | * registered. This mechanism replaces the previous #ifdef LOCAL_APIC - | ||
87 | * !using_apic_timer decisions in do_timer_interrupt_hook() | ||
88 | */ | ||
89 | static struct clock_event_device pit_ce = { | ||
90 | .name = "pit", | ||
91 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
92 | .set_mode = init_pit_timer, | ||
93 | .set_next_event = pit_next_event, | ||
94 | .irq = 0, | ||
95 | }; | ||
96 | |||
97 | /* | ||
98 | * Initialize the conversion factor and the min/max deltas of the clock event | ||
99 | * structure and register the clock event source with the framework. | ||
100 | */ | ||
101 | void __init setup_pit_timer(void) | 20 | void __init setup_pit_timer(void) |
102 | { | 21 | { |
103 | /* | 22 | clockevent_i8253_init(true); |
104 | * Start pit with the boot cpu mask and make it global after the | 23 | global_clock_event = &i8253_clockevent; |
105 | * IO_APIC has been initialized. | ||
106 | */ | ||
107 | pit_ce.cpumask = cpumask_of(smp_processor_id()); | ||
108 | |||
109 | clockevents_config_and_register(&pit_ce, CLOCK_TICK_RATE, 0xF, 0x7FFF); | ||
110 | global_clock_event = &pit_ce; | ||
111 | } | 24 | } |
112 | 25 | ||
113 | #ifndef CONFIG_X86_64 | 26 | #ifndef CONFIG_X86_64 |
@@ -121,7 +34,7 @@ static int __init init_pit_clocksource(void) | |||
121 | * - when local APIC timer is active (PIT is switched off) | 34 | * - when local APIC timer is active (PIT is switched off) |
122 | */ | 35 | */ |
123 | if (num_possible_cpus() > 1 || is_hpet_enabled() || | 36 | if (num_possible_cpus() > 1 || is_hpet_enabled() || |
124 | pit_ce.mode != CLOCK_EVT_MODE_PERIODIC) | 37 | i8253_clockevent.mode != CLOCK_EVT_MODE_PERIODIC) |
125 | return 0; | 38 | return 0; |
126 | 39 | ||
127 | return clocksource_i8253_init(); | 40 | return clocksource_i8253_init(); |