aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/hpet.c80
-rw-r--r--arch/i386/kernel/i8253.c2
-rw-r--r--arch/i386/kernel/setup.c1
-rw-r--r--arch/i386/kernel/time.c1
-rw-r--r--arch/i386/kernel/tsc.c83
-rw-r--r--arch/x86_64/kernel/hpet.c109
-rw-r--r--arch/x86_64/kernel/time.c2
-rw-r--r--arch/x86_64/kernel/tsc.c7
-rw-r--r--drivers/clocksource/acpi_pm.c5
-rw-r--r--drivers/clocksource/cyclone.c2
-rw-r--r--include/asm-x86_64/tsc.h1
-rw-r--r--kernel/time/clocksource.c8
12 files changed, 135 insertions, 166 deletions
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
index e1006b7acc9e..f3ab61ee7498 100644
--- a/arch/i386/kernel/hpet.c
+++ b/arch/i386/kernel/hpet.c
@@ -201,12 +201,30 @@ static int hpet_next_event(unsigned long delta,
201} 201}
202 202
203/* 203/*
204 * Clock source related code
205 */
206static cycle_t read_hpet(void)
207{
208 return (cycle_t)hpet_readl(HPET_COUNTER);
209}
210
211static struct clocksource clocksource_hpet = {
212 .name = "hpet",
213 .rating = 250,
214 .read = read_hpet,
215 .mask = HPET_MASK,
216 .shift = HPET_SHIFT,
217 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
218};
219
220/*
204 * Try to setup the HPET timer 221 * Try to setup the HPET timer
205 */ 222 */
206int __init hpet_enable(void) 223int __init hpet_enable(void)
207{ 224{
208 unsigned long id; 225 unsigned long id;
209 uint64_t hpet_freq; 226 uint64_t hpet_freq;
227 u64 tmp;
210 228
211 if (!is_hpet_capable()) 229 if (!is_hpet_capable())
212 return 0; 230 return 0;
@@ -253,6 +271,25 @@ int __init hpet_enable(void)
253 /* Start the counter */ 271 /* Start the counter */
254 hpet_start_counter(); 272 hpet_start_counter();
255 273
274 /* Initialize and register HPET clocksource
275 *
276 * hpet period is in femto seconds per cycle
277 * so we need to convert this to ns/cyc units
278 * aproximated by mult/2^shift
279 *
280 * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
281 * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
282 * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
283 * (fsec/cyc << shift)/1000000 = mult
284 * (hpet_period << shift)/FSEC_PER_NSEC = mult
285 */
286 tmp = (u64)hpet_period << HPET_SHIFT;
287 do_div(tmp, FSEC_PER_NSEC);
288 clocksource_hpet.mult = (u32)tmp;
289
290 clocksource_register(&clocksource_hpet);
291
292
256 if (id & HPET_ID_LEGSUP) { 293 if (id & HPET_ID_LEGSUP) {
257 hpet_enable_int(); 294 hpet_enable_int();
258 hpet_reserve_platform_timers(id); 295 hpet_reserve_platform_timers(id);
@@ -273,49 +310,6 @@ out_nohpet:
273 return 0; 310 return 0;
274} 311}
275 312
276/*
277 * Clock source related code
278 */
279static cycle_t read_hpet(void)
280{
281 return (cycle_t)hpet_readl(HPET_COUNTER);
282}
283
284static struct clocksource clocksource_hpet = {
285 .name = "hpet",
286 .rating = 250,
287 .read = read_hpet,
288 .mask = HPET_MASK,
289 .shift = HPET_SHIFT,
290 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
291};
292
293static int __init init_hpet_clocksource(void)
294{
295 u64 tmp;
296
297 if (!hpet_virt_address)
298 return -ENODEV;
299
300 /*
301 * hpet period is in femto seconds per cycle
302 * so we need to convert this to ns/cyc units
303 * aproximated by mult/2^shift
304 *
305 * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
306 * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
307 * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
308 * (fsec/cyc << shift)/1000000 = mult
309 * (hpet_period << shift)/FSEC_PER_NSEC = mult
310 */
311 tmp = (u64)hpet_period << HPET_SHIFT;
312 do_div(tmp, FSEC_PER_NSEC);
313 clocksource_hpet.mult = (u32)tmp;
314
315 return clocksource_register(&clocksource_hpet);
316}
317
318module_init(init_hpet_clocksource);
319 313
320#ifdef CONFIG_HPET_EMULATE_RTC 314#ifdef CONFIG_HPET_EMULATE_RTC
321 315
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c
index a6bc7bb38834..5cbb776b3089 100644
--- a/arch/i386/kernel/i8253.c
+++ b/arch/i386/kernel/i8253.c
@@ -195,4 +195,4 @@ static int __init init_pit_clocksource(void)
195 clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20); 195 clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
196 return clocksource_register(&clocksource_pit); 196 return clocksource_register(&clocksource_pit);
197} 197}
198module_init(init_pit_clocksource); 198arch_initcall(init_pit_clocksource);
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 122623dcc6e1..698c24fe482e 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -657,5 +657,4 @@ void __init setup_arch(char **cmdline_p)
657 conswitchp = &dummy_con; 657 conswitchp = &dummy_con;
658#endif 658#endif
659#endif 659#endif
660 tsc_init();
661} 660}
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index ccd3734edb8f..94e5cb091104 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -279,5 +279,6 @@ void __init hpet_time_init(void)
279 */ 279 */
280void __init time_init(void) 280void __init time_init(void)
281{ 281{
282 tsc_init();
282 late_time_init = choose_time_init(); 283 late_time_init = choose_time_init();
283} 284}
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
index 59222a04234b..875d8a6ecc02 100644
--- a/arch/i386/kernel/tsc.c
+++ b/arch/i386/kernel/tsc.c
@@ -184,34 +184,6 @@ int recalibrate_cpu_khz(void)
184 184
185EXPORT_SYMBOL(recalibrate_cpu_khz); 185EXPORT_SYMBOL(recalibrate_cpu_khz);
186 186
187void __init tsc_init(void)
188{
189 if (!cpu_has_tsc || tsc_disable)
190 goto out_no_tsc;
191
192 cpu_khz = calculate_cpu_khz();
193 tsc_khz = cpu_khz;
194
195 if (!cpu_khz)
196 goto out_no_tsc;
197
198 printk("Detected %lu.%03lu MHz processor.\n",
199 (unsigned long)cpu_khz / 1000,
200 (unsigned long)cpu_khz % 1000);
201
202 set_cyc2ns_scale(cpu_khz);
203 use_tsc_delay();
204 return;
205
206out_no_tsc:
207 /*
208 * Set the tsc_disable flag if there's no TSC support, this
209 * makes it a fast flag for the kernel to see whether it
210 * should be using the TSC.
211 */
212 tsc_disable = 1;
213}
214
215#ifdef CONFIG_CPU_FREQ 187#ifdef CONFIG_CPU_FREQ
216 188
217/* 189/*
@@ -381,28 +353,47 @@ static void __init check_geode_tsc_reliable(void)
381static inline void check_geode_tsc_reliable(void) { } 353static inline void check_geode_tsc_reliable(void) { }
382#endif 354#endif
383 355
384static int __init init_tsc_clocksource(void) 356
357void __init tsc_init(void)
385{ 358{
359 if (!cpu_has_tsc || tsc_disable)
360 goto out_no_tsc;
386 361
387 if (cpu_has_tsc && tsc_khz && !tsc_disable) { 362 cpu_khz = calculate_cpu_khz();
388 /* check blacklist */ 363 tsc_khz = cpu_khz;
389 dmi_check_system(bad_tsc_dmi_table);
390 364
391 unsynchronized_tsc(); 365 if (!cpu_khz)
392 check_geode_tsc_reliable(); 366 goto out_no_tsc;
393 current_tsc_khz = tsc_khz;
394 clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
395 clocksource_tsc.shift);
396 /* lower the rating if we already know its unstable: */
397 if (check_tsc_unstable()) {
398 clocksource_tsc.rating = 0;
399 clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
400 }
401 367
402 return clocksource_register(&clocksource_tsc); 368 printk("Detected %lu.%03lu MHz processor.\n",
369 (unsigned long)cpu_khz / 1000,
370 (unsigned long)cpu_khz % 1000);
371
372 set_cyc2ns_scale(cpu_khz);
373 use_tsc_delay();
374
375 /* Check and install the TSC clocksource */
376 dmi_check_system(bad_tsc_dmi_table);
377
378 unsynchronized_tsc();
379 check_geode_tsc_reliable();
380 current_tsc_khz = tsc_khz;
381 clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
382 clocksource_tsc.shift);
383 /* lower the rating if we already know its unstable: */
384 if (check_tsc_unstable()) {
385 clocksource_tsc.rating = 0;
386 clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
403 } 387 }
388 clocksource_register(&clocksource_tsc);
404 389
405 return 0; 390 return;
406}
407 391
408module_init(init_tsc_clocksource); 392out_no_tsc:
393 /*
394 * Set the tsc_disable flag if there's no TSC support, this
395 * makes it a fast flag for the kernel to see whether it
396 * should be using the TSC.
397 */
398 tsc_disable = 1;
399}
diff --git a/arch/x86_64/kernel/hpet.c b/arch/x86_64/kernel/hpet.c
index 65a0edd71a17..8cf0b8a13778 100644
--- a/arch/x86_64/kernel/hpet.c
+++ b/arch/x86_64/kernel/hpet.c
@@ -12,6 +12,12 @@
12#include <asm/timex.h> 12#include <asm/timex.h>
13#include <asm/hpet.h> 13#include <asm/hpet.h>
14 14
15#define HPET_MASK 0xFFFFFFFF
16#define HPET_SHIFT 22
17
18/* FSEC = 10^-15 NSEC = 10^-9 */
19#define FSEC_PER_NSEC 1000000
20
15int nohpet __initdata; 21int nohpet __initdata;
16 22
17unsigned long hpet_address; 23unsigned long hpet_address;
@@ -106,9 +112,31 @@ int hpet_timer_stop_set_go(unsigned long tick)
106 return 0; 112 return 0;
107} 113}
108 114
115static cycle_t read_hpet(void)
116{
117 return (cycle_t)hpet_readl(HPET_COUNTER);
118}
119
120static cycle_t __vsyscall_fn vread_hpet(void)
121{
122 return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
123}
124
125struct clocksource clocksource_hpet = {
126 .name = "hpet",
127 .rating = 250,
128 .read = read_hpet,
129 .mask = (cycle_t)HPET_MASK,
130 .mult = 0, /* set below */
131 .shift = HPET_SHIFT,
132 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
133 .vread = vread_hpet,
134};
135
109int hpet_arch_init(void) 136int hpet_arch_init(void)
110{ 137{
111 unsigned int id; 138 unsigned int id;
139 u64 tmp;
112 140
113 if (!hpet_address) 141 if (!hpet_address)
114 return -1; 142 return -1;
@@ -132,6 +160,22 @@ int hpet_arch_init(void)
132 160
133 hpet_use_timer = (id & HPET_ID_LEGSUP); 161 hpet_use_timer = (id & HPET_ID_LEGSUP);
134 162
163 /*
164 * hpet period is in femto seconds per cycle
165 * so we need to convert this to ns/cyc units
166 * aproximated by mult/2^shift
167 *
168 * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
169 * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
170 * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
171 * (fsec/cyc << shift)/1000000 = mult
172 * (hpet_period << shift)/FSEC_PER_NSEC = mult
173 */
174 tmp = (u64)hpet_period << HPET_SHIFT;
175 do_div(tmp, FSEC_PER_NSEC);
176 clocksource_hpet.mult = (u32)tmp;
177 clocksource_register(&clocksource_hpet);
178
135 return hpet_timer_stop_set_go(hpet_tick); 179 return hpet_timer_stop_set_go(hpet_tick);
136} 180}
137 181
@@ -444,68 +488,3 @@ static int __init nohpet_setup(char *s)
444} 488}
445 489
446__setup("nohpet", nohpet_setup); 490__setup("nohpet", nohpet_setup);
447
448#define HPET_MASK 0xFFFFFFFF
449#define HPET_SHIFT 22
450
451/* FSEC = 10^-15 NSEC = 10^-9 */
452#define FSEC_PER_NSEC 1000000
453
454static void *hpet_ptr;
455
456static cycle_t read_hpet(void)
457{
458 return (cycle_t)readl(hpet_ptr);
459}
460
461static cycle_t __vsyscall_fn vread_hpet(void)
462{
463 return readl((void __iomem *)fix_to_virt(VSYSCALL_HPET) + 0xf0);
464}
465
466struct clocksource clocksource_hpet = {
467 .name = "hpet",
468 .rating = 250,
469 .read = read_hpet,
470 .mask = (cycle_t)HPET_MASK,
471 .mult = 0, /* set below */
472 .shift = HPET_SHIFT,
473 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
474 .vread = vread_hpet,
475};
476
477static int __init init_hpet_clocksource(void)
478{
479 unsigned long hpet_period;
480 void __iomem *hpet_base;
481 u64 tmp;
482
483 if (!hpet_address)
484 return -ENODEV;
485
486 /* calculate the hpet address: */
487 hpet_base = ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
488 hpet_ptr = hpet_base + HPET_COUNTER;
489
490 /* calculate the frequency: */
491 hpet_period = readl(hpet_base + HPET_PERIOD);
492
493 /*
494 * hpet period is in femto seconds per cycle
495 * so we need to convert this to ns/cyc units
496 * aproximated by mult/2^shift
497 *
498 * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
499 * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
500 * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
501 * (fsec/cyc << shift)/1000000 = mult
502 * (hpet_period << shift)/FSEC_PER_NSEC = mult
503 */
504 tmp = (u64)hpet_period << HPET_SHIFT;
505 do_div(tmp, FSEC_PER_NSEC);
506 clocksource_hpet.mult = (u32)tmp;
507
508 return clocksource_register(&clocksource_hpet);
509}
510
511module_init(init_hpet_clocksource);
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index c9addcfb96dc..75d73a9aa9ff 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -358,6 +358,8 @@ void __init time_init(void)
358 set_cyc2ns_scale(cpu_khz); 358 set_cyc2ns_scale(cpu_khz);
359 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", 359 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
360 cpu_khz / 1000, cpu_khz % 1000); 360 cpu_khz / 1000, cpu_khz % 1000);
361 init_tsc_clocksource();
362
361 setup_irq(0, &irq0); 363 setup_irq(0, &irq0);
362} 364}
363 365
diff --git a/arch/x86_64/kernel/tsc.c b/arch/x86_64/kernel/tsc.c
index 895831865019..1a0edbbffaa0 100644
--- a/arch/x86_64/kernel/tsc.c
+++ b/arch/x86_64/kernel/tsc.c
@@ -210,7 +210,7 @@ void mark_tsc_unstable(void)
210} 210}
211EXPORT_SYMBOL_GPL(mark_tsc_unstable); 211EXPORT_SYMBOL_GPL(mark_tsc_unstable);
212 212
213static int __init init_tsc_clocksource(void) 213void __init init_tsc_clocksource(void)
214{ 214{
215 if (!notsc) { 215 if (!notsc) {
216 clocksource_tsc.mult = clocksource_khz2mult(cpu_khz, 216 clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
@@ -218,9 +218,6 @@ static int __init init_tsc_clocksource(void)
218 if (check_tsc_unstable()) 218 if (check_tsc_unstable())
219 clocksource_tsc.rating = 0; 219 clocksource_tsc.rating = 0;
220 220
221 return clocksource_register(&clocksource_tsc); 221 clocksource_register(&clocksource_tsc);
222 } 222 }
223 return 0;
224} 223}
225
226module_init(init_tsc_clocksource);
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index ccaa6a39cb4b..d42060ede930 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -214,4 +214,7 @@ pm_good:
214 return clocksource_register(&clocksource_acpi_pm); 214 return clocksource_register(&clocksource_acpi_pm);
215} 215}
216 216
217module_init(init_acpi_pm_clocksource); 217/* We use fs_initcall because we want the PCI fixups to have run
218 * but we still need to load before device_initcall
219 */
220fs_initcall(init_acpi_pm_clocksource);
diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c
index 4f3925ceb360..1bde303b970b 100644
--- a/drivers/clocksource/cyclone.c
+++ b/drivers/clocksource/cyclone.c
@@ -116,4 +116,4 @@ static int __init init_cyclone_clocksource(void)
116 return clocksource_register(&clocksource_cyclone); 116 return clocksource_register(&clocksource_cyclone);
117} 117}
118 118
119module_init(init_cyclone_clocksource); 119arch_initcall(init_cyclone_clocksource);
diff --git a/include/asm-x86_64/tsc.h b/include/asm-x86_64/tsc.h
index 9a0a368852c7..26c3e9828288 100644
--- a/include/asm-x86_64/tsc.h
+++ b/include/asm-x86_64/tsc.h
@@ -55,6 +55,7 @@ static __always_inline cycles_t get_cycles_sync(void)
55extern void tsc_init(void); 55extern void tsc_init(void);
56extern void mark_tsc_unstable(void); 56extern void mark_tsc_unstable(void);
57extern int unsynchronized_tsc(void); 57extern int unsynchronized_tsc(void);
58extern void init_tsc_clocksource(void);
58 59
59/* 60/*
60 * Boot-time check whether the TSCs are synchronized across 61 * Boot-time check whether the TSCs are synchronized across
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 193a0793af95..5b0e46b56fd0 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -55,16 +55,18 @@ static DEFINE_SPINLOCK(clocksource_lock);
55static char override_name[32]; 55static char override_name[32];
56static int finished_booting; 56static int finished_booting;
57 57
58/* clocksource_done_booting - Called near the end of bootup 58/* clocksource_done_booting - Called near the end of core bootup
59 * 59 *
60 * Hack to avoid lots of clocksource churn at boot time 60 * Hack to avoid lots of clocksource churn at boot time.
61 * We use fs_initcall because we want this to start before
62 * device_initcall but after subsys_initcall.
61 */ 63 */
62static int __init clocksource_done_booting(void) 64static int __init clocksource_done_booting(void)
63{ 65{
64 finished_booting = 1; 66 finished_booting = 1;
65 return 0; 67 return 0;
66} 68}
67late_initcall(clocksource_done_booting); 69fs_initcall(clocksource_done_booting);
68 70
69#ifdef CONFIG_CLOCKSOURCE_WATCHDOG 71#ifdef CONFIG_CLOCKSOURCE_WATCHDOG
70static LIST_HEAD(watchdog_list); 72static LIST_HEAD(watchdog_list);