diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 9 | ||||
-rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 110 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/dmtimer.h | 35 |
3 files changed, 149 insertions, 5 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index f1e3ec1c16e..1140e98c977 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -44,6 +44,9 @@ | |||
44 | #include <plat/common.h> | 44 | #include <plat/common.h> |
45 | #include <plat/omap_hwmod.h> | 45 | #include <plat/omap_hwmod.h> |
46 | #include <plat/omap_device.h> | 46 | #include <plat/omap_device.h> |
47 | #include <plat/omap-pm.h> | ||
48 | |||
49 | #include "powerdomain.h" | ||
47 | 50 | ||
48 | /* Parent clocks, eventually these will come from the clock framework */ | 51 | /* Parent clocks, eventually these will come from the clock framework */ |
49 | 52 | ||
@@ -433,6 +436,7 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) | |||
433 | struct dmtimer_platform_data *pdata; | 436 | struct dmtimer_platform_data *pdata; |
434 | struct omap_device *od; | 437 | struct omap_device *od; |
435 | struct omap_timer_capability_dev_attr *timer_dev_attr; | 438 | struct omap_timer_capability_dev_attr *timer_dev_attr; |
439 | struct powerdomain *pwrdm; | ||
436 | 440 | ||
437 | pr_debug("%s: %s\n", __func__, oh->name); | 441 | pr_debug("%s: %s\n", __func__, oh->name); |
438 | 442 | ||
@@ -467,6 +471,11 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused) | |||
467 | if ((sys_timer_reserved >> (id - 1)) & 0x1) | 471 | if ((sys_timer_reserved >> (id - 1)) & 0x1) |
468 | pdata->reserved = 1; | 472 | pdata->reserved = 1; |
469 | 473 | ||
474 | pwrdm = omap_hwmod_get_pwrdm(oh); | ||
475 | pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); | ||
476 | #ifdef CONFIG_PM | ||
477 | pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; | ||
478 | #endif | ||
470 | od = omap_device_build(name, id, oh, pdata, sizeof(*pdata), | 479 | od = omap_device_build(name, id, oh, pdata, sizeof(*pdata), |
471 | omap2_dmtimer_latency, | 480 | omap2_dmtimer_latency, |
472 | ARRAY_SIZE(omap2_dmtimer_latency), | 481 | ARRAY_SIZE(omap2_dmtimer_latency), |
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index c8df3c36b3a..43eb75038ba 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
@@ -77,6 +77,29 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, | |||
77 | __omap_dm_timer_write(timer, reg, value, timer->posted); | 77 | __omap_dm_timer_write(timer, reg, value, timer->posted); |
78 | } | 78 | } |
79 | 79 | ||
80 | static void omap_timer_restore_context(struct omap_dm_timer *timer) | ||
81 | { | ||
82 | omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_OFFSET, | ||
83 | timer->context.tiocp_cfg); | ||
84 | if (timer->revision > 1) | ||
85 | __raw_writel(timer->context.tistat, timer->sys_stat); | ||
86 | |||
87 | __raw_writel(timer->context.tisr, timer->irq_stat); | ||
88 | omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, | ||
89 | timer->context.twer); | ||
90 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, | ||
91 | timer->context.tcrr); | ||
92 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, | ||
93 | timer->context.tldr); | ||
94 | omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, | ||
95 | timer->context.tmar); | ||
96 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, | ||
97 | timer->context.tsicr); | ||
98 | __raw_writel(timer->context.tier, timer->irq_ena); | ||
99 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, | ||
100 | timer->context.tclr); | ||
101 | } | ||
102 | |||
80 | static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) | 103 | static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) |
81 | { | 104 | { |
82 | int c; | 105 | int c; |
@@ -96,12 +119,14 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer) | |||
96 | 119 | ||
97 | static void omap_dm_timer_reset(struct omap_dm_timer *timer) | 120 | static void omap_dm_timer_reset(struct omap_dm_timer *timer) |
98 | { | 121 | { |
122 | omap_dm_timer_enable(timer); | ||
99 | if (timer->pdev->id != 1) { | 123 | if (timer->pdev->id != 1) { |
100 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); | 124 | omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06); |
101 | omap_dm_timer_wait_for_reset(timer); | 125 | omap_dm_timer_wait_for_reset(timer); |
102 | } | 126 | } |
103 | 127 | ||
104 | __omap_dm_timer_reset(timer, 0, 0); | 128 | __omap_dm_timer_reset(timer, 0, 0); |
129 | omap_dm_timer_disable(timer); | ||
105 | timer->posted = 1; | 130 | timer->posted = 1; |
106 | } | 131 | } |
107 | 132 | ||
@@ -117,8 +142,6 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer) | |||
117 | return -EINVAL; | 142 | return -EINVAL; |
118 | } | 143 | } |
119 | 144 | ||
120 | omap_dm_timer_enable(timer); | ||
121 | |||
122 | if (pdata->needs_manual_reset) | 145 | if (pdata->needs_manual_reset) |
123 | omap_dm_timer_reset(timer); | 146 | omap_dm_timer_reset(timer); |
124 | 147 | ||
@@ -193,7 +216,6 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_request_specific); | |||
193 | 216 | ||
194 | void omap_dm_timer_free(struct omap_dm_timer *timer) | 217 | void omap_dm_timer_free(struct omap_dm_timer *timer) |
195 | { | 218 | { |
196 | omap_dm_timer_disable(timer); | ||
197 | clk_put(timer->fclk); | 219 | clk_put(timer->fclk); |
198 | 220 | ||
199 | WARN_ON(!timer->reserved); | 221 | WARN_ON(!timer->reserved); |
@@ -275,6 +297,11 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask); | |||
275 | 297 | ||
276 | void omap_dm_timer_trigger(struct omap_dm_timer *timer) | 298 | void omap_dm_timer_trigger(struct omap_dm_timer *timer) |
277 | { | 299 | { |
300 | if (unlikely(pm_runtime_suspended(&timer->pdev->dev))) { | ||
301 | pr_err("%s: timer%d not enabled.\n", __func__, timer->id); | ||
302 | return; | ||
303 | } | ||
304 | |||
278 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); | 305 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); |
279 | } | 306 | } |
280 | EXPORT_SYMBOL_GPL(omap_dm_timer_trigger); | 307 | EXPORT_SYMBOL_GPL(omap_dm_timer_trigger); |
@@ -283,11 +310,23 @@ void omap_dm_timer_start(struct omap_dm_timer *timer) | |||
283 | { | 310 | { |
284 | u32 l; | 311 | u32 l; |
285 | 312 | ||
313 | omap_dm_timer_enable(timer); | ||
314 | |||
315 | if (timer->loses_context) { | ||
316 | u32 ctx_loss_cnt_after = | ||
317 | timer->get_context_loss_count(&timer->pdev->dev); | ||
318 | if (ctx_loss_cnt_after != timer->ctx_loss_count) | ||
319 | omap_timer_restore_context(timer); | ||
320 | } | ||
321 | |||
286 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 322 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
287 | if (!(l & OMAP_TIMER_CTRL_ST)) { | 323 | if (!(l & OMAP_TIMER_CTRL_ST)) { |
288 | l |= OMAP_TIMER_CTRL_ST; | 324 | l |= OMAP_TIMER_CTRL_ST; |
289 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 325 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
290 | } | 326 | } |
327 | |||
328 | /* Save the context */ | ||
329 | timer->context.tclr = l; | ||
291 | } | 330 | } |
292 | EXPORT_SYMBOL_GPL(omap_dm_timer_start); | 331 | EXPORT_SYMBOL_GPL(omap_dm_timer_start); |
293 | 332 | ||
@@ -311,9 +350,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source) | |||
311 | if (source < 0 || source >= 3) | 350 | if (source < 0 || source >= 3) |
312 | return -EINVAL; | 351 | return -EINVAL; |
313 | 352 | ||
314 | omap_dm_timer_disable(timer); | ||
315 | ret = pdata->set_timer_src(timer->pdev, source); | 353 | ret = pdata->set_timer_src(timer->pdev, source); |
316 | omap_dm_timer_enable(timer); | ||
317 | 354 | ||
318 | return ret; | 355 | return ret; |
319 | } | 356 | } |
@@ -324,6 +361,7 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, | |||
324 | { | 361 | { |
325 | u32 l; | 362 | u32 l; |
326 | 363 | ||
364 | omap_dm_timer_enable(timer); | ||
327 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 365 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
328 | if (autoreload) | 366 | if (autoreload) |
329 | l |= OMAP_TIMER_CTRL_AR; | 367 | l |= OMAP_TIMER_CTRL_AR; |
@@ -333,6 +371,10 @@ void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, | |||
333 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); | 371 | omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load); |
334 | 372 | ||
335 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); | 373 | omap_dm_timer_write_reg(timer, OMAP_TIMER_TRIGGER_REG, 0); |
374 | /* Save the context */ | ||
375 | timer->context.tclr = l; | ||
376 | timer->context.tldr = load; | ||
377 | omap_dm_timer_disable(timer); | ||
336 | } | 378 | } |
337 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load); | 379 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load); |
338 | 380 | ||
@@ -342,6 +384,15 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, | |||
342 | { | 384 | { |
343 | u32 l; | 385 | u32 l; |
344 | 386 | ||
387 | omap_dm_timer_enable(timer); | ||
388 | |||
389 | if (timer->loses_context) { | ||
390 | u32 ctx_loss_cnt_after = | ||
391 | timer->get_context_loss_count(&timer->pdev->dev); | ||
392 | if (ctx_loss_cnt_after != timer->ctx_loss_count) | ||
393 | omap_timer_restore_context(timer); | ||
394 | } | ||
395 | |||
345 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 396 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
346 | if (autoreload) { | 397 | if (autoreload) { |
347 | l |= OMAP_TIMER_CTRL_AR; | 398 | l |= OMAP_TIMER_CTRL_AR; |
@@ -352,6 +403,11 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, | |||
352 | l |= OMAP_TIMER_CTRL_ST; | 403 | l |= OMAP_TIMER_CTRL_ST; |
353 | 404 | ||
354 | __omap_dm_timer_load_start(timer, l, load, timer->posted); | 405 | __omap_dm_timer_load_start(timer, l, load, timer->posted); |
406 | |||
407 | /* Save the context */ | ||
408 | timer->context.tclr = l; | ||
409 | timer->context.tldr = load; | ||
410 | timer->context.tcrr = load; | ||
355 | } | 411 | } |
356 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); | 412 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start); |
357 | 413 | ||
@@ -360,6 +416,7 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, | |||
360 | { | 416 | { |
361 | u32 l; | 417 | u32 l; |
362 | 418 | ||
419 | omap_dm_timer_enable(timer); | ||
363 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 420 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
364 | if (enable) | 421 | if (enable) |
365 | l |= OMAP_TIMER_CTRL_CE; | 422 | l |= OMAP_TIMER_CTRL_CE; |
@@ -367,6 +424,11 @@ void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, | |||
367 | l &= ~OMAP_TIMER_CTRL_CE; | 424 | l &= ~OMAP_TIMER_CTRL_CE; |
368 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 425 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
369 | omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); | 426 | omap_dm_timer_write_reg(timer, OMAP_TIMER_MATCH_REG, match); |
427 | |||
428 | /* Save the context */ | ||
429 | timer->context.tclr = l; | ||
430 | timer->context.tmar = match; | ||
431 | omap_dm_timer_disable(timer); | ||
370 | } | 432 | } |
371 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_match); | 433 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_match); |
372 | 434 | ||
@@ -375,6 +437,7 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, | |||
375 | { | 437 | { |
376 | u32 l; | 438 | u32 l; |
377 | 439 | ||
440 | omap_dm_timer_enable(timer); | ||
378 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 441 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
379 | l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | | 442 | l &= ~(OMAP_TIMER_CTRL_GPOCFG | OMAP_TIMER_CTRL_SCPWM | |
380 | OMAP_TIMER_CTRL_PT | (0x03 << 10)); | 443 | OMAP_TIMER_CTRL_PT | (0x03 << 10)); |
@@ -384,6 +447,10 @@ void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, | |||
384 | l |= OMAP_TIMER_CTRL_PT; | 447 | l |= OMAP_TIMER_CTRL_PT; |
385 | l |= trigger << 10; | 448 | l |= trigger << 10; |
386 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 449 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
450 | |||
451 | /* Save the context */ | ||
452 | timer->context.tclr = l; | ||
453 | omap_dm_timer_disable(timer); | ||
387 | } | 454 | } |
388 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm); | 455 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_pwm); |
389 | 456 | ||
@@ -391,6 +458,7 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) | |||
391 | { | 458 | { |
392 | u32 l; | 459 | u32 l; |
393 | 460 | ||
461 | omap_dm_timer_enable(timer); | ||
394 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); | 462 | l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); |
395 | l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); | 463 | l &= ~(OMAP_TIMER_CTRL_PRE | (0x07 << 2)); |
396 | if (prescaler >= 0x00 && prescaler <= 0x07) { | 464 | if (prescaler >= 0x00 && prescaler <= 0x07) { |
@@ -398,13 +466,23 @@ void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler) | |||
398 | l |= prescaler << 2; | 466 | l |= prescaler << 2; |
399 | } | 467 | } |
400 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); | 468 | omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l); |
469 | |||
470 | /* Save the context */ | ||
471 | timer->context.tclr = l; | ||
472 | omap_dm_timer_disable(timer); | ||
401 | } | 473 | } |
402 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler); | 474 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler); |
403 | 475 | ||
404 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, | 476 | void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, |
405 | unsigned int value) | 477 | unsigned int value) |
406 | { | 478 | { |
479 | omap_dm_timer_enable(timer); | ||
407 | __omap_dm_timer_int_enable(timer, value); | 480 | __omap_dm_timer_int_enable(timer, value); |
481 | |||
482 | /* Save the context */ | ||
483 | timer->context.tier = value; | ||
484 | timer->context.twer = value; | ||
485 | omap_dm_timer_disable(timer); | ||
408 | } | 486 | } |
409 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); | 487 | EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable); |
410 | 488 | ||
@@ -412,6 +490,11 @@ unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer) | |||
412 | { | 490 | { |
413 | unsigned int l; | 491 | unsigned int l; |
414 | 492 | ||
493 | if (unlikely(pm_runtime_suspended(&timer->pdev->dev))) { | ||
494 | pr_err("%s: timer%d not enabled.\n", __func__, timer->id); | ||
495 | return 0; | ||
496 | } | ||
497 | |||
415 | l = __raw_readl(timer->irq_stat); | 498 | l = __raw_readl(timer->irq_stat); |
416 | 499 | ||
417 | return l; | 500 | return l; |
@@ -421,18 +504,33 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status); | |||
421 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) | 504 | void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value) |
422 | { | 505 | { |
423 | __omap_dm_timer_write_status(timer, value); | 506 | __omap_dm_timer_write_status(timer, value); |
507 | /* Save the context */ | ||
508 | timer->context.tisr = value; | ||
424 | } | 509 | } |
425 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); | 510 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_status); |
426 | 511 | ||
427 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) | 512 | unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer) |
428 | { | 513 | { |
514 | if (unlikely(pm_runtime_suspended(&timer->pdev->dev))) { | ||
515 | pr_err("%s: timer%d not enabled.\n", __func__, timer->id); | ||
516 | return 0; | ||
517 | } | ||
518 | |||
429 | return __omap_dm_timer_read_counter(timer, timer->posted); | 519 | return __omap_dm_timer_read_counter(timer, timer->posted); |
430 | } | 520 | } |
431 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); | 521 | EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter); |
432 | 522 | ||
433 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) | 523 | void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value) |
434 | { | 524 | { |
525 | if (unlikely(pm_runtime_suspended(&timer->pdev->dev))) { | ||
526 | pr_err("%s: timer%d not enabled.\n", __func__, timer->id); | ||
527 | return; | ||
528 | } | ||
529 | |||
435 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); | 530 | omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, value); |
531 | |||
532 | /* Save the context */ | ||
533 | timer->context.tcrr = value; | ||
436 | } | 534 | } |
437 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter); | 535 | EXPORT_SYMBOL_GPL(omap_dm_timer_write_counter); |
438 | 536 | ||
@@ -511,6 +609,8 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev) | |||
511 | timer->irq = irq->start; | 609 | timer->irq = irq->start; |
512 | timer->reserved = pdata->reserved; | 610 | timer->reserved = pdata->reserved; |
513 | timer->pdev = pdev; | 611 | timer->pdev = pdev; |
612 | timer->loses_context = pdata->loses_context; | ||
613 | timer->get_context_loss_count = pdata->get_context_loss_count; | ||
514 | 614 | ||
515 | /* Skip pm_runtime_enable for OMAP1 */ | 615 | /* Skip pm_runtime_enable for OMAP1 */ |
516 | if (!pdata->needs_manual_reset) { | 616 | if (!pdata->needs_manual_reset) { |
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h index 29764c34f57..9519d87179e 100644 --- a/arch/arm/plat-omap/include/plat/dmtimer.h +++ b/arch/arm/plat-omap/include/plat/dmtimer.h | |||
@@ -73,11 +73,38 @@ struct omap_timer_capability_dev_attr { | |||
73 | struct omap_dm_timer; | 73 | struct omap_dm_timer; |
74 | struct clk; | 74 | struct clk; |
75 | 75 | ||
76 | struct timer_regs { | ||
77 | u32 tidr; | ||
78 | u32 tiocp_cfg; | ||
79 | u32 tistat; | ||
80 | u32 tisr; | ||
81 | u32 tier; | ||
82 | u32 twer; | ||
83 | u32 tclr; | ||
84 | u32 tcrr; | ||
85 | u32 tldr; | ||
86 | u32 ttrg; | ||
87 | u32 twps; | ||
88 | u32 tmar; | ||
89 | u32 tcar1; | ||
90 | u32 tsicr; | ||
91 | u32 tcar2; | ||
92 | u32 tpir; | ||
93 | u32 tnir; | ||
94 | u32 tcvr; | ||
95 | u32 tocr; | ||
96 | u32 towr; | ||
97 | }; | ||
98 | |||
76 | struct dmtimer_platform_data { | 99 | struct dmtimer_platform_data { |
77 | int (*set_timer_src)(struct platform_device *pdev, int source); | 100 | int (*set_timer_src)(struct platform_device *pdev, int source); |
78 | int timer_ip_version; | 101 | int timer_ip_version; |
79 | u32 needs_manual_reset:1; | 102 | u32 needs_manual_reset:1; |
80 | bool reserved; | 103 | bool reserved; |
104 | |||
105 | bool loses_context; | ||
106 | |||
107 | u32 (*get_context_loss_count)(struct device *dev); | ||
81 | }; | 108 | }; |
82 | 109 | ||
83 | struct omap_dm_timer *omap_dm_timer_request(void); | 110 | struct omap_dm_timer *omap_dm_timer_request(void); |
@@ -245,8 +272,14 @@ struct omap_dm_timer { | |||
245 | unsigned long rate; | 272 | unsigned long rate; |
246 | unsigned reserved:1; | 273 | unsigned reserved:1; |
247 | unsigned posted:1; | 274 | unsigned posted:1; |
275 | struct timer_regs context; | ||
276 | bool loses_context; | ||
277 | int ctx_loss_count; | ||
278 | int revision; | ||
248 | struct platform_device *pdev; | 279 | struct platform_device *pdev; |
249 | struct list_head node; | 280 | struct list_head node; |
281 | |||
282 | u32 (*get_context_loss_count)(struct device *dev); | ||
250 | }; | 283 | }; |
251 | 284 | ||
252 | int omap_dm_timer_prepare(struct omap_dm_timer *timer); | 285 | int omap_dm_timer_prepare(struct omap_dm_timer *timer); |
@@ -278,6 +311,7 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) | |||
278 | /* Assume v1 ip if bits [31:16] are zero */ | 311 | /* Assume v1 ip if bits [31:16] are zero */ |
279 | tidr = __raw_readl(timer->io_base); | 312 | tidr = __raw_readl(timer->io_base); |
280 | if (!(tidr >> 16)) { | 313 | if (!(tidr >> 16)) { |
314 | timer->revision = 1; | ||
281 | timer->sys_stat = timer->io_base + | 315 | timer->sys_stat = timer->io_base + |
282 | OMAP_TIMER_V1_SYS_STAT_OFFSET; | 316 | OMAP_TIMER_V1_SYS_STAT_OFFSET; |
283 | timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET; | 317 | timer->irq_stat = timer->io_base + OMAP_TIMER_V1_STAT_OFFSET; |
@@ -286,6 +320,7 @@ static inline void __omap_dm_timer_init_regs(struct omap_dm_timer *timer) | |||
286 | timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET; | 320 | timer->pend = timer->io_base + _OMAP_TIMER_WRITE_PEND_OFFSET; |
287 | timer->func_base = timer->io_base; | 321 | timer->func_base = timer->io_base; |
288 | } else { | 322 | } else { |
323 | timer->revision = 2; | ||
289 | timer->sys_stat = 0; | 324 | timer->sys_stat = 0; |
290 | timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS; | 325 | timer->irq_stat = timer->io_base + OMAP_TIMER_V2_IRQSTATUS; |
291 | timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET; | 326 | timer->irq_ena = timer->io_base + OMAP_TIMER_V2_IRQENABLE_SET; |