Browse Source

Merge tag 'imx-fixes-3.13' of git://git.linaro.org/people/shawnguo/linux-2.6 into fixes

From Shawn Guo, imx fixes for 3.13:
 - A couple of imx5 and imx6 clock fixes
 - Two follow-up patches for improving/fixing the commit "ARM: imx:
   replace imx6q_restart()with mxc_restart()"
 - One compile fix for imx6sl with randconfig
 - Commits to fix pllv3 relock/power issues found in IPU/HDMI testing

* tag 'imx-fixes-3.13' of git://git.linaro.org/people/shawnguo/linux-2.6:
  ARM: dts: i.MX51: Fix OTG PHY clock
  ARM: imx: set up pllv3 POWER and BYPASS sequentially
  ARM: imx: pllv3 needs relock in .set_rate() call
  ARM: imx: add sleep for pllv3 relock
  ARM: imx6q: add missing sentinel to divider table
  ARM: imx: v7_cpu_resume() is needed by imx6sl build
  ARM: imx: improve mxc_restart() on the SRC bit writes
  ARM: imx: remove imx_src_prepare_restart() call
  ARM: i.MX6q: fix the wrong parent of can_root clock
Olof Johansson 11 years ago
parent
commit
004f47bcad

+ 1 - 1
arch/arm/boot/dts/imx51.dtsi

@@ -190,7 +190,7 @@
 
 			usbphy0: usbphy@0 {
 				compatible = "usb-nop-xceiv";
-				clocks = <&clks 124>;
+				clocks = <&clks 75>;
 				clock-names = "main_clk";
 				status = "okay";
 			};

+ 2 - 2
arch/arm/mach-imx/Makefile

@@ -102,8 +102,8 @@ obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
 
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
-# i.MX6SL reuses pm-imx6q.c
-obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o
+# i.MX6SL reuses i.MX6Q code
+obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o
 endif
 
 # i.MX5 based machines

+ 4 - 3
arch/arm/mach-imx/clk-imx6q.c

