aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/time.c')
-rw-r--r--arch/mips/kernel/time.c66
1 files changed, 24 insertions, 42 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index e535f86efa2f..8aa544f73a5e 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -11,7 +11,6 @@
11 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. 12 * option) any later version.
13 */ 13 */
14#include <linux/clocksource.h>
15#include <linux/types.h> 14#include <linux/types.h>
16#include <linux/kernel.h> 15#include <linux/kernel.h>
17#include <linux/init.h> 16#include <linux/init.h>
@@ -83,17 +82,11 @@ static void null_timer_ack(void) { /* nothing */ }
83/* 82/*
84 * Null high precision timer functions for systems lacking one. 83 * Null high precision timer functions for systems lacking one.
85 */ 84 */
86static unsigned int null_hpt_read(void) 85static cycle_t null_hpt_read(void)
87{ 86{
88 return 0; 87 return 0;
89} 88}
90 89
91static void __init null_hpt_init(void)
92{
93 /* nothing */
94}
95
96
97/* 90/*
98 * Timer ack for an R4k-compatible timer of a known frequency. 91 * Timer ack for an R4k-compatible timer of a known frequency.
99 */ 92 */
@@ -101,10 +94,8 @@ static void c0_timer_ack(void)
101{ 94{
102 unsigned int count; 95 unsigned int count;
103 96
104#ifndef CONFIG_SOC_PNX8550 /* pnx8550 resets to zero */
105 /* Ack this timer interrupt and set the next one. */ 97 /* Ack this timer interrupt and set the next one. */
106 expirelo += cycles_per_jiffy; 98 expirelo += cycles_per_jiffy;
107#endif
108 write_c0_compare(expirelo); 99 write_c0_compare(expirelo);
109 100
110 /* Check to see if we have missed any timer interrupts. */ 101 /* Check to see if we have missed any timer interrupts. */
@@ -118,7 +109,7 @@ static void c0_timer_ack(void)
118/* 109/*
119 * High precision timer functions for a R4k-compatible timer. 110 * High precision timer functions for a R4k-compatible timer.
120 */ 111 */
121static unsigned int c0_hpt_read(void) 112static cycle_t c0_hpt_read(void)
122{ 113{
123 return read_c0_count(); 114 return read_c0_count();
124} 115}
@@ -132,9 +123,6 @@ static void __init c0_hpt_timer_init(void)
132 123
133int (*mips_timer_state)(void); 124int (*mips_timer_state)(void);
134void (*mips_timer_ack)(void); 125void (*mips_timer_ack)(void);
135unsigned int (*mips_hpt_read)(void);
136void (*mips_hpt_init)(void) __initdata = null_hpt_init;
137unsigned int mips_hpt_mask = 0xffffffff;
138 126
139/* last time when xtime and rtc are sync'ed up */ 127/* last time when xtime and rtc are sync'ed up */
140static long last_rtc_update; 128static long last_rtc_update;
@@ -276,8 +264,7 @@ static struct irqaction timer_irqaction = {
276 264
277static unsigned int __init calibrate_hpt(void) 265static unsigned int __init calibrate_hpt(void)
278{ 266{
279 u64 frequency; 267 cycle_t frequency, hpt_start, hpt_end, hpt_count, hz;
280 u32 hpt_start, hpt_end, hpt_count, hz;
281 268
282 const int loops = HZ / 10; 269 const int loops = HZ / 10;
283 int log_2_loops = 0; 270 int log_2_loops = 0;
@@ -303,28 +290,23 @@ static unsigned int __init calibrate_hpt(void)
303 * during the calculated number of periods between timer 290 * during the calculated number of periods between timer
304 * interrupts. 291 * interrupts.
305 */ 292 */
306 hpt_start = mips_hpt_read(); 293 hpt_start = clocksource_mips.read();
307 do { 294 do {
308 while (mips_timer_state()); 295 while (mips_timer_state());
309 while (!mips_timer_state()); 296 while (!mips_timer_state());
310 } while (--i); 297 } while (--i);
311 hpt_end = mips_hpt_read(); 298 hpt_end = clocksource_mips.read();
312 299
313 hpt_count = (hpt_end - hpt_start) & mips_hpt_mask; 300 hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask;
314 hz = HZ; 301 hz = HZ;
315 frequency = (u64)hpt_count * (u64)hz; 302 frequency = hpt_count * hz;
316 303
317 return frequency >> log_2_loops; 304 return frequency >> log_2_loops;
318} 305}
319 306
320static cycle_t read_mips_hpt(void) 307struct clocksource clocksource_mips = {
321{
322 return (cycle_t)mips_hpt_read();
323}
324
325static struct clocksource clocksource_mips = {
326 .name = "MIPS", 308 .name = "MIPS",
327 .read = read_mips_hpt, 309 .mask = 0xffffffff,
328 .is_continuous = 1, 310 .is_continuous = 1,
329}; 311};
330 312
@@ -333,7 +315,7 @@ static void __init init_mips_clocksource(void)
333 u64 temp; 315 u64 temp;
334 u32 shift; 316 u32 shift;
335 317
336 if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read) 318 if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read)
337 return; 319 return;
338 320
339 /* Calclate a somewhat reasonable rating value */ 321 /* Calclate a somewhat reasonable rating value */
@@ -347,7 +329,6 @@ static void __init init_mips_clocksource(void)
347 } 329 }
348 clocksource_mips.shift = shift; 330 clocksource_mips.shift = shift;
349 clocksource_mips.mult = (u32)temp; 331 clocksource_mips.mult = (u32)temp;
350 clocksource_mips.mask = mips_hpt_mask;
351 332
352 clocksource_register(&clocksource_mips); 333 clocksource_register(&clocksource_mips);
353} 334}
@@ -367,32 +348,36 @@ void __init time_init(void)
367 -xtime.tv_sec, -xtime.tv_nsec); 348 -xtime.tv_sec, -xtime.tv_nsec);
368 349
369 /* Choose appropriate high precision timer routines. */ 350 /* Choose appropriate high precision timer routines. */
370 if (!cpu_has_counter && !mips_hpt_read) 351 if (!cpu_has_counter && !clocksource_mips.read)
371 /* No high precision timer -- sorry. */ 352 /* No high precision timer -- sorry. */
372 mips_hpt_read = null_hpt_read; 353 clocksource_mips.read = null_hpt_read;
373 else if (!mips_hpt_frequency && !mips_timer_state) { 354 else if (!mips_hpt_frequency && !mips_timer_state) {
374 /* A high precision timer of unknown frequency. */ 355 /* A high precision timer of unknown frequency. */
375 if (!mips_hpt_read) 356 if (!clocksource_mips.read)
376 /* No external high precision timer -- use R4k. */ 357 /* No external high precision timer -- use R4k. */
377 mips_hpt_read = c0_hpt_read; 358 clocksource_mips.read = c0_hpt_read;
378 } else { 359 } else {
379 /* We know counter frequency. Or we can get it. */ 360 /* We know counter frequency. Or we can get it. */
380 if (!mips_hpt_read) { 361 if (!clocksource_mips.read) {
381 /* No external high precision timer -- use R4k. */ 362 /* No external high precision timer -- use R4k. */
382 mips_hpt_read = c0_hpt_read; 363 clocksource_mips.read = c0_hpt_read;
383 364
384 if (!mips_timer_state) { 365 if (!mips_timer_state) {
385 /* No external timer interrupt -- use R4k. */ 366 /* No external timer interrupt -- use R4k. */
386 mips_hpt_init = c0_hpt_timer_init;
387 mips_timer_ack = c0_timer_ack; 367 mips_timer_ack = c0_timer_ack;
368 /* Calculate cache parameters. */
369 cycles_per_jiffy =
370 (mips_hpt_frequency + HZ / 2) / HZ;
371 /*
372 * This sets up the high precision
373 * timer for the first interrupt.
374 */
375 c0_hpt_timer_init();
388 } 376 }
389 } 377 }
390 if (!mips_hpt_frequency) 378 if (!mips_hpt_frequency)
391 mips_hpt_frequency = calibrate_hpt(); 379 mips_hpt_frequency = calibrate_hpt();
392 380
393 /* Calculate cache parameters. */
394 cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ;
395
396 /* Report the high precision timer rate for a reference. */ 381 /* Report the high precision timer rate for a reference. */
397 printk("Using %u.%03u MHz high precision timer.\n", 382 printk("Using %u.%03u MHz high precision timer.\n",
398 ((mips_hpt_frequency + 500) / 1000) / 1000, 383 ((mips_hpt_frequency + 500) / 1000) / 1000,
@@ -403,9 +388,6 @@ void __init time_init(void)
403 /* No timer interrupt ack (e.g. i8254). */ 388 /* No timer interrupt ack (e.g. i8254). */
404 mips_timer_ack = null_timer_ack; 389 mips_timer_ack = null_timer_ack;
405 390
406 /* This sets up the high precision timer for the first interrupt. */
407 mips_hpt_init();
408
409 /* 391 /*
410 * Call board specific timer interrupt setup. 392 * Call board specific timer interrupt setup.
411 * 393 *