diff options
Diffstat (limited to 'arch/arm/mach-imx/clk-pllv3.c')
-rw-r--r-- | arch/arm/mach-imx/clk-pllv3.c | 51 |
1 files changed, 34 insertions, 17 deletions
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 = { |