aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
-rw-r--r--arch/arm/mach-omap2/timer.c70
1 files changed, 52 insertions, 18 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 684d2fc3d485..099e4060afe9 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -108,7 +108,7 @@ static int omap2_gp_timer_set_next_event(unsigned long cycles,
108 struct clock_event_device *evt) 108 struct clock_event_device *evt)
109{ 109{
110 __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST, 110 __omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
111 0xffffffff - cycles, 1); 111 0xffffffff - cycles, OMAP_TIMER_POSTED);
112 112
113 return 0; 113 return 0;
114} 114}
@@ -118,7 +118,7 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
118{ 118{
119 u32 period; 119 u32 period;
120 120
121 __omap_dm_timer_stop(&clkev, 1, clkev.rate); 121 __omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
122 122
123 switch (mode) { 123 switch (mode) {
124 case CLOCK_EVT_MODE_PERIODIC: 124 case CLOCK_EVT_MODE_PERIODIC:
@@ -126,10 +126,10 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
126 period -= 1; 126 period -= 1;
127 /* Looks like we need to first set the load value separately */ 127 /* Looks like we need to first set the load value separately */
128 __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, 128 __omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG,
129 0xffffffff - period, 1); 129 0xffffffff - period, OMAP_TIMER_POSTED);
130 __omap_dm_timer_load_start(&clkev, 130 __omap_dm_timer_load_start(&clkev,
131 OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST, 131 OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
132 0xffffffff - period, 1); 132 0xffffffff - period, OMAP_TIMER_POSTED);
133 break; 133 break;
134 case CLOCK_EVT_MODE_ONESHOT: 134 case CLOCK_EVT_MODE_ONESHOT:
135 break; 135 break;
@@ -222,10 +222,24 @@ void __init omap_dmtimer_init(void)
222 } 222 }
223} 223}
224 224
225/**
226 * omap_dm_timer_get_errata - get errata flags for a timer
227 *
228 * Get the timer errata flags that are specific to the OMAP device being used.
229 */
230u32 __init omap_dm_timer_get_errata(void)
231{
232 if (cpu_is_omap24xx())
233 return 0;
234
235 return OMAP_TIMER_ERRATA_I103_I767;
236}
237
225static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, 238static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
226 int gptimer_id, 239 int gptimer_id,
227 const char *fck_source, 240 const char *fck_source,
228 const char *property) 241 const char *property,
242 int posted)
229{ 243{
230 char name[10]; /* 10 = sizeof("gptXX_Xck0") */ 244 char name[10]; /* 10 = sizeof("gptXX_Xck0") */
231 const char *oh_name; 245 const char *oh_name;
@@ -260,9 +274,7 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
260 oh_name = name; 274 oh_name = name;
261 } 275 }
262 276
263 omap_hwmod_setup_one(oh_name);
264 oh = omap_hwmod_lookup(oh_name); 277 oh = omap_hwmod_lookup(oh_name);
265
266 if (!oh) 278 if (!oh)
267 return -ENODEV; 279 return -ENODEV;
268 280
@@ -292,8 +304,6 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
292 if (IS_ERR(timer->fclk)) 304 if (IS_ERR(timer->fclk))
293 return -ENODEV; 305 return -ENODEV;
294 306
295 omap_hwmod_enable(oh);
296
297 /* FIXME: Need to remove hard-coded test on timer ID */ 307 /* FIXME: Need to remove hard-coded test on timer ID */
298 if (gptimer_id != 12) { 308 if (gptimer_id != 12) {
299 struct clk *src; 309 struct clk *src;
@@ -302,19 +312,26 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
302 if (IS_ERR(src)) { 312 if (IS_ERR(src)) {
303 res = -EINVAL; 313 res = -EINVAL;
304 } else { 314 } else {
305 res = __omap_dm_timer_set_source(timer->fclk, src); 315 res = clk_set_parent(timer->fclk, src);
306 if (IS_ERR_VALUE(res)) 316 if (IS_ERR_VALUE(res))
307 pr_warn("%s: %s cannot set source\n", 317 pr_warn("%s: %s cannot set source\n",
308 __func__, oh->name); 318 __func__, oh->name);
309 clk_put(src); 319 clk_put(src);
310 } 320 }
311 } 321 }
322
323 omap_hwmod_setup_one(oh_name);
324 omap_hwmod_enable(oh);
312 __omap_dm_timer_init_regs(timer); 325 __omap_dm_timer_init_regs(timer);
313 __omap_dm_timer_reset(timer, 1, 1);
314 timer->posted = 1;
315 326
316 timer->rate = clk_get_rate(timer->fclk); 327 if (posted)
328 __omap_dm_timer_enable_posted(timer);
329
330 /* Check that the intended posted configuration matches the actual */
331 if (posted != timer->posted)
332 return -EINVAL;
317 333
334 timer->rate = clk_get_rate(timer->fclk);
318 timer->reserved = 1; 335 timer->reserved = 1;
319 336
320 return res; 337 return res;
@@ -326,7 +343,17 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
326{ 343{
327 int res; 344 int res;
328 345
329 res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property); 346 clkev.errata = omap_dm_timer_get_errata();
347
348 /*
349 * For clock-event timers we never read the timer counter and
350 * so we are not impacted by errata i103 and i767. Therefore,
351 * we can safely ignore this errata for clock-event timers.
352 */
353 __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
354
355 res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
356 OMAP_TIMER_POSTED);
330 BUG_ON(res); 357 BUG_ON(res);
331 358
332 omap2_gp_timer_irq.dev_id = &clkev; 359 omap2_gp_timer_irq.dev_id = &clkev;
@@ -359,7 +386,8 @@ static bool use_gptimer_clksrc;
359 */ 386 */
360static cycle_t clocksource_read_cycles(struct clocksource *cs) 387static cycle_t clocksource_read_cycles(struct clocksource *cs)
361{ 388{
362 return (cycle_t)__omap_dm_timer_read_counter(&clksrc, 1); 389 return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
390 OMAP_TIMER_NONPOSTED);
363} 391}
364 392
365static struct clocksource clocksource_gpt = { 393static struct clocksource clocksource_gpt = {
@@ -373,7 +401,8 @@ static struct clocksource clocksource_gpt = {
373static u32 notrace dmtimer_read_sched_clock(void) 401static u32 notrace dmtimer_read_sched_clock(void)
374{ 402{
375 if (clksrc.reserved) 403 if (clksrc.reserved)
376 return __omap_dm_timer_read_counter(&clksrc, 1); 404 return __omap_dm_timer_read_counter(&clksrc,
405 OMAP_TIMER_NONPOSTED);
377 406
378 return 0; 407 return 0;
379} 408}
@@ -451,11 +480,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
451{ 480{
452 int res; 481 int res;
453 482
454 res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL); 483 clksrc.errata = omap_dm_timer_get_errata();
484
485 res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
486 OMAP_TIMER_NONPOSTED);
455 BUG_ON(res); 487 BUG_ON(res);
456 488
457 __omap_dm_timer_load_start(&clksrc, 489 __omap_dm_timer_load_start(&clksrc,
458 OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1); 490 OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0,
491 OMAP_TIMER_NONPOSTED);
459 setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate); 492 setup_sched_clock(dmtimer_read_sched_clock, 32, clksrc.rate);
460 493
461 if (clocksource_register_hz(&clocksource_gpt, clksrc.rate)) 494 if (clocksource_register_hz(&clocksource_gpt, clksrc.rate))
@@ -693,6 +726,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
693 if (timer_dev_attr) 726 if (timer_dev_attr)
694 pdata->timer_capability = timer_dev_attr->timer_capability; 727 pdata->timer_capability = timer_dev_attr->timer_capability;
695 728
729 pdata->timer_errata = omap_dm_timer_get_errata();
696 pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; 730 pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
697 731
698 pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata), 732 pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),