diff options
Diffstat (limited to 'arch/arm/mach-omap2/timer.c')
| -rw-r--r-- | arch/arm/mach-omap2/timer.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 4f61148ec168..7d45c84c69ba 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | 54 | ||
| 55 | #include "soc.h" | 55 | #include "soc.h" |
| 56 | #include "common.h" | 56 | #include "common.h" |
| 57 | #include "control.h" | ||
| 57 | #include "powerdomain.h" | 58 | #include "powerdomain.h" |
| 58 | #include "omap-secure.h" | 59 | #include "omap-secure.h" |
| 59 | 60 | ||
| @@ -496,7 +497,8 @@ static void __init realtime_counter_init(void) | |||
| 496 | void __iomem *base; | 497 | void __iomem *base; |
| 497 | static struct clk *sys_clk; | 498 | static struct clk *sys_clk; |
| 498 | unsigned long rate; | 499 | unsigned long rate; |
| 499 | unsigned int reg, num, den; | 500 | unsigned int reg; |
| 501 | unsigned long long num, den; | ||
| 500 | 502 | ||
| 501 | base = ioremap(REALTIME_COUNTER_BASE, SZ_32); | 503 | base = ioremap(REALTIME_COUNTER_BASE, SZ_32); |
| 502 | if (!base) { | 504 | if (!base) { |
| @@ -511,13 +513,42 @@ static void __init realtime_counter_init(void) | |||
| 511 | } | 513 | } |
| 512 | 514 | ||
| 513 | rate = clk_get_rate(sys_clk); | 515 | rate = clk_get_rate(sys_clk); |
| 516 | |||
| 517 | if (soc_is_dra7xx()) { | ||
| 518 | /* | ||
| 519 | * Errata i856 says the 32.768KHz crystal does not start at | ||
| 520 | * power on, so the CPU falls back to an emulated 32KHz clock | ||
| 521 | * based on sysclk / 610 instead. This causes the master counter | ||
| 522 | * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2 | ||
| 523 | * (OR sysclk * 75 / 244) | ||
| 524 | * | ||
| 525 | * This affects at least the DRA7/AM572x 1.0, 1.1 revisions. | ||
| 526 | * Of course any board built without a populated 32.768KHz | ||
| 527 | * crystal would also need this fix even if the CPU is fixed | ||
| 528 | * later. | ||
| 529 | * | ||
| 530 | * Either case can be detected by using the two speedselect bits | ||
| 531 | * If they are not 0, then the 32.768KHz clock driving the | ||
| 532 | * coarse counter that corrects the fine counter every time it | ||
| 533 | * ticks is actually rate/610 rather than 32.768KHz and we | ||
| 534 | * should compensate to avoid the 570ppm (at 20MHz, much worse | ||
| 535 | * at other rates) too fast system time. | ||
| 536 | */ | ||
| 537 | reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP); | ||
| 538 | if (reg & DRA7_SPEEDSELECT_MASK) { | ||
| 539 | num = 75; | ||
| 540 | den = 244; | ||
| 541 | goto sysclk1_based; | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 514 | /* Numerator/denumerator values refer TRM Realtime Counter section */ | 545 | /* Numerator/denumerator values refer TRM Realtime Counter section */ |
| 515 | switch (rate) { | 546 | switch (rate) { |
| 516 | case 1200000: | 547 | case 12000000: |
| 517 | num = 64; | 548 | num = 64; |
| 518 | den = 125; | 549 | den = 125; |
| 519 | break; | 550 | break; |
| 520 | case 1300000: | 551 | case 13000000: |
| 521 | num = 768; | 552 | num = 768; |
| 522 | den = 1625; | 553 | den = 1625; |
| 523 | break; | 554 | break; |
| @@ -529,11 +560,11 @@ static void __init realtime_counter_init(void) | |||
| 529 | num = 192; | 560 | num = 192; |
| 530 | den = 625; | 561 | den = 625; |
| 531 | break; | 562 | break; |
| 532 | case 2600000: | 563 | case 26000000: |
| 533 | num = 384; | 564 | num = 384; |
| 534 | den = 1625; | 565 | den = 1625; |
| 535 | break; | 566 | break; |
| 536 | case 2700000: | 567 | case 27000000: |
| 537 | num = 256; | 568 | num = 256; |
| 538 | den = 1125; | 569 | den = 1125; |
| 539 | break; | 570 | break; |
| @@ -545,6 +576,7 @@ static void __init realtime_counter_init(void) | |||
| 545 | break; | 576 | break; |
| 546 | } | 577 | } |
| 547 | 578 | ||
| 579 | sysclk1_based: | ||
| 548 | /* Program numerator and denumerator registers */ | 580 | /* Program numerator and denumerator registers */ |
| 549 | reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) & | 581 | reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) & |
| 550 | NUMERATOR_DENUMERATOR_MASK; | 582 | NUMERATOR_DENUMERATOR_MASK; |
| @@ -556,7 +588,7 @@ static void __init realtime_counter_init(void) | |||
| 556 | reg |= den; | 588 | reg |= den; |
| 557 | writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); | 589 | writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET); |
| 558 | 590 | ||
| 559 | arch_timer_freq = (rate / den) * num; | 591 | arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den); |
| 560 | set_cntfreq(); | 592 | set_cntfreq(); |
| 561 | 593 | ||
| 562 | iounmap(base); | 594 | iounmap(base); |