@@ -122,13 +122,14 @@ static struct clk_div_table clk_enet_ref_table[] = {
 	{ .val = 1, .div = 10, },
 	{ .val = 2, .div = 5, },
 	{ .val = 3, .div = 4, },
+	{ /* sentinel */ }
 };
 
 static struct clk_div_table post_div_table[] = {
 	{ .val = 2, .div = 1, },
 	{ .val = 1, .div = 2, },
 	{ .val = 0, .div = 4, },
-	{ }
+	{ /* sentinel */ }
 };
 
 static struct clk_div_table video_div_table[] = {
@@ -136,7 +137,7 @@ static struct clk_div_table video_div_table[] = {
 	{ .val = 1, .div = 2, },
 	{ .val = 2, .div = 1, },
 	{ .val = 3, .div = 4, },
-	{ }
+	{ /* sentinel */ }
 };
 
 static void __init imx6q_clocks_init(struct device_node *ccm_node)
@@ -298,7 +299,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[asrc_podf]        = imx_clk_divider("asrc_podf",        "asrc_pred",         base + 0x30, 9,  3);
 	clk[spdif_pred]       = imx_clk_divider("spdif_pred",       "spdif_sel",         base + 0x30, 25, 3);
 	clk[spdif_podf]       = imx_clk_divider("spdif_podf",       "spdif_pred",        base + 0x30, 22, 3);
-	clk[can_root]         = imx_clk_divider("can_root",         "pll3_usb_otg",      base + 0x20, 2,  6);
+	clk[can_root]         = imx_clk_divider("can_root",         "pll3_60m",          base + 0x20, 2,  6);
 	clk[ecspi_root]       = imx_clk_divider("ecspi_root",       "pll3_60m",          base + 0x38, 19, 6);
 	clk[gpu2d_core_podf]  = imx_clk_divider("gpu2d_core_podf",  "gpu2d_core_sel",    base + 0x18, 23, 3);
 	clk[gpu3d_core_podf]  = imx_clk_divider("gpu3d_core_podf",  "gpu3d_core_sel",    base + 0x18, 26, 3);

+ 34 - 17
arch/arm/mach-imx/clk-pllv3.c

@@ -12,6 +12,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -45,33 +46,49 @@ struct clk_pllv3 {
 
 #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
 
+static int clk_pllv3_wait_lock(struct clk_pllv3 *pll)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(10);
+	u32 val = readl_relaxed(pll->base) & BM_PLL_POWER;
+
+	/* No need to wait for lock when pll is not powered up */
+	if ((pll->powerup_set && !val) || (!pll->powerup_set && val))
+		return 0;
+
+	/* Wait for PLL to lock */
+	do {
+		if (readl_relaxed(pll->base) & BM_PLL_LOCK)
+			break;
+		if (time_after(jiffies, timeout))
+			break;
+		usleep_range(50, 500);
+	} while (1);
+
+	return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT;
+}
+
 static int clk_pllv3_prepare(struct clk_hw *hw)
 {
 	struct clk_pllv3 *pll = to_clk_pllv3(hw);
-	unsigned long timeout;
 	u32 val;
+	int ret;
 
 	val = readl_relaxed(pll->base);
-	val &= ~BM_PLL_BYPASS;
 	if (pll->powerup_set)
 		val |= BM_PLL_POWER;
 	else
 		val &= ~BM_PLL_POWER;
 	writel_relaxed(val, pll->base);
 
-	timeout = jiffies + msecs_to_jiffies(10);
-	/* Wait for PLL to lock */
-	do {
-		if (readl_relaxed(pll->base) & BM_PLL_LOCK)
-			break;
-		if (time_after(jiffies, timeout))
-			break;
-	} while (1);
+	ret = clk_pllv3_wait_lock(pll);
+	if (ret)
+		return ret;
 
-	if (readl_relaxed(pll->base) & BM_PLL_LOCK)
-		return 0;
-	else
-		return -ETIMEDOUT;
+	val = readl_relaxed(pll->base);
+	val &= ~BM_PLL_BYPASS;
+	writel_relaxed(val, pll->base);
+
+	return 0;
 }
 
 static void clk_pllv3_unprepare(struct clk_hw *hw)
@@ -146,7 +163,7 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
 	val |= div;
 	writel_relaxed(val, pll->base);
 
-	return 0;
+	return clk_pllv3_wait_lock(pll);
 }
 
 static const struct clk_ops clk_pllv3_ops = {
@@ -202,7 +219,7 @@ static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
 	val |= div;
 	writel_relaxed(val, pll->base);
 
-	return 0;
+	return clk_pllv3_wait_lock(pll);
 }
 
 static const struct clk_ops clk_pllv3_sys_ops = {
@@ -276,7 +293,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
 	writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
 	writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
 
-	return 0;
+	return clk_pllv3_wait_lock(pll);
 }
 
 static const struct clk_ops clk_pllv3_av_ops = {

+ 0 - 5
arch/arm/mach-imx/common.h

@@ -127,11 +127,6 @@ static inline void imx_smp_prepare(void) {}
 static inline void imx_scu_standby_enable(void) {}
 #endif
 void imx_src_init(void);
-#ifdef CONFIG_HAVE_IMX_SRC
-void imx_src_prepare_restart(void);
-#else
-static inline void imx_src_prepare_restart(void) {}
-#endif
 void imx_gpc_init(void);
 void imx_gpc_pre_suspend(void);
 void imx_gpc_post_resume(void);

+ 0 - 15
arch/arm/mach-imx/src.c

@@ -115,21 +115,6 @@ void imx_set_cpu_arg(int cpu, u32 arg)
 	writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
 }
 
-void imx_src_prepare_restart(void)
-{
-	u32 val;
-
-	/* clear enable bits of secondary cores */
-	spin_lock(&scr_lock);
-	val = readl_relaxed(src_base + SRC_SCR);
-	val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE);
-	writel_relaxed(val, src_base + SRC_SCR);
-	spin_unlock(&scr_lock);
-
-	/* clear persistent entry register of primary core */
-	writel_relaxed(0, src_base + SRC_GPR1);
-}
-
 void __init imx_src_init(void)
 {
 	struct device_node *np;

+ 8 - 4
arch/arm/mach-imx/system.c

@@ -42,9 +42,6 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
 {
 	unsigned int wcr_enable;
 
-	if (cpu_is_imx6q() || cpu_is_imx6dl())
-		imx_src_prepare_restart();
-
 	if (wdog_clk)
 		clk_enable(wdog_clk);
 
@@ -55,7 +52,14 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
 
 	/* Assert SRS signal */
 	__raw_writew(wcr_enable, wdog_base);
-	/* write twice to ensure the request will not get ignored */
+	/*
+	 * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
+	 * written twice), we add another two writes to ensure there must be at
+	 * least two writes happen in the same one 32kHz clock period.  We save
+	 * the target check here, since the writes shouldn't be a huge burden
+	 * for other platforms.
+	 */
+	__raw_writew(wcr_enable, wdog_base);
 	__raw_writew(wcr_enable, wdog_base);
 
 	/* wait for reset to assert... */