1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 2014 MundoReader S.L. |
4 | * Author: Heiko Stuebner <heiko@sntech.de> |
5 | * |
6 | * Copyright (c) 2015 Rockchip Electronics Co. Ltd. |
7 | * Author: Xing Zheng <zhengxing@rock-chips.com> |
8 | */ |
9 | |
10 | #include <asm/div64.h> |
11 | #include <linux/slab.h> |
12 | #include <linux/io.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/clk-provider.h> |
15 | #include <linux/iopoll.h> |
16 | #include <linux/regmap.h> |
17 | #include <linux/clk.h> |
18 | #include "clk.h" |
19 | |
20 | #define PLL_MODE_MASK 0x3 |
21 | #define PLL_MODE_SLOW 0x0 |
22 | #define PLL_MODE_NORM 0x1 |
23 | #define PLL_MODE_DEEP 0x2 |
24 | #define PLL_RK3328_MODE_MASK 0x1 |
25 | |
26 | struct rockchip_clk_pll { |
27 | struct clk_hw hw; |
28 | |
29 | struct clk_mux pll_mux; |
30 | const struct clk_ops *pll_mux_ops; |
31 | |
32 | struct notifier_block clk_nb; |
33 | |
34 | void __iomem *reg_base; |
35 | int lock_offset; |
36 | unsigned int lock_shift; |
37 | enum rockchip_pll_type type; |
38 | u8 flags; |
39 | const struct rockchip_pll_rate_table *rate_table; |
40 | unsigned int rate_count; |
41 | spinlock_t *lock; |
42 | |
43 | struct rockchip_clk_provider *ctx; |
44 | }; |
45 | |
46 | #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) |
47 | #define to_rockchip_clk_pll_nb(nb) \ |
48 | container_of(nb, struct rockchip_clk_pll, clk_nb) |
49 | |
50 | static const struct rockchip_pll_rate_table *rockchip_get_pll_settings( |
51 | struct rockchip_clk_pll *pll, unsigned long rate) |
52 | { |
53 | const struct rockchip_pll_rate_table *rate_table = pll->rate_table; |
54 | int i; |
55 | |
56 | for (i = 0; i < pll->rate_count; i++) { |
57 | if (rate == rate_table[i].rate) |
58 | return &rate_table[i]; |
59 | } |
60 | |
61 | return NULL; |
62 | } |
63 | |
64 | static long rockchip_pll_round_rate(struct clk_hw *hw, |
65 | unsigned long drate, unsigned long *prate) |
66 | { |
67 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
68 | const struct rockchip_pll_rate_table *rate_table = pll->rate_table; |
69 | int i; |
70 | |
71 | /* Assumming rate_table is in descending order */ |
72 | for (i = 0; i < pll->rate_count; i++) { |
73 | if (drate >= rate_table[i].rate) |
74 | return rate_table[i].rate; |
75 | } |
76 | |
77 | /* return minimum supported value */ |
78 | return rate_table[i - 1].rate; |
79 | } |
80 | |
81 | /* |
82 | * Wait for the pll to reach the locked state. |
83 | * The calling set_rate function is responsible for making sure the |
84 | * grf regmap is available. |
85 | */ |
86 | static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) |
87 | { |
88 | struct regmap *grf = pll->ctx->grf; |
89 | unsigned int val; |
90 | int ret; |
91 | |
92 | ret = regmap_read_poll_timeout(grf, pll->lock_offset, val, |
93 | val & BIT(pll->lock_shift), 0, 1000); |
94 | if (ret) |
95 | pr_err("%s: timeout waiting for pll to lock\n" , __func__); |
96 | |
97 | return ret; |
98 | } |
99 | |
100 | /* |
101 | * PLL used in RK3036 |
102 | */ |
103 | |
104 | #define RK3036_PLLCON(i) (i * 0x4) |
105 | #define RK3036_PLLCON0_FBDIV_MASK 0xfff |
106 | #define RK3036_PLLCON0_FBDIV_SHIFT 0 |
107 | #define RK3036_PLLCON0_POSTDIV1_MASK 0x7 |
108 | #define RK3036_PLLCON0_POSTDIV1_SHIFT 12 |
109 | #define RK3036_PLLCON1_REFDIV_MASK 0x3f |
110 | #define RK3036_PLLCON1_REFDIV_SHIFT 0 |
111 | #define RK3036_PLLCON1_POSTDIV2_MASK 0x7 |
112 | #define RK3036_PLLCON1_POSTDIV2_SHIFT 6 |
113 | #define RK3036_PLLCON1_LOCK_STATUS BIT(10) |
114 | #define RK3036_PLLCON1_DSMPD_MASK 0x1 |
115 | #define RK3036_PLLCON1_DSMPD_SHIFT 12 |
116 | #define RK3036_PLLCON1_PWRDOWN BIT(13) |
117 | #define RK3036_PLLCON2_FRAC_MASK 0xffffff |
118 | #define RK3036_PLLCON2_FRAC_SHIFT 0 |
119 | |
120 | static int rockchip_rk3036_pll_wait_lock(struct rockchip_clk_pll *pll) |
121 | { |
122 | u32 pllcon; |
123 | int ret; |
124 | |
125 | /* |
126 | * Lock time typical 250, max 500 input clock cycles @24MHz |
127 | * So define a very safe maximum of 1000us, meaning 24000 cycles. |
128 | */ |
129 | ret = readl_relaxed_poll_timeout(pll->reg_base + RK3036_PLLCON(1), |
130 | pllcon, |
131 | pllcon & RK3036_PLLCON1_LOCK_STATUS, |
132 | 0, 1000); |
133 | if (ret) |
134 | pr_err("%s: timeout waiting for pll to lock\n" , __func__); |
135 | |
136 | return ret; |
137 | } |
138 | |
139 | static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll, |
140 | struct rockchip_pll_rate_table *rate) |
141 | { |
142 | u32 pllcon; |
143 | |
144 | pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0)); |
145 | rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT) |
146 | & RK3036_PLLCON0_FBDIV_MASK); |
147 | rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT) |
148 | & RK3036_PLLCON0_POSTDIV1_MASK); |
149 | |
150 | pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1)); |
151 | rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT) |
152 | & RK3036_PLLCON1_REFDIV_MASK); |
153 | rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT) |
154 | & RK3036_PLLCON1_POSTDIV2_MASK); |
155 | rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT) |
156 | & RK3036_PLLCON1_DSMPD_MASK); |
157 | |
158 | pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2)); |
159 | rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT) |
160 | & RK3036_PLLCON2_FRAC_MASK); |
161 | } |
162 | |
163 | static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw, |
164 | unsigned long prate) |
165 | { |
166 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
167 | struct rockchip_pll_rate_table cur; |
168 | u64 rate64 = prate; |
169 | |
170 | rockchip_rk3036_pll_get_params(pll, rate: &cur); |
171 | |
172 | rate64 *= cur.fbdiv; |
173 | do_div(rate64, cur.refdiv); |
174 | |
175 | if (cur.dsmpd == 0) { |
176 | /* fractional mode */ |
177 | u64 frac_rate64 = prate * cur.frac; |
178 | |
179 | do_div(frac_rate64, cur.refdiv); |
180 | rate64 += frac_rate64 >> 24; |
181 | } |
182 | |
183 | do_div(rate64, cur.postdiv1); |
184 | do_div(rate64, cur.postdiv2); |
185 | |
186 | return (unsigned long)rate64; |
187 | } |
188 | |
189 | static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll, |
190 | const struct rockchip_pll_rate_table *rate) |
191 | { |
192 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; |
193 | struct clk_mux *pll_mux = &pll->pll_mux; |
194 | struct rockchip_pll_rate_table cur; |
195 | u32 pllcon; |
196 | int rate_change_remuxed = 0; |
197 | int cur_parent; |
198 | int ret; |
199 | |
200 | pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n" , |
201 | __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, |
202 | rate->postdiv2, rate->dsmpd, rate->frac); |
203 | |
204 | rockchip_rk3036_pll_get_params(pll, rate: &cur); |
205 | cur.rate = 0; |
206 | |
207 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); |
208 | if (cur_parent == PLL_MODE_NORM) { |
209 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); |
210 | rate_change_remuxed = 1; |
211 | } |
212 | |
213 | /* update pll values */ |
214 | writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK, |
215 | RK3036_PLLCON0_FBDIV_SHIFT) | |
216 | HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK, |
217 | RK3036_PLLCON0_POSTDIV1_SHIFT), |
218 | pll->reg_base + RK3036_PLLCON(0)); |
219 | |
220 | writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK, |
221 | RK3036_PLLCON1_REFDIV_SHIFT) | |
222 | HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK, |
223 | RK3036_PLLCON1_POSTDIV2_SHIFT) | |
224 | HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK, |
225 | RK3036_PLLCON1_DSMPD_SHIFT), |
226 | pll->reg_base + RK3036_PLLCON(1)); |
227 | |
228 | /* GPLL CON2 is not HIWORD_MASK */ |
229 | pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2)); |
230 | pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT); |
231 | pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT; |
232 | writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2)); |
233 | |
234 | /* wait for the pll to lock */ |
235 | ret = rockchip_rk3036_pll_wait_lock(pll); |
236 | if (ret) { |
237 | pr_warn("%s: pll update unsuccessful, trying to restore old params\n" , |
238 | __func__); |
239 | rockchip_rk3036_pll_set_params(pll, rate: &cur); |
240 | } |
241 | |
242 | if (rate_change_remuxed) |
243 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); |
244 | |
245 | return ret; |
246 | } |
247 | |
248 | static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate, |
249 | unsigned long prate) |
250 | { |
251 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
252 | const struct rockchip_pll_rate_table *rate; |
253 | |
254 | pr_debug("%s: changing %s to %lu with a parent rate of %lu\n" , |
255 | __func__, __clk_get_name(hw->clk), drate, prate); |
256 | |
257 | /* Get required rate settings from table */ |
258 | rate = rockchip_get_pll_settings(pll, rate: drate); |
259 | if (!rate) { |
260 | pr_err("%s: Invalid rate : %lu for pll clk %s\n" , __func__, |
261 | drate, __clk_get_name(hw->clk)); |
262 | return -EINVAL; |
263 | } |
264 | |
265 | return rockchip_rk3036_pll_set_params(pll, rate); |
266 | } |
267 | |
268 | static int rockchip_rk3036_pll_enable(struct clk_hw *hw) |
269 | { |
270 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
271 | |
272 | writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0), |
273 | addr: pll->reg_base + RK3036_PLLCON(1)); |
274 | rockchip_rk3036_pll_wait_lock(pll); |
275 | |
276 | return 0; |
277 | } |
278 | |
279 | static void rockchip_rk3036_pll_disable(struct clk_hw *hw) |
280 | { |
281 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
282 | |
283 | writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN, |
284 | RK3036_PLLCON1_PWRDOWN, 0), |
285 | addr: pll->reg_base + RK3036_PLLCON(1)); |
286 | } |
287 | |
288 | static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw) |
289 | { |
290 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
291 | u32 pllcon = readl(addr: pll->reg_base + RK3036_PLLCON(1)); |
292 | |
293 | return !(pllcon & RK3036_PLLCON1_PWRDOWN); |
294 | } |
295 | |
296 | static int rockchip_rk3036_pll_init(struct clk_hw *hw) |
297 | { |
298 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
299 | const struct rockchip_pll_rate_table *rate; |
300 | struct rockchip_pll_rate_table cur; |
301 | unsigned long drate; |
302 | |
303 | if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) |
304 | return 0; |
305 | |
306 | drate = clk_hw_get_rate(hw); |
307 | rate = rockchip_get_pll_settings(pll, rate: drate); |
308 | |
309 | /* when no rate setting for the current rate, rely on clk_set_rate */ |
310 | if (!rate) |
311 | return 0; |
312 | |
313 | rockchip_rk3036_pll_get_params(pll, rate: &cur); |
314 | |
315 | pr_debug("%s: pll %s@%lu: Hz\n" , __func__, __clk_get_name(hw->clk), |
316 | drate); |
317 | pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n" , |
318 | cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2, |
319 | cur.dsmpd, cur.frac); |
320 | pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n" , |
321 | rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, |
322 | rate->dsmpd, rate->frac); |
323 | |
324 | if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || |
325 | rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || |
326 | rate->dsmpd != cur.dsmpd || |
327 | (!cur.dsmpd && (rate->frac != cur.frac))) { |
328 | struct clk *parent = clk_get_parent(clk: hw->clk); |
329 | |
330 | if (!parent) { |
331 | pr_warn("%s: parent of %s not available\n" , |
332 | __func__, __clk_get_name(hw->clk)); |
333 | return 0; |
334 | } |
335 | |
336 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n" , |
337 | __func__, __clk_get_name(hw->clk)); |
338 | rockchip_rk3036_pll_set_params(pll, rate); |
339 | } |
340 | |
341 | return 0; |
342 | } |
343 | |
344 | static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = { |
345 | .recalc_rate = rockchip_rk3036_pll_recalc_rate, |
346 | .enable = rockchip_rk3036_pll_enable, |
347 | .disable = rockchip_rk3036_pll_disable, |
348 | .is_enabled = rockchip_rk3036_pll_is_enabled, |
349 | }; |
350 | |
351 | static const struct clk_ops rockchip_rk3036_pll_clk_ops = { |
352 | .recalc_rate = rockchip_rk3036_pll_recalc_rate, |
353 | .round_rate = rockchip_pll_round_rate, |
354 | .set_rate = rockchip_rk3036_pll_set_rate, |
355 | .enable = rockchip_rk3036_pll_enable, |
356 | .disable = rockchip_rk3036_pll_disable, |
357 | .is_enabled = rockchip_rk3036_pll_is_enabled, |
358 | .init = rockchip_rk3036_pll_init, |
359 | }; |
360 | |
361 | /* |
362 | * PLL used in RK3066, RK3188 and RK3288 |
363 | */ |
364 | |
365 | #define RK3066_PLL_RESET_DELAY(nr) ((nr * 500) / 24 + 1) |
366 | |
367 | #define RK3066_PLLCON(i) (i * 0x4) |
368 | #define RK3066_PLLCON0_OD_MASK 0xf |
369 | #define RK3066_PLLCON0_OD_SHIFT 0 |
370 | #define RK3066_PLLCON0_NR_MASK 0x3f |
371 | #define RK3066_PLLCON0_NR_SHIFT 8 |
372 | #define RK3066_PLLCON1_NF_MASK 0x1fff |
373 | #define RK3066_PLLCON1_NF_SHIFT 0 |
374 | #define RK3066_PLLCON2_NB_MASK 0xfff |
375 | #define RK3066_PLLCON2_NB_SHIFT 0 |
376 | #define RK3066_PLLCON3_RESET (1 << 5) |
377 | #define RK3066_PLLCON3_PWRDOWN (1 << 1) |
378 | #define RK3066_PLLCON3_BYPASS (1 << 0) |
379 | |
380 | static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll, |
381 | struct rockchip_pll_rate_table *rate) |
382 | { |
383 | u32 pllcon; |
384 | |
385 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0)); |
386 | rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) |
387 | & RK3066_PLLCON0_NR_MASK) + 1; |
388 | rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) |
389 | & RK3066_PLLCON0_OD_MASK) + 1; |
390 | |
391 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1)); |
392 | rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) |
393 | & RK3066_PLLCON1_NF_MASK) + 1; |
394 | |
395 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2)); |
396 | rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) |
397 | & RK3066_PLLCON2_NB_MASK) + 1; |
398 | } |
399 | |
400 | static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw, |
401 | unsigned long prate) |
402 | { |
403 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
404 | struct rockchip_pll_rate_table cur; |
405 | u64 rate64 = prate; |
406 | u32 pllcon; |
407 | |
408 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3)); |
409 | if (pllcon & RK3066_PLLCON3_BYPASS) { |
410 | pr_debug("%s: pll %s is bypassed\n" , __func__, |
411 | clk_hw_get_name(hw)); |
412 | return prate; |
413 | } |
414 | |
415 | rockchip_rk3066_pll_get_params(pll, rate: &cur); |
416 | |
417 | rate64 *= cur.nf; |
418 | do_div(rate64, cur.nr); |
419 | do_div(rate64, cur.no); |
420 | |
421 | return (unsigned long)rate64; |
422 | } |
423 | |
424 | static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll, |
425 | const struct rockchip_pll_rate_table *rate) |
426 | { |
427 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; |
428 | struct clk_mux *pll_mux = &pll->pll_mux; |
429 | struct rockchip_pll_rate_table cur; |
430 | int rate_change_remuxed = 0; |
431 | int cur_parent; |
432 | int ret; |
433 | |
434 | pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n" , |
435 | __func__, rate->rate, rate->nr, rate->no, rate->nf); |
436 | |
437 | rockchip_rk3066_pll_get_params(pll, rate: &cur); |
438 | cur.rate = 0; |
439 | |
440 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); |
441 | if (cur_parent == PLL_MODE_NORM) { |
442 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); |
443 | rate_change_remuxed = 1; |
444 | } |
445 | |
446 | /* enter reset mode */ |
447 | writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), |
448 | addr: pll->reg_base + RK3066_PLLCON(3)); |
449 | |
450 | /* update pll values */ |
451 | writel(HIWORD_UPDATE(rate->nr - 1, RK3066_PLLCON0_NR_MASK, |
452 | RK3066_PLLCON0_NR_SHIFT) | |
453 | HIWORD_UPDATE(rate->no - 1, RK3066_PLLCON0_OD_MASK, |
454 | RK3066_PLLCON0_OD_SHIFT), |
455 | addr: pll->reg_base + RK3066_PLLCON(0)); |
456 | |
457 | writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK, |
458 | RK3066_PLLCON1_NF_SHIFT), |
459 | pll->reg_base + RK3066_PLLCON(1)); |
460 | writel_relaxed(HIWORD_UPDATE(rate->nb - 1, RK3066_PLLCON2_NB_MASK, |
461 | RK3066_PLLCON2_NB_SHIFT), |
462 | pll->reg_base + RK3066_PLLCON(2)); |
463 | |
464 | /* leave reset and wait the reset_delay */ |
465 | writel(HIWORD_UPDATE(0, RK3066_PLLCON3_RESET, 0), |
466 | addr: pll->reg_base + RK3066_PLLCON(3)); |
467 | udelay(RK3066_PLL_RESET_DELAY(rate->nr)); |
468 | |
469 | /* wait for the pll to lock */ |
470 | ret = rockchip_pll_wait_lock(pll); |
471 | if (ret) { |
472 | pr_warn("%s: pll update unsuccessful, trying to restore old params\n" , |
473 | __func__); |
474 | rockchip_rk3066_pll_set_params(pll, rate: &cur); |
475 | } |
476 | |
477 | if (rate_change_remuxed) |
478 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); |
479 | |
480 | return ret; |
481 | } |
482 | |
483 | static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, |
484 | unsigned long prate) |
485 | { |
486 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
487 | const struct rockchip_pll_rate_table *rate; |
488 | |
489 | pr_debug("%s: changing %s to %lu with a parent rate of %lu\n" , |
490 | __func__, clk_hw_get_name(hw), drate, prate); |
491 | |
492 | /* Get required rate settings from table */ |
493 | rate = rockchip_get_pll_settings(pll, rate: drate); |
494 | if (!rate) { |
495 | pr_err("%s: Invalid rate : %lu for pll clk %s\n" , __func__, |
496 | drate, clk_hw_get_name(hw)); |
497 | return -EINVAL; |
498 | } |
499 | |
500 | return rockchip_rk3066_pll_set_params(pll, rate); |
501 | } |
502 | |
503 | static int rockchip_rk3066_pll_enable(struct clk_hw *hw) |
504 | { |
505 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
506 | |
507 | writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0), |
508 | addr: pll->reg_base + RK3066_PLLCON(3)); |
509 | rockchip_pll_wait_lock(pll); |
510 | |
511 | return 0; |
512 | } |
513 | |
514 | static void rockchip_rk3066_pll_disable(struct clk_hw *hw) |
515 | { |
516 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
517 | |
518 | writel(HIWORD_UPDATE(RK3066_PLLCON3_PWRDOWN, |
519 | RK3066_PLLCON3_PWRDOWN, 0), |
520 | addr: pll->reg_base + RK3066_PLLCON(3)); |
521 | } |
522 | |
523 | static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw) |
524 | { |
525 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
526 | u32 pllcon = readl(addr: pll->reg_base + RK3066_PLLCON(3)); |
527 | |
528 | return !(pllcon & RK3066_PLLCON3_PWRDOWN); |
529 | } |
530 | |
531 | static int rockchip_rk3066_pll_init(struct clk_hw *hw) |
532 | { |
533 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
534 | const struct rockchip_pll_rate_table *rate; |
535 | struct rockchip_pll_rate_table cur; |
536 | unsigned long drate; |
537 | |
538 | if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) |
539 | return 0; |
540 | |
541 | drate = clk_hw_get_rate(hw); |
542 | rate = rockchip_get_pll_settings(pll, rate: drate); |
543 | |
544 | /* when no rate setting for the current rate, rely on clk_set_rate */ |
545 | if (!rate) |
546 | return 0; |
547 | |
548 | rockchip_rk3066_pll_get_params(pll, rate: &cur); |
549 | |
550 | pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n" , |
551 | __func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr, |
552 | rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb); |
553 | if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf |
554 | || rate->nb != cur.nb) { |
555 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n" , |
556 | __func__, clk_hw_get_name(hw)); |
557 | rockchip_rk3066_pll_set_params(pll, rate); |
558 | } |
559 | |
560 | return 0; |
561 | } |
562 | |
563 | static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { |
564 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, |
565 | .enable = rockchip_rk3066_pll_enable, |
566 | .disable = rockchip_rk3066_pll_disable, |
567 | .is_enabled = rockchip_rk3066_pll_is_enabled, |
568 | }; |
569 | |
570 | static const struct clk_ops rockchip_rk3066_pll_clk_ops = { |
571 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, |
572 | .round_rate = rockchip_pll_round_rate, |
573 | .set_rate = rockchip_rk3066_pll_set_rate, |
574 | .enable = rockchip_rk3066_pll_enable, |
575 | .disable = rockchip_rk3066_pll_disable, |
576 | .is_enabled = rockchip_rk3066_pll_is_enabled, |
577 | .init = rockchip_rk3066_pll_init, |
578 | }; |
579 | |
580 | /* |
581 | * PLL used in RK3399 |
582 | */ |
583 | |
584 | #define RK3399_PLLCON(i) (i * 0x4) |
585 | #define RK3399_PLLCON0_FBDIV_MASK 0xfff |
586 | #define RK3399_PLLCON0_FBDIV_SHIFT 0 |
587 | #define RK3399_PLLCON1_REFDIV_MASK 0x3f |
588 | #define RK3399_PLLCON1_REFDIV_SHIFT 0 |
589 | #define RK3399_PLLCON1_POSTDIV1_MASK 0x7 |
590 | #define RK3399_PLLCON1_POSTDIV1_SHIFT 8 |
591 | #define RK3399_PLLCON1_POSTDIV2_MASK 0x7 |
592 | #define RK3399_PLLCON1_POSTDIV2_SHIFT 12 |
593 | #define RK3399_PLLCON2_FRAC_MASK 0xffffff |
594 | #define RK3399_PLLCON2_FRAC_SHIFT 0 |
595 | #define RK3399_PLLCON2_LOCK_STATUS BIT(31) |
596 | #define RK3399_PLLCON3_PWRDOWN BIT(0) |
597 | #define RK3399_PLLCON3_DSMPD_MASK 0x1 |
598 | #define RK3399_PLLCON3_DSMPD_SHIFT 3 |
599 | |
600 | static int rockchip_rk3399_pll_wait_lock(struct rockchip_clk_pll *pll) |
601 | { |
602 | u32 pllcon; |
603 | int ret; |
604 | |
605 | /* |
606 | * Lock time typical 250, max 500 input clock cycles @24MHz |
607 | * So define a very safe maximum of 1000us, meaning 24000 cycles. |
608 | */ |
609 | ret = readl_relaxed_poll_timeout(pll->reg_base + RK3399_PLLCON(2), |
610 | pllcon, |
611 | pllcon & RK3399_PLLCON2_LOCK_STATUS, |
612 | 0, 1000); |
613 | if (ret) |
614 | pr_err("%s: timeout waiting for pll to lock\n" , __func__); |
615 | |
616 | return ret; |
617 | } |
618 | |
619 | static void rockchip_rk3399_pll_get_params(struct rockchip_clk_pll *pll, |
620 | struct rockchip_pll_rate_table *rate) |
621 | { |
622 | u32 pllcon; |
623 | |
624 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(0)); |
625 | rate->fbdiv = ((pllcon >> RK3399_PLLCON0_FBDIV_SHIFT) |
626 | & RK3399_PLLCON0_FBDIV_MASK); |
627 | |
628 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(1)); |
629 | rate->refdiv = ((pllcon >> RK3399_PLLCON1_REFDIV_SHIFT) |
630 | & RK3399_PLLCON1_REFDIV_MASK); |
631 | rate->postdiv1 = ((pllcon >> RK3399_PLLCON1_POSTDIV1_SHIFT) |
632 | & RK3399_PLLCON1_POSTDIV1_MASK); |
633 | rate->postdiv2 = ((pllcon >> RK3399_PLLCON1_POSTDIV2_SHIFT) |
634 | & RK3399_PLLCON1_POSTDIV2_MASK); |
635 | |
636 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); |
637 | rate->frac = ((pllcon >> RK3399_PLLCON2_FRAC_SHIFT) |
638 | & RK3399_PLLCON2_FRAC_MASK); |
639 | |
640 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(3)); |
641 | rate->dsmpd = ((pllcon >> RK3399_PLLCON3_DSMPD_SHIFT) |
642 | & RK3399_PLLCON3_DSMPD_MASK); |
643 | } |
644 | |
645 | static unsigned long rockchip_rk3399_pll_recalc_rate(struct clk_hw *hw, |
646 | unsigned long prate) |
647 | { |
648 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
649 | struct rockchip_pll_rate_table cur; |
650 | u64 rate64 = prate; |
651 | |
652 | rockchip_rk3399_pll_get_params(pll, rate: &cur); |
653 | |
654 | rate64 *= cur.fbdiv; |
655 | do_div(rate64, cur.refdiv); |
656 | |
657 | if (cur.dsmpd == 0) { |
658 | /* fractional mode */ |
659 | u64 frac_rate64 = prate * cur.frac; |
660 | |
661 | do_div(frac_rate64, cur.refdiv); |
662 | rate64 += frac_rate64 >> 24; |
663 | } |
664 | |
665 | do_div(rate64, cur.postdiv1); |
666 | do_div(rate64, cur.postdiv2); |
667 | |
668 | return (unsigned long)rate64; |
669 | } |
670 | |
671 | static int rockchip_rk3399_pll_set_params(struct rockchip_clk_pll *pll, |
672 | const struct rockchip_pll_rate_table *rate) |
673 | { |
674 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; |
675 | struct clk_mux *pll_mux = &pll->pll_mux; |
676 | struct rockchip_pll_rate_table cur; |
677 | u32 pllcon; |
678 | int rate_change_remuxed = 0; |
679 | int cur_parent; |
680 | int ret; |
681 | |
682 | pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n" , |
683 | __func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv, |
684 | rate->postdiv2, rate->dsmpd, rate->frac); |
685 | |
686 | rockchip_rk3399_pll_get_params(pll, rate: &cur); |
687 | cur.rate = 0; |
688 | |
689 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); |
690 | if (cur_parent == PLL_MODE_NORM) { |
691 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); |
692 | rate_change_remuxed = 1; |
693 | } |
694 | |
695 | /* update pll values */ |
696 | writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3399_PLLCON0_FBDIV_MASK, |
697 | RK3399_PLLCON0_FBDIV_SHIFT), |
698 | pll->reg_base + RK3399_PLLCON(0)); |
699 | |
700 | writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3399_PLLCON1_REFDIV_MASK, |
701 | RK3399_PLLCON1_REFDIV_SHIFT) | |
702 | HIWORD_UPDATE(rate->postdiv1, RK3399_PLLCON1_POSTDIV1_MASK, |
703 | RK3399_PLLCON1_POSTDIV1_SHIFT) | |
704 | HIWORD_UPDATE(rate->postdiv2, RK3399_PLLCON1_POSTDIV2_MASK, |
705 | RK3399_PLLCON1_POSTDIV2_SHIFT), |
706 | pll->reg_base + RK3399_PLLCON(1)); |
707 | |
708 | /* xPLL CON2 is not HIWORD_MASK */ |
709 | pllcon = readl_relaxed(pll->reg_base + RK3399_PLLCON(2)); |
710 | pllcon &= ~(RK3399_PLLCON2_FRAC_MASK << RK3399_PLLCON2_FRAC_SHIFT); |
711 | pllcon |= rate->frac << RK3399_PLLCON2_FRAC_SHIFT; |
712 | writel_relaxed(pllcon, pll->reg_base + RK3399_PLLCON(2)); |
713 | |
714 | writel_relaxed(HIWORD_UPDATE(rate->dsmpd, RK3399_PLLCON3_DSMPD_MASK, |
715 | RK3399_PLLCON3_DSMPD_SHIFT), |
716 | pll->reg_base + RK3399_PLLCON(3)); |
717 | |
718 | /* wait for the pll to lock */ |
719 | ret = rockchip_rk3399_pll_wait_lock(pll); |
720 | if (ret) { |
721 | pr_warn("%s: pll update unsuccessful, trying to restore old params\n" , |
722 | __func__); |
723 | rockchip_rk3399_pll_set_params(pll, rate: &cur); |
724 | } |
725 | |
726 | if (rate_change_remuxed) |
727 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); |
728 | |
729 | return ret; |
730 | } |
731 | |
732 | static int rockchip_rk3399_pll_set_rate(struct clk_hw *hw, unsigned long drate, |
733 | unsigned long prate) |
734 | { |
735 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
736 | const struct rockchip_pll_rate_table *rate; |
737 | |
738 | pr_debug("%s: changing %s to %lu with a parent rate of %lu\n" , |
739 | __func__, __clk_get_name(hw->clk), drate, prate); |
740 | |
741 | /* Get required rate settings from table */ |
742 | rate = rockchip_get_pll_settings(pll, rate: drate); |
743 | if (!rate) { |
744 | pr_err("%s: Invalid rate : %lu for pll clk %s\n" , __func__, |
745 | drate, __clk_get_name(hw->clk)); |
746 | return -EINVAL; |
747 | } |
748 | |
749 | return rockchip_rk3399_pll_set_params(pll, rate); |
750 | } |
751 | |
752 | static int rockchip_rk3399_pll_enable(struct clk_hw *hw) |
753 | { |
754 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
755 | |
756 | writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0), |
757 | addr: pll->reg_base + RK3399_PLLCON(3)); |
758 | rockchip_rk3399_pll_wait_lock(pll); |
759 | |
760 | return 0; |
761 | } |
762 | |
763 | static void rockchip_rk3399_pll_disable(struct clk_hw *hw) |
764 | { |
765 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
766 | |
767 | writel(HIWORD_UPDATE(RK3399_PLLCON3_PWRDOWN, |
768 | RK3399_PLLCON3_PWRDOWN, 0), |
769 | addr: pll->reg_base + RK3399_PLLCON(3)); |
770 | } |
771 | |
772 | static int rockchip_rk3399_pll_is_enabled(struct clk_hw *hw) |
773 | { |
774 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
775 | u32 pllcon = readl(addr: pll->reg_base + RK3399_PLLCON(3)); |
776 | |
777 | return !(pllcon & RK3399_PLLCON3_PWRDOWN); |
778 | } |
779 | |
780 | static int rockchip_rk3399_pll_init(struct clk_hw *hw) |
781 | { |
782 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
783 | const struct rockchip_pll_rate_table *rate; |
784 | struct rockchip_pll_rate_table cur; |
785 | unsigned long drate; |
786 | |
787 | if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) |
788 | return 0; |
789 | |
790 | drate = clk_hw_get_rate(hw); |
791 | rate = rockchip_get_pll_settings(pll, rate: drate); |
792 | |
793 | /* when no rate setting for the current rate, rely on clk_set_rate */ |
794 | if (!rate) |
795 | return 0; |
796 | |
797 | rockchip_rk3399_pll_get_params(pll, rate: &cur); |
798 | |
799 | pr_debug("%s: pll %s@%lu: Hz\n" , __func__, __clk_get_name(hw->clk), |
800 | drate); |
801 | pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n" , |
802 | cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2, |
803 | cur.dsmpd, cur.frac); |
804 | pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n" , |
805 | rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2, |
806 | rate->dsmpd, rate->frac); |
807 | |
808 | if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 || |
809 | rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 || |
810 | rate->dsmpd != cur.dsmpd || |
811 | (!cur.dsmpd && (rate->frac != cur.frac))) { |
812 | struct clk *parent = clk_get_parent(clk: hw->clk); |
813 | |
814 | if (!parent) { |
815 | pr_warn("%s: parent of %s not available\n" , |
816 | __func__, __clk_get_name(hw->clk)); |
817 | return 0; |
818 | } |
819 | |
820 | pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n" , |
821 | __func__, __clk_get_name(hw->clk)); |
822 | rockchip_rk3399_pll_set_params(pll, rate); |
823 | } |
824 | |
825 | return 0; |
826 | } |
827 | |
828 | static const struct clk_ops rockchip_rk3399_pll_clk_norate_ops = { |
829 | .recalc_rate = rockchip_rk3399_pll_recalc_rate, |
830 | .enable = rockchip_rk3399_pll_enable, |
831 | .disable = rockchip_rk3399_pll_disable, |
832 | .is_enabled = rockchip_rk3399_pll_is_enabled, |
833 | }; |
834 | |
835 | static const struct clk_ops rockchip_rk3399_pll_clk_ops = { |
836 | .recalc_rate = rockchip_rk3399_pll_recalc_rate, |
837 | .round_rate = rockchip_pll_round_rate, |
838 | .set_rate = rockchip_rk3399_pll_set_rate, |
839 | .enable = rockchip_rk3399_pll_enable, |
840 | .disable = rockchip_rk3399_pll_disable, |
841 | .is_enabled = rockchip_rk3399_pll_is_enabled, |
842 | .init = rockchip_rk3399_pll_init, |
843 | }; |
844 | |
845 | /* |
846 | * PLL used in RK3588 |
847 | */ |
848 | |
849 | #define RK3588_PLLCON(i) (i * 0x4) |
850 | #define RK3588_PLLCON0_M_MASK 0x3ff |
851 | #define RK3588_PLLCON0_M_SHIFT 0 |
852 | #define RK3588_PLLCON1_P_MASK 0x3f |
853 | #define RK3588_PLLCON1_P_SHIFT 0 |
854 | #define RK3588_PLLCON1_S_MASK 0x7 |
855 | #define RK3588_PLLCON1_S_SHIFT 6 |
856 | #define RK3588_PLLCON2_K_MASK 0xffff |
857 | #define RK3588_PLLCON2_K_SHIFT 0 |
858 | #define RK3588_PLLCON1_PWRDOWN BIT(13) |
859 | #define RK3588_PLLCON6_LOCK_STATUS BIT(15) |
860 | |
861 | static int rockchip_rk3588_pll_wait_lock(struct rockchip_clk_pll *pll) |
862 | { |
863 | u32 pllcon; |
864 | int ret; |
865 | |
866 | /* |
867 | * Lock time typical 250, max 500 input clock cycles @24MHz |
868 | * So define a very safe maximum of 1000us, meaning 24000 cycles. |
869 | */ |
870 | ret = readl_relaxed_poll_timeout(pll->reg_base + RK3588_PLLCON(6), |
871 | pllcon, |
872 | pllcon & RK3588_PLLCON6_LOCK_STATUS, |
873 | 0, 1000); |
874 | if (ret) |
875 | pr_err("%s: timeout waiting for pll to lock\n" , __func__); |
876 | |
877 | return ret; |
878 | } |
879 | |
880 | static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll, |
881 | struct rockchip_pll_rate_table *rate) |
882 | { |
883 | u32 pllcon; |
884 | |
885 | pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(0)); |
886 | rate->m = ((pllcon >> RK3588_PLLCON0_M_SHIFT) & RK3588_PLLCON0_M_MASK); |
887 | |
888 | pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1)); |
889 | rate->p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) & RK3588_PLLCON1_P_MASK); |
890 | rate->s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) & RK3588_PLLCON1_S_MASK); |
891 | |
892 | pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(2)); |
893 | rate->k = ((pllcon >> RK3588_PLLCON2_K_SHIFT) & RK3588_PLLCON2_K_MASK); |
894 | } |
895 | |
896 | static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned long prate) |
897 | { |
898 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
899 | struct rockchip_pll_rate_table cur; |
900 | u64 rate64 = prate, postdiv; |
901 | |
902 | rockchip_rk3588_pll_get_params(pll, rate: &cur); |
903 | |
904 | rate64 *= cur.m; |
905 | do_div(rate64, cur.p); |
906 | |
907 | if (cur.k) { |
908 | /* fractional mode */ |
909 | u64 frac_rate64 = prate * cur.k; |
910 | |
911 | postdiv = cur.p * 65535; |
912 | do_div(frac_rate64, postdiv); |
913 | rate64 += frac_rate64; |
914 | } |
915 | rate64 = rate64 >> cur.s; |
916 | |
917 | return (unsigned long)rate64; |
918 | } |
919 | |
920 | static int rockchip_rk3588_pll_set_params(struct rockchip_clk_pll *pll, |
921 | const struct rockchip_pll_rate_table *rate) |
922 | { |
923 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; |
924 | struct clk_mux *pll_mux = &pll->pll_mux; |
925 | struct rockchip_pll_rate_table cur; |
926 | int rate_change_remuxed = 0; |
927 | int cur_parent; |
928 | int ret; |
929 | |
930 | pr_debug("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n" , |
931 | __func__, rate->rate, rate->p, rate->m, rate->s, rate->k); |
932 | |
933 | rockchip_rk3588_pll_get_params(pll, rate: &cur); |
934 | cur.rate = 0; |
935 | |
936 | if (pll->type == pll_rk3588) { |
937 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); |
938 | if (cur_parent == PLL_MODE_NORM) { |
939 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); |
940 | rate_change_remuxed = 1; |
941 | } |
942 | } |
943 | |
944 | /* set pll power down */ |
945 | writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, |
946 | RK3588_PLLCON1_PWRDOWN, 0), |
947 | addr: pll->reg_base + RK3399_PLLCON(1)); |
948 | |
949 | /* update pll values */ |
950 | writel_relaxed(HIWORD_UPDATE(rate->m, RK3588_PLLCON0_M_MASK, RK3588_PLLCON0_M_SHIFT), |
951 | pll->reg_base + RK3399_PLLCON(0)); |
952 | |
953 | writel_relaxed(HIWORD_UPDATE(rate->p, RK3588_PLLCON1_P_MASK, RK3588_PLLCON1_P_SHIFT) | |
954 | HIWORD_UPDATE(rate->s, RK3588_PLLCON1_S_MASK, RK3588_PLLCON1_S_SHIFT), |
955 | pll->reg_base + RK3399_PLLCON(1)); |
956 | |
957 | writel_relaxed(HIWORD_UPDATE(rate->k, RK3588_PLLCON2_K_MASK, RK3588_PLLCON2_K_SHIFT), |
958 | pll->reg_base + RK3399_PLLCON(2)); |
959 | |
960 | /* set pll power up */ |
961 | writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0), |
962 | addr: pll->reg_base + RK3588_PLLCON(1)); |
963 | |
964 | /* wait for the pll to lock */ |
965 | ret = rockchip_rk3588_pll_wait_lock(pll); |
966 | if (ret) { |
967 | pr_warn("%s: pll update unsuccessful, trying to restore old params\n" , |
968 | __func__); |
969 | rockchip_rk3588_pll_set_params(pll, rate: &cur); |
970 | } |
971 | |
972 | if ((pll->type == pll_rk3588) && rate_change_remuxed) |
973 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); |
974 | |
975 | return ret; |
976 | } |
977 | |
978 | static int rockchip_rk3588_pll_set_rate(struct clk_hw *hw, unsigned long drate, |
979 | unsigned long prate) |
980 | { |
981 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
982 | const struct rockchip_pll_rate_table *rate; |
983 | |
984 | pr_debug("%s: changing %s to %lu with a parent rate of %lu\n" , |
985 | __func__, __clk_get_name(hw->clk), drate, prate); |
986 | |
987 | /* Get required rate settings from table */ |
988 | rate = rockchip_get_pll_settings(pll, rate: drate); |
989 | if (!rate) { |
990 | pr_err("%s: Invalid rate : %lu for pll clk %s\n" , __func__, |
991 | drate, __clk_get_name(hw->clk)); |
992 | return -EINVAL; |
993 | } |
994 | |
995 | return rockchip_rk3588_pll_set_params(pll, rate); |
996 | } |
997 | |
998 | static int rockchip_rk3588_pll_enable(struct clk_hw *hw) |
999 | { |
1000 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
1001 | |
1002 | writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0), |
1003 | addr: pll->reg_base + RK3588_PLLCON(1)); |
1004 | rockchip_rk3588_pll_wait_lock(pll); |
1005 | |
1006 | return 0; |
1007 | } |
1008 | |
1009 | static void rockchip_rk3588_pll_disable(struct clk_hw *hw) |
1010 | { |
1011 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
1012 | |
1013 | writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, RK3588_PLLCON1_PWRDOWN, 0), |
1014 | addr: pll->reg_base + RK3588_PLLCON(1)); |
1015 | } |
1016 | |
1017 | static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw) |
1018 | { |
1019 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
1020 | u32 pllcon = readl(addr: pll->reg_base + RK3588_PLLCON(1)); |
1021 | |
1022 | return !(pllcon & RK3588_PLLCON1_PWRDOWN); |
1023 | } |
1024 | |
1025 | static int rockchip_rk3588_pll_init(struct clk_hw *hw) |
1026 | { |
1027 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); |
1028 | |
1029 | if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE)) |
1030 | return 0; |
1031 | |
1032 | return 0; |
1033 | } |
1034 | |
1035 | static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = { |
1036 | .recalc_rate = rockchip_rk3588_pll_recalc_rate, |
1037 | .enable = rockchip_rk3588_pll_enable, |
1038 | .disable = rockchip_rk3588_pll_disable, |
1039 | .is_enabled = rockchip_rk3588_pll_is_enabled, |
1040 | }; |
1041 | |
1042 | static const struct clk_ops rockchip_rk3588_pll_clk_ops = { |
1043 | .recalc_rate = rockchip_rk3588_pll_recalc_rate, |
1044 | .round_rate = rockchip_pll_round_rate, |
1045 | .set_rate = rockchip_rk3588_pll_set_rate, |
1046 | .enable = rockchip_rk3588_pll_enable, |
1047 | .disable = rockchip_rk3588_pll_disable, |
1048 | .is_enabled = rockchip_rk3588_pll_is_enabled, |
1049 | .init = rockchip_rk3588_pll_init, |
1050 | }; |
1051 | |
1052 | /* |
1053 | * Common registering of pll clocks |
1054 | */ |
1055 | |
1056 | struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, |
1057 | enum rockchip_pll_type pll_type, |
1058 | const char *name, const char *const *parent_names, |
1059 | u8 num_parents, int con_offset, int grf_lock_offset, |
1060 | int lock_shift, int mode_offset, int mode_shift, |
1061 | struct rockchip_pll_rate_table *rate_table, |
1062 | unsigned long flags, u8 clk_pll_flags) |
1063 | { |
1064 | const char *pll_parents[3]; |
1065 | struct clk_init_data init; |
1066 | struct rockchip_clk_pll *pll; |
1067 | struct clk_mux *pll_mux; |
1068 | struct clk *pll_clk, *mux_clk; |
1069 | char pll_name[20]; |
1070 | |
1071 | if ((pll_type != pll_rk3328 && num_parents != 2) || |
1072 | (pll_type == pll_rk3328 && num_parents != 1)) { |
1073 | pr_err("%s: needs two parent clocks\n" , __func__); |
1074 | return ERR_PTR(error: -EINVAL); |
1075 | } |
1076 | |
1077 | /* name the actual pll */ |
1078 | snprintf(buf: pll_name, size: sizeof(pll_name), fmt: "pll_%s" , name); |
1079 | |
1080 | pll = kzalloc(size: sizeof(*pll), GFP_KERNEL); |
1081 | if (!pll) |
1082 | return ERR_PTR(error: -ENOMEM); |
1083 | |
1084 | /* create the mux on top of the real pll */ |
1085 | pll->pll_mux_ops = &clk_mux_ops; |
1086 | pll_mux = &pll->pll_mux; |
1087 | pll_mux->reg = ctx->reg_base + mode_offset; |
1088 | pll_mux->shift = mode_shift; |
1089 | if (pll_type == pll_rk3328) |
1090 | pll_mux->mask = PLL_RK3328_MODE_MASK; |
1091 | else |
1092 | pll_mux->mask = PLL_MODE_MASK; |
1093 | pll_mux->flags = 0; |
1094 | pll_mux->lock = &ctx->lock; |
1095 | pll_mux->hw.init = &init; |
1096 | |
1097 | if (pll_type == pll_rk3036 || |
1098 | pll_type == pll_rk3066 || |
1099 | pll_type == pll_rk3328 || |
1100 | pll_type == pll_rk3399 || |
1101 | pll_type == pll_rk3588) |
1102 | pll_mux->flags |= CLK_MUX_HIWORD_MASK; |
1103 | |
1104 | /* the actual muxing is xin24m, pll-output, xin32k */ |
1105 | pll_parents[0] = parent_names[0]; |
1106 | pll_parents[1] = pll_name; |
1107 | pll_parents[2] = parent_names[1]; |
1108 | |
1109 | init.name = name; |
1110 | init.flags = CLK_SET_RATE_PARENT; |
1111 | init.ops = pll->pll_mux_ops; |
1112 | init.parent_names = pll_parents; |
1113 | if (pll_type == pll_rk3328) |
1114 | init.num_parents = 2; |
1115 | else |
1116 | init.num_parents = ARRAY_SIZE(pll_parents); |
1117 | |
1118 | mux_clk = clk_register(NULL, hw: &pll_mux->hw); |
1119 | if (IS_ERR(ptr: mux_clk)) |
1120 | goto err_mux; |
1121 | |
1122 | /* now create the actual pll */ |
1123 | init.name = pll_name; |
1124 | |
1125 | /* keep all plls untouched for now */ |
1126 | init.flags = flags | CLK_IGNORE_UNUSED; |
1127 | |
1128 | init.parent_names = &parent_names[0]; |
1129 | init.num_parents = 1; |
1130 | |
1131 | if (rate_table) { |
1132 | int len; |
1133 | |
1134 | /* find count of rates in rate_table */ |
1135 | for (len = 0; rate_table[len].rate != 0; ) |
1136 | len++; |
1137 | |
1138 | pll->rate_count = len; |
1139 | pll->rate_table = kmemdup(p: rate_table, |
1140 | size: pll->rate_count * |
1141 | sizeof(struct rockchip_pll_rate_table), |
1142 | GFP_KERNEL); |
1143 | WARN(!pll->rate_table, |
1144 | "%s: could not allocate rate table for %s\n" , |
1145 | __func__, name); |
1146 | } |
1147 | |
1148 | switch (pll_type) { |
1149 | case pll_rk3036: |
1150 | case pll_rk3328: |
1151 | if (!pll->rate_table) |
1152 | init.ops = &rockchip_rk3036_pll_clk_norate_ops; |
1153 | else |
1154 | init.ops = &rockchip_rk3036_pll_clk_ops; |
1155 | break; |
1156 | case pll_rk3066: |
1157 | if (!pll->rate_table || IS_ERR(ptr: ctx->grf)) |
1158 | init.ops = &rockchip_rk3066_pll_clk_norate_ops; |
1159 | else |
1160 | init.ops = &rockchip_rk3066_pll_clk_ops; |
1161 | break; |
1162 | case pll_rk3399: |
1163 | if (!pll->rate_table) |
1164 | init.ops = &rockchip_rk3399_pll_clk_norate_ops; |
1165 | else |
1166 | init.ops = &rockchip_rk3399_pll_clk_ops; |
1167 | break; |
1168 | case pll_rk3588: |
1169 | case pll_rk3588_core: |
1170 | if (!pll->rate_table) |
1171 | init.ops = &rockchip_rk3588_pll_clk_norate_ops; |
1172 | else |
1173 | init.ops = &rockchip_rk3588_pll_clk_ops; |
1174 | init.flags = flags; |
1175 | break; |
1176 | default: |
1177 | pr_warn("%s: Unknown pll type for pll clk %s\n" , |
1178 | __func__, name); |
1179 | } |
1180 | |
1181 | pll->hw.init = &init; |
1182 | pll->type = pll_type; |
1183 | pll->reg_base = ctx->reg_base + con_offset; |
1184 | pll->lock_offset = grf_lock_offset; |
1185 | pll->lock_shift = lock_shift; |
1186 | pll->flags = clk_pll_flags; |
1187 | pll->lock = &ctx->lock; |
1188 | pll->ctx = ctx; |
1189 | |
1190 | pll_clk = clk_register(NULL, hw: &pll->hw); |
1191 | if (IS_ERR(ptr: pll_clk)) { |
1192 | pr_err("%s: failed to register pll clock %s : %ld\n" , |
1193 | __func__, name, PTR_ERR(pll_clk)); |
1194 | goto err_pll; |
1195 | } |
1196 | |
1197 | return mux_clk; |
1198 | |
1199 | err_pll: |
1200 | kfree(objp: pll->rate_table); |
1201 | clk_unregister(clk: mux_clk); |
1202 | mux_clk = pll_clk; |
1203 | err_mux: |
1204 | kfree(objp: pll); |
1205 | return mux_clk; |
1206 | } |
1207 | |