diff options
Diffstat (limited to 'arch/mips/kernel/time.c')
| -rw-r--r-- | arch/mips/kernel/time.c | 319 |
1 files changed, 53 insertions, 266 deletions
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index debe86c2f691..e535f86efa2f 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
| @@ -11,6 +11,7 @@ | |||
| 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> | ||
| 14 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| 15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| @@ -67,15 +68,9 @@ int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time; | |||
| 67 | int (*rtc_mips_set_mmss)(unsigned long); | 68 | int (*rtc_mips_set_mmss)(unsigned long); |
| 68 | 69 | ||
| 69 | 70 | ||
| 70 | /* usecs per counter cycle, shifted to left by 32 bits */ | ||
| 71 | static unsigned int sll32_usecs_per_cycle; | ||
| 72 | |||
| 73 | /* how many counter cycles in a jiffy */ | 71 | /* how many counter cycles in a jiffy */ |
| 74 | static unsigned long cycles_per_jiffy __read_mostly; | 72 | static unsigned long cycles_per_jiffy __read_mostly; |
| 75 | 73 | ||
| 76 | /* Cycle counter value at the previous timer interrupt.. */ | ||
| 77 | static unsigned int timerhi, timerlo; | ||
| 78 | |||
| 79 | /* expirelo is the count value for next CPU timer interrupt */ | 74 | /* expirelo is the count value for next CPU timer interrupt */ |
| 80 | static unsigned int expirelo; | 75 | static unsigned int expirelo; |
| 81 | 76 | ||
| @@ -93,7 +88,7 @@ static unsigned int null_hpt_read(void) | |||
| 93 | return 0; | 88 | return 0; |
| 94 | } | 89 | } |
| 95 | 90 | ||
| 96 | static void null_hpt_init(unsigned int count) | 91 | static void __init null_hpt_init(void) |
| 97 | { | 92 | { |
| 98 | /* nothing */ | 93 | /* nothing */ |
| 99 | } | 94 | } |
| @@ -128,186 +123,18 @@ static unsigned int c0_hpt_read(void) | |||
| 128 | return read_c0_count(); | 123 | return read_c0_count(); |
| 129 | } | 124 | } |
| 130 | 125 | ||
| 131 | /* For use solely as a high precision timer. */ | ||
| 132 | static void c0_hpt_init(unsigned int count) | ||
| 133 | { | ||
| 134 | write_c0_count(read_c0_count() - count); | ||
| 135 | } | ||
| 136 | |||
| 137 | /* For use both as a high precision timer and an interrupt source. */ | 126 | /* For use both as a high precision timer and an interrupt source. */ |
| 138 | static void c0_hpt_timer_init(unsigned int count) | 127 | static void __init c0_hpt_timer_init(void) |
| 139 | { | 128 | { |
| 140 | count = read_c0_count() - count; | 129 | expirelo = read_c0_count() + cycles_per_jiffy; |
| 141 | expirelo = (count / cycles_per_jiffy + 1) * cycles_per_jiffy; | ||
| 142 | write_c0_count(expirelo - cycles_per_jiffy); | ||
| 143 | write_c0_compare(expirelo); | 130 | write_c0_compare(expirelo); |
| 144 | write_c0_count(count); | ||
| 145 | } | 131 | } |
| 146 | 132 | ||
| 147 | int (*mips_timer_state)(void); | 133 | int (*mips_timer_state)(void); |
| 148 | void (*mips_timer_ack)(void); | 134 | void (*mips_timer_ack)(void); |
| 149 | unsigned int (*mips_hpt_read)(void); | 135 | unsigned int (*mips_hpt_read)(void); |
| 150 | void (*mips_hpt_init)(unsigned int); | 136 | void (*mips_hpt_init)(void) __initdata = null_hpt_init; |
| 151 | 137 | unsigned int mips_hpt_mask = 0xffffffff; | |
| 152 | /* | ||
| 153 | * Gettimeoffset routines. These routines returns the time duration | ||
| 154 | * since last timer interrupt in usecs. | ||
| 155 | * | ||
| 156 | * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset. | ||
| 157 | * Otherwise use calibrate_gettimeoffset() | ||
| 158 | * | ||
| 159 | * If the CPU does not have the counter register, you can either supply | ||
| 160 | * your own gettimeoffset() routine, or use null_gettimeoffset(), which | ||
| 161 | * gives the same resolution as HZ. | ||
| 162 | */ | ||
| 163 | |||
| 164 | static unsigned long null_gettimeoffset(void) | ||
| 165 | { | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | |||
| 170 | /* The function pointer to one of the gettimeoffset funcs. */ | ||
| 171 | unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset; | ||
| 172 | |||
| 173 | |||
| 174 | static unsigned long fixed_rate_gettimeoffset(void) | ||
| 175 | { | ||
| 176 | u32 count; | ||
| 177 | unsigned long res; | ||
| 178 | |||
| 179 | /* Get last timer tick in absolute kernel time */ | ||
| 180 | count = mips_hpt_read(); | ||
| 181 | |||
| 182 | /* .. relative to previous jiffy (32 bits is enough) */ | ||
| 183 | count -= timerlo; | ||
| 184 | |||
| 185 | __asm__("multu %1,%2" | ||
| 186 | : "=h" (res) | ||
| 187 | : "r" (count), "r" (sll32_usecs_per_cycle) | ||
| 188 | : "lo", GCC_REG_ACCUM); | ||
| 189 | |||
| 190 | /* | ||
| 191 | * Due to possible jiffies inconsistencies, we need to check | ||
| 192 | * the result so that we'll get a timer that is monotonic. | ||
| 193 | */ | ||
| 194 | if (res >= USECS_PER_JIFFY) | ||
| 195 | res = USECS_PER_JIFFY - 1; | ||
| 196 | |||
| 197 | return res; | ||
| 198 | } | ||
| 199 | |||
| 200 | |||
| 201 | /* | ||
| 202 | * Cached "1/(clocks per usec) * 2^32" value. | ||
| 203 | * It has to be recalculated once each jiffy. | ||
| 204 | */ | ||
| 205 | static unsigned long cached_quotient; | ||
| 206 | |||
| 207 | /* Last jiffy when calibrate_divXX_gettimeoffset() was called. */ | ||
| 208 | static unsigned long last_jiffies; | ||
| 209 | |||
| 210 | /* | ||
| 211 | * This is moved from dec/time.c:do_ioasic_gettimeoffset() by Maciej. | ||
| 212 | */ | ||
| 213 | static unsigned long calibrate_div32_gettimeoffset(void) | ||
| 214 | { | ||
| 215 | u32 count; | ||
| 216 | unsigned long res, tmp; | ||
| 217 | unsigned long quotient; | ||
| 218 | |||
| 219 | tmp = jiffies; | ||
| 220 | |||
| 221 | quotient = cached_quotient; | ||
| 222 | |||
| 223 | if (last_jiffies != tmp) { | ||
| 224 | last_jiffies = tmp; | ||
| 225 | if (last_jiffies != 0) { | ||
| 226 | unsigned long r0; | ||
| 227 | do_div64_32(r0, timerhi, timerlo, tmp); | ||
| 228 | do_div64_32(quotient, USECS_PER_JIFFY, | ||
| 229 | USECS_PER_JIFFY_FRAC, r0); | ||
| 230 | cached_quotient = quotient; | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | /* Get last timer tick in absolute kernel time */ | ||
| 235 | count = mips_hpt_read(); | ||
| 236 | |||
| 237 | /* .. relative to previous jiffy (32 bits is enough) */ | ||
| 238 | count -= timerlo; | ||
| 239 | |||
| 240 | __asm__("multu %1,%2" | ||
| 241 | : "=h" (res) | ||
| 242 | : "r" (count), "r" (quotient) | ||
| 243 | : "lo", GCC_REG_ACCUM); | ||
| 244 | |||
| 245 | /* | ||
| 246 | * Due to possible jiffies inconsistencies, we need to check | ||
| 247 | * the result so that we'll get a timer that is monotonic. | ||
| 248 | */ | ||
| 249 | if (res >= USECS_PER_JIFFY) | ||
| 250 | res = USECS_PER_JIFFY - 1; | ||
| 251 | |||
| 252 | return res; | ||
| 253 | } | ||
| 254 | |||
| 255 | static unsigned long calibrate_div64_gettimeoffset(void) | ||
| 256 | { | ||
| 257 | u32 count; | ||
| 258 | unsigned long res, tmp; | ||
| 259 | unsigned long quotient; | ||
| 260 | |||
| 261 | tmp = jiffies; | ||
| 262 | |||
| 263 | quotient = cached_quotient; | ||
| 264 | |||
| 265 | if (last_jiffies != tmp) { | ||
| 266 | last_jiffies = tmp; | ||
| 267 | if (last_jiffies) { | ||
| 268 | unsigned long r0; | ||
| 269 | __asm__(".set push\n\t" | ||
| 270 | ".set mips3\n\t" | ||
| 271 | "lwu %0,%3\n\t" | ||
| 272 | "dsll32 %1,%2,0\n\t" | ||
| 273 | "or %1,%1,%0\n\t" | ||
| 274 | "ddivu $0,%1,%4\n\t" | ||
| 275 | "mflo %1\n\t" | ||
| 276 | "dsll32 %0,%5,0\n\t" | ||
| 277 | "or %0,%0,%6\n\t" | ||
| 278 | "ddivu $0,%0,%1\n\t" | ||
| 279 | "mflo %0\n\t" | ||
| 280 | ".set pop" | ||
| 281 | : "=&r" (quotient), "=&r" (r0) | ||
| 282 | : "r" (timerhi), "m" (timerlo), | ||
| 283 | "r" (tmp), "r" (USECS_PER_JIFFY), | ||
| 284 | "r" (USECS_PER_JIFFY_FRAC) | ||
| 285 | : "hi", "lo", GCC_REG_ACCUM); | ||
| 286 | cached_quotient = quotient; | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | /* Get last timer tick in absolute kernel time */ | ||
| 291 | count = mips_hpt_read(); | ||
| 292 | |||
| 293 | /* .. relative to previous jiffy (32 bits is enough) */ | ||
| 294 | count -= timerlo; | ||
| 295 | |||
| 296 | __asm__("multu %1,%2" | ||
| 297 | : "=h" (res) | ||
| 298 | : "r" (count), "r" (quotient) | ||
| 299 | : "lo", GCC_REG_ACCUM); | ||
| 300 | |||
| 301 | /* | ||
| 302 | * Due to possible jiffies inconsistencies, we need to check | ||
| 303 | * the result so that we'll get a timer that is monotonic. | ||
| 304 | */ | ||
| 305 | if (res >= USECS_PER_JIFFY) | ||
| 306 | res = USECS_PER_JIFFY - 1; | ||
| 307 | |||
| 308 | return res; | ||
| 309 | } | ||
| 310 | |||
| 311 | 138 | ||
| 312 | /* last time when xtime and rtc are sync'ed up */ | 139 | /* last time when xtime and rtc are sync'ed up */ |
| 313 | static long last_rtc_update; | 140 | static long last_rtc_update; |
| @@ -334,18 +161,10 @@ void local_timer_interrupt(int irq, void *dev_id) | |||
| 334 | */ | 161 | */ |
| 335 | irqreturn_t timer_interrupt(int irq, void *dev_id) | 162 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
| 336 | { | 163 | { |
| 337 | unsigned long j; | ||
| 338 | unsigned int count; | ||
| 339 | |||
| 340 | write_seqlock(&xtime_lock); | 164 | write_seqlock(&xtime_lock); |
| 341 | 165 | ||
| 342 | count = mips_hpt_read(); | ||
| 343 | mips_timer_ack(); | 166 | mips_timer_ack(); |
| 344 | 167 | ||
| 345 | /* Update timerhi/timerlo for intra-jiffy calibration. */ | ||
| 346 | timerhi += count < timerlo; /* Wrap around */ | ||
| 347 | timerlo = count; | ||
| 348 | |||
| 349 | /* | 168 | /* |
| 350 | * call the generic timer interrupt handling | 169 | * call the generic timer interrupt handling |
| 351 | */ | 170 | */ |
| @@ -368,47 +187,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
| 368 | } | 187 | } |
| 369 | } | 188 | } |
| 370 | 189 | ||
| 371 | /* | ||
| 372 | * If jiffies has overflown in this timer_interrupt, we must | ||
| 373 | * update the timer[hi]/[lo] to make fast gettimeoffset funcs | ||
| 374 | * quotient calc still valid. -arca | ||
| 375 | * | ||
| 376 | * The first timer interrupt comes late as interrupts are | ||
| 377 | * enabled long after timers are initialized. Therefore the | ||
| 378 | * high precision timer is fast, leading to wrong gettimeoffset() | ||
| 379 | * calculations. We deal with it by setting it based on the | ||
| 380 | * number of its ticks between the second and the third interrupt. | ||
| 381 | * That is still somewhat imprecise, but it's a good estimate. | ||
| 382 | * --macro | ||
| 383 | */ | ||
| 384 | j = jiffies; | ||
| 385 | if (j < 4) { | ||
| 386 | static unsigned int prev_count; | ||
| 387 | static int hpt_initialized; | ||
| 388 | |||
| 389 | switch (j) { | ||
| 390 | case 0: | ||
| 391 | timerhi = timerlo = 0; | ||
| 392 | mips_hpt_init(count); | ||
| 393 | break; | ||
| 394 | case 2: | ||
| 395 | prev_count = count; | ||
| 396 | break; | ||
| 397 | case 3: | ||
| 398 | if (!hpt_initialized) { | ||
| 399 | unsigned int c3 = 3 * (count - prev_count); | ||
| 400 | |||
| 401 | timerhi = 0; | ||
| 402 | timerlo = c3; | ||
| 403 | mips_hpt_init(count - c3); | ||
| 404 | hpt_initialized = 1; | ||
| 405 | } | ||
| 406 | break; | ||
| 407 | default: | ||
| 408 | break; | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | write_sequnlock(&xtime_lock); | 190 | write_sequnlock(&xtime_lock); |
| 413 | 191 | ||
| 414 | /* | 192 | /* |
| @@ -476,12 +254,11 @@ asmlinkage void ll_local_timer_interrupt(int irq) | |||
| 476 | * 1) board_time_init() - | 254 | * 1) board_time_init() - |
| 477 | * a) (optional) set up RTC routines, | 255 | * a) (optional) set up RTC routines, |
| 478 | * b) (optional) calibrate and set the mips_hpt_frequency | 256 | * b) (optional) calibrate and set the mips_hpt_frequency |
| 479 | * (only needed if you intended to use fixed_rate_gettimeoffset | 257 | * (only needed if you intended to use cpu counter as timer interrupt |
| 480 | * or use cpu counter as timer interrupt source) | 258 | * source) |
| 481 | * 2) setup xtime based on rtc_mips_get_time(). | 259 | * 2) setup xtime based on rtc_mips_get_time(). |
| 482 | * 3) choose a appropriate gettimeoffset routine. | 260 | * 3) calculate a couple of cached variables for later usage |
| 483 | * 4) calculate a couple of cached variables for later usage | 261 | * 4) plat_timer_setup() - |
| 484 | * 5) plat_timer_setup() - | ||
| 485 | * a) (optional) over-write any choices made above by time_init(). | 262 | * a) (optional) over-write any choices made above by time_init(). |
| 486 | * b) machine specific code should setup the timer irqaction. | 263 | * b) machine specific code should setup the timer irqaction. |
| 487 | * c) enable the timer interrupt | 264 | * c) enable the timer interrupt |
| @@ -533,13 +310,48 @@ static unsigned int __init calibrate_hpt(void) | |||
| 533 | } while (--i); | 310 | } while (--i); |
| 534 | hpt_end = mips_hpt_read(); | 311 | hpt_end = mips_hpt_read(); |
| 535 | 312 | ||
| 536 | hpt_count = hpt_end - hpt_start; | 313 | hpt_count = (hpt_end - hpt_start) & mips_hpt_mask; |
| 537 | hz = HZ; | 314 | hz = HZ; |
| 538 | frequency = (u64)hpt_count * (u64)hz; | 315 | frequency = (u64)hpt_count * (u64)hz; |
| 539 | 316 | ||
| 540 | return frequency >> log_2_loops; | 317 | return frequency >> log_2_loops; |
| 541 | } | 318 | } |
| 542 | 319 | ||
| 320 | static cycle_t read_mips_hpt(void) | ||
| 321 | { | ||
| 322 | return (cycle_t)mips_hpt_read(); | ||
| 323 | } | ||
| 324 | |||
| 325 | static struct clocksource clocksource_mips = { | ||
| 326 | .name = "MIPS", | ||
| 327 | .read = read_mips_hpt, | ||
| 328 | .is_continuous = 1, | ||
| 329 | }; | ||
| 330 | |||
| 331 | static void __init init_mips_clocksource(void) | ||
| 332 | { | ||
| 333 | u64 temp; | ||
| 334 | u32 shift; | ||
| 335 | |||
| 336 | if (!mips_hpt_frequency || mips_hpt_read == null_hpt_read) | ||
| 337 | return; | ||
| 338 | |||
| 339 | /* Calclate a somewhat reasonable rating value */ | ||
| 340 | clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; | ||
| 341 | /* Find a shift value */ | ||
| 342 | for (shift = 32; shift > 0; shift--) { | ||
| 343 | temp = (u64) NSEC_PER_SEC << shift; | ||
| 344 | do_div(temp, mips_hpt_frequency); | ||
| 345 | if ((temp >> 32) == 0) | ||
| 346 | break; | ||
| 347 | } | ||
| 348 | clocksource_mips.shift = shift; | ||
| 349 | clocksource_mips.mult = (u32)temp; | ||
| 350 | clocksource_mips.mask = mips_hpt_mask; | ||
| 351 | |||
| 352 | clocksource_register(&clocksource_mips); | ||
| 353 | } | ||
| 354 | |||
| 543 | void __init time_init(void) | 355 | void __init time_init(void) |
| 544 | { | 356 | { |
| 545 | if (board_time_init) | 357 | if (board_time_init) |
| @@ -555,41 +367,21 @@ void __init time_init(void) | |||
| 555 | -xtime.tv_sec, -xtime.tv_nsec); | 367 | -xtime.tv_sec, -xtime.tv_nsec); |
| 556 | 368 | ||
| 557 | /* Choose appropriate high precision timer routines. */ | 369 | /* Choose appropriate high precision timer routines. */ |
| 558 | if (!cpu_has_counter && !mips_hpt_read) { | 370 | if (!cpu_has_counter && !mips_hpt_read) |
| 559 | /* No high precision timer -- sorry. */ | 371 | /* No high precision timer -- sorry. */ |
| 560 | mips_hpt_read = null_hpt_read; | 372 | mips_hpt_read = null_hpt_read; |
| 561 | mips_hpt_init = null_hpt_init; | 373 | else if (!mips_hpt_frequency && !mips_timer_state) { |
| 562 | } else if (!mips_hpt_frequency && !mips_timer_state) { | ||
| 563 | /* A high precision timer of unknown frequency. */ | 374 | /* A high precision timer of unknown frequency. */ |
| 564 | if (!mips_hpt_read) { | 375 | if (!mips_hpt_read) |
| 565 | /* No external high precision timer -- use R4k. */ | 376 | /* No external high precision timer -- use R4k. */ |
| 566 | mips_hpt_read = c0_hpt_read; | 377 | mips_hpt_read = c0_hpt_read; |
| 567 | mips_hpt_init = c0_hpt_init; | ||
| 568 | } | ||
| 569 | |||
| 570 | if (cpu_has_mips32r1 || cpu_has_mips32r2 || | ||
| 571 | (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || | ||
| 572 | (current_cpu_data.isa_level == MIPS_CPU_ISA_II)) | ||
| 573 | /* | ||
| 574 | * We need to calibrate the counter but we don't have | ||
| 575 | * 64-bit division. | ||
| 576 | */ | ||
| 577 | do_gettimeoffset = calibrate_div32_gettimeoffset; | ||
| 578 | else | ||
| 579 | /* | ||
| 580 | * We need to calibrate the counter but we *do* have | ||
| 581 | * 64-bit division. | ||
| 582 | */ | ||
| 583 | do_gettimeoffset = calibrate_div64_gettimeoffset; | ||
| 584 | } else { | 378 | } else { |
| 585 | /* We know counter frequency. Or we can get it. */ | 379 | /* We know counter frequency. Or we can get it. */ |
| 586 | if (!mips_hpt_read) { | 380 | if (!mips_hpt_read) { |
| 587 | /* No external high precision timer -- use R4k. */ | 381 | /* No external high precision timer -- use R4k. */ |
| 588 | mips_hpt_read = c0_hpt_read; | 382 | mips_hpt_read = c0_hpt_read; |
| 589 | 383 | ||
| 590 | if (mips_timer_state) | 384 | if (!mips_timer_state) { |
| 591 | mips_hpt_init = c0_hpt_init; | ||
| 592 | else { | ||
| 593 | /* No external timer interrupt -- use R4k. */ | 385 | /* No external timer interrupt -- use R4k. */ |
| 594 | mips_hpt_init = c0_hpt_timer_init; | 386 | mips_hpt_init = c0_hpt_timer_init; |
| 595 | mips_timer_ack = c0_timer_ack; | 387 | mips_timer_ack = c0_timer_ack; |
| @@ -598,16 +390,9 @@ void __init time_init(void) | |||
| 598 | if (!mips_hpt_frequency) | 390 | if (!mips_hpt_frequency) |
| 599 | mips_hpt_frequency = calibrate_hpt(); | 391 | mips_hpt_frequency = calibrate_hpt(); |
| 600 | 392 | ||
| 601 | do_gettimeoffset = fixed_rate_gettimeoffset; | ||
| 602 | |||
| 603 | /* Calculate cache parameters. */ | 393 | /* Calculate cache parameters. */ |
| 604 | cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ; | 394 | cycles_per_jiffy = (mips_hpt_frequency + HZ / 2) / HZ; |
| 605 | 395 | ||
| 606 | /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */ | ||
| 607 | do_div64_32(sll32_usecs_per_cycle, | ||
| 608 | 1000000, mips_hpt_frequency / 2, | ||
| 609 | mips_hpt_frequency); | ||
| 610 | |||
| 611 | /* Report the high precision timer rate for a reference. */ | 396 | /* Report the high precision timer rate for a reference. */ |
| 612 | printk("Using %u.%03u MHz high precision timer.\n", | 397 | printk("Using %u.%03u MHz high precision timer.\n", |
| 613 | ((mips_hpt_frequency + 500) / 1000) / 1000, | 398 | ((mips_hpt_frequency + 500) / 1000) / 1000, |
| @@ -619,7 +404,7 @@ void __init time_init(void) | |||
| 619 | mips_timer_ack = null_timer_ack; | 404 | mips_timer_ack = null_timer_ack; |
| 620 | 405 | ||
| 621 | /* This sets up the high precision timer for the first interrupt. */ | 406 | /* This sets up the high precision timer for the first interrupt. */ |
| 622 | mips_hpt_init(mips_hpt_read()); | 407 | mips_hpt_init(); |
| 623 | 408 | ||
| 624 | /* | 409 | /* |
| 625 | * Call board specific timer interrupt setup. | 410 | * Call board specific timer interrupt setup. |
| @@ -633,6 +418,8 @@ void __init time_init(void) | |||
| 633 | * is not invoked accidentally. | 418 | * is not invoked accidentally. |
| 634 | */ | 419 | */ |
| 635 | plat_timer_setup(&timer_irqaction); | 420 | plat_timer_setup(&timer_irqaction); |
| 421 | |||
| 422 | init_mips_clocksource(); | ||
| 636 | } | 423 | } |
| 637 | 424 | ||
| 638 | #define FEBRUARY 2 | 425 | #define FEBRUARY 2 |
