diff options
Diffstat (limited to 'arch/arm/mach-u300/timer.c')
-rw-r--r-- | arch/arm/mach-u300/timer.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c index 9a5f9fb352ce..5226162fac69 100644 --- a/arch/arm/mach-u300/timer.c +++ b/arch/arm/mach-u300/timer.c | |||
@@ -184,11 +184,13 @@ | |||
184 | #define U300_TIMER_APP_CRC (0x100) | 184 | #define U300_TIMER_APP_CRC (0x100) |
185 | #define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE (0x00000001) | 185 | #define U300_TIMER_APP_CRC_CLOCK_REQUEST_ENABLE (0x00000001) |
186 | 186 | ||
187 | #define TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) | ||
188 | #define US_PER_TICK ((1000000 + (HZ/2)) / HZ) | ||
189 | |||
190 | static void __iomem *u300_timer_base; | 187 | static void __iomem *u300_timer_base; |
191 | 188 | ||
189 | struct u300_clockevent_data { | ||
190 | struct clock_event_device cevd; | ||
191 | unsigned ticks_per_jiffy; | ||
192 | }; | ||
193 | |||
192 | /* | 194 | /* |
193 | * The u300_set_mode() function is always called first, if we | 195 | * The u300_set_mode() function is always called first, if we |
194 | * have oneshot timer active, the oneshot scheduling function | 196 | * have oneshot timer active, the oneshot scheduling function |
@@ -197,6 +199,9 @@ static void __iomem *u300_timer_base; | |||
197 | static void u300_set_mode(enum clock_event_mode mode, | 199 | static void u300_set_mode(enum clock_event_mode mode, |
198 | struct clock_event_device *evt) | 200 | struct clock_event_device *evt) |
199 | { | 201 | { |
202 | struct u300_clockevent_data *cevdata = | ||
203 | container_of(evt, struct u300_clockevent_data, cevd); | ||
204 | |||
200 | switch (mode) { | 205 | switch (mode) { |
201 | case CLOCK_EVT_MODE_PERIODIC: | 206 | case CLOCK_EVT_MODE_PERIODIC: |
202 | /* Disable interrupts on GPT1 */ | 207 | /* Disable interrupts on GPT1 */ |
@@ -209,7 +214,7 @@ static void u300_set_mode(enum clock_event_mode mode, | |||
209 | * Set the periodic mode to a certain number of ticks per | 214 | * Set the periodic mode to a certain number of ticks per |
210 | * jiffy. | 215 | * jiffy. |
211 | */ | 216 | */ |
212 | writel(TICKS_PER_JIFFY, | 217 | writel(cevdata->ticks_per_jiffy, |
213 | u300_timer_base + U300_TIMER_APP_GPT1TC); | 218 | u300_timer_base + U300_TIMER_APP_GPT1TC); |
214 | /* | 219 | /* |
215 | * Set continuous mode, so the timer keeps triggering | 220 | * Set continuous mode, so the timer keeps triggering |
@@ -305,20 +310,23 @@ static int u300_set_next_event(unsigned long cycles, | |||
305 | return 0; | 310 | return 0; |
306 | } | 311 | } |
307 | 312 | ||
308 | 313 | static struct u300_clockevent_data u300_clockevent_data = { | |
309 | /* Use general purpose timer 1 as clock event */ | 314 | /* Use general purpose timer 1 as clock event */ |
310 | static struct clock_event_device clockevent_u300_1mhz = { | 315 | .cevd = { |
311 | .name = "GPT1", | 316 | .name = "GPT1", |
312 | .rating = 300, /* Reasonably fast and accurate clock event */ | 317 | /* Reasonably fast and accurate clock event */ |
313 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 318 | .rating = 300, |
314 | .set_next_event = u300_set_next_event, | 319 | .features = CLOCK_EVT_FEAT_PERIODIC | |
315 | .set_mode = u300_set_mode, | 320 | CLOCK_EVT_FEAT_ONESHOT, |
321 | .set_next_event = u300_set_next_event, | ||
322 | .set_mode = u300_set_mode, | ||
323 | }, | ||
316 | }; | 324 | }; |
317 | 325 | ||
318 | /* Clock event timer interrupt handler */ | 326 | /* Clock event timer interrupt handler */ |
319 | static irqreturn_t u300_timer_interrupt(int irq, void *dev_id) | 327 | static irqreturn_t u300_timer_interrupt(int irq, void *dev_id) |
320 | { | 328 | { |
321 | struct clock_event_device *evt = &clockevent_u300_1mhz; | 329 | struct clock_event_device *evt = &u300_clockevent_data.cevd; |
322 | /* ACK/Clear timer IRQ for the APP GPT1 Timer */ | 330 | /* ACK/Clear timer IRQ for the APP GPT1 Timer */ |
323 | 331 | ||
324 | writel(U300_TIMER_APP_GPT1IA_IRQ_ACK, | 332 | writel(U300_TIMER_APP_GPT1IA_IRQ_ACK, |
@@ -379,6 +387,8 @@ static void __init u300_timer_init_of(struct device_node *np) | |||
379 | clk_prepare_enable(clk); | 387 | clk_prepare_enable(clk); |
380 | rate = clk_get_rate(clk); | 388 | rate = clk_get_rate(clk); |
381 | 389 | ||
390 | u300_clockevent_data.ticks_per_jiffy = DIV_ROUND_CLOSEST(rate, HZ); | ||
391 | |||
382 | setup_sched_clock(u300_read_sched_clock, 32, rate); | 392 | setup_sched_clock(u300_read_sched_clock, 32, rate); |
383 | 393 | ||
384 | u300_delay_timer.read_current_timer = &u300_read_current_timer; | 394 | u300_delay_timer.read_current_timer = &u300_read_current_timer; |
@@ -428,7 +438,7 @@ static void __init u300_timer_init_of(struct device_node *np) | |||
428 | pr_err("timer: failed to initialize U300 clock source\n"); | 438 | pr_err("timer: failed to initialize U300 clock source\n"); |
429 | 439 | ||
430 | /* Configure and register the clockevent */ | 440 | /* Configure and register the clockevent */ |
431 | clockevents_config_and_register(&clockevent_u300_1mhz, rate, | 441 | clockevents_config_and_register(&u300_clockevent_data.cevd, rate, |
432 | 1, 0xffffffff); | 442 | 1, 0xffffffff); |
433 | 443 | ||
434 | /* | 444 | /* |