diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/cevt-r4k.c | 12 | ||||
-rw-r--r-- | arch/mips/kernel/time.c | 87 |
2 files changed, 40 insertions, 59 deletions
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 076f52b9bb79..24a2d907aa0d 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c | |||
@@ -219,7 +219,7 @@ static int c0_compare_int_usable(void) | |||
219 | return 1; | 219 | return 1; |
220 | } | 220 | } |
221 | 221 | ||
222 | void __cpuinit mips_clockevent_init(void) | 222 | int __cpuinit mips_clockevent_init(void) |
223 | { | 223 | { |
224 | uint64_t mips_freq = mips_hpt_frequency; | 224 | uint64_t mips_freq = mips_hpt_frequency; |
225 | unsigned int cpu = smp_processor_id(); | 225 | unsigned int cpu = smp_processor_id(); |
@@ -227,7 +227,7 @@ void __cpuinit mips_clockevent_init(void) | |||
227 | unsigned int irq; | 227 | unsigned int irq; |
228 | 228 | ||
229 | if (!cpu_has_counter || !mips_hpt_frequency) | 229 | if (!cpu_has_counter || !mips_hpt_frequency) |
230 | return; | 230 | return -ENXIO; |
231 | 231 | ||
232 | #ifdef CONFIG_MIPS_MT_SMTC | 232 | #ifdef CONFIG_MIPS_MT_SMTC |
233 | setup_smtc_dummy_clockevent_device(); | 233 | setup_smtc_dummy_clockevent_device(); |
@@ -237,11 +237,11 @@ void __cpuinit mips_clockevent_init(void) | |||
237 | * device. | 237 | * device. |
238 | */ | 238 | */ |
239 | if (cpu) | 239 | if (cpu) |
240 | return; | 240 | return 0; |
241 | #endif | 241 | #endif |
242 | 242 | ||
243 | if (!c0_compare_int_usable()) | 243 | if (!c0_compare_int_usable()) |
244 | return; | 244 | return -ENXIO; |
245 | 245 | ||
246 | /* | 246 | /* |
247 | * With vectored interrupts things are getting platform specific. | 247 | * With vectored interrupts things are getting platform specific. |
@@ -277,7 +277,7 @@ void __cpuinit mips_clockevent_init(void) | |||
277 | clockevents_register_device(cd); | 277 | clockevents_register_device(cd); |
278 | 278 | ||
279 | if (cp0_timer_irq_installed) | 279 | if (cp0_timer_irq_installed) |
280 | return; | 280 | return 0; |
281 | 281 | ||
282 | cp0_timer_irq_installed = 1; | 282 | cp0_timer_irq_installed = 1; |
283 | 283 | ||
@@ -287,4 +287,6 @@ void __cpuinit mips_clockevent_init(void) | |||
287 | #else | 287 | #else |
288 | setup_irq(irq, &c0_compare_irqaction); | 288 | setup_irq(irq, &c0_compare_irqaction); |
289 | #endif | 289 | #endif |
290 | |||
291 | return 0; | ||
290 | } | 292 | } |
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 3284b9b4ecac..d7d52efff51f 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
@@ -91,48 +91,6 @@ static struct clocksource clocksource_mips = { | |||
91 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 91 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
92 | }; | 92 | }; |
93 | 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) | 94 | void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) |
137 | { | 95 | { |
138 | u64 temp; | 96 | u64 temp; |
@@ -194,21 +152,42 @@ void __init plat_timer_setup(void) | |||
194 | BUG(); | 152 | BUG(); |
195 | } | 153 | } |
196 | 154 | ||
155 | static __init int cpu_has_mfc0_count_bug(void) | ||
156 | { | ||
157 | switch (current_cpu_type()) { | ||
158 | case CPU_R4000PC: | ||
159 | case CPU_R4000SC: | ||
160 | case CPU_R4000MC: | ||
161 | /* | ||
162 | * V3.0 is documented as suffering from the mfc0 from count bug. | ||
163 | * Afaik this is the last version of the R4000. Later versions | ||
164 | * were marketed as R4400. | ||
165 | */ | ||
166 | return 1; | ||
167 | |||
168 | case CPU_R4400PC: | ||
169 | case CPU_R4400SC: | ||
170 | case CPU_R4400MC: | ||
171 | /* | ||
172 | * The published errata for the R4400 upto 3.0 say the CPU | ||
173 | * has the mfc0 from count bug. | ||
174 | */ | ||
175 | if ((current_cpu_data.processor_id & 0xff) <= 0x30) | ||
176 | return 1; | ||
177 | |||
178 | /* | ||
179 | * I don't have erratas for newer R4400 so be paranoid. | ||
180 | */ | ||
181 | return 1; | ||
182 | } | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
197 | void __init time_init(void) | 187 | void __init time_init(void) |
198 | { | 188 | { |
199 | plat_time_init(); | 189 | plat_time_init(); |
200 | 190 | ||
201 | if (cpu_has_counter && (mips_hpt_frequency || mips_timer_state)) { | 191 | if (mips_clockevent_init() || !cpu_has_mfc0_count_bug()) |
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(); | 192 | init_mips_clocksource(); |
211 | } | ||
212 | |||
213 | mips_clockevent_init(); | ||
214 | } | 193 | } |