aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/cevt-r4k.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/cevt-r4k.c')
-rw-r--r--arch/mips/kernel/cevt-r4k.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index ae2984fff580..bab935a3d74b 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -28,7 +28,7 @@ static int mips_next_event(unsigned long delta,
28 cnt = read_c0_count(); 28 cnt = read_c0_count();
29 cnt += delta; 29 cnt += delta;
30 write_c0_compare(cnt); 30 write_c0_compare(cnt);
31 res = ((long)(read_c0_count() - cnt ) > 0) ? -ETIME : 0; 31 res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
32#ifdef CONFIG_MIPS_MT_SMTC 32#ifdef CONFIG_MIPS_MT_SMTC
33 evpe(vpflags); 33 evpe(vpflags);
34 local_irq_restore(flags); 34 local_irq_restore(flags);
@@ -179,7 +179,7 @@ static int c0_compare_int_pending(void)
179 179
180static int c0_compare_int_usable(void) 180static int c0_compare_int_usable(void)
181{ 181{
182 const unsigned int delta = 0x300000; 182 unsigned int delta;
183 unsigned int cnt; 183 unsigned int cnt;
184 184
185 /* 185 /*
@@ -192,11 +192,17 @@ static int c0_compare_int_usable(void)
192 return 0; 192 return 0;
193 } 193 }
194 194
195 cnt = read_c0_count(); 195 for (delta = 0x10; delta <= 0x400000; delta <<= 1) {
196 cnt += delta; 196 cnt = read_c0_count();
197 write_c0_compare(cnt); 197 cnt += delta;
198 write_c0_compare(cnt);
199 irq_disable_hazard();
200 if ((int)(read_c0_count() - cnt) < 0)
201 break;
202 /* increase delta if the timer was already expired */
203 }
198 204
199 while ((long)(read_c0_count() - cnt) <= 0) 205 while ((int)(read_c0_count() - cnt) <= 0)
200 ; /* Wait for expiry */ 206 ; /* Wait for expiry */
201 207
202 if (!c0_compare_int_pending()) 208 if (!c0_compare_int_pending())
@@ -218,9 +224,9 @@ void __cpuinit mips_clockevent_init(void)
218 uint64_t mips_freq = mips_hpt_frequency; 224 uint64_t mips_freq = mips_hpt_frequency;
219 unsigned int cpu = smp_processor_id(); 225 unsigned int cpu = smp_processor_id();
220 struct clock_event_device *cd; 226 struct clock_event_device *cd;
221 unsigned int irq = MIPS_CPU_IRQ_BASE + 7; 227 unsigned int irq;
222 228
223 if (!cpu_has_counter) 229 if (!cpu_has_counter || !mips_hpt_frequency)
224 return; 230 return;
225 231
226#ifdef CONFIG_MIPS_MT_SMTC 232#ifdef CONFIG_MIPS_MT_SMTC
@@ -237,6 +243,15 @@ void __cpuinit mips_clockevent_init(void)
237 if (!c0_compare_int_usable()) 243 if (!c0_compare_int_usable())
238 return; 244 return;
239 245
246 /*
247 * With vectored interrupts things are getting platform specific.
248 * get_c0_compare_int is a hook to allow a platform to return the
249 * interrupt number of it's liking.
250 */
251 irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
252 if (get_c0_compare_int)
253 irq = get_c0_compare_int();
254
240 cd = &per_cpu(mips_clockevent_device, cpu); 255 cd = &per_cpu(mips_clockevent_device, cpu);
241 256
242 cd->name = "MIPS"; 257 cd->name = "MIPS";
@@ -261,13 +276,15 @@ void __cpuinit mips_clockevent_init(void)
261 276
262 clockevents_register_device(cd); 277 clockevents_register_device(cd);
263 278
264 if (!cp0_timer_irq_installed) { 279 if (!cp0_timer_irq_installed)
280 return;
281
282 cp0_timer_irq_installed = 1;
283
265#ifdef CONFIG_MIPS_MT_SMTC 284#ifdef CONFIG_MIPS_MT_SMTC
266#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq) 285#define CPUCTR_IMASKBIT (0x100 << cp0_compare_irq)
267 setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT); 286 setup_irq_smtc(irq, &c0_compare_irqaction, CPUCTR_IMASKBIT);
268#else 287#else
269 setup_irq(irq, &c0_compare_irqaction); 288 setup_irq(irq, &c0_compare_irqaction);
270#endif /* CONFIG_MIPS_MT_SMTC */ 289#endif
271 cp0_timer_irq_installed = 1;
272 }
273} 290}