diff options
Diffstat (limited to 'arch/mips/au1000/common/time.c')
-rw-r--r-- | arch/mips/au1000/common/time.c | 106 |
1 files changed, 2 insertions, 104 deletions
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 94f09194d63d..fa1c62f05515 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c | |||
@@ -53,9 +53,6 @@ static unsigned long r4k_cur; /* What counter should be at next timer irq */ | |||
53 | int no_au1xxx_32khz; | 53 | int no_au1xxx_32khz; |
54 | extern int allow_au1k_wait; /* default off for CP0 Counter */ | 54 | extern int allow_au1k_wait; /* default off for CP0 Counter */ |
55 | 55 | ||
56 | /* Cycle counter value at the previous timer interrupt.. */ | ||
57 | static unsigned int timerhi = 0, timerlo = 0; | ||
58 | |||
59 | #ifdef CONFIG_PM | 56 | #ifdef CONFIG_PM |
60 | #if HZ < 100 || HZ > 1000 | 57 | #if HZ < 100 || HZ > 1000 |
61 | #error "unsupported HZ value! Must be in [100,1000]" | 58 | #error "unsupported HZ value! Must be in [100,1000]" |
@@ -82,7 +79,6 @@ unsigned long wtimer; | |||
82 | void mips_timer_interrupt(void) | 79 | void mips_timer_interrupt(void) |
83 | { | 80 | { |
84 | int irq = 63; | 81 | int irq = 63; |
85 | unsigned long count; | ||
86 | 82 | ||
87 | irq_enter(); | 83 | irq_enter(); |
88 | kstat_this_cpu.irqs[irq]++; | 84 | kstat_this_cpu.irqs[irq]++; |
@@ -91,10 +87,6 @@ void mips_timer_interrupt(void) | |||
91 | goto null; | 87 | goto null; |
92 | 88 | ||
93 | do { | 89 | do { |
94 | count = read_c0_count(); | ||
95 | timerhi += (count < timerlo); /* Wrap around */ | ||
96 | timerlo = count; | ||
97 | |||
98 | kstat_this_cpu.irqs[irq]++; | 90 | kstat_this_cpu.irqs[irq]++; |
99 | do_timer(1); | 91 | do_timer(1); |
100 | #ifndef CONFIG_SMP | 92 | #ifndef CONFIG_SMP |
@@ -231,7 +223,6 @@ wakeup_counter0_set(int ticks) | |||
231 | */ | 223 | */ |
232 | unsigned long cal_r4koff(void) | 224 | unsigned long cal_r4koff(void) |
233 | { | 225 | { |
234 | unsigned long count; | ||
235 | unsigned long cpu_speed; | 226 | unsigned long cpu_speed; |
236 | unsigned long flags; | 227 | unsigned long flags; |
237 | unsigned long counter; | 228 | unsigned long counter; |
@@ -258,7 +249,7 @@ unsigned long cal_r4koff(void) | |||
258 | 249 | ||
259 | #if defined(CONFIG_AU1000_USE32K) | 250 | #if defined(CONFIG_AU1000_USE32K) |
260 | { | 251 | { |
261 | unsigned long start, end; | 252 | unsigned long start, end, count; |
262 | 253 | ||
263 | start = au_readl(SYS_RTCREAD); | 254 | start = au_readl(SYS_RTCREAD); |
264 | start += 2; | 255 | start += 2; |
@@ -282,7 +273,6 @@ unsigned long cal_r4koff(void) | |||
282 | #else | 273 | #else |
283 | cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * | 274 | cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * |
284 | AU1000_SRC_CLK; | 275 | AU1000_SRC_CLK; |
285 | count = cpu_speed / 2; | ||
286 | #endif | 276 | #endif |
287 | } | 277 | } |
288 | else { | 278 | else { |
@@ -291,98 +281,15 @@ unsigned long cal_r4koff(void) | |||
291 | * NOTE: some old silicon doesn't allow reading the PLL. | 281 | * NOTE: some old silicon doesn't allow reading the PLL. |
292 | */ | 282 | */ |
293 | cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; | 283 | cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; |
294 | count = cpu_speed / 2; | ||
295 | no_au1xxx_32khz = 1; | 284 | no_au1xxx_32khz = 1; |
296 | } | 285 | } |
297 | mips_hpt_frequency = count; | 286 | mips_hpt_frequency = cpu_speed; |
298 | // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) | 287 | // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) |
299 | set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); | 288 | set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); |
300 | spin_unlock_irqrestore(&time_lock, flags); | 289 | spin_unlock_irqrestore(&time_lock, flags); |
301 | return (cpu_speed / HZ); | 290 | return (cpu_speed / HZ); |
302 | } | 291 | } |
303 | 292 | ||
304 | /* This is for machines which generate the exact clock. */ | ||
305 | #define USECS_PER_JIFFY (1000000/HZ) | ||
306 | #define USECS_PER_JIFFY_FRAC (0x100000000LL*1000000/HZ&0xffffffff) | ||
307 | |||
308 | static unsigned long | ||
309 | div64_32(unsigned long v1, unsigned long v2, unsigned long v3) | ||
310 | { | ||
311 | unsigned long r0; | ||
312 | do_div64_32(r0, v1, v2, v3); | ||
313 | return r0; | ||
314 | } | ||
315 | |||
316 | static unsigned long do_fast_cp0_gettimeoffset(void) | ||
317 | { | ||
318 | u32 count; | ||
319 | unsigned long res, tmp; | ||
320 | unsigned long r0; | ||
321 | |||
322 | /* Last jiffy when do_fast_gettimeoffset() was called. */ | ||
323 | static unsigned long last_jiffies=0; | ||
324 | unsigned long quotient; | ||
325 | |||
326 | /* | ||
327 | * Cached "1/(clocks per usec)*2^32" value. | ||
328 | * It has to be recalculated once each jiffy. | ||
329 | */ | ||
330 | static unsigned long cached_quotient=0; | ||
331 | |||
332 | tmp = jiffies; | ||
333 | |||
334 | quotient = cached_quotient; | ||
335 | |||
336 | if (tmp && last_jiffies != tmp) { | ||
337 | last_jiffies = tmp; | ||
338 | if (last_jiffies != 0) { | ||
339 | r0 = div64_32(timerhi, timerlo, tmp); | ||
340 | quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0); | ||
341 | cached_quotient = quotient; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | /* Get last timer tick in absolute kernel time */ | ||
346 | count = read_c0_count(); | ||
347 | |||
348 | /* .. relative to previous jiffy (32 bits is enough) */ | ||
349 | count -= timerlo; | ||
350 | |||
351 | __asm__("multu\t%1,%2\n\t" | ||
352 | "mfhi\t%0" | ||
353 | : "=r" (res) | ||
354 | : "r" (count), "r" (quotient) | ||
355 | : "hi", "lo", GCC_REG_ACCUM); | ||
356 | |||
357 | /* | ||
358 | * Due to possible jiffies inconsistencies, we need to check | ||
359 | * the result so that we'll get a timer that is monotonic. | ||
360 | */ | ||
361 | if (res >= USECS_PER_JIFFY) | ||
362 | res = USECS_PER_JIFFY-1; | ||
363 | |||
364 | return res; | ||
365 | } | ||
366 | |||
367 | #ifdef CONFIG_PM | ||
368 | static unsigned long do_fast_pm_gettimeoffset(void) | ||
369 | { | ||
370 | unsigned long pc0; | ||
371 | unsigned long offset; | ||
372 | |||
373 | pc0 = au_readl(SYS_TOYREAD); | ||
374 | au_sync(); | ||
375 | offset = pc0 - last_pc0; | ||
376 | if (offset > 2*MATCH20_INC) { | ||
377 | printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", | ||
378 | (unsigned)offset, (unsigned)last_pc0, | ||
379 | (unsigned)last_match20, (unsigned)pc0); | ||
380 | } | ||
381 | offset = (unsigned long)((offset * 305) / 10); | ||
382 | return offset; | ||
383 | } | ||
384 | #endif | ||
385 | |||
386 | void __init plat_timer_setup(struct irqaction *irq) | 293 | void __init plat_timer_setup(struct irqaction *irq) |
387 | { | 294 | { |
388 | unsigned int est_freq; | 295 | unsigned int est_freq; |
@@ -420,7 +327,6 @@ void __init plat_timer_setup(struct irqaction *irq) | |||
420 | unsigned int c0_status; | 327 | unsigned int c0_status; |
421 | 328 | ||
422 | printk("WARNING: no 32KHz clock found.\n"); | 329 | printk("WARNING: no 32KHz clock found.\n"); |
423 | do_gettimeoffset = do_fast_cp0_gettimeoffset; | ||
424 | 330 | ||
425 | /* Ensure we get CPO_COUNTER interrupts. | 331 | /* Ensure we get CPO_COUNTER interrupts. |
426 | */ | 332 | */ |
@@ -445,19 +351,11 @@ void __init plat_timer_setup(struct irqaction *irq) | |||
445 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); | 351 | while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); |
446 | startup_match20_interrupt(counter0_irq); | 352 | startup_match20_interrupt(counter0_irq); |
447 | 353 | ||
448 | do_gettimeoffset = do_fast_pm_gettimeoffset; | ||
449 | |||
450 | /* We can use the real 'wait' instruction. | 354 | /* We can use the real 'wait' instruction. |
451 | */ | 355 | */ |
452 | allow_au1k_wait = 1; | 356 | allow_au1k_wait = 1; |
453 | } | 357 | } |
454 | 358 | ||
455 | #else | ||
456 | /* We have to do this here instead of in timer_init because | ||
457 | * the generic code in arch/mips/kernel/time.c will write | ||
458 | * over our function pointer. | ||
459 | */ | ||
460 | do_gettimeoffset = do_fast_cp0_gettimeoffset; | ||
461 | #endif | 359 | #endif |
462 | } | 360 | } |
463 | 361 | ||