diff options
Diffstat (limited to 'drivers/clk/rockchip/clk-pll.c')
-rw-r--r-- | drivers/clk/rockchip/clk-pll.c | 63 |
1 files changed, 13 insertions, 50 deletions
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index f2a1c7abf4d9..a3e886a38480 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c | |||
@@ -34,7 +34,6 @@ struct rockchip_clk_pll { | |||
34 | const struct clk_ops *pll_mux_ops; | 34 | const struct clk_ops *pll_mux_ops; |
35 | 35 | ||
36 | struct notifier_block clk_nb; | 36 | struct notifier_block clk_nb; |
37 | bool rate_change_remuxed; | ||
38 | 37 | ||
39 | void __iomem *reg_base; | 38 | void __iomem *reg_base; |
40 | int lock_offset; | 39 | int lock_offset; |
@@ -109,38 +108,6 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) | |||
109 | } | 108 | } |
110 | 109 | ||
111 | /** | 110 | /** |
112 | * Set pll mux when changing the pll rate. | ||
113 | * This makes sure to move the pll mux away from the actual pll before | ||
114 | * changing its rate and back to the original parent after the change. | ||
115 | */ | ||
116 | static int rockchip_pll_notifier_cb(struct notifier_block *nb, | ||
117 | unsigned long event, void *data) | ||
118 | { | ||
119 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll_nb(nb); | ||
120 | struct clk_mux *pll_mux = &pll->pll_mux; | ||
121 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; | ||
122 | int cur_parent; | ||
123 | |||
124 | switch (event) { | ||
125 | case PRE_RATE_CHANGE: | ||
126 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); | ||
127 | if (cur_parent == PLL_MODE_NORM) { | ||
128 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); | ||
129 | pll->rate_change_remuxed = 1; | ||
130 | } | ||
131 | break; | ||
132 | case POST_RATE_CHANGE: | ||
133 | if (pll->rate_change_remuxed) { | ||
134 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); | ||
135 | pll->rate_change_remuxed = 0; | ||
136 | } | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | return NOTIFY_OK; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * PLL used in RK3066, RK3188 and RK3288 | 111 | * PLL used in RK3066, RK3188 and RK3288 |
145 | */ | 112 | */ |
146 | 113 | ||
@@ -194,6 +161,10 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, | |||
194 | const struct rockchip_pll_rate_table *rate; | 161 | const struct rockchip_pll_rate_table *rate; |
195 | unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); | 162 | unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); |
196 | struct regmap *grf = rockchip_clk_get_grf(); | 163 | struct regmap *grf = rockchip_clk_get_grf(); |
164 | struct clk_mux *pll_mux = &pll->pll_mux; | ||
165 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; | ||
166 | int rate_change_remuxed = 0; | ||
167 | int cur_parent; | ||
197 | int ret; | 168 | int ret; |
198 | 169 | ||
199 | if (IS_ERR(grf)) { | 170 | if (IS_ERR(grf)) { |
@@ -216,6 +187,12 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, | |||
216 | pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", | 187 | pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", |
217 | __func__, rate->rate, rate->nr, rate->no, rate->nf); | 188 | __func__, rate->rate, rate->nr, rate->no, rate->nf); |
218 | 189 | ||
190 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); | ||
191 | if (cur_parent == PLL_MODE_NORM) { | ||
192 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); | ||
193 | rate_change_remuxed = 1; | ||
194 | } | ||
195 | |||
219 | /* enter reset mode */ | 196 | /* enter reset mode */ |
220 | writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), | 197 | writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), |
221 | pll->reg_base + RK3066_PLLCON(3)); | 198 | pll->reg_base + RK3066_PLLCON(3)); |
@@ -247,6 +224,9 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, | |||
247 | rockchip_rk3066_pll_set_rate(hw, old_rate, prate); | 224 | rockchip_rk3066_pll_set_rate(hw, old_rate, prate); |
248 | } | 225 | } |
249 | 226 | ||
227 | if (rate_change_remuxed) | ||
228 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); | ||
229 | |||
250 | return ret; | 230 | return ret; |
251 | } | 231 | } |
252 | 232 | ||
@@ -310,7 +290,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
310 | struct clk_mux *pll_mux; | 290 | struct clk_mux *pll_mux; |
311 | struct clk *pll_clk, *mux_clk; | 291 | struct clk *pll_clk, *mux_clk; |
312 | char pll_name[20]; | 292 | char pll_name[20]; |
313 | int ret; | ||
314 | 293 | ||
315 | if (num_parents != 2) { | 294 | if (num_parents != 2) { |
316 | pr_err("%s: needs two parent clocks\n", __func__); | 295 | pr_err("%s: needs two parent clocks\n", __func__); |
@@ -367,7 +346,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
367 | pll->lock_offset = grf_lock_offset; | 346 | pll->lock_offset = grf_lock_offset; |
368 | pll->lock_shift = lock_shift; | 347 | pll->lock_shift = lock_shift; |
369 | pll->lock = lock; | 348 | pll->lock = lock; |
370 | pll->clk_nb.notifier_call = rockchip_pll_notifier_cb; | ||
371 | 349 | ||
372 | pll_clk = clk_register(NULL, &pll->hw); | 350 | pll_clk = clk_register(NULL, &pll->hw); |
373 | if (IS_ERR(pll_clk)) { | 351 | if (IS_ERR(pll_clk)) { |
@@ -377,14 +355,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
377 | goto err_pll; | 355 | goto err_pll; |
378 | } | 356 | } |
379 | 357 | ||
380 | ret = clk_notifier_register(pll_clk, &pll->clk_nb); | ||
381 | if (ret) { | ||
382 | pr_err("%s: failed to register clock notifier for %s : %d\n", | ||
383 | __func__, name, ret); | ||
384 | mux_clk = ERR_PTR(ret); | ||
385 | goto err_pll_notifier; | ||
386 | } | ||
387 | |||
388 | /* create the mux on top of the real pll */ | 358 | /* create the mux on top of the real pll */ |
389 | pll->pll_mux_ops = &clk_mux_ops; | 359 | pll->pll_mux_ops = &clk_mux_ops; |
390 | pll_mux = &pll->pll_mux; | 360 | pll_mux = &pll->pll_mux; |
@@ -417,13 +387,6 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | |||
417 | return mux_clk; | 387 | return mux_clk; |
418 | 388 | ||
419 | err_mux: | 389 | err_mux: |
420 | ret = clk_notifier_unregister(pll_clk, &pll->clk_nb); | ||
421 | if (ret) { | ||
422 | pr_err("%s: could not unregister clock notifier in error path : %d\n", | ||
423 | __func__, ret); | ||
424 | return mux_clk; | ||
425 | } | ||
426 | err_pll_notifier: | ||
427 | clk_unregister(pll_clk); | 390 | clk_unregister(pll_clk); |
428 | err_pll: | 391 | err_pll: |
429 | kfree(pll); | 392 | kfree(pll); |