aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/rockchip/clk-pll.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/rockchip/clk-pll.c')
-rw-r--r--drivers/clk/rockchip/clk-pll.c63
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 */
116static 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
419err_mux: 389err_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 }
426err_pll_notifier:
427 clk_unregister(pll_clk); 390 clk_unregister(pll_clk);
428err_pll: 391err_pll:
429 kfree(pll); 392 kfree(pll);