aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2006-10-23 11:21:27 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-10-31 15:13:23 -0500
commit16b7b2ac0148e839da86af8747b6fa4aad43a9b7 (patch)
tree93912ae2e9c64f71a8cca028677fd918b9edf0fa /arch/mips
parent70e46f48cb5933119712ee27945309a4bfc98282 (diff)
[MIPS] Fixup migration to GENERIC_TIME
Since we already moved to GENERIC_TIME, we should implement alternatives of old do_gettimeoffset routines to get sub-jiffies resolution from gettimeofday(). This patch includes: * MIPS clocksource support (based on works by Manish Lachwani). * remove unused gettimeoffset routines and related codes. * remove unised 64bit do_div64_32(). * simplify mips_hpt_init. (no argument needed, __init tag) * simplify c0_hpt_timer_init. (no need to write to c0_count) * remove some hpt_init routines. * mips_hpt_mask variable to specify bitmask of hpt value. * convert jmr3927_do_gettimeoffset to jmr3927_hpt_read. * convert ip27_do_gettimeoffset to ip27_hpt_read. * convert bcm1480_do_gettimeoffset to bcm1480_hpt_read. * simplify sb1250 hpt functions. (no need to subtract and shift) Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/au1000/common/time.c98
-rw-r--r--arch/mips/dec/time.c9
-rw-r--r--arch/mips/jmr3927/rbhma3100/setup.c40
-rw-r--r--arch/mips/kernel/time.c319
-rw-r--r--arch/mips/philips/pnx8550/common/time.c4
-rw-r--r--arch/mips/pmc-sierra/yosemite/smp.c6
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c16
-rw-r--r--arch/mips/sibyte/bcm1480/time.c33
-rw-r--r--arch/mips/sibyte/sb1250/time.c28
9 files changed, 92 insertions, 461 deletions
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index 6768638883ea..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]"
@@ -90,10 +87,6 @@ void mips_timer_interrupt(void)
90 goto null; 87 goto null;
91 88
92 do { 89 do {
93 count = read_c0_count();
94 timerhi += (count < timerlo); /* Wrap around */
95 timerlo = count;
96
97 kstat_this_cpu.irqs[irq]++; 90 kstat_this_cpu.irqs[irq]++;
98 do_timer(1); 91 do_timer(1);
99#ifndef CONFIG_SMP 92#ifndef CONFIG_SMP
@@ -297,88 +290,6 @@ unsigned long cal_r4koff(void)
297 return (cpu_speed / HZ); 290 return (cpu_speed / HZ);
298} 291}
299 292
300/* This is for machines which generate the exact clock. */
301#define USECS_PER_JIFFY (1000000/HZ)
302#define USECS_PER_JIFFY_FRAC (0x100000000LL*1000000/HZ&0xffffffff)
303
304static unsigned long
305div64_32(unsigned long v1, unsigned long v2, unsigned long v3)
306{
307 unsigned long r0;
308 do_div64_32(r0, v1, v2, v3);
309 return r0;
310}
311
312static unsigned long do_fast_cp0_gettimeoffset(void)
313{
314 u32 count;
315 unsigned long res, tmp;
316 unsigned long r0;
317
318 /* Last jiffy when do_fast_gettimeoffset() was called. */
319 static unsigned long last_jiffies=0;
320 unsigned long quotient;
321
322 /*
323 * Cached "1/(clocks per usec)*2^32" value.
324 * It has to be recalculated once each jiffy.
325 */
326 static unsigned long cached_quotient=0;
327
328 tmp = jiffies;
329
330 quotient = cached_quotient;
331
332 if (tmp && last_jiffies != tmp) {
333 last_jiffies = tmp;
334 if (last_jiffies != 0) {
335 r0 = div64_32(timerhi, timerlo, tmp);
336 quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0);
337 cached_quotient = quotient;
338 }
339 }
340
341 /* Get last timer tick in absolute kernel time */
342 count = read_c0_count();
343
344 /* .. relative to previous jiffy (32 bits is enough) */
345 count -= timerlo;
346
347 __asm__("multu\t%1,%2\n\t"
348 "mfhi\t%0"
349 : "=r" (res)
350 : "r" (count), "r" (quotient)
351 : "hi", "lo", GCC_REG_ACCUM);
352
353 /*
354 * Due to possible jiffies inconsistencies, we need to check
355 * the result so that we'll get a timer that is monotonic.
356 */
357 if (res >= USECS_PER_JIFFY)
358 res = USECS_PER_JIFFY-1;
359
360 return res;
361}
362
363#ifdef CONFIG_PM
364static unsigned long do_fast_pm_gettimeoffset(void)
365{
366 unsigned long pc0;
367 unsigned long offset;
368
369 pc0 = au_readl(SYS_TOYREAD);
370 au_sync();
371 offset = pc0 - last_pc0;
372 if (offset > 2*MATCH20_INC) {
373 printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n",
374 (unsigned)offset, (unsigned)last_pc0,
375 (unsigned)last_match20, (unsigned)pc0);
376 }
377 offset = (unsigned long)((offset * 305) / 10);
378 return offset;
379}
380#endif
381
382void __init plat_timer_setup(struct irqaction *irq) 293void __init plat_timer_setup(struct irqaction *irq)
383{ 294{
384 unsigned int est_freq; 295 unsigned int est_freq;
@@ -416,7 +327,6 @@ void __init plat_timer_setup(struct irqaction *irq)
416 unsigned int c0_status; 327 unsigned int c0_status;
417 328
418 printk("WARNING: no 32KHz clock found.\n"); 329 printk("WARNING: no 32KHz clock found.\n");
419 do_gettimeoffset = do_fast_cp0_gettimeoffset;
420 330
421 /* Ensure we get CPO_COUNTER interrupts. 331 /* Ensure we get CPO_COUNTER interrupts.
422 */ 332 */
@@ -441,19 +351,11 @@ void __init plat_timer_setup(struct irqaction *irq)
441 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); 351 while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
442 startup_match20_interrupt(counter0_irq); 352 startup_match20_interrupt(counter0_irq);
443 353
444 do_gettimeoffset = do_fast_pm_gettimeoffset;
445
446 /* We can use the real 'wait' instruction. 354 /* We can use the real 'wait' instruction.
447 */ 355 */
448 allow_au1k_wait = 1; 356 allow_au1k_wait = 1;
449 } 357 }
450 358
451#else
452 /* We have to do this here instead of in timer_init because
453 * the generic code in arch/mips/kernel/time.c will write
454 * over our function pointer.
455 */
456 do_gettimeoffset = do_fast_cp0_gettimeoffset;
457#endif 359#endif
458} 360}
459 361
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index 4cf0c06e2414..69e424e9ab6f 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -160,11 +160,6 @@ static unsigned int dec_ioasic_hpt_read(void)
160 return ioasic_read(IO_REG_FCTR); 160 return ioasic_read(IO_REG_FCTR);
161} 161}
162 162
163static void dec_ioasic_hpt_init(unsigned int count)
164{
165 ioasic_write(IO_REG_FCTR, ioasic_read(IO_REG_FCTR) - count);
166}
167
168 163
169void __init dec_time_init(void) 164void __init dec_time_init(void)
170{ 165{
@@ -174,11 +169,9 @@ void __init dec_time_init(void)
174 mips_timer_state = dec_timer_state; 169 mips_timer_state = dec_timer_state;
175 mips_timer_ack = dec_timer_ack; 170 mips_timer_ack = dec_timer_ack;
176 171
177 if (!cpu_has_counter && IOASIC) { 172 if (!cpu_has_counter && IOASIC)
178 /* For pre-R4k systems we use the I/O ASIC's counter. */ 173 /* For pre-R4k systems we use the I/O ASIC's counter. */
179 mips_hpt_read = dec_ioasic_hpt_read; 174 mips_hpt_read = dec_ioasic_hpt_read;
180 mips_hpt_init = dec_ioasic_hpt_init;
181 }
182 175
183 /* Set up the rate of periodic DS1287 interrupts. */ 176 /* Set up the rate of periodic DS1287 interrupts. */
184 CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A); 177 CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A);
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 025434054ed0..16e5dfe7aa8a 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -170,12 +170,20 @@ static void jmr3927_machine_power_off(void)
170 while (1); 170 while (1);
171} 171}
172 172
173static unsigned int jmr3927_hpt_read(void)
174{
175 /* We assume this function is called xtime_lock held. */
176 return jiffies * (JMR3927_TIMER_CLK / HZ) + jmr3927_tmrptr->trr;
177}
178
173#define USE_RTC_DS1742 179#define USE_RTC_DS1742
174#ifdef USE_RTC_DS1742 180#ifdef USE_RTC_DS1742
175extern void rtc_ds1742_init(unsigned long base); 181extern void rtc_ds1742_init(unsigned long base);
176#endif 182#endif
177static void __init jmr3927_time_init(void) 183static void __init jmr3927_time_init(void)
178{ 184{
185 mips_hpt_read = jmr3927_hpt_read;
186 mips_hpt_frequency = JMR3927_TIMER_CLK;
179#ifdef USE_RTC_DS1742 187#ifdef USE_RTC_DS1742
180 if (jmr3927_have_nvram()) { 188 if (jmr3927_have_nvram()) {
181 rtc_ds1742_init(JMR3927_IOC_NVRAMB_ADDR); 189 rtc_ds1742_init(JMR3927_IOC_NVRAMB_ADDR);
@@ -183,12 +191,8 @@ static void __init jmr3927_time_init(void)
183#endif 191#endif
184} 192}
185 193
186unsigned long jmr3927_do_gettimeoffset(void);
187
188void __init plat_timer_setup(struct irqaction *irq) 194void __init plat_timer_setup(struct irqaction *irq)
189{ 195{
190 do_gettimeoffset = jmr3927_do_gettimeoffset;
191
192 jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ; 196 jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ;
193 jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE; 197 jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE;
194 jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD; 198 jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD;
@@ -200,34 +204,6 @@ void __init plat_timer_setup(struct irqaction *irq)
200 204
201#define USECS_PER_JIFFY (1000000/HZ) 205#define USECS_PER_JIFFY (1000000/HZ)
202 206
203unsigned long jmr3927_do_gettimeoffset(void)
204{
205 unsigned long count;
206 unsigned long res = 0;
207
208 /* MUST read TRR before TISR. */
209 count = jmr3927_tmrptr->trr;
210
211 if (jmr3927_tmrptr->tisr & TXx927_TMTISR_TIIS) {
212 /* timer interrupt is pending. use Max value. */
213 res = USECS_PER_JIFFY - 1;
214 } else {
215 /* convert to usec */
216 /* res = count / (JMR3927_TIMER_CLK / 1000000); */
217 res = (count << 7) / ((JMR3927_TIMER_CLK << 7) / 1000000);
218
219 /*
220 * Due to possible jiffies inconsistencies, we need to check
221 * the result so that we'll get a timer that is monotonic.
222 */
223 if (res >= USECS_PER_JIFFY)
224 res = USECS_PER_JIFFY-1;
225 }
226
227 return res;
228}
229
230
231//#undef DO_WRITE_THROUGH 207//#undef DO_WRITE_THROUGH
232#define DO_WRITE_THROUGH 208#define DO_WRITE_THROUGH
233#define DO_ENABLE_CACHE 209#define DO_ENABLE_CACHE
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;
67int (*rtc_mips_set_mmss)(unsigned long); 68int (*rtc_mips_set_mmss)(unsigned long);
68 69
69 70
70/* usecs per counter cycle, shifted to left by 32 bits */
71static unsigned int sll32_usecs_per_cycle;
72
73/* how many counter cycles in a jiffy */ 71/* how many counter cycles in a jiffy */
74static unsigned long cycles_per_jiffy __read_mostly; 72static unsigned long cycles_per_jiffy __read_mostly;
75 73
76/* Cycle counter value at the previous timer interrupt.. */
77static 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 */
80static unsigned int expirelo; 75static 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
96static void null_hpt_init(unsigned int count) 91static 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. */
132static 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. */
138static void c0_hpt_timer_init(unsigned int count) 127static 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
147int (*mips_timer_state)(void); 133int (*mips_timer_state)(void);
148void (*mips_timer_ack)(void); 134void (*mips_timer_ack)(void);
149unsigned int (*mips_hpt_read)(void); 135unsigned int (*mips_hpt_read)(void);
150void (*mips_hpt_init)(unsigned int); 136void (*mips_hpt_init)(void) __initdata = null_hpt_init;
151 137unsigned 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
164static unsigned long null_gettimeoffset(void)
165{
166 return 0;
167}
168
169
170/* The function pointer to one of the gettimeoffset funcs. */
171unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset;
172
173
174static 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 */
205static unsigned long cached_quotient;
206
207/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */
208static unsigned long last_jiffies;
209
210/*
211 * This is moved from dec/time.c:do_ioasic_gettimeoffset() by Maciej.
212 */
213static 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
255static 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 */
313static long last_rtc_update; 140static long last_rtc_update;
@@ -334,18 +161,10 @@ void local_timer_interrupt(int irq, void *dev_id)
334 */ 161 */
335irqreturn_t timer_interrupt(int irq, void *dev_id) 162irqreturn_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
320static cycle_t read_mips_hpt(void)
321{
322 return (cycle_t)mips_hpt_read();
323}
324
325static struct clocksource clocksource_mips = {
326 .name = "MIPS",
327 .read = read_mips_hpt,
328 .is_continuous = 1,
329};
330
331static 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
543void __init time_init(void) 355void __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
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c
index 0af655b1f330..65c440e8480b 100644
--- a/arch/mips/philips/pnx8550/common/time.c
+++ b/arch/mips/philips/pnx8550/common/time.c
@@ -41,8 +41,8 @@ extern unsigned int mips_hpt_frequency;
41 * 1) board_time_init() - 41 * 1) board_time_init() -
42 * a) (optional) set up RTC routines, 42 * a) (optional) set up RTC routines,
43 * b) (optional) calibrate and set the mips_hpt_frequency 43 * b) (optional) calibrate and set the mips_hpt_frequency
44 * (only needed if you intended to use fixed_rate_gettimeoffset 44 * (only needed if you intended to use cpu counter as timer interrupt
45 * or use cpu counter as timer interrupt source) 45 * source)
46 */ 46 */
47 47
48void pnx8550_time_init(void) 48void pnx8550_time_init(void)
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 65fa3a23ea5e..3cc0436db6cf 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -3,9 +3,7 @@
3 3
4#include <asm/pmon.h> 4#include <asm/pmon.h>
5#include <asm/titan_dep.h> 5#include <asm/titan_dep.h>
6 6#include <asm/time.h>
7extern unsigned int (*mips_hpt_read)(void);
8extern void (*mips_hpt_init)(unsigned int);
9 7
10#define LAUNCHSTACK_SIZE 256 8#define LAUNCHSTACK_SIZE 256
11 9
@@ -101,7 +99,7 @@ void prom_cpus_done(void)
101 */ 99 */
102void prom_init_secondary(void) 100void prom_init_secondary(void)
103{ 101{
104 mips_hpt_init(mips_hpt_read()); 102 mips_hpt_init();
105 103
106 set_c0_status(ST0_CO | ST0_IE | ST0_IM); 104 set_c0_status(ST0_CO | ST0_IE | ST0_IM);
107} 105}
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 4e870fc4469b..c965705f3427 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -134,13 +134,6 @@ again:
134 irq_exit(); 134 irq_exit();
135} 135}
136 136
137unsigned long ip27_do_gettimeoffset(void)
138{
139 unsigned long ct_cur1;
140 ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY;
141 return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000;
142}
143
144/* Includes for ioc3_init(). */ 137/* Includes for ioc3_init(). */
145#include <asm/sn/types.h> 138#include <asm/sn/types.h>
146#include <asm/sn/sn0/addrs.h> 139#include <asm/sn/sn0/addrs.h>
@@ -248,12 +241,17 @@ void __init plat_timer_setup(struct irqaction *irq)
248 setup_irq(irqno, &rt_irqaction); 241 setup_irq(irqno, &rt_irqaction);
249} 242}
250 243
244static unsigned int ip27_hpt_read(void)
245{
246 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
247}
248
251void __init ip27_time_init(void) 249void __init ip27_time_init(void)
252{ 250{
251 mips_hpt_read = ip27_hpt_read;
252 mips_hpt_frequency = CYCLES_PER_SEC;
253 xtime.tv_sec = get_m48t35_time(); 253 xtime.tv_sec = get_m48t35_time();
254 xtime.tv_nsec = 0; 254 xtime.tv_nsec = 0;
255
256 do_gettimeoffset = ip27_do_gettimeoffset;
257} 255}
258 256
259void __init cpu_time_init(void) 257void __init cpu_time_init(void)
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
index bf12af46132e..e136bde5248e 100644
--- a/arch/mips/sibyte/bcm1480/time.c
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -47,6 +47,12 @@
47#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1 47#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
48#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2 48#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
49 49
50#ifdef CONFIG_SIMULATION
51#define BCM1480_HPT_VALUE 50000
52#else
53#define BCM1480_HPT_VALUE 1000000
54#endif
55
50extern int bcm1480_steal_irq(int irq); 56extern int bcm1480_steal_irq(int irq);
51 57
52void bcm1480_time_init(void) 58void bcm1480_time_init(void)
@@ -59,11 +65,6 @@ void bcm1480_time_init(void)
59 BUG(); 65 BUG();
60 } 66 }
61 67
62 if (!cpu) {
63 /* Use our own gettimeoffset() routine */
64 do_gettimeoffset = bcm1480_gettimeoffset;
65 }
66
67 bcm1480_mask_irq(cpu, irq); 68 bcm1480_mask_irq(cpu, irq);
68 69
69 /* Map the timer interrupt to ip[4] of this cpu */ 70 /* Map the timer interrupt to ip[4] of this cpu */
@@ -74,11 +75,7 @@ void bcm1480_time_init(void)
74 /* Disable the timer and set up the count */ 75 /* Disable the timer and set up the count */
75 __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG))); 76 __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
76 __raw_writeq( 77 __raw_writeq(
77#ifndef CONFIG_SIMULATION 78 BCM1480_HPT_VALUE/HZ
78 1000000/HZ
79#else
80 50000/HZ
81#endif
82 , IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT))); 79 , IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
83 80
84 /* Set the timer running */ 81 /* Set the timer running */
@@ -122,16 +119,16 @@ void bcm1480_timer_interrupt(void)
122 } 119 }
123} 120}
124 121
125/* 122static unsigned int bcm1480_hpt_read(void)
126 * We use our own do_gettimeoffset() instead of the generic one,
127 * because the generic one does not work for SMP case.
128 * In addition, since we use general timer 0 for system time,
129 * we can get accurate intra-jiffy offset without calibration.
130 */
131unsigned long bcm1480_gettimeoffset(void)
132{ 123{
124 /* We assume this function is called xtime_lock held. */
133 unsigned long count = 125 unsigned long count =
134 __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT))); 126 __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
127 return (jiffies + 1) * (BCM1480_HPT_VALUE / HZ) - count;
128}
135 129
136 return 1000000/HZ - count; 130void __init bcm1480_hpt_setup(void)
131{
132 mips_hpt_read = bcm1480_hpt_read;
133 mips_hpt_frequency = BCM1480_HPT_VALUE;
137} 134}
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 0ccf1796dd78..bcb74f2c1948 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -47,15 +47,11 @@
47 47
48#define SB1250_HPT_NUM 3 48#define SB1250_HPT_NUM 3
49#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ 49#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */
50#define SB1250_HPT_SHIFT ((sizeof(unsigned int)*8)-V_SCD_TIMER_WIDTH)
51 50
52 51
53extern int sb1250_steal_irq(int irq); 52extern int sb1250_steal_irq(int irq);
54 53
55static unsigned int sb1250_hpt_read(void); 54static unsigned int sb1250_hpt_read(void);
56static void sb1250_hpt_init(unsigned int);
57
58static unsigned int hpt_offset;
59 55
60void __init sb1250_hpt_setup(void) 56void __init sb1250_hpt_setup(void)
61{ 57{
@@ -69,13 +65,9 @@ void __init sb1250_hpt_setup(void)
69 __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, 65 __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
70 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG))); 66 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
71 67
72 /* 68 mips_hpt_frequency = V_SCD_TIMER_FREQ;
73 * we need to fill 32 bits, so just use the upper 23 bits and pretend
74 * the timer is going 512Mhz instead of 1Mhz
75 */
76 mips_hpt_frequency = V_SCD_TIMER_FREQ << SB1250_HPT_SHIFT;
77 mips_hpt_init = sb1250_hpt_init;
78 mips_hpt_read = sb1250_hpt_read; 69 mips_hpt_read = sb1250_hpt_read;
70 mips_hpt_mask = M_SCD_TIMER_INIT;
79 } 71 }
80} 72}
81 73
@@ -149,11 +141,7 @@ void sb1250_timer_interrupt(void)
149 141
150/* 142/*
151 * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over 143 * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
152 * again. There's no easy way to set to a specific value so store init value 144 * again.
153 * in hpt_offset and subtract each time.
154 *
155 * Note: Timer isn't full 32bits so shift it into the upper part making
156 * it appear to run at a higher frequency.
157 */ 145 */
158static unsigned int sb1250_hpt_read(void) 146static unsigned int sb1250_hpt_read(void)
159{ 147{
@@ -161,13 +149,5 @@ static unsigned int sb1250_hpt_read(void)
161 149
162 count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)))); 150 count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT))));
163 151
164 count = (SB1250_HPT_VALUE - count) << SB1250_HPT_SHIFT; 152 return SB1250_HPT_VALUE - count;
165
166 return count - hpt_offset;
167}
168
169static void sb1250_hpt_init(unsigned int count)
170{
171 hpt_offset = count;
172 return;
173} 153}