1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/errno.h>
34#include <linux/sched.h>
35#include <linux/kernel.h>
36#include <linux/param.h>
37#include <linux/string.h>
38#include <linux/mm.h>
39#include <linux/interrupt.h>
40#include <linux/time.h>
41#include <linux/delay.h>
42#include <linux/init.h>
43#include <linux/smp.h>
44#include <linux/module.h>
45#include <linux/sysdev.h>
46#include <linux/bcd.h>
47#include <linux/efi.h>
48#include <linux/mca.h>
49
50#include <asm/io.h>
51#include <asm/smp.h>
52#include <asm/irq.h>
53#include <asm/msr.h>
54#include <asm/delay.h>
55#include <asm/mpspec.h>
56#include <asm/uaccess.h>
57#include <asm/processor.h>
58#include <asm/timer.h>
59#include <asm/time.h>
60
61#include "mach_time.h"
62
63#include <linux/timex.h>
64
65#include <asm/hpet.h>
66
67#include <asm/arch_hooks.h>
68
69#include "io_ports.h"
70
71#include <asm/i8259.h>
72
73#include "do_timer.h"
74
75unsigned int cpu_khz;
76EXPORT_SYMBOL(cpu_khz);
77
78DEFINE_SPINLOCK(rtc_lock);
79EXPORT_SYMBOL(rtc_lock);
80
81
82
83
84
85
86volatile unsigned long cmos_lock = 0;
87EXPORT_SYMBOL(cmos_lock);
88
89
90unsigned char rtc_cmos_read(unsigned char addr)
91{
92 unsigned char val;
93 lock_cmos_prefix(addr);
94 outb_p(addr, RTC_PORT(0));
95 val = inb_p(RTC_PORT(1));
96 lock_cmos_suffix(addr);
97 return val;
98}
99EXPORT_SYMBOL(rtc_cmos_read);
100
101void rtc_cmos_write(unsigned char val, unsigned char addr)
102{
103 lock_cmos_prefix(addr);
104 outb_p(addr, RTC_PORT(0));
105 outb_p(val, RTC_PORT(1));
106 lock_cmos_suffix(addr);
107}
108EXPORT_SYMBOL(rtc_cmos_write);
109
110static int set_rtc_mmss(unsigned long nowtime)
111{
112 int retval;
113 unsigned long flags;
114
115
116
117 spin_lock_irqsave(&rtc_lock, flags);
118 retval = set_wallclock(nowtime);
119 spin_unlock_irqrestore(&rtc_lock, flags);
120
121 return retval;
122}
123
124
125int timer_ack;
126
127unsigned long profile_pc(struct pt_regs *regs)
128{
129 unsigned long pc = instruction_pointer(regs);
130
131#ifdef CONFIG_SMP
132 if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->xcs) &&
133 in_lock_functions(pc)) {
134#ifdef CONFIG_FRAME_POINTER
135 return *(unsigned long *)(regs->ebp + 4);
136#else
137 unsigned long *sp = (unsigned long *)®s->esp;
138
139
140
141
142 if (sp[0] >> 22)
143 return sp[0];
144 if (sp[1] >> 22)
145 return sp[1];
146#endif
147 }
148#endif
149 return pc;
150}
151EXPORT_SYMBOL(profile_pc);
152
153
154
155
156
157
158irqreturn_t timer_interrupt(int irq, void *dev_id)
159{
160#ifdef CONFIG_X86_IO_APIC
161 if (timer_ack) {
162
163
164
165
166
167
168 spin_lock(&i8259A_lock);
169 outb(0x0c, PIC_MASTER_OCW3);
170
171 inb(PIC_MASTER_POLL);
172 spin_unlock(&i8259A_lock);
173 }
174#endif
175
176 do_timer_interrupt_hook();
177
178 if (MCA_bus) {
179
180
181
182
183
184
185
186
187
188 u8 irq_v = inb_p( 0x61 );
189 outb_p( irq_v|0x80, 0x61 );
190 }
191
192 return IRQ_HANDLED;
193}
194
195
196unsigned long read_persistent_clock(void)
197{
198 unsigned long retval;
199 unsigned long flags;
200
201 spin_lock_irqsave(&rtc_lock, flags);
202
203 retval = get_wallclock();
204
205 spin_unlock_irqrestore(&rtc_lock, flags);
206
207 return retval;
208}
209
210static void sync_cmos_clock(unsigned long dummy);
211
212static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0);
213int no_sync_cmos_clock;
214
215static void sync_cmos_clock(unsigned long dummy)
216{
217 struct timeval now, next;
218 int fail = 1;
219
220
221
222
223
224
225
226
227 if (!ntp_synced())
228
229
230
231
232 return;
233
234 do_gettimeofday(&now);
235 if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
236 now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2)
237 fail = set_rtc_mmss(now.tv_sec);
238
239 next.tv_usec = USEC_AFTER - now.tv_usec;
240 if (next.tv_usec <= 0)
241 next.tv_usec += USEC_PER_SEC;
242
243 if (!fail)
244 next.tv_sec = 659;
245 else
246 next.tv_sec = 0;
247
248 if (next.tv_usec >= USEC_PER_SEC) {
249 next.tv_sec++;
250 next.tv_usec -= USEC_PER_SEC;
251 }
252 mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next));
253}
254
255void notify_arch_cmos_timer(void)
256{
257 if (!no_sync_cmos_clock)
258 mod_timer(&sync_cmos_timer, jiffies + 1);
259}
260
261extern void (*late_time_init)(void);
262
263void __init hpet_time_init(void)
264{
265 if (!hpet_enable())
266 setup_pit_timer();
267 time_init_hook();
268}
269
270
271
272
273
274
275
276
277
278void __init time_init(void)
279{
280 tsc_init();
281 late_time_init = choose_time_init();
282}
283