summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2015-01-06 15:44:00 +0100
committerPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2017-03-09 01:39:58 +0100
commit0eb6d4d6523488e84561712d1a65df9c40c9f3fa (patch)
tree26a0215fc549ec8f18a520dd94a9c06dd11be582 /arch
parent0574f786d3c85ab1a9fe9ee8ade65e3ae83e18a4 (diff)
ARM: sun6i: Wait for PLL lock bit on PLL update
This unifies the handling of PLL updates for sun6i (A31) by waiting for the PLL lock bit of an updated PLL. This changes the previous practice of either waiting for a "magic" duration using sdelay() or not waiting at all. Note, that we can't use a timer-based timeout, as the PLL update may affect the timekeeping.
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun6i.h2
-rw-r--r--arch/arm/mach-sunxi/clock_sun6i.c33
2 files changed, 33 insertions, 2 deletions
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index 3f87672c62..633e158c6a 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -178,6 +178,8 @@ struct sunxi_ccm_reg {
#define CPU_CLK_SRC_OSC24M 1
#define CPU_CLK_SRC_PLL1 2
+#define CCM_PLLx_CTRL_LOCK (0x1 << 28)
+
#define CCM_PLL1_CTRL_M(n) ((((n) - 1) & 0x3) << 0)
#define CCM_PLL1_CTRL_K(n) ((((n) - 1) & 0x3) << 4)
#define CCM_PLL1_CTRL_N(n) ((((n) - 1) & 0x1f) << 8)
diff --git a/arch/arm/mach-sunxi/clock_sun6i.c b/arch/arm/mach-sunxi/clock_sun6i.c
index d123b3acb2..d9b4a2581b 100644
--- a/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/arch/arm/mach-sunxi/clock_sun6i.c
@@ -89,6 +89,32 @@ void clock_init_uart(void)
#endif
}
+int clock_twi_onoff(int port, int state)
+{
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ if (port > 3)
+ return -1;
+
+ /* set the apb clock gate for twi */
+ if (state)
+ setbits_le32(&ccm->apb2_gate,
+ CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT+port));
+ else
+ clrbits_le32(&ccm->apb2_gate,
+ CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT+port));
+
+ return 0;
+}
+
+static inline void wait_for_pll_lock(u32 *reg)
+{
+ do {
+ /* spin */
+ } while ((readl(reg) & CCM_PLLx_CTRL_LOCK) != CCM_PLLx_CTRL_LOCK);
+}
+
#ifdef CONFIG_SPL_BUILD
void clock_set_pll1(unsigned int clk)
{
@@ -118,7 +144,8 @@ void clock_set_pll1(unsigned int clk)
writel(CCM_PLL1_CTRL_EN | CCM_PLL1_CTRL_P(p) |
CCM_PLL1_CTRL_N(clk / (24000000 * k / m)) |
CCM_PLL1_CTRL_K(k) | CCM_PLL1_CTRL_M(m), &ccm->pll1_cfg);
- sdelay(200);
+
+ wait_for_pll_lock(&ccm->pll1_cfg);
/* Switch CPU to PLL1 */
writel(AXI_DIV_3 << AXI_DIV_SHIFT |
@@ -143,6 +170,8 @@ void clock_set_pll3(unsigned int clk)
writel(CCM_PLL3_CTRL_EN | CCM_PLL3_CTRL_INTEGER_MODE |
CCM_PLL3_CTRL_N(clk / (24000000 / m)) | CCM_PLL3_CTRL_M(m),
&ccm->pll3_cfg);
+
+ wait_for_pll_lock(&ccm->pll3_cfg);
}
void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
@@ -173,7 +202,7 @@ void clock_set_pll5(unsigned int clk, bool sigma_delta_enable)
CCM_PLL5_CTRL_N(clk / (24000000 * k / m)) |
CCM_PLL5_CTRL_K(k) | CCM_PLL5_CTRL_M(m), &ccm->pll5_cfg);
- udelay(5500);
+ wait_for_pll_lock(&ccm->pll5_cfg);
}
#ifdef CONFIG_MACH_SUN6I