aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/time.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-01-17 01:14:17 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-17 02:15:28 -0500
commit36ddf31b689a8c11d424e43565d2aa440b77bbf4 (patch)
tree8cc1e98a496811126c41a9ec31f894c64bae13df /arch/sh/kernel/time.c
parentb66c1a3919abb40f9bd8fb92a0d9fd77eb899c54 (diff)
[PATCH] sh: Simplistic clock framework
This adds a relatively simplistic clock framework for sh. The initial goal behind this is to clean up the arch/sh/kernel/time.c mess and to get the CPU subtype-specific frequency setting and calculation code moved somewhere more sensible. This only deals with the core clocks at the moment, though it's trivial for other drivers to define their own clocks as desired. Signed-off-by: Paul Mundt <lethal@linux-sh.org> Cc: john stultz <johnstul@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/sh/kernel/time.c')
-rw-r--r--arch/sh/kernel/time.c518
1 files changed, 32 insertions, 486 deletions
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 671b876416bf..314a275c04e0 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka 4 * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> 5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
6 * Copyright (C) 2002, 2003, 2004 Paul Mundt 6 * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
7 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> 7 * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org>
8 * 8 *
9 * Some code taken from i386 version. 9 * Some code taken from i386 version.
@@ -11,50 +11,21 @@
11 */ 11 */
12 12
13#include <linux/config.h> 13#include <linux/config.h>
14#include <linux/errno.h>
15#include <linux/module.h>
16#include <linux/sched.h>
17#include <linux/kernel.h> 14#include <linux/kernel.h>
18#include <linux/param.h> 15#include <linux/module.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/interrupt.h>
22#include <linux/time.h>
23#include <linux/delay.h>
24#include <linux/init.h> 16#include <linux/init.h>
25#include <linux/smp.h>
26#include <linux/profile.h> 17#include <linux/profile.h>
27 18#include <asm/clock.h>
28#include <asm/processor.h>
29#include <asm/uaccess.h>
30#include <asm/io.h>
31#include <asm/irq.h>
32#include <asm/delay.h>
33#include <asm/machvec.h>
34#include <asm/rtc.h> 19#include <asm/rtc.h>
35#include <asm/freq.h> 20#include <asm/timer.h>
36#include <asm/cpu/timer.h>
37#ifdef CONFIG_SH_KGDB
38#include <asm/kgdb.h> 21#include <asm/kgdb.h>
39#endif
40
41#include <linux/timex.h>
42#include <linux/irq.h>
43
44#define TMU_TOCR_INIT 0x00
45#define TMU0_TCR_INIT 0x0020
46#define TMU_TSTR_INIT 1
47
48#define TMU0_TCR_CALIB 0x0000
49
50#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
51#define CLOCKGEN_MEMCLKCR 0xbb040038
52#define MEMCLKCR_RATIO_MASK 0x7
53#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
54 22
55extern unsigned long wall_jiffies; 23extern unsigned long wall_jiffies;
56#define TICK_SIZE (tick_nsec / 1000) 24struct sys_timer *sys_timer;
57DEFINE_SPINLOCK(tmu0_lock); 25
26/* Move this somewhere more sensible.. */
27DEFINE_SPINLOCK(rtc_lock);
28EXPORT_SYMBOL(rtc_lock);
58 29
59/* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want 30/* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want
60 * these routines anywhere... */ 31 * these routines anywhere... */
@@ -66,98 +37,14 @@ void (*rtc_get_time)(struct timespec *);
66int (*rtc_set_time)(const time_t); 37int (*rtc_set_time)(const time_t);
67#endif 38#endif
68 39
69#if defined(CONFIG_CPU_SUBTYPE_SH7300)
70static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 };
71#endif
72#if defined(CONFIG_CPU_SH3)
73static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
74static int stc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
75#define bfc_divisors stc_multipliers
76#define bfc_values stc_values
77static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 };
78static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 };
79static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
80static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 };
81#elif defined(CONFIG_CPU_SH4)
82#if defined(CONFIG_CPU_SUBTYPE_SH73180)
83static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 };
84static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
85#define bfc_divisors ifc_divisors /* Same */
86#define bfc_values ifc_values
87#define pfc_divisors ifc_divisors /* Same */
88#define pfc_values ifc_values
89#else
90static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
91static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 };
92#define bfc_divisors ifc_divisors /* Same */
93#define bfc_values ifc_values
94static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
95static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 };
96#endif
97#else
98#error "Unknown ifc/bfc/pfc/stc values for this processor"
99#endif
100
101/* 40/*
102 * Scheduler clock - returns current time in nanosec units. 41 * Scheduler clock - returns current time in nanosec units.
103 */ 42 */
104unsigned long long sched_clock(void) 43unsigned long long __attribute__ ((weak)) sched_clock(void)
105{ 44{
106 return (unsigned long long)jiffies * (1000000000 / HZ); 45 return (unsigned long long)jiffies * (1000000000 / HZ);
107} 46}
108 47
109static unsigned long do_gettimeoffset(void)
110{
111 int count;
112 unsigned long flags;
113
114 static int count_p = 0x7fffffff; /* for the first call after boot */
115 static unsigned long jiffies_p = 0;
116
117 /*
118 * cache volatile jiffies temporarily; we have IRQs turned off.
119 */
120 unsigned long jiffies_t;
121
122 spin_lock_irqsave(&tmu0_lock, flags);
123 /* timer count may underflow right here */
124 count = ctrl_inl(TMU0_TCNT); /* read the latched count */
125
126 jiffies_t = jiffies;
127
128 /*
129 * avoiding timer inconsistencies (they are rare, but they happen)...
130 * there is one kind of problem that must be avoided here:
131 * 1. the timer counter underflows
132 */
133
134 if( jiffies_t == jiffies_p ) {
135 if( count > count_p ) {
136 /* the nutcase */
137
138 if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */
139 /*
140 * We cannot detect lost timer interrupts ...
141 * well, that's why we call them lost, don't we? :)
142 * [hmm, on the Pentium and Alpha we can ... sort of]
143 */
144 count -= LATCH;
145 } else {
146 printk("do_slow_gettimeoffset(): hardware timer problem?\n");
147 }
148 }
149 } else
150 jiffies_p = jiffies_t;
151
152 count_p = count;
153 spin_unlock_irqrestore(&tmu0_lock, flags);
154
155 count = ((LATCH-1) - count) * TICK_SIZE;
156 count = (count + LATCH/2) / LATCH;
157
158 return count;
159}
160
161void do_gettimeofday(struct timeval *tv) 48void do_gettimeofday(struct timeval *tv)
162{ 49{
163 unsigned long seq; 50 unsigned long seq;
@@ -166,7 +53,7 @@ void do_gettimeofday(struct timeval *tv)
166 53
167 do { 54 do {
168 seq = read_seqbegin(&xtime_lock); 55 seq = read_seqbegin(&xtime_lock);
169 usec = do_gettimeoffset(); 56 usec = get_timer_offset();
170 57
171 lost = jiffies - wall_jiffies; 58 lost = jiffies - wall_jiffies;
172 if (lost) 59 if (lost)
@@ -202,7 +89,7 @@ int do_settimeofday(struct timespec *tv)
202 * wall time. Discover what correction gettimeofday() would have 89 * wall time. Discover what correction gettimeofday() would have
203 * made, and then undo it! 90 * made, and then undo it!
204 */ 91 */
205 nsec -= 1000 * (do_gettimeoffset() + 92 nsec -= 1000 * (get_timer_offset() +
206 (jiffies - wall_jiffies) * (1000000 / HZ)); 93 (jiffies - wall_jiffies) * (1000000 / HZ));
207 94
208 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 95 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
@@ -224,10 +111,10 @@ EXPORT_SYMBOL(do_settimeofday);
224static long last_rtc_update; 111static long last_rtc_update;
225 112
226/* 113/*
227 * timer_interrupt() needs to keep up the real-time clock, 114 * handle_timer_tick() needs to keep up the real-time clock,
228 * as well as call the "do_timer()" routine every clocktick 115 * as well as call the "do_timer()" routine every clocktick
229 */ 116 */
230static inline void do_timer_interrupt(int irq, struct pt_regs *regs) 117void handle_timer_tick(struct pt_regs *regs)
231{ 118{
232 do_timer(regs); 119 do_timer(regs);
233#ifndef CONFIG_SMP 120#ifndef CONFIG_SMP
@@ -252,337 +139,35 @@ static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
252 if (rtc_set_time(xtime.tv_sec) == 0) 139 if (rtc_set_time(xtime.tv_sec) == 0)
253 last_rtc_update = xtime.tv_sec; 140 last_rtc_update = xtime.tv_sec;
254 else 141 else
255 last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ 142 /* do it again in 60s */
143 last_rtc_update = xtime.tv_sec - 600;
256 } 144 }
257} 145}
258 146
259/* 147static struct sysdev_class timer_sysclass = {
260 * This is the same as the above, except we _also_ save the current 148 set_kset_name("timer"),
261 * Time Stamp Counter value at the time of the timer interrupt, so that
262 * we later on can estimate the time of day more exactly.
263 */
264static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
265{
266 unsigned long timer_status;
267
268 /* Clear UNF bit */
269 timer_status = ctrl_inw(TMU0_TCR);
270 timer_status &= ~0x100;
271 ctrl_outw(timer_status, TMU0_TCR);
272
273 /*
274 * Here we are in the timer irq handler. We just have irqs locally
275 * disabled but we don't know if the timer_bh is running on the other
276 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
277 * the irq version of write_lock because as just said we have irq
278 * locally disabled. -arca
279 */
280 write_seqlock(&xtime_lock);
281 do_timer_interrupt(irq, regs);
282 write_sequnlock(&xtime_lock);
283
284 return IRQ_HANDLED;
285}
286
287/*
288 * Hah! We'll see if this works (switching from usecs to nsecs).
289 */
290static unsigned int __init get_timer_frequency(void)
291{
292 u32 freq;
293 struct timespec ts1, ts2;
294 unsigned long diff_nsec;
295 unsigned long factor;
296
297 /* Setup the timer: We don't want to generate interrupts, just
298 * have it count down at its natural rate.
299 */
300 ctrl_outb(0, TMU_TSTR);
301#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
302 ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
303#endif
304 ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR);
305 ctrl_outl(0xffffffff, TMU0_TCOR);
306 ctrl_outl(0xffffffff, TMU0_TCNT);
307
308 rtc_get_time(&ts2);
309
310 do {
311 rtc_get_time(&ts1);
312 } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
313
314 /* actually start the timer */
315 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
316
317 do {
318 rtc_get_time(&ts2);
319 } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
320
321 freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
322 if (ts2.tv_nsec < ts1.tv_nsec) {
323 ts2.tv_nsec += 1000000000;
324 ts2.tv_sec--;
325 }
326
327 diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec);
328
329 /* this should work well if the RTC has a precision of n Hz, where
330 * n is an integer. I don't think we have to worry about the other
331 * cases. */
332 factor = (1000000000 + diff_nsec/2) / diff_nsec;
333
334 if (factor * diff_nsec > 1100000000 ||
335 factor * diff_nsec < 900000000)
336 panic("weird RTC (diff_nsec %ld)", diff_nsec);
337
338 return freq * factor;
339}
340
341void (*board_time_init)(void);
342void (*board_timer_setup)(struct irqaction *irq);
343
344static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ;
345
346static int __init sh_pclk_setup(char *str)
347{
348 unsigned int freq;
349
350 if (get_option(&str, &freq))
351 sh_pclk_freq = freq;
352
353 return 1;
354}
355__setup("sh_pclk=", sh_pclk_setup);
356
357static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL};
358
359void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc)
360{
361 unsigned int frqcr = ctrl_inw(FRQCR);
362
363#if defined(CONFIG_CPU_SH3)
364#if defined(CONFIG_CPU_SUBTYPE_SH7300)
365 *ifc = md_table[((frqcr & 0x0070) >> 4)];
366 *bfc = md_table[((frqcr & 0x0700) >> 8)];
367 *pfc = md_table[frqcr & 0x0007];
368#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
369 *bfc = stc_multipliers[(frqcr & 0x0300) >> 8];
370 *ifc = ifc_divisors[(frqcr & 0x0030) >> 4];
371 *pfc = pfc_divisors[frqcr & 0x0003];
372#else
373 unsigned int tmp;
374
375 tmp = (frqcr & 0x8000) >> 13;
376 tmp |= (frqcr & 0x0030) >> 4;
377 *bfc = stc_multipliers[tmp];
378 tmp = (frqcr & 0x4000) >> 12;
379 tmp |= (frqcr & 0x000c) >> 2;
380 *ifc = ifc_divisors[tmp];
381 tmp = (frqcr & 0x2000) >> 11;
382 tmp |= frqcr & 0x0003;
383 *pfc = pfc_divisors[tmp];
384#endif
385#elif defined(CONFIG_CPU_SH4)
386#if defined(CONFIG_CPU_SUBTYPE_SH73180)
387 *ifc = ifc_divisors[(frqcr>> 20) & 0x0007];
388 *bfc = bfc_divisors[(frqcr>> 12) & 0x0007];
389 *pfc = pfc_divisors[frqcr & 0x0007];
390#else
391 *ifc = ifc_divisors[(frqcr >> 6) & 0x0007];
392 *bfc = bfc_divisors[(frqcr >> 3) & 0x0007];
393 *pfc = pfc_divisors[frqcr & 0x0007];
394#endif
395#endif
396}
397
398/*
399 * This bit of ugliness builds up accessor routines to get at both
400 * the divisors and the physical values.
401 */
402#define _FREQ_TABLE(x) \
403 unsigned int get_##x##_divisor(unsigned int value) \
404 { return x##_divisors[value]; } \
405 \
406 unsigned int get_##x##_value(unsigned int divisor) \
407 { return x##_values[(divisor - 1)]; }
408
409_FREQ_TABLE(ifc);
410_FREQ_TABLE(bfc);
411_FREQ_TABLE(pfc);
412
413#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
414
415/*
416 * The ST40 divisors are totally different so we set the cpu data
417 * clocks using a different algorithm
418 *
419 * I've just plugged this from the 2.4 code
420 * - Alex Bennee <kernel-hacker@bennee.com>
421 */
422#define CCN_PVR_CHIP_SHIFT 24
423#define CCN_PVR_CHIP_MASK 0xff
424#define CCN_PVR_CHIP_ST40STB1 0x4
425
426
427struct frqcr_data {
428 unsigned short frqcr;
429
430 struct {
431 unsigned char multiplier;
432 unsigned char divisor;
433 } factor[3];
434};
435
436static struct frqcr_data st40_frqcr_table[] = {
437 { 0x000, {{1,1}, {1,1}, {1,2}}},
438 { 0x002, {{1,1}, {1,1}, {1,4}}},
439 { 0x004, {{1,1}, {1,1}, {1,8}}},
440 { 0x008, {{1,1}, {1,2}, {1,2}}},
441 { 0x00A, {{1,1}, {1,2}, {1,4}}},
442 { 0x00C, {{1,1}, {1,2}, {1,8}}},
443 { 0x011, {{1,1}, {2,3}, {1,6}}},
444 { 0x013, {{1,1}, {2,3}, {1,3}}},
445 { 0x01A, {{1,1}, {1,2}, {1,4}}},
446 { 0x01C, {{1,1}, {1,2}, {1,8}}},
447 { 0x023, {{1,1}, {2,3}, {1,3}}},
448 { 0x02C, {{1,1}, {1,2}, {1,8}}},
449 { 0x048, {{1,2}, {1,2}, {1,4}}},
450 { 0x04A, {{1,2}, {1,2}, {1,6}}},
451 { 0x04C, {{1,2}, {1,2}, {1,8}}},
452 { 0x05A, {{1,2}, {1,3}, {1,6}}},
453 { 0x05C, {{1,2}, {1,3}, {1,6}}},
454 { 0x063, {{1,2}, {1,4}, {1,4}}},
455 { 0x06C, {{1,2}, {1,4}, {1,8}}},
456 { 0x091, {{1,3}, {1,3}, {1,6}}},
457 { 0x093, {{1,3}, {1,3}, {1,6}}},
458 { 0x0A3, {{1,3}, {1,6}, {1,6}}},
459 { 0x0DA, {{1,4}, {1,4}, {1,8}}},
460 { 0x0DC, {{1,4}, {1,4}, {1,8}}},
461 { 0x0EC, {{1,4}, {1,8}, {1,8}}},
462 { 0x123, {{1,4}, {1,4}, {1,8}}},
463 { 0x16C, {{1,4}, {1,8}, {1,8}}},
464}; 149};
465 150
466struct memclk_data { 151static int __init timer_init_sysfs(void)
467 unsigned char multiplier;
468 unsigned char divisor;
469};
470
471static struct memclk_data st40_memclk_table[8] = {
472 {1,1}, // 000
473 {1,2}, // 001
474 {1,3}, // 010
475 {2,3}, // 011
476 {1,4}, // 100
477 {1,6}, // 101
478 {1,8}, // 110
479 {1,8} // 111
480};
481
482static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr)
483{ 152{
484 unsigned int cpu_clock, master_clock, bus_clock, memory_clock; 153 int ret = sysdev_class_register(&timer_sysclass);
485 struct frqcr_data *d; 154 if (ret != 0)
486 int a; 155 return ret;
487 unsigned long memclkcr;
488 struct memclk_data *e;
489 156
490 for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) { 157 sys_timer->dev.cls = &timer_sysclass;
491 d = &st40_frqcr_table[a]; 158 return sysdev_register(&sys_timer->dev);
492 159}
493 if (d->frqcr == (frqcr & 0x1ff))
494 break;
495 }
496 160
497 if (a == ARRAY_SIZE(st40_frqcr_table)) { 161device_initcall(timer_init_sysfs);
498 d = st40_frqcr_table;
499 162
500 printk("ERROR: Unrecognised FRQCR value (0x%x), " 163void (*board_time_init)(void);
501 "using default multipliers\n", frqcr);
502 }
503
504 memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
505 e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
506
507 printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d "
508 "Mem: %d/%d Periph: %d/%d\n",
509 d->factor[0].multiplier, d->factor[0].divisor,
510 d->factor[1].multiplier, d->factor[1].divisor,
511 e->multiplier, e->divisor,
512 d->factor[2].multiplier, d->factor[2].divisor);
513
514 master_clock = module_clock * d->factor[2].divisor
515 / d->factor[2].multiplier;
516 bus_clock = master_clock * d->factor[1].multiplier
517 / d->factor[1].divisor;
518 memory_clock = master_clock * e->multiplier
519 / e->divisor;
520 cpu_clock = master_clock * d->factor[0].multiplier
521 / d->factor[0].divisor;
522
523 current_cpu_data.cpu_clock = cpu_clock;
524 current_cpu_data.master_clock = master_clock;
525 current_cpu_data.bus_clock = bus_clock;
526 current_cpu_data.memory_clock = memory_clock;
527 current_cpu_data.module_clock = module_clock;
528}
529#endif
530 164
531void __init time_init(void) 165void __init time_init(void)
532{ 166{
533 unsigned int timer_freq = 0;
534 unsigned int ifc, pfc, bfc;
535 unsigned long interval;
536#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
537 unsigned long pvr;
538 unsigned short frqcr;
539#endif
540
541 if (board_time_init) 167 if (board_time_init)
542 board_time_init(); 168 board_time_init();
543 169
544 /* 170 clk_init();
545 * If we don't have an RTC (such as with the SH7300), don't attempt to
546 * probe the timer frequency. Rely on an either hardcoded peripheral
547 * clock value, or on the sh_pclk command line option. Note that we
548 * still need to have CONFIG_SH_PCLK_FREQ set in order for things like
549 * CLOCK_TICK_RATE to be sane.
550 */
551 current_cpu_data.module_clock = sh_pclk_freq;
552
553#ifdef CONFIG_SH_PCLK_CALC
554 /* XXX: Switch this over to a more generic test. */
555 {
556 unsigned int freq;
557
558 /*
559 * If we've specified a peripheral clock frequency, and we have
560 * an RTC, compare it against the autodetected value. Complain
561 * if there's a mismatch.
562 */
563 timer_freq = get_timer_frequency();
564 freq = timer_freq * 4;
565
566 if (sh_pclk_freq && (sh_pclk_freq/100*99 > freq || sh_pclk_freq/100*101 < freq)) {
567 printk(KERN_NOTICE "Calculated peripheral clock value "
568 "%d differs from sh_pclk value %d, fixing..\n",
569 freq, sh_pclk_freq);
570 current_cpu_data.module_clock = freq;
571 }
572 }
573#endif
574
575#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
576 /* XXX: Update ST40 code to use board_time_init() */
577 pvr = ctrl_inl(CCN_PVR);
578 frqcr = ctrl_inw(FRQCR);
579 printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr);
580
581 if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1)
582 st40_specific_time_init(current_cpu_data.module_clock, frqcr);
583 else
584#endif
585 get_current_frequency_divisors(&ifc, &bfc, &pfc);
586 171
587 if (rtc_get_time) { 172 if (rtc_get_time) {
588 rtc_get_time(&xtime); 173 rtc_get_time(&xtime);
@@ -594,51 +179,12 @@ void __init time_init(void)
594 set_normalized_timespec(&wall_to_monotonic, 179 set_normalized_timespec(&wall_to_monotonic,
595 -xtime.tv_sec, -xtime.tv_nsec); 180 -xtime.tv_sec, -xtime.tv_nsec);
596 181
597 if (board_timer_setup) {
598 board_timer_setup(&irq0);
599 } else {
600 setup_irq(TIMER_IRQ, &irq0);
601 }
602
603 /* 182 /*
604 * for ST40 chips the current_cpu_data should already be set 183 * Find the timer to use as the system timer, it will be
605 * so not having valid pfc/bfc/ifc shouldn't be a problem 184 * initialized for us.
606 */ 185 */
607 if (!current_cpu_data.master_clock) 186 sys_timer = get_sys_timer();
608 current_cpu_data.master_clock = current_cpu_data.module_clock * pfc; 187 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
609 if (!current_cpu_data.bus_clock)
610 current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc;
611 if (!current_cpu_data.cpu_clock)
612 current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc;
613
614 printk("CPU clock: %d.%02dMHz\n",
615 (current_cpu_data.cpu_clock / 1000000),
616 (current_cpu_data.cpu_clock % 1000000)/10000);
617 printk("Bus clock: %d.%02dMHz\n",
618 (current_cpu_data.bus_clock / 1000000),
619 (current_cpu_data.bus_clock % 1000000)/10000);
620#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
621 printk("Memory clock: %d.%02dMHz\n",
622 (current_cpu_data.memory_clock / 1000000),
623 (current_cpu_data.memory_clock % 1000000)/10000);
624#endif
625 printk("Module clock: %d.%02dMHz\n",
626 (current_cpu_data.module_clock / 1000000),
627 (current_cpu_data.module_clock % 1000000)/10000);
628
629 interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ;
630
631 printk("Interval = %ld\n", interval);
632
633 /* Start TMU0 */
634 ctrl_outb(0, TMU_TSTR);
635#if !defined(CONFIG_CPU_SUBTYPE_SH7300)
636 ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
637#endif
638 ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
639 ctrl_outl(interval, TMU0_TCOR);
640 ctrl_outl(interval, TMU0_TCNT);
641 ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
642 188
643#if defined(CONFIG_SH_KGDB) 189#if defined(CONFIG_SH_KGDB)
644 /* 190 /*