diff options
author | Stefan Agner <stefan@agner.ch> | 2014-12-02 11:59:42 -0500 |
---|---|---|
committer | Shawn Guo <shawn.guo@linaro.org> | 2015-01-05 07:53:05 -0500 |
commit | 60ad8467c1bf0cae19ccc9d142914a2288ac85e7 (patch) | |
tree | a2782b25c553337c63e21fa4d5227fd4f45a5430 | |
parent | da06aae8b5cae1bd0ac5b7518c9693fe07c06488 (diff) |
ARM: imx: pllv3: add shift for frequency multiplier
Add shift capabilties for the frequency multiplier (DIV_SELECT) to
support Vybrid's USB PLL oddity. The PLL3 and PLL7 are the only
PLL control registers which have the DIV_SELECT bit shifted by
one. Be aware, there are known documentation errors in the
reference manual too.
Signed-off-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
-rw-r--r-- | arch/arm/mach-imx/clk-pllv3.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-vf610.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk.h | 1 |
3 files changed, 10 insertions, 5 deletions
diff --git a/arch/arm/mach-imx/clk-pllv3.c b/arch/arm/mach-imx/clk-pllv3.c index 0ad6e5442fd8..641ebc508920 100644 --- a/arch/arm/mach-imx/clk-pllv3.c +++ b/arch/arm/mach-imx/clk-pllv3.c | |||
@@ -31,6 +31,7 @@ | |||
31 | * @base: base address of PLL registers | 31 | * @base: base address of PLL registers |
32 | * @powerup_set: set POWER bit to power up the PLL | 32 | * @powerup_set: set POWER bit to power up the PLL |
33 | * @div_mask: mask of divider bits | 33 | * @div_mask: mask of divider bits |
34 | * @div_shift: shift of divider bits | ||
34 | * | 35 | * |
35 | * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 | 36 | * IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3 |
36 | * is actually a multiplier, and always sits at bit 0. | 37 | * is actually a multiplier, and always sits at bit 0. |
@@ -40,6 +41,7 @@ struct clk_pllv3 { | |||
40 | void __iomem *base; | 41 | void __iomem *base; |
41 | bool powerup_set; | 42 | bool powerup_set; |
42 | u32 div_mask; | 43 | u32 div_mask; |
44 | u32 div_shift; | ||
43 | }; | 45 | }; |
44 | 46 | ||
45 | #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) |
@@ -97,7 +99,7 @@ static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw, | |||
97 | unsigned long parent_rate) | 99 | unsigned long parent_rate) |
98 | { | 100 | { |
99 | struct clk_pllv3 *pll = to_clk_pllv3(hw); | 101 | struct clk_pllv3 *pll = to_clk_pllv3(hw); |
100 | u32 div = readl_relaxed(pll->base) & pll->div_mask; | 102 | u32 div = (readl_relaxed(pll->base) >> pll->div_shift) & pll->div_mask; |
101 | 103 | ||
102 | return (div == 1) ? parent_rate * 22 : parent_rate * 20; | 104 | return (div == 1) ? parent_rate * 22 : parent_rate * 20; |
103 | } | 105 | } |
@@ -125,8 +127,8 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate, | |||
125 | return -EINVAL; | 127 | return -EINVAL; |
126 | 128 | ||
127 | val = readl_relaxed(pll->base); | 129 | val = readl_relaxed(pll->base); |
128 | val &= ~pll->div_mask; | 130 | val &= ~(pll->div_mask << pll->div_shift); |
129 | val |= div; | 131 | val |= (div << pll->div_shift); |
130 | writel_relaxed(val, pll->base); | 132 | writel_relaxed(val, pll->base); |
131 | 133 | ||
132 | return clk_pllv3_wait_lock(pll); | 134 | return clk_pllv3_wait_lock(pll); |
@@ -295,6 +297,8 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, | |||
295 | case IMX_PLLV3_SYS: | 297 | case IMX_PLLV3_SYS: |
296 | ops = &clk_pllv3_sys_ops; | 298 | ops = &clk_pllv3_sys_ops; |
297 | break; | 299 | break; |
300 | case IMX_PLLV3_USB_VF610: | ||
301 | pll->div_shift = 1; | ||
298 | case IMX_PLLV3_USB: | 302 | case IMX_PLLV3_USB: |
299 | ops = &clk_pllv3_ops; | 303 | ops = &clk_pllv3_ops; |
300 | pll->powerup_set = true; | 304 | pll->powerup_set = true; |
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c index 5937ddee1a99..cb21777c3ab6 100644 --- a/arch/arm/mach-imx/clk-vf610.c +++ b/arch/arm/mach-imx/clk-vf610.c | |||
@@ -172,11 +172,11 @@ static void __init vf610_clocks_init(struct device_node *ccm_node) | |||
172 | 172 | ||
173 | clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); | 173 | clk[VF610_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll1", "pll1_bypass_src", PLL1_CTRL, 0x1); |
174 | clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); | 174 | clk[VF610_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "pll2_bypass_src", PLL2_CTRL, 0x1); |
175 | clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x1); | 175 | clk[VF610_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll3", "pll3_bypass_src", PLL3_CTRL, 0x2); |
176 | clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); | 176 | clk[VF610_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "pll4_bypass_src", PLL4_CTRL, 0x7f); |
177 | clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); | 177 | clk[VF610_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll5", "pll5_bypass_src", PLL5_CTRL, 0x3); |
178 | clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f); | 178 | clk[VF610_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_AV, "pll6", "pll6_bypass_src", PLL6_CTRL, 0x7f); |
179 | clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x1); | 179 | clk[VF610_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB_VF610, "pll7", "pll7_bypass_src", PLL7_CTRL, 0x2); |
180 | 180 | ||
181 | clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); | 181 | clk[VF610_PLL1_BYPASS] = imx_clk_mux_flags("pll1_bypass", PLL1_CTRL, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); |
182 | clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); | 182 | clk[VF610_PLL2_BYPASS] = imx_clk_mux_flags("pll2_bypass", PLL2_CTRL, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); |
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 5ef82e2f8fc5..6a07903a28bc 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h | |||
@@ -20,6 +20,7 @@ enum imx_pllv3_type { | |||
20 | IMX_PLLV3_GENERIC, | 20 | IMX_PLLV3_GENERIC, |
21 | IMX_PLLV3_SYS, | 21 | IMX_PLLV3_SYS, |
22 | IMX_PLLV3_USB, | 22 | IMX_PLLV3_USB, |
23 | IMX_PLLV3_USB_VF610, | ||
23 | IMX_PLLV3_AV, | 24 | IMX_PLLV3_AV, |
24 | IMX_PLLV3_ENET, | 25 | IMX_PLLV3_ENET, |
25 | }; | 26 | }; |