diff options
author | Michel Jaouen <michel.jaouen@stericsson.com> | 2012-08-31 08:21:30 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-23 14:51:34 -0400 |
commit | 804971ec3793d30f40c1a74775dd3fe89deb461a (patch) | |
tree | edec886d66c3b2b02c4030cb679d730156abe2e2 /drivers/mfd/db8500-prcmu.c | |
parent | 0dd96360e21ec7963aeba253261db87a32e728c6 (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: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/db8500-prcmu.c')
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 0e63cdd9b52a..6fb11b76071e 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); |
@@ -1013,6 +1016,7 @@ int db8500_prcmu_set_arm_opp(u8 opp) | |||
1013 | (mb1_transfer.ack.arm_opp != opp)) | 1016 | (mb1_transfer.ack.arm_opp != opp)) |
1014 | r = -EIO; | 1017 | r = -EIO; |
1015 | 1018 | ||
1019 | compute_armss_rate(); | ||
1016 | mutex_unlock(&mb1_transfer.lock); | 1020 | mutex_unlock(&mb1_transfer.lock); |
1017 | 1021 | ||
1018 | return r; | 1022 | return r; |
@@ -1612,6 +1616,7 @@ static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate, | |||
1612 | if ((branch == PLL_FIX) || ((branch == PLL_DIV) && | 1616 | if ((branch == PLL_FIX) || ((branch == PLL_DIV) && |
1613 | (val & PRCM_PLL_FREQ_DIV2EN) && | 1617 | (val & PRCM_PLL_FREQ_DIV2EN) && |
1614 | ((reg == PRCM_PLLSOC0_FREQ) || | 1618 | ((reg == PRCM_PLLSOC0_FREQ) || |
1619 | (reg == PRCM_PLLARM_FREQ) || | ||
1615 | (reg == PRCM_PLLDDR_FREQ)))) | 1620 | (reg == PRCM_PLLDDR_FREQ)))) |
1616 | div *= 2; | 1621 | div *= 2; |
1617 | 1622 | ||
@@ -1661,6 +1666,39 @@ static unsigned long clock_rate(u8 clock) | |||
1661 | else | 1666 | else |
1662 | return 0; | 1667 | return 0; |
1663 | } | 1668 | } |
1669 | static unsigned long latest_armss_rate; | ||
1670 | static unsigned long armss_rate(void) | ||
1671 | { | ||
1672 | return latest_armss_rate; | ||
1673 | } | ||
1674 | |||
1675 | static void compute_armss_rate(void) | ||
1676 | { | ||
1677 | u32 r; | ||
1678 | unsigned long rate; | ||
1679 | |||
1680 | r = readl(PRCM_ARM_CHGCLKREQ); | ||
1681 | |||
1682 | if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) { | ||
1683 | /* External ARMCLKFIX clock */ | ||
1684 | |||
1685 | rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX); | ||
1686 | |||
1687 | /* Check PRCM_ARM_CHGCLKREQ divider */ | ||
1688 | if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL)) | ||
1689 | rate /= 2; | ||
1690 | |||
1691 | /* Check PRCM_ARMCLKFIX_MGT divider */ | ||
1692 | r = readl(PRCM_ARMCLKFIX_MGT); | ||
1693 | r &= PRCM_CLK_MGT_CLKPLLDIV_MASK; | ||
1694 | rate /= r; | ||
1695 | |||
1696 | } else {/* ARM PLL */ | ||
1697 | rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV); | ||
1698 | } | ||
1699 | |||
1700 | latest_armss_rate = rate; | ||
1701 | } | ||
1664 | 1702 | ||
1665 | static unsigned long dsiclk_rate(u8 n) | 1703 | static unsigned long dsiclk_rate(u8 n) |
1666 | { | 1704 | { |
@@ -1707,6 +1745,8 @@ unsigned long prcmu_clock_rate(u8 clock) | |||
1707 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | 1745 | return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); |
1708 | else if (clock == PRCMU_PLLSOC1) | 1746 | else if (clock == PRCMU_PLLSOC1) |
1709 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | 1747 | return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); |
1748 | else if (clock == PRCMU_ARMSS) | ||
1749 | return armss_rate(); | ||
1710 | else if (clock == PRCMU_PLLDDR) | 1750 | else if (clock == PRCMU_PLLDDR) |
1711 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); | 1751 | return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); |
1712 | else if (clock == PRCMU_PLLDSI) | 1752 | else if (clock == PRCMU_PLLDSI) |
@@ -2693,6 +2733,7 @@ void __init db8500_prcmu_early_init(void) | |||
2693 | handle_simple_irq); | 2733 | handle_simple_irq); |
2694 | set_irq_flags(irq, IRQF_VALID); | 2734 | set_irq_flags(irq, IRQF_VALID); |
2695 | } | 2735 | } |
2736 | compute_armss_rate(); | ||
2696 | } | 2737 | } |
2697 | 2738 | ||
2698 | static void __init init_prcm_registers(void) | 2739 | static void __init init_prcm_registers(void) |