Commit 20aee5b6 authored by Michel Jaouen's avatar Michel Jaouen Committed by Mike Turquette

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: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarRickard Andersson <rickard.andersson@stericsson.com>
Signed-off-by: default avatarMichel Jaouen <michel.jaouen@stericsson.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarMike Turquette <mturquette@linaro.org>
parent 70b1fce2
...@@ -418,6 +418,9 @@ static struct { ...@@ -418,6 +418,9 @@ static struct {
static atomic_t ac_wake_req_state = ATOMIC_INIT(0); static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
/* Functions definition */
static void compute_armss_rate(void);
/* Spinlocks */ /* Spinlocks */
static DEFINE_SPINLOCK(prcmu_lock); static DEFINE_SPINLOCK(prcmu_lock);
static DEFINE_SPINLOCK(clkout_lock); static DEFINE_SPINLOCK(clkout_lock);
...@@ -517,6 +520,7 @@ static struct dsiescclk dsiescclk[3] = { ...@@ -517,6 +520,7 @@ static struct dsiescclk dsiescclk[3] = {
} }
}; };
/* /*
* Used by MCDE to setup all necessary PRCMU registers * Used by MCDE to setup all necessary PRCMU registers
*/ */
...@@ -1013,6 +1017,7 @@ int db8500_prcmu_set_arm_opp(u8 opp) ...@@ -1013,6 +1017,7 @@ int db8500_prcmu_set_arm_opp(u8 opp)
(mb1_transfer.ack.arm_opp != opp)) (mb1_transfer.ack.arm_opp != opp))
r = -EIO; r = -EIO;
compute_armss_rate();
mutex_unlock(&mb1_transfer.lock); mutex_unlock(&mb1_transfer.lock);
return r; return r;
...@@ -1612,6 +1617,7 @@ static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate, ...@@ -1612,6 +1617,7 @@ static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,
if ((branch == PLL_FIX) || ((branch == PLL_DIV) && if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&
(val & PRCM_PLL_FREQ_DIV2EN) && (val & PRCM_PLL_FREQ_DIV2EN) &&
((reg == PRCM_PLLSOC0_FREQ) || ((reg == PRCM_PLLSOC0_FREQ) ||
(reg == PRCM_PLLARM_FREQ) ||
(reg == PRCM_PLLDDR_FREQ)))) (reg == PRCM_PLLDDR_FREQ))))
div *= 2; div *= 2;
...@@ -1661,6 +1667,39 @@ static unsigned long clock_rate(u8 clock) ...@@ -1661,6 +1667,39 @@ static unsigned long clock_rate(u8 clock)
else else
return 0; return 0;
} }
static unsigned long latest_armss_rate;
static unsigned long armss_rate(void)
{
return latest_armss_rate;
}
static void compute_armss_rate(void)
{
u32 r;
unsigned long rate;
r = readl(PRCM_ARM_CHGCLKREQ);
if (r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ) {
/* External ARMCLKFIX clock */
rate = pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_FIX);
/* Check PRCM_ARM_CHGCLKREQ divider */
if (!(r & PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL))
rate /= 2;
/* Check PRCM_ARMCLKFIX_MGT divider */
r = readl(PRCM_ARMCLKFIX_MGT);
r &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
rate /= r;
} else {/* ARM PLL */
rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV);
}
latest_armss_rate = rate;
}
static unsigned long dsiclk_rate(u8 n) static unsigned long dsiclk_rate(u8 n)
{ {
...@@ -1707,6 +1746,8 @@ unsigned long prcmu_clock_rate(u8 clock) ...@@ -1707,6 +1746,8 @@ unsigned long prcmu_clock_rate(u8 clock)
return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
else if (clock == PRCMU_PLLSOC1) else if (clock == PRCMU_PLLSOC1)
return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
else if (clock == PRCMU_ARMSS)
return armss_rate();
else if (clock == PRCMU_PLLDDR) else if (clock == PRCMU_PLLDDR)
return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
else if (clock == PRCMU_PLLDSI) else if (clock == PRCMU_PLLDSI)
...@@ -2693,6 +2734,7 @@ void __init db8500_prcmu_early_init(void) ...@@ -2693,6 +2734,7 @@ void __init db8500_prcmu_early_init(void)
handle_simple_irq); handle_simple_irq);
set_irq_flags(irq, IRQF_VALID); set_irq_flags(irq, IRQF_VALID);
} }
compute_armss_rate();
} }
static void __init init_prcm_registers(void) static void __init init_prcm_registers(void)
......
...@@ -61,7 +61,8 @@ ...@@ -61,7 +61,8 @@
#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2 #define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2
#define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114) #define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114)
#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ 0x1 #define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0)
#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_DIVSEL BIT(16)
#define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98) #define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98)
#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1 #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1
...@@ -140,6 +141,7 @@ ...@@ -140,6 +141,7 @@
/* PRCMU clock/PLL/reset registers */ /* PRCMU clock/PLL/reset registers */
#define PRCM_PLLSOC0_FREQ (_PRCMU_BASE + 0x080) #define PRCM_PLLSOC0_FREQ (_PRCMU_BASE + 0x080)
#define PRCM_PLLSOC1_FREQ (_PRCMU_BASE + 0x084) #define PRCM_PLLSOC1_FREQ (_PRCMU_BASE + 0x084)
#define PRCM_PLLARM_FREQ (_PRCMU_BASE + 0x088)
#define PRCM_PLLDDR_FREQ (_PRCMU_BASE + 0x08C) #define PRCM_PLLDDR_FREQ (_PRCMU_BASE + 0x08C)
#define PRCM_PLL_FREQ_D_SHIFT 0 #define PRCM_PLL_FREQ_D_SHIFT 0
#define PRCM_PLL_FREQ_D_MASK BITS(0, 7) #define PRCM_PLL_FREQ_D_MASK BITS(0, 7)
......
...@@ -136,6 +136,7 @@ enum prcmu_clock { ...@@ -136,6 +136,7 @@ enum prcmu_clock {
PRCMU_TIMCLK, PRCMU_TIMCLK,
PRCMU_PLLSOC0, PRCMU_PLLSOC0,
PRCMU_PLLSOC1, PRCMU_PLLSOC1,
PRCMU_ARMSS,
PRCMU_PLLDDR, PRCMU_PLLDDR,
PRCMU_PLLDSI, PRCMU_PLLDSI,
PRCMU_DSI0CLK, PRCMU_DSI0CLK,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment