diff options
| author | Olof Johansson <olof@lixom.net> | 2013-11-11 12:39:37 -0500 |
|---|---|---|
| committer | Olof Johansson <olof@lixom.net> | 2013-11-11 12:39:37 -0500 |
| commit | 004f47bcadd61345306c74404999bd6ee16e22e1 (patch) | |
| tree | 777f2a418315177e101f7061a1f70f5e844407b8 | |
| parent | 4d7e8061b7dbc327d19e2dd9687e41719d03403e (diff) | |
| parent | 036e29918078e38b0b127b89deb4c595028c1bc0 (diff) | |
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
| -rw-r--r-- | arch/arm/boot/dts/imx51.dtsi | 2 | ||||
| -rw-r--r-- | arch/arm/mach-imx/Makefile | 4 | ||||
| -rw-r--r-- | arch/arm/mach-imx/clk-imx6q.c | 7 | ||||
| -rw-r--r-- | arch/arm/mach-imx/clk-pllv3.c | 51 | ||||
| -rw-r--r-- | arch/arm/mach-imx/common.h | 5 | ||||
| -rw-r--r-- | arch/arm/mach-imx/src.c | 15 | ||||
| -rw-r--r-- | arch/arm/mach-imx/system.c | 12 |
7 files changed, 49 insertions, 47 deletions
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi index f4dcff3a9969..4bcdd3ad15e5 100644 --- a/arch/arm/boot/dts/imx51.dtsi +++ b/arch/arm/boot/dts/imx51.dtsi | |||
| @@ -190,7 +190,7 @@ | |||
| 190 | 190 | ||
| 191 | usbphy0: usbphy@0 { | 191 | usbphy0: usbphy@0 { |
| 192 | compatible = "usb-nop-xceiv"; | 192 | compatible = "usb-nop-xceiv"; |
| 193 | clocks = <&clks 124>; | 193 | clocks = <&clks 75>; |
| 194 | clock-names = "main_clk"; | 194 | clock-names = "main_clk"; |
| 195 | status = "okay"; | 195 | status = "okay"; |
| 196 | }; | 196 | }; |
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index bbe1f5bb799c..1789e2b31903 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile | |||
| @@ -102,8 +102,8 @@ obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o | |||
| 102 | 102 | ||
| 103 | ifeq ($(CONFIG_PM),y) | 103 | ifeq ($(CONFIG_PM),y) |
| 104 | obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o | 104 | obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o |
| 105 | # i.MX6SL reuses pm-imx6q.c | 105 | # i.MX6SL reuses i.MX6Q code |
| 106 | obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o | 106 | obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o headsmp.o |
| 107 | endif | 107 | endif |
| 108 | 108 | ||
| 109 | # i.MX5 based machines | 109 | # i.MX5 based machines |
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index d756d91fd741..04cfd0fcb0e5 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c | |||
| @@ -122,13 +122,14 @@ static struct clk_div_table clk_enet_ref_table[] = { | |||
| 122 | { .val = 1, .div = 10, }, | 122 | { .val = 1, .div = 10, }, |
| 123 | { .val = 2, .div = 5, }, | 123 | { .val = 2, .div = 5, }, |
| 124 | { .val = 3, .div = 4, }, | 124 | { .val = 3, .div = 4, }, |
| 125 | { /* sentinel */ } | ||
| 125 | }; | 126 | }; |
| 126 | 127 | ||
| 127 | static struct clk_div_table post_div_table[] = { | 128 | static struct clk_div_table post_div_table[] = { |
| 128 | { .val = 2, .div = 1, }, | 129 | { .val = 2, .div = 1, }, |
| 129 | { .val = 1, .div = 2, }, | 130 | { .val = 1, .div = 2, }, |
| 130 | { .val = 0, .div = 4, }, | 131 | { .val = 0, .div = 4, }, |
| 131 | { } | 132 | { /* sentinel */ } |
| 132 | }; | 133 | }; |
| 133 | 134 | ||
| 134 | static struct clk_div_table video_div_table[] = { | 135 | static struct clk_div_table video_div_table[] = { |
| @@ -136,7 +137,7 @@ static struct clk_div_table video_div_table[] = { | |||
| 136 | { .val = 1, .div = 2, }, | 137 | { .val = 1, .div = 2, }, |
| 137 | { .val = 2, .div = 1, }, | 138 | { .val = 2, .div = 1, }, |
| 138 | { .val = 3, .div = 4, }, | 139 | { .val = 3, .div = 4, }, |
| 139 | { } | 140 | { /* sentinel */ } |
| 140 | }; | 141 | }; |
| 141 | 142 | ||
| 142 | static void __init imx6q_clocks_init(struct device_node *ccm_node) | 143 | 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) | |||
| 298 | clk[asrc_podf] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3); | 299 | clk[asrc_podf] = imx_clk_divider("asrc_podf", "asrc_pred", base + 0x30, 9, 3); |
| 299 | clk[spdif_pred] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3); | 300 | clk[spdif_pred] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3); |
| 300 | clk[spdif_podf] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3); | 301 | clk[spdif_podf] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3); |
| 301 | clk[can_root] = imx_clk_divider("can_root", "pll3_usb_otg", base + 0x20, 2, 6); | 302 | clk[can_root] = imx_clk_divider("can_root", "pll3_60m", base + 0x20, 2, 6); |
| 302 | clk[ecspi_root] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6); | 303 | clk[ecspi_root] = imx_clk_divider("ecspi_root", "pll3_60m", base + 0x38, 19, 6); |
| 303 | clk[gpu2d_core_podf] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3); | 304 | clk[gpu2d_core_podf] = imx_clk_divider("gpu2d_core_podf", "gpu2d_core_sel", base + 0x18, 23, 3); |
| 304 | clk[gpu3d_core_podf] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3); | 305 | clk[gpu3d_core_podf] = imx_clk_divider("gpu3d_core_podf", "gpu3d_core_sel", base + 0x18, 26, 3); |
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index f6640b6a7b31..61364050fccd 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
| 14 | #include <linux/clk-provider.h> | 14 | #include <linux/clk-provider.h> |
| 15 | #include <linux/delay.h> | ||
| 15 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 17 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
| @@ -45,33 +46,49 @@ struct clk_pllv3 { | |||
| 45 | 46 | ||
| 46 | #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) | 47 | #define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw) |
| 47 | 48 | ||
| 49 | static int clk_pllv3_wait_lock(struct clk_pllv3 *pll) | ||
| 50 | { | ||
| 51 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
| 52 | u32 val = readl_relaxed(pll->base) & BM_PLL_POWER; | ||
| 53 | |||
| 54 | /* No need to wait for lock when pll is not powered up */ | ||
| 55 | if ((pll->powerup_set && !val) || (!pll->powerup_set && val)) | ||
| 56 | return 0; | ||
| 57 | |||
| 58 | /* Wait for PLL to lock */ | ||
| 59 | do { | ||
| 60 | if (readl_relaxed(pll->base) & BM_PLL_LOCK) | ||
| 61 | break; | ||
| 62 | if (time_after(jiffies, timeout)) | ||
| 63 | break; | ||
| 64 | usleep_range(50, 500); | ||
| 65 | } while (1); | ||
| 66 | |||
| 67 | return readl_relaxed(pll->base) & BM_PLL_LOCK ? 0 : -ETIMEDOUT; | ||
| 68 | } | ||
| 69 | |||
| 48 | static int clk_pllv3_prepare(struct clk_hw *hw) | 70 | static int clk_pllv3_prepare(struct clk_hw *hw) |
| 49 | { | 71 | { |
| 50 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | 72 | struct clk_pllv3 *pll = to_clk_pllv3(hw); |
| 51 | unsigned long timeout; | ||
| 52 | u32 val; | 73 | u32 val; |
| 74 | int ret; | ||
| 53 | 75 | ||
| 54 | val = readl_relaxed(pll->base); | 76 | val = readl_relaxed(pll->base); |
| 55 | val &= ~BM_PLL_BYPASS; | ||
| 56 | if (pll->powerup_set) | 77 | if (pll->powerup_set) |
| 57 | val |= BM_PLL_POWER; | 78 | val |= BM_PLL_POWER; |
| 58 | else | 79 | else |
| 59 | val &= ~BM_PLL_POWER; | 80 | val &= ~BM_PLL_POWER; |
| 60 | writel_relaxed(val, pll->base); | 81 | writel_relaxed(val, pll->base); |
| 61 | 82 | ||
| 62 | timeout = jiffies + msecs_to_jiffies(10); | 83 | ret = clk_pllv3_wait_lock(pll); |
| 63 | /* Wait for PLL to lock */ | 84 | if (ret) |
| 64 | do { | 85 | return ret; |
| 65 | if (readl_relaxed(pll->base) & BM_PLL_LOCK) | ||
| 66 | break; | ||
| 67 | if (time_after(jiffies, timeout)) | ||
| 68 | break; | ||
| 69 | } while (1); | ||
| 70 | 86 | ||
| 71 | if (readl_relaxed(pll->base) & BM_PLL_LOCK) | 87 | val = readl_relaxed(pll->base); |
| 72 | return 0; | 88 | val &= ~BM_PLL_BYPASS; |
| 73 | else | 89 | writel_relaxed(val, pll->base); |
| 74 | return -ETIMEDOUT; | 90 | |
| 91 | return 0; | ||
| 75 | } | 92 | } |
| 76 | 93 | ||
| 77 | static void clk_pllv3_unprepare(struct clk_hw *hw) | 94 | 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, | |||
| 146 | val |= div; | 163 | val |= div; |
| 147 | writel_relaxed(val, pll->base); | 164 | writel_relaxed(val, pll->base); |
| 148 | 165 | ||
| 149 | return 0; | 166 | return clk_pllv3_wait_lock(pll); |
| 150 | } | 167 | } |
| 151 | 168 | ||
| 152 | static const struct clk_ops clk_pllv3_ops = { | 169 | 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, | |||
| 202 | val |= div; | 219 | val |= div; |
| 203 | writel_relaxed(val, pll->base); | 220 | writel_relaxed(val, pll->base); |
| 204 | 221 | ||
| 205 | return 0; | 222 | return clk_pllv3_wait_lock(pll); |
| 206 | } | 223 | } |
| 207 | 224 | ||
| 208 | static const struct clk_ops clk_pllv3_sys_ops = { | 225 | 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, | |||
| 276 | writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); | 293 | writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET); |
| 277 | writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); | 294 | writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET); |
| 278 | 295 | ||
| 279 | return 0; | 296 | return clk_pllv3_wait_lock(pll); |
| 280 | } | 297 | } |
| 281 | 298 | ||
| 282 | static const struct clk_ops clk_pllv3_av_ops = { | 299 | static const struct clk_ops clk_pllv3_av_ops = { |
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 7cbe22d0c6e9..24a7899e36a8 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h | |||
| @@ -127,11 +127,6 @@ static inline void imx_smp_prepare(void) {} | |||
| 127 | static inline void imx_scu_standby_enable(void) {} | 127 | static inline void imx_scu_standby_enable(void) {} |
| 128 | #endif | 128 | #endif |
| 129 | void imx_src_init(void); | 129 | void imx_src_init(void); |
| 130 | #ifdef CONFIG_HAVE_IMX_SRC | ||
| 131 | void imx_src_prepare_restart(void); | ||
| 132 | #else | ||
| 133 | static inline void imx_src_prepare_restart(void) {} | ||
| 134 | #endif | ||
| 135 | void imx_gpc_init(void); | 130 | void imx_gpc_init(void); |
| 136 | void imx_gpc_pre_suspend(void); | 131 | void imx_gpc_pre_suspend(void); |
| 137 | void imx_gpc_post_resume(void); | 132 | void imx_gpc_post_resume(void); |
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 4754373e7e7d..45f7f4e0a447 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c | |||
| @@ -115,21 +115,6 @@ void imx_set_cpu_arg(int cpu, u32 arg) | |||
| 115 | writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4); | 115 | writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | void imx_src_prepare_restart(void) | ||
| 119 | { | ||
| 120 | u32 val; | ||
| 121 | |||
| 122 | /* clear enable bits of secondary cores */ | ||
| 123 | spin_lock(&scr_lock); | ||
| 124 | val = readl_relaxed(src_base + SRC_SCR); | ||
| 125 | val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE); | ||
| 126 | writel_relaxed(val, src_base + SRC_SCR); | ||
| 127 | spin_unlock(&scr_lock); | ||
| 128 | |||
| 129 | /* clear persistent entry register of primary core */ | ||
| 130 | writel_relaxed(0, src_base + SRC_GPR1); | ||
| 131 | } | ||
| 132 | |||
| 133 | void __init imx_src_init(void) | 118 | void __init imx_src_init(void) |
| 134 | { | 119 | { |
| 135 | struct device_node *np; | 120 | struct device_node *np; |
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index e6edcd38b282..5e3027d3692f 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c | |||
| @@ -42,9 +42,6 @@ void mxc_restart(enum reboot_mode mode, const char *cmd) | |||
| 42 | { | 42 | { |
| 43 | unsigned int wcr_enable; | 43 | unsigned int wcr_enable; |
| 44 | 44 | ||
| 45 | if (cpu_is_imx6q() || cpu_is_imx6dl()) | ||
| 46 | imx_src_prepare_restart(); | ||
| 47 | |||
| 48 | if (wdog_clk) | 45 | if (wdog_clk) |
| 49 | clk_enable(wdog_clk); | 46 | clk_enable(wdog_clk); |
| 50 | 47 | ||
| @@ -55,7 +52,14 @@ void mxc_restart(enum reboot_mode mode, const char *cmd) | |||
| 55 | 52 | ||
| 56 | /* Assert SRS signal */ | 53 | /* Assert SRS signal */ |
| 57 | __raw_writew(wcr_enable, wdog_base); | 54 | __raw_writew(wcr_enable, wdog_base); |
| 58 | /* write twice to ensure the request will not get ignored */ | 55 | /* |
| 56 | * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be | ||
| 57 | * written twice), we add another two writes to ensure there must be at | ||
| 58 | * least two writes happen in the same one 32kHz clock period. We save | ||
| 59 | * the target check here, since the writes shouldn't be a huge burden | ||
| 60 | * for other platforms. | ||
| 61 | */ | ||
| 62 | __raw_writew(wcr_enable, wdog_base); | ||
| 59 | __raw_writew(wcr_enable, wdog_base); | 63 | __raw_writew(wcr_enable, wdog_base); |
| 60 | 64 | ||
| 61 | /* wait for reset to assert... */ | 65 | /* wait for reset to assert... */ |
