diff options
Diffstat (limited to 'arch/arm/mach-exynos/mct.c')
-rw-r--r-- | arch/arm/mach-exynos/mct.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 85b5527d0918..897d9a9cf226 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/percpu.h> | 21 | #include <linux/percpu.h> |
22 | 22 | ||
23 | #include <asm/hardware/gic.h> | 23 | #include <asm/hardware/gic.h> |
24 | #include <asm/localtimer.h> | ||
24 | 25 | ||
25 | #include <plat/cpu.h> | 26 | #include <plat/cpu.h> |
26 | 27 | ||
@@ -29,12 +30,13 @@ | |||
29 | #include <mach/regs-mct.h> | 30 | #include <mach/regs-mct.h> |
30 | #include <asm/mach/time.h> | 31 | #include <asm/mach/time.h> |
31 | 32 | ||
33 | #define TICK_BASE_CNT 1 | ||
34 | |||
32 | enum { | 35 | enum { |
33 | MCT_INT_SPI, | 36 | MCT_INT_SPI, |
34 | MCT_INT_PPI | 37 | MCT_INT_PPI |
35 | }; | 38 | }; |
36 | 39 | ||
37 | static unsigned long clk_cnt_per_tick; | ||
38 | static unsigned long clk_rate; | 40 | static unsigned long clk_rate; |
39 | static unsigned int mct_int_type; | 41 | static unsigned int mct_int_type; |
40 | 42 | ||
@@ -205,11 +207,14 @@ static int exynos4_comp_set_next_event(unsigned long cycles, | |||
205 | static void exynos4_comp_set_mode(enum clock_event_mode mode, | 207 | static void exynos4_comp_set_mode(enum clock_event_mode mode, |
206 | struct clock_event_device *evt) | 208 | struct clock_event_device *evt) |
207 | { | 209 | { |
210 | unsigned long cycles_per_jiffy; | ||
208 | exynos4_mct_comp0_stop(); | 211 | exynos4_mct_comp0_stop(); |
209 | 212 | ||
210 | switch (mode) { | 213 | switch (mode) { |
211 | case CLOCK_EVT_MODE_PERIODIC: | 214 | case CLOCK_EVT_MODE_PERIODIC: |
212 | exynos4_mct_comp0_start(mode, clk_cnt_per_tick); | 215 | cycles_per_jiffy = |
216 | (((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); | ||
217 | exynos4_mct_comp0_start(mode, cycles_per_jiffy); | ||
213 | break; | 218 | break; |
214 | 219 | ||
215 | case CLOCK_EVT_MODE_ONESHOT: | 220 | case CLOCK_EVT_MODE_ONESHOT: |
@@ -248,9 +253,7 @@ static struct irqaction mct_comp_event_irq = { | |||
248 | 253 | ||
249 | static void exynos4_clockevent_init(void) | 254 | static void exynos4_clockevent_init(void) |
250 | { | 255 | { |
251 | clk_cnt_per_tick = clk_rate / 2 / HZ; | 256 | clockevents_calc_mult_shift(&mct_comp_device, clk_rate, 5); |
252 | |||
253 | clockevents_calc_mult_shift(&mct_comp_device, clk_rate / 2, 5); | ||
254 | mct_comp_device.max_delta_ns = | 257 | mct_comp_device.max_delta_ns = |
255 | clockevent_delta2ns(0xffffffff, &mct_comp_device); | 258 | clockevent_delta2ns(0xffffffff, &mct_comp_device); |
256 | mct_comp_device.min_delta_ns = | 259 | mct_comp_device.min_delta_ns = |
@@ -258,7 +261,10 @@ static void exynos4_clockevent_init(void) | |||
258 | mct_comp_device.cpumask = cpumask_of(0); | 261 | mct_comp_device.cpumask = cpumask_of(0); |
259 | clockevents_register_device(&mct_comp_device); | 262 | clockevents_register_device(&mct_comp_device); |
260 | 263 | ||
261 | setup_irq(IRQ_MCT_G0, &mct_comp_event_irq); | 264 | if (soc_is_exynos5250()) |
265 | setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq); | ||
266 | else | ||
267 | setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq); | ||
262 | } | 268 | } |
263 | 269 | ||
264 | #ifdef CONFIG_LOCAL_TIMERS | 270 | #ifdef CONFIG_LOCAL_TIMERS |
@@ -314,12 +320,15 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode, | |||
314 | struct clock_event_device *evt) | 320 | struct clock_event_device *evt) |
315 | { | 321 | { |
316 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); | 322 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); |
323 | unsigned long cycles_per_jiffy; | ||
317 | 324 | ||
318 | exynos4_mct_tick_stop(mevt); | 325 | exynos4_mct_tick_stop(mevt); |
319 | 326 | ||
320 | switch (mode) { | 327 | switch (mode) { |
321 | case CLOCK_EVT_MODE_PERIODIC: | 328 | case CLOCK_EVT_MODE_PERIODIC: |
322 | exynos4_mct_tick_start(clk_cnt_per_tick, mevt); | 329 | cycles_per_jiffy = |
330 | (((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); | ||
331 | exynos4_mct_tick_start(cycles_per_jiffy, mevt); | ||
323 | break; | 332 | break; |
324 | 333 | ||
325 | case CLOCK_EVT_MODE_ONESHOT: | 334 | case CLOCK_EVT_MODE_ONESHOT: |
@@ -375,7 +384,7 @@ static struct irqaction mct_tick1_event_irq = { | |||
375 | .handler = exynos4_mct_tick_isr, | 384 | .handler = exynos4_mct_tick_isr, |
376 | }; | 385 | }; |
377 | 386 | ||
378 | static void exynos4_mct_tick_init(struct clock_event_device *evt) | 387 | static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt) |
379 | { | 388 | { |
380 | struct mct_clock_event_device *mevt; | 389 | struct mct_clock_event_device *mevt; |
381 | unsigned int cpu = smp_processor_id(); | 390 | unsigned int cpu = smp_processor_id(); |
@@ -393,7 +402,7 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) | |||
393 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 402 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
394 | evt->rating = 450; | 403 | evt->rating = 450; |
395 | 404 | ||
396 | clockevents_calc_mult_shift(evt, clk_rate / 2, 5); | 405 | clockevents_calc_mult_shift(evt, clk_rate / (TICK_BASE_CNT + 1), 5); |
397 | evt->max_delta_ns = | 406 | evt->max_delta_ns = |
398 | clockevent_delta2ns(0x7fffffff, evt); | 407 | clockevent_delta2ns(0x7fffffff, evt); |
399 | evt->min_delta_ns = | 408 | evt->min_delta_ns = |
@@ -401,33 +410,27 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) | |||
401 | 410 | ||
402 | clockevents_register_device(evt); | 411 | clockevents_register_device(evt); |
403 | 412 | ||
404 | exynos4_mct_write(0x1, mevt->base + MCT_L_TCNTB_OFFSET); | 413 | exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); |
405 | 414 | ||
406 | if (mct_int_type == MCT_INT_SPI) { | 415 | if (mct_int_type == MCT_INT_SPI) { |
407 | if (cpu == 0) { | 416 | if (cpu == 0) { |
408 | mct_tick0_event_irq.dev_id = mevt; | 417 | mct_tick0_event_irq.dev_id = mevt; |
409 | evt->irq = IRQ_MCT_L0; | 418 | evt->irq = EXYNOS4_IRQ_MCT_L0; |
410 | setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq); | 419 | setup_irq(EXYNOS4_IRQ_MCT_L0, &mct_tick0_event_irq); |
411 | } else { | 420 | } else { |
412 | mct_tick1_event_irq.dev_id = mevt; | 421 | mct_tick1_event_irq.dev_id = mevt; |
413 | evt->irq = IRQ_MCT_L1; | 422 | evt->irq = EXYNOS4_IRQ_MCT_L1; |
414 | setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq); | 423 | setup_irq(EXYNOS4_IRQ_MCT_L1, &mct_tick1_event_irq); |
415 | irq_set_affinity(IRQ_MCT_L1, cpumask_of(1)); | 424 | irq_set_affinity(EXYNOS4_IRQ_MCT_L1, cpumask_of(1)); |
416 | } | 425 | } |
417 | } else { | 426 | } else { |
418 | enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0); | 427 | enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0); |
419 | } | 428 | } |
420 | } | ||
421 | |||
422 | /* Setup the local clock events for a CPU */ | ||
423 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
424 | { | ||
425 | exynos4_mct_tick_init(evt); | ||
426 | 429 | ||
427 | return 0; | 430 | return 0; |
428 | } | 431 | } |
429 | 432 | ||
430 | void local_timer_stop(struct clock_event_device *evt) | 433 | static void exynos4_local_timer_stop(struct clock_event_device *evt) |
431 | { | 434 | { |
432 | unsigned int cpu = smp_processor_id(); | 435 | unsigned int cpu = smp_processor_id(); |
433 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | 436 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); |
@@ -437,8 +440,13 @@ void local_timer_stop(struct clock_event_device *evt) | |||
437 | else | 440 | else |
438 | remove_irq(evt->irq, &mct_tick1_event_irq); | 441 | remove_irq(evt->irq, &mct_tick1_event_irq); |
439 | else | 442 | else |
440 | disable_percpu_irq(IRQ_MCT_LOCALTIMER); | 443 | disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER); |
441 | } | 444 | } |
445 | |||
446 | static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = { | ||
447 | .setup = exynos4_local_timer_setup, | ||
448 | .stop = exynos4_local_timer_stop, | ||
449 | }; | ||
442 | #endif /* CONFIG_LOCAL_TIMERS */ | 450 | #endif /* CONFIG_LOCAL_TIMERS */ |
443 | 451 | ||
444 | static void __init exynos4_timer_resources(void) | 452 | static void __init exynos4_timer_resources(void) |
@@ -452,12 +460,14 @@ static void __init exynos4_timer_resources(void) | |||
452 | if (mct_int_type == MCT_INT_PPI) { | 460 | if (mct_int_type == MCT_INT_PPI) { |
453 | int err; | 461 | int err; |
454 | 462 | ||
455 | err = request_percpu_irq(IRQ_MCT_LOCALTIMER, | 463 | err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, |
456 | exynos4_mct_tick_isr, "MCT", | 464 | exynos4_mct_tick_isr, "MCT", |
457 | &percpu_mct_tick); | 465 | &percpu_mct_tick); |
458 | WARN(err, "MCT: can't request IRQ %d (%d)\n", | 466 | WARN(err, "MCT: can't request IRQ %d (%d)\n", |
459 | IRQ_MCT_LOCALTIMER, err); | 467 | EXYNOS_IRQ_MCT_LOCALTIMER, err); |
460 | } | 468 | } |
469 | |||
470 | local_timer_register(&exynos4_mct_tick_ops); | ||
461 | #endif /* CONFIG_LOCAL_TIMERS */ | 471 | #endif /* CONFIG_LOCAL_TIMERS */ |
462 | } | 472 | } |
463 | 473 | ||