diff options
author | Michel Jaouen <michel.jaouen@stericsson.com> | 2012-08-31 08:21:30 -0400 |
---|---|---|
committer | Mike Turquette <mturquette@linaro.org> | 2012-09-06 20:57:21 -0400 |
commit | 20aee5b6d7738206bfd37b352a97c75627d6fa6d (patch) | |
tree | f45347497f0b6861521ae80246534cfce49748de /drivers/mfd/db8500-prcmu.c | |
parent | 70b1fce2ec3a89e68a35d99e5e9c6c90338b3dd1 (diff) |
mfd: dbx500: Provide a more accurate smp_twd clock
The local timer clock is based on ARM subsystem clock. This patch
obtains a more exact value of that clock by reading PRCMU registers.
Using this increases the accuracy of the local timer events.
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Rickard Andersson <rickard.andersson@stericsson.com>
Signed-off-by: Michel Jaouen <michel.jaouen@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Mike Turquette <mturquette@linaro.org>
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 7040a0081130..6b37e2d6ed8f 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -418,6 +418,9 @@ static struct { | |||
418 | 418 | ||
419 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); | 419 | static atomic_t ac_wake_req_state = ATOMIC_INIT(0); |
420 | 420 | ||
421 | /* Functions definition */ | ||
422 | static void compute_armss_rate(void); | ||
423 | |||
421 | /* Spinlocks */ | 424 | /* Spinlocks */ |
422 | static DEFINE_SPINLOCK(prcmu_lock); | 425 | static DEFINE_SPINLOCK(prcmu_lock); |
423 | static DEFINE_SPINLOCK(clkout_lock); | 426 | static DEFINE_SPINLOCK(clkout_lock); |
@@ -517,6 +520,7 @@ static struct dsiescclk dsiescclk[3] = { | |||
517 | } | 520 | } |
518 | }; | 521 | }; |
519 | 522 | ||
523 | |||
520 | /* | 524 | /* |
521 | * Used by MCDE to setup all necessary PRCMU registers | 525 | * Used by MCDE to setup all necessary PRCMU registers |
522 | */ | 526 | */ |
@@ -1013,6 +1017,7 @@ int db8500_prcmu_set_arm_opp(u8 opp) | |||
1013 | (mb1_transfer.ack.arm_opp != opp)) | 1017 | (mb1_transfer.ack.arm_opp != opp)) |
1014 | r = -EIO; | 1018 | r = -EIO; |
1015 | 1019 | ||
1020 | compute_armss_rate(); | ||
1016 | mutex_unlock(&mb1_transfer.lock); | 1021 | mutex_unlock(&mb1_transfer.lock); |
1017 | 1022 | ||
1018 | return r; | 1023 | return r; |
@@ -1612,6 +1617,7 @@ static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate, | |||
1612 | if ((branch == PLL_FIX) || ((branch == PLL_DIV) && | 1617 | if ((branch == PLL_FIX) || ((branch == PLL_DIV) && |
1613 | (val & PRCM_PLL_FREQ_DIV2EN) && | 1618 | (val & PRCM_PLL_FREQ_DIV2EN) && |
1614 | ((reg == PRCM_PLLSOC0_FREQ) || | 1619 | ((reg == PRCM_PLLSOC0_FREQ) || |
1620 | (reg == PRCM_PLLARM_FREQ) || | ||
1615 | (reg == PRCM_PLLDDR_FREQ)))) | 1621 | (reg == PRCM_PLLDDR_FREQ)))) |
1616 | div *= 2; | 1622 | div *= 2; |
1617 | 1623 | ||
@@ -1661,6 +1667,39 @@ static unsigned long clock_rate(u8 clock) | |||
1661 | else | 1667 | else |
1662 | return 0; | 1668 | return 0; |
1663 | } | 1669 | } |
1670 | static unsigned long latest_armss_rate; | ||
1671 | static unsigned long armss_rate(void) | ||
1672 | { | ||
1673 | return latest_armss_rate; | ||
1674 | } | ||
1675 | |||
1676 | static void compute_armss_rate(void) | ||
1677 | { | ||
1678 | u32 r; | ||
1679 | unsigned long rate; | ||
1680 | |||
1681 | r = readl(PRCM_ARM_CHGCLKREQ); | ||
1682 | |||
1683 | if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) { | ||
1684 | /* External ARMCLKFIX clock */ | ||
1685 | |||
1686 | rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX); | ||
1687 | |||
1688 | /* Check PRCM_ARM_CHGCLKREQ divider */ | ||
1689 | if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL)) | ||
1690 | rate /= 2; | ||
1691 | |||
1692 | /* Check PRCM_ARMCLKFIX_MGT divider */ | ||
1693 | r = readl(PRCM_ARMCLKFIX_MGT); | ||
1694 | r &= PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
1695 | rate /= r; | ||
1696 | |||
1697 | } else {/* ARM PLL */ | ||
1698 | rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV); | ||
1699 | } | ||
1700 | |||
1701 | latest_armss_rate = rate; | ||
1702 | } | ||
1664 | 1703 | ||
1665 | static unsigned long dsiclk_rate(u8 n) | 1704 | static unsigned long dsiclk_rate(u8 n) |
1666 | { | 1705 | { |
@@ -1707,6 +1746,8 @@ unsigned long prcmu_clock_rate(u8 clock) | |||
1707 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | 1746 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); |
1708 | else if (clock == PRCMU_PLLSOC1) | 1747 | else if (clock == PRCMU_PLLSOC1) |
1709 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | 1748 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); |
1749 | else if (clock == PRCMU_ARMSS) | ||
1750 | return armss_rate(); | ||
1710 | else if (clock == PRCMU_PLLDDR) | 1751 | else if (clock == PRCMU_PLLDDR) |
1711 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | 1752 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); |
1712 | else if (clock == PRCMU_PLLDSI) | 1753 | else if (clock == PRCMU_PLLDSI) |
@@ -2693,6 +2734,7 @@ void __init db8500_prcmu_early_init(void) | |||
2693 | handle_simple_irq); | 2734 | handle_simple_irq); |
2694 | set_irq_flags(irq, IRQF_VALID); | 2735 | set_irq_flags(irq, IRQF_VALID); |
2695 | } | 2736 | } |
2737 | compute_armss_rate(); | ||
2696 | } | 2738 | } |
2697 | 2739 | ||
2698 | static void __init init_prcm_registers(void) | 2740 | static void __init init_prcm_registers(void) |