Commit 004f47bc authored by Olof Johansson's avatar Olof Johansson

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
parents 4d7e8061 036e2991
......@@ -190,7 +190,7 @@ esdhc4: esdhc@70024000 {
usbphy0: usbphy@0 {
compatible = "usb-nop-xceiv";
clocks = <&clks 124>;
clocks = <&clks 75>;
clock-names = "main_clk";
status = "okay";
};
......
......@@ -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
......
......@@ -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);
......
......@@ -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 = {
......
......@@ -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);
......
......@@ -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;
......
......@@ -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... */
......
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