aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/db8500-prcmu.c
diff options
context:
space:
mode:
authorMichel Jaouen <michel.jaouen@stericsson.com>2012-08-31 08:21:30 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-09-23 14:51:34 -0400
commit804971ec3793d30f40c1a74775dd3fe89deb461a (patch)
treeedec886d66c3b2b02c4030cb679d730156abe2e2 /drivers/mfd/db8500-prcmu.c
parent0dd96360e21ec7963aeba253261db87a32e728c6 (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.c41
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
419static atomic_t ac_wake_req_state = ATOMIC_INIT(0); 419static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
420 420
421/* Functions definition */
422static void compute_armss_rate(void);
423
421/* Spinlocks */ 424/* Spinlocks */
422static DEFINE_SPINLOCK(prcmu_lock); 425static DEFINE_SPINLOCK(prcmu_lock);
423static DEFINE_SPINLOCK(clkout_lock); 426static 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}
1669static unsigned long latest_armss_rate;
1670static unsigned long armss_rate(void)
1671{
1672 return latest_armss_rate;
1673}
1674
1675static 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
1665static unsigned long dsiclk_rate(u8 n) 1703static 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
2698static void __init init_prcm_registers(void) 2739static void __init init_prcm_registers(void)