aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/au1000/common/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/au1000/common/time.c')
-rw-r--r--arch/mips/au1000/common/time.c106
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 */
53int no_au1xxx_32khz; 53int no_au1xxx_32khz;
54extern int allow_au1k_wait; /* default off for CP0 Counter */ 54extern int allow_au1k_wait; /* default off for CP0 Counter */
55 55
56/* Cycle counter value at the previous timer interrupt.. */
57static 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;
82void mips_timer_interrupt(void) 79void 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 */
232unsigned long cal_r4koff(void) 224unsigned 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
308static unsigned long
309div64_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
316static 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
368static 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
386void __init plat_timer_setup(struct irqaction *irq) 293void __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