Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+42 −0
Original line number Original line Diff line number Diff line
@@ -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] = {
	}
	}
};
};



/*
/*
* 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)
		(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,
	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)
	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)
		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)
					 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)
+3 −1
Original line number Original line Diff line number Diff line
@@ -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 @@
/* 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)
+1 −0
Original line number Original line Diff line number Diff line
@@ -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,