diff options
author | Changhwan Youn <chaos.youn@samsung.com> | 2012-03-09 18:09:21 -0500 |
---|---|---|
committer | Kukjin Kim <kgene.kim@samsung.com> | 2012-03-10 10:26:59 -0500 |
commit | 4d2e4d7f2c2b1a4382286821a59fa2f4012cb748 (patch) | |
tree | 93f3f8631c16c0a7e6784b12a9df05cfb51faf3a /arch | |
parent | 3dbe6d4cacc76100f3166cd824d3ce7a8cef7cef (diff) |
ARM: EXYNOS: fix cycle count for periodic mode of clock event timers
EXYNOS SOC series use MCT for kernel timer and MCT has two types of
clock event timers, which are mct-comp and mct-tick.
Because the clock rate of each event timer is diffent from the other,
this patch fixes cycles_per_jiffy for each timer's periodic mode.
Signed-off-by: Changhwan Youn <chaos.youn@samsung.com>
Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-exynos/mct.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 85b5527d091..3e894ba25b0 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c | |||
@@ -29,12 +29,13 @@ | |||
29 | #include <mach/regs-mct.h> | 29 | #include <mach/regs-mct.h> |
30 | #include <asm/mach/time.h> | 30 | #include <asm/mach/time.h> |
31 | 31 | ||
32 | #define TICK_BASE_CNT 1 | ||
33 | |||
32 | enum { | 34 | enum { |
33 | MCT_INT_SPI, | 35 | MCT_INT_SPI, |
34 | MCT_INT_PPI | 36 | MCT_INT_PPI |
35 | }; | 37 | }; |
36 | 38 | ||
37 | static unsigned long clk_cnt_per_tick; | ||
38 | static unsigned long clk_rate; | 39 | static unsigned long clk_rate; |
39 | static unsigned int mct_int_type; | 40 | static unsigned int mct_int_type; |
40 | 41 | ||
@@ -205,11 +206,14 @@ static int exynos4_comp_set_next_event(unsigned long cycles, | |||
205 | static void exynos4_comp_set_mode(enum clock_event_mode mode, | 206 | static void exynos4_comp_set_mode(enum clock_event_mode mode, |
206 | struct clock_event_device *evt) | 207 | struct clock_event_device *evt) |
207 | { | 208 | { |
209 | unsigned long cycles_per_jiffy; | ||
208 | exynos4_mct_comp0_stop(); | 210 | exynos4_mct_comp0_stop(); |
209 | 211 | ||
210 | switch (mode) { | 212 | switch (mode) { |
211 | case CLOCK_EVT_MODE_PERIODIC: | 213 | case CLOCK_EVT_MODE_PERIODIC: |
212 | exynos4_mct_comp0_start(mode, clk_cnt_per_tick); | 214 | cycles_per_jiffy = |
215 | (((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); | ||
216 | exynos4_mct_comp0_start(mode, cycles_per_jiffy); | ||
213 | break; | 217 | break; |
214 | 218 | ||
215 | case CLOCK_EVT_MODE_ONESHOT: | 219 | case CLOCK_EVT_MODE_ONESHOT: |
@@ -248,9 +252,7 @@ static struct irqaction mct_comp_event_irq = { | |||
248 | 252 | ||
249 | static void exynos4_clockevent_init(void) | 253 | static void exynos4_clockevent_init(void) |
250 | { | 254 | { |
251 | clk_cnt_per_tick = clk_rate / 2 / HZ; | 255 | 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 = | 256 | mct_comp_device.max_delta_ns = |
255 | clockevent_delta2ns(0xffffffff, &mct_comp_device); | 257 | clockevent_delta2ns(0xffffffff, &mct_comp_device); |
256 | mct_comp_device.min_delta_ns = | 258 | mct_comp_device.min_delta_ns = |
@@ -314,12 +316,15 @@ static inline void exynos4_tick_set_mode(enum clock_event_mode mode, | |||
314 | struct clock_event_device *evt) | 316 | struct clock_event_device *evt) |
315 | { | 317 | { |
316 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); | 318 | struct mct_clock_event_device *mevt = this_cpu_ptr(&percpu_mct_tick); |
319 | unsigned long cycles_per_jiffy; | ||
317 | 320 | ||
318 | exynos4_mct_tick_stop(mevt); | 321 | exynos4_mct_tick_stop(mevt); |
319 | 322 | ||
320 | switch (mode) { | 323 | switch (mode) { |
321 | case CLOCK_EVT_MODE_PERIODIC: | 324 | case CLOCK_EVT_MODE_PERIODIC: |
322 | exynos4_mct_tick_start(clk_cnt_per_tick, mevt); | 325 | cycles_per_jiffy = |
326 | (((unsigned long long) NSEC_PER_SEC / HZ * evt->mult) >> evt->shift); | ||
327 | exynos4_mct_tick_start(cycles_per_jiffy, mevt); | ||
323 | break; | 328 | break; |
324 | 329 | ||
325 | case CLOCK_EVT_MODE_ONESHOT: | 330 | case CLOCK_EVT_MODE_ONESHOT: |
@@ -393,7 +398,7 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) | |||
393 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | 398 | evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; |
394 | evt->rating = 450; | 399 | evt->rating = 450; |
395 | 400 | ||
396 | clockevents_calc_mult_shift(evt, clk_rate / 2, 5); | 401 | clockevents_calc_mult_shift(evt, clk_rate / (TICK_BASE_CNT + 1), 5); |
397 | evt->max_delta_ns = | 402 | evt->max_delta_ns = |
398 | clockevent_delta2ns(0x7fffffff, evt); | 403 | clockevent_delta2ns(0x7fffffff, evt); |
399 | evt->min_delta_ns = | 404 | evt->min_delta_ns = |
@@ -401,7 +406,7 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) | |||
401 | 406 | ||
402 | clockevents_register_device(evt); | 407 | clockevents_register_device(evt); |
403 | 408 | ||
404 | exynos4_mct_write(0x1, mevt->base + MCT_L_TCNTB_OFFSET); | 409 | exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); |
405 | 410 | ||
406 | if (mct_int_type == MCT_INT_SPI) { | 411 | if (mct_int_type == MCT_INT_SPI) { |
407 | if (cpu == 0) { | 412 | if (cpu == 0) { |