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. See 7 * Documentation/mips/time.README. 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 */ 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/profile.h> 21 #include <linux/time.h> 22 #include <linux/timex.h> 23 #include <linux/smp.h> 24 #include <linux/kernel_stat.h> 25 #include <linux/spinlock.h> 26 #include <linux/interrupt.h> 27 #include <linux/module.h> 28 #include <linux/kallsyms.h> 29 30 #include <asm/bootinfo.h> 31 #include <asm/cache.h> 32 #include <asm/compiler.h> 33 #include <asm/cpu.h> 34 #include <asm/cpu-features.h> 35 #include <asm/div64.h> 36 #include <asm/sections.h> 37 #include <asm/smtc_ipi.h> 38 #include <asm/time.h> 39 40 #include <irq.h> 41 42 /* 43 * forward reference 44 */ 45 DEFINE_SPINLOCK(rtc_lock); 46 EXPORT_SYMBOL(rtc_lock); 47 48 int __weak rtc_mips_set_time(unsigned long sec) 49 { 50 return 0; 51 } 52 EXPORT_SYMBOL(rtc_mips_set_time); 53 54 int __weak rtc_mips_set_mmss(unsigned long nowtime) 55 { 56 return rtc_mips_set_time(nowtime); 57 } 58 59 int update_persistent_clock(struct timespec now) 60 { 61 return rtc_mips_set_mmss(now.tv_sec); 62 } 63 64 /* 65 * Null high precision timer functions for systems lacking one. 66 */ 67 static cycle_t null_hpt_read(void) 68 { 69 return 0; 70 } 71 72 /* 73 * High precision timer functions for a R4k-compatible timer. 74 */ 75 static cycle_t c0_hpt_read(void) 76 { 77 return read_c0_count(); 78 } 79 80 int (*mips_timer_state)(void); 81 82 /* 83 * local_timer_interrupt() does profiling and process accounting 84 * on a per-CPU basis. 85 * 86 * In UP mode, it is invoked from the (global) timer_interrupt. 87 * 88 * In SMP mode, it might invoked by per-CPU timer interrupt, or 89 * a broadcasted inter-processor interrupt which itself is triggered 90 * by the global timer interrupt. 91 */ 92 void local_timer_interrupt(int irq, void *dev_id) 93 { 94 profile_tick(CPU_PROFILING); 95 update_process_times(user_mode(get_irq_regs())); 96 } 97 98 int null_perf_irq(void) 99 { 100 return 0; 101 } 102 103 EXPORT_SYMBOL(null_perf_irq); 104 105 int (*perf_irq)(void) = null_perf_irq; 106 107 EXPORT_SYMBOL(perf_irq); 108 109 /* 110 * time_init() - it does the following things. 111 * 112 * 1) plat_time_init() - 113 * a) (optional) set up RTC routines, 114 * b) (optional) calibrate and set the mips_hpt_frequency 115 * (only needed if you intended to use cpu counter as timer interrupt 116 * source) 117 * 2) calculate a couple of cached variables for later usage 118 * 3) plat_timer_setup() - 119 * a) (optional) over-write any choices made above by time_init(). 120 * b) machine specific code should setup the timer irqaction. 121 * c) enable the timer interrupt 122 */ 123 124 unsigned int mips_hpt_frequency; 125 126 static unsigned int __init calibrate_hpt(void) 127 { 128 cycle_t frequency, hpt_start, hpt_end, hpt_count, hz; 129 130 const int loops = HZ / 10; 131 int log_2_loops = 0; 132 int i; 133 134 /* 135 * We want to calibrate for 0.1s, but to avoid a 64-bit 136 * division we round the number of loops up to the nearest 137 * power of 2. 138 */ 139 while (loops > 1 << log_2_loops) 140 log_2_loops++; 141 i = 1 << log_2_loops; 142 143 /* 144 * Wait for a rising edge of the timer interrupt. 145 */ 146 while (mips_timer_state()); 147 while (!mips_timer_state()); 148 149 /* 150 * Now see how many high precision timer ticks happen 151 * during the calculated number of periods between timer 152 * interrupts. 153 */ 154 hpt_start = clocksource_mips.read(); 155 do { 156 while (mips_timer_state()); 157 while (!mips_timer_state()); 158 } while (--i); 159 hpt_end = clocksource_mips.read(); 160 161 hpt_count = (hpt_end - hpt_start) & clocksource_mips.mask; 162 hz = HZ; 163 frequency = hpt_count * hz; 164 165 return frequency >> log_2_loops; 166 } 167 168 struct clocksource clocksource_mips = { 169 .name = "MIPS", 170 .mask = CLOCKSOURCE_MASK(32), 171 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 172 }; 173 174 void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) 175 { 176 u64 temp; 177 u32 shift; 178 179 /* Find a shift value */ 180 for (shift = 32; shift > 0; shift--) { 181 temp = (u64) NSEC_PER_SEC << shift; 182 do_div(temp, clock); 183 if ((temp >> 32) == 0) 184 break; 185 } 186 cs->shift = shift; 187 cs->mult = (u32) temp; 188 } 189 190 void __cpuinit clockevent_set_clock(struct clock_event_device *cd, 191 unsigned int clock) 192 { 193 u64 temp; 194 u32 shift; 195 196 /* Find a shift value */ 197 for (shift = 32; shift > 0; shift--) { 198 temp = (u64) NSEC_PER_SEC << shift; 199 do_div(temp, clock); 200 if ((temp >> 32) == 0) 201 break; 202 } 203 cd->shift = shift; 204 cd->mult = (u32) temp; 205 } 206 207 static void __init init_mips_clocksource(void) 208 { 209 if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read) 210 return; 211 212 /* Calclate a somewhat reasonable rating value */ 213 clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000; 214 215 clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); 216 217 clocksource_register(&clocksource_mips); 218 } 219 220 void __init __weak plat_time_init(void) 221 { 222 } 223 224 void __init __weak plat_timer_setup(struct irqaction *irq) 225 { 226 } 227 228 void __init time_init(void) 229 { 230 plat_time_init(); 231 232 /* Choose appropriate high precision timer routines. */ 233 if (!cpu_has_counter && !clocksource_mips.read) 234 /* No high precision timer -- sorry. */ 235 clocksource_mips.read = null_hpt_read; 236 else if (!mips_hpt_frequency && !mips_timer_state) { 237 /* A high precision timer of unknown frequency. */ 238 if (!clocksource_mips.read) 239 /* No external high precision timer -- use R4k. */ 240 clocksource_mips.read = c0_hpt_read; 241 } else { 242 /* We know counter frequency. Or we can get it. */ 243 if (!clocksource_mips.read) { 244 /* No external high precision timer -- use R4k. */ 245 clocksource_mips.read = c0_hpt_read; 246 } 247 if (!mips_hpt_frequency) 248 mips_hpt_frequency = calibrate_hpt(); 249 250 /* Report the high precision timer rate for a reference. */ 251 printk("Using %u.%03u MHz high precision timer.\n", 252 ((mips_hpt_frequency + 500) / 1000) / 1000, 253 ((mips_hpt_frequency + 500) / 1000) % 1000); 254 } 255 256 init_mips_clocksource(); 257 mips_clockevent_init(); 258 } 259