Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[linux-2.6] / arch / mips / kernel / time.c
1 /*
2  * Copyright 2001 MontaVista Software Inc.
3  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4  * Copyright (c) 2003, 2004  Maciej W. Rozycki
5  *
6  * Common time service routines for MIPS machines.
7  *
8  * This program is free software; you can redistribute  it and/or modify it
9  * under  the terms of  the GNU General  Public License as published by the
10  * Free Software Foundation;  either version 2 of the  License, or (at your
11  * option) any later version.
12  */
13 #include <linux/bug.h>
14 #include <linux/clockchips.h>
15 #include <linux/types.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/sched.h>
19 #include <linux/param.h>
20 #include <linux/time.h>
21 #include <linux/timex.h>
22 #include <linux/smp.h>
23 #include <linux/spinlock.h>
24 #include <linux/module.h>
25
26 #include <asm/cpu-features.h>
27 #include <asm/div64.h>
28 #include <asm/smtc_ipi.h>
29 #include <asm/time.h>
30
31 /*
32  * forward reference
33  */
34 DEFINE_SPINLOCK(rtc_lock);
35 EXPORT_SYMBOL(rtc_lock);
36
37 int __weak rtc_mips_set_time(unsigned long sec)
38 {
39         return 0;
40 }
41 EXPORT_SYMBOL(rtc_mips_set_time);
42
43 int __weak rtc_mips_set_mmss(unsigned long nowtime)
44 {
45         return rtc_mips_set_time(nowtime);
46 }
47
48 int update_persistent_clock(struct timespec now)
49 {
50         return rtc_mips_set_mmss(now.tv_sec);
51 }
52
53 /*
54  * High precision timer functions for a R4k-compatible timer.
55  */
56 static cycle_t c0_hpt_read(void)
57 {
58         return read_c0_count();
59 }
60
61 int (*mips_timer_state)(void);
62
63 int null_perf_irq(void)
64 {
65         return 0;
66 }
67
68 EXPORT_SYMBOL(null_perf_irq);
69
70 int (*perf_irq)(void) = null_perf_irq;
71
72 EXPORT_SYMBOL(perf_irq);
73
74 /*
75  * time_init() - it does the following things.
76  *
77  * 1) plat_time_init() -
78  *      a) (optional) set up RTC routines,
79  *      b) (optional) calibrate and set the mips_hpt_frequency
80  *          (only needed if you intended to use cpu counter as timer interrupt
81  *           source)
82  * 2) calculate a couple of cached variables for later usage
83  */
84
85 unsigned int mips_hpt_frequency;
86
87 static struct clocksource clocksource_mips = {
88         .name           = "MIPS",
89         .read           = c0_hpt_read,
90         .mask           = CLOCKSOURCE_MASK(32),
91         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
92 };
93
94 static unsigned int __init calibrate_hpt(void)
95 {
96         cycle_t frequency, hpt_start, hpt_end, hpt_count, hz;
97
98         const int loops = HZ / 10;
99         int log_2_loops = 0;
100         int i;
101
102         /*
103          * We want to calibrate for 0.1s, but to avoid a 64-bit
104          * division we round the number of loops up to the nearest
105          * power of 2.
106          */
107         while (loops > 1 << log_2_loops)
108                 log_2_loops++;
109         i = 1 << log_2_loops;
110
111         /*
112          * Wait for a rising edge of the timer interrupt.
113          */
114         while (mips_timer_state());
115         while (!mips_timer_state());
116
117         /*
118          * Now see how many high precision timer ticks happen
119          * during the calculated number of periods between timer
120          * interrupts.
121          */
122         hpt_start = clocksource_mips.read();
123         do {
124                 while (mips_timer_state());
125                 while (!mips_timer_state());
126         } while (--i);
127         hpt_end = clocksource_mips.read();
128
129         hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask;
130         hz = HZ;
131         frequency = hpt_count * hz;
132
133         return frequency >> log_2_loops;
134 }
135
136 void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
137 {
138         u64 temp;
139         u32 shift;
140
141         /* Find a shift value */
142         for (shift = 32; shift > 0; shift--) {
143                 temp = (u64) NSEC_PER_SEC << shift;
144                 do_div(temp, clock);
145                 if ((temp >> 32) == 0)
146                         break;
147         }
148         cs->shift = shift;
149         cs->mult = (u32) temp;
150 }
151
152 void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
153         unsigned int clock)
154 {
155         u64 temp;
156         u32 shift;
157
158         /* Find a shift value */
159         for (shift = 32; shift > 0; shift--) {
160                 temp = (u64) clock << shift;
161                 do_div(temp, NSEC_PER_SEC);
162                 if ((temp >> 32) == 0)
163                         break;
164         }
165         cd->shift = shift;
166         cd->mult = (u32) temp;
167 }
168
169 static void __init init_mips_clocksource(void)
170 {
171         /* Calclate a somewhat reasonable rating value */
172         clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
173
174         clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
175
176         clocksource_register(&clocksource_mips);
177 }
178
179 void __init __weak plat_time_init(void)
180 {
181 }
182
183 /*
184  * This function exists in order to cause an error due to a duplicate
185  * definition if platform code should have its own implementation.  The hook
186  * to use instead is plat_time_init.  plat_time_init does not receive the
187  * irqaction pointer argument anymore.  This is because any function which
188  * initializes an interrupt timer now takes care of its own request_irq rsp.
189  * setup_irq calls and each clock_event_device should use its own
190  * struct irqrequest.
191  */
192 void __init plat_timer_setup(void)
193 {
194         BUG();
195 }
196
197 void __init time_init(void)
198 {
199         plat_time_init();
200
201         if (cpu_has_counter && (mips_hpt_frequency || mips_timer_state)) {
202                 /* We know counter frequency.  Or we can get it.  */
203                 if (!mips_hpt_frequency)
204                         mips_hpt_frequency = calibrate_hpt();
205
206                 /* Report the high precision timer rate for a reference.  */
207                 printk("Using %u.%03u MHz high precision timer.\n",
208                        ((mips_hpt_frequency + 500) / 1000) / 1000,
209                        ((mips_hpt_frequency + 500) / 1000) % 1000);
210                 init_mips_clocksource();
211         }
212
213         mips_clockevent_init();
214 }