kernel: bump 5.10 to 5.10.103
[openwrt/staging/jow.git] / target / linux / at91 / patches-5.10 / 106-clk-at91-clk-sam9x60-pll-allow-runtime-changes-for-p.patch
1 From 6fe2927863de96edf35d8357712dbf83a489f556 Mon Sep 17 00:00:00 2001
2 From: Claudiu Beznea <claudiu.beznea@microchip.com>
3 Date: Thu, 19 Nov 2020 17:43:12 +0200
4 Subject: [PATCH 106/247] clk: at91: clk-sam9x60-pll: allow runtime changes for
5 pll
6
7 Allow runtime frequency changes for PLLs registered with proper flags.
8 This is necessary for CPU PLL on SAMA7G5 which is used by DVFS.
9
10 Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
11 Link: https://lore.kernel.org/r/1605800597-16720-7-git-send-email-claudiu.beznea@microchip.com
12 Signed-off-by: Stephen Boyd <sboyd@kernel.org>
13 ---
14 drivers/clk/at91/clk-sam9x60-pll.c | 145 +++++++++++++++++++++++++----
15 drivers/clk/at91/pmc.h | 4 +-
16 drivers/clk/at91/sam9x60.c | 22 ++++-
17 drivers/clk/at91/sama7g5.c | 67 +++++++++----
18 4 files changed, 197 insertions(+), 41 deletions(-)
19
20 --- a/drivers/clk/at91/clk-sam9x60-pll.c
21 +++ b/drivers/clk/at91/clk-sam9x60-pll.c
22 @@ -229,6 +229,57 @@ static int sam9x60_frac_pll_set_rate(str
23 return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
24 }
25
26 +static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
27 + unsigned long parent_rate)
28 +{
29 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
30 + struct sam9x60_frac *frac = to_sam9x60_frac(core);
31 + struct regmap *regmap = core->regmap;
32 + unsigned long irqflags;
33 + unsigned int val, cfrac, cmul;
34 + long ret;
35 +
36 + ret = sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
37 + if (ret <= 0)
38 + return ret;
39 +
40 + spin_lock_irqsave(core->lock, irqflags);
41 +
42 + regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
43 + core->id);
44 + regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
45 + cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
46 + cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
47 +
48 + if (cmul == frac->mul && cfrac == frac->frac)
49 + goto unlock;
50 +
51 + regmap_write(regmap, AT91_PMC_PLL_CTRL1,
52 + (frac->mul << core->layout->mul_shift) |
53 + (frac->frac << core->layout->frac_shift));
54 +
55 + regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
56 + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
57 + AT91_PMC_PLL_UPDT_UPDATE | core->id);
58 +
59 + regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
60 + AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
61 + AT91_PMC_PLL_CTRL0_ENLOCK |
62 + AT91_PMC_PLL_CTRL0_ENPLL);
63 +
64 + regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
65 + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
66 + AT91_PMC_PLL_UPDT_UPDATE | core->id);
67 +
68 + while (!sam9x60_pll_ready(regmap, core->id))
69 + cpu_relax();
70 +
71 +unlock:
72 + spin_unlock_irqrestore(core->lock, irqflags);
73 +
74 + return ret;
75 +}
76 +
77 static const struct clk_ops sam9x60_frac_pll_ops = {
78 .prepare = sam9x60_frac_pll_prepare,
79 .unprepare = sam9x60_frac_pll_unprepare,
80 @@ -238,6 +289,15 @@ static const struct clk_ops sam9x60_frac
81 .set_rate = sam9x60_frac_pll_set_rate,
82 };
83
84 +static const struct clk_ops sam9x60_frac_pll_ops_chg = {
85 + .prepare = sam9x60_frac_pll_prepare,
86 + .unprepare = sam9x60_frac_pll_unprepare,
87 + .is_prepared = sam9x60_frac_pll_is_prepared,
88 + .recalc_rate = sam9x60_frac_pll_recalc_rate,
89 + .round_rate = sam9x60_frac_pll_round_rate,
90 + .set_rate = sam9x60_frac_pll_set_rate_chg,
91 +};
92 +
93 static int sam9x60_div_pll_prepare(struct clk_hw *hw)
94 {
95 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
96 @@ -384,6 +444,44 @@ static int sam9x60_div_pll_set_rate(stru
97 return 0;
98 }
99
100 +static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
101 + unsigned long parent_rate)
102 +{
103 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
104 + struct sam9x60_div *div = to_sam9x60_div(core);
105 + struct regmap *regmap = core->regmap;
106 + unsigned long irqflags;
107 + unsigned int val, cdiv;
108 +
109 + div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
110 +
111 + spin_lock_irqsave(core->lock, irqflags);
112 + regmap_update_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
113 + core->id);
114 + regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
115 + cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
116 +
117 + /* Stop if nothing changed. */
118 + if (cdiv == div->div)
119 + goto unlock;
120 +
121 + regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
122 + core->layout->div_mask,
123 + (div->div << core->layout->div_shift));
124 +
125 + regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
126 + AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
127 + AT91_PMC_PLL_UPDT_UPDATE | core->id);
128 +
129 + while (!sam9x60_pll_ready(regmap, core->id))
130 + cpu_relax();
131 +
132 +unlock:
133 + spin_unlock_irqrestore(core->lock, irqflags);
134 +
135 + return 0;
136 +}
137 +
138 static const struct clk_ops sam9x60_div_pll_ops = {
139 .prepare = sam9x60_div_pll_prepare,
140 .unprepare = sam9x60_div_pll_unprepare,
141 @@ -393,17 +491,26 @@ static const struct clk_ops sam9x60_div_
142 .set_rate = sam9x60_div_pll_set_rate,
143 };
144
145 +static const struct clk_ops sam9x60_div_pll_ops_chg = {
146 + .prepare = sam9x60_div_pll_prepare,
147 + .unprepare = sam9x60_div_pll_unprepare,
148 + .is_prepared = sam9x60_div_pll_is_prepared,
149 + .recalc_rate = sam9x60_div_pll_recalc_rate,
150 + .round_rate = sam9x60_div_pll_round_rate,
151 + .set_rate = sam9x60_div_pll_set_rate_chg,
152 +};
153 +
154 struct clk_hw * __init
155 sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
156 const char *name, const char *parent_name,
157 struct clk_hw *parent_hw, u8 id,
158 const struct clk_pll_characteristics *characteristics,
159 - const struct clk_pll_layout *layout, bool critical)
160 + const struct clk_pll_layout *layout, u32 flags)
161 {
162 struct sam9x60_frac *frac;
163 struct clk_hw *hw;
164 struct clk_init_data init;
165 - unsigned long parent_rate, flags;
166 + unsigned long parent_rate, irqflags;
167 unsigned int val;
168 int ret;
169
170 @@ -417,10 +524,12 @@ sam9x60_clk_register_frac_pll(struct reg
171 init.name = name;
172 init.parent_names = &parent_name;
173 init.num_parents = 1;
174 - init.ops = &sam9x60_frac_pll_ops;
175 - init.flags = CLK_SET_RATE_GATE;
176 - if (critical)
177 - init.flags |= CLK_IS_CRITICAL;
178 + if (flags & CLK_SET_RATE_GATE)
179 + init.ops = &sam9x60_frac_pll_ops;
180 + else
181 + init.ops = &sam9x60_frac_pll_ops_chg;
182 +
183 + init.flags = flags;
184
185 frac->core.id = id;
186 frac->core.hw.init = &init;
187 @@ -429,7 +538,7 @@ sam9x60_clk_register_frac_pll(struct reg
188 frac->core.regmap = regmap;
189 frac->core.lock = lock;
190
191 - spin_lock_irqsave(frac->core.lock, flags);
192 + spin_lock_irqsave(frac->core.lock, irqflags);
193 if (sam9x60_pll_ready(regmap, id)) {
194 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
195 AT91_PMC_PLL_UPDT_ID_MSK, id);
196 @@ -457,7 +566,7 @@ sam9x60_clk_register_frac_pll(struct reg
197 goto free;
198 }
199 }
200 - spin_unlock_irqrestore(frac->core.lock, flags);
201 + spin_unlock_irqrestore(frac->core.lock, irqflags);
202
203 hw = &frac->core.hw;
204 ret = clk_hw_register(NULL, hw);
205 @@ -469,7 +578,7 @@ sam9x60_clk_register_frac_pll(struct reg
206 return hw;
207
208 free:
209 - spin_unlock_irqrestore(frac->core.lock, flags);
210 + spin_unlock_irqrestore(frac->core.lock, irqflags);
211 kfree(frac);
212 return hw;
213 }
214 @@ -478,12 +587,12 @@ struct clk_hw * __init
215 sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
216 const char *name, const char *parent_name, u8 id,
217 const struct clk_pll_characteristics *characteristics,
218 - const struct clk_pll_layout *layout, bool critical)
219 + const struct clk_pll_layout *layout, u32 flags)
220 {
221 struct sam9x60_div *div;
222 struct clk_hw *hw;
223 struct clk_init_data init;
224 - unsigned long flags;
225 + unsigned long irqflags;
226 unsigned int val;
227 int ret;
228
229 @@ -497,11 +606,11 @@ sam9x60_clk_register_div_pll(struct regm
230 init.name = name;
231 init.parent_names = &parent_name;
232 init.num_parents = 1;
233 - init.ops = &sam9x60_div_pll_ops;
234 - init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
235 - CLK_SET_RATE_PARENT;
236 - if (critical)
237 - init.flags |= CLK_IS_CRITICAL;
238 + if (flags & CLK_SET_RATE_GATE)
239 + init.ops = &sam9x60_div_pll_ops;
240 + else
241 + init.ops = &sam9x60_div_pll_ops_chg;
242 + init.flags = flags;
243
244 div->core.id = id;
245 div->core.hw.init = &init;
246 @@ -510,14 +619,14 @@ sam9x60_clk_register_div_pll(struct regm
247 div->core.regmap = regmap;
248 div->core.lock = lock;
249
250 - spin_lock_irqsave(div->core.lock, flags);
251 + spin_lock_irqsave(div->core.lock, irqflags);
252
253 regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
254 AT91_PMC_PLL_UPDT_ID_MSK, id);
255 regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
256 div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
257
258 - spin_unlock_irqrestore(div->core.lock, flags);
259 + spin_unlock_irqrestore(div->core.lock, irqflags);
260
261 hw = &div->core.hw;
262 ret = clk_hw_register(NULL, hw);
263 --- a/drivers/clk/at91/pmc.h
264 +++ b/drivers/clk/at91/pmc.h
265 @@ -190,14 +190,14 @@ struct clk_hw * __init
266 sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
267 const char *name, const char *parent_name, u8 id,
268 const struct clk_pll_characteristics *characteristics,
269 - const struct clk_pll_layout *layout, bool critical);
270 + const struct clk_pll_layout *layout, u32 flags);
271
272 struct clk_hw * __init
273 sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
274 const char *name, const char *parent_name,
275 struct clk_hw *parent_hw, u8 id,
276 const struct clk_pll_characteristics *characteristics,
277 - const struct clk_pll_layout *layout, bool critical);
278 + const struct clk_pll_layout *layout, u32 flags);
279
280 struct clk_hw * __init
281 at91_clk_register_programmable(struct regmap *regmap, const char *name,
282 --- a/drivers/clk/at91/sam9x60.c
283 +++ b/drivers/clk/at91/sam9x60.c
284 @@ -224,13 +224,24 @@ static void __init sam9x60_pmc_setup(str
285 hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "pllack_fracck",
286 "mainck", sam9x60_pmc->chws[PMC_MAIN],
287 0, &plla_characteristics,
288 - &pll_frac_layout, true);
289 + &pll_frac_layout,
290 + /*
291 + * This feeds pllack_divck which
292 + * feeds CPU. It should not be
293 + * disabled.
294 + */
295 + CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
296 if (IS_ERR(hw))
297 goto err_free;
298
299 hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "pllack_divck",
300 "pllack_fracck", 0, &plla_characteristics,
301 - &pll_div_layout, true);
302 + &pll_div_layout,
303 + /*
304 + * This feeds CPU. It should not
305 + * be disabled.
306 + */
307 + CLK_IS_CRITICAL | CLK_SET_RATE_GATE);
308 if (IS_ERR(hw))
309 goto err_free;
310
311 @@ -239,13 +250,16 @@ static void __init sam9x60_pmc_setup(str
312 hw = sam9x60_clk_register_frac_pll(regmap, &pmc_pll_lock, "upllck_fracck",
313 "main_osc", main_osc_hw, 1,
314 &upll_characteristics,
315 - &pll_frac_layout, false);
316 + &pll_frac_layout, CLK_SET_RATE_GATE);
317 if (IS_ERR(hw))
318 goto err_free;
319
320 hw = sam9x60_clk_register_div_pll(regmap, &pmc_pll_lock, "upllck_divck",
321 "upllck_fracck", 1, &upll_characteristics,
322 - &pll_div_layout, false);
323 + &pll_div_layout,
324 + CLK_SET_RATE_GATE |
325 + CLK_SET_PARENT_GATE |
326 + CLK_SET_RATE_PARENT);
327 if (IS_ERR(hw))
328 goto err_free;
329
330 --- a/drivers/clk/at91/sama7g5.c
331 +++ b/drivers/clk/at91/sama7g5.c
332 @@ -95,15 +95,15 @@ static const struct clk_pll_layout pll_l
333 * @p: clock parent
334 * @l: clock layout
335 * @t: clock type
336 - * @f: true if clock is critical and cannot be disabled
337 + * @f: clock flags
338 * @eid: export index in sama7g5->chws[] array
339 */
340 static const struct {
341 const char *n;
342 const char *p;
343 const struct clk_pll_layout *l;
344 + unsigned long f;
345 u8 t;
346 - u8 c;
347 u8 eid;
348 } sama7g5_plls[][PLL_ID_MAX] = {
349 [PLL_ID_CPU] = {
350 @@ -111,13 +111,18 @@ static const struct {
351 .p = "mainck",
352 .l = &pll_layout_frac,
353 .t = PLL_TYPE_FRAC,
354 - .c = 1, },
355 + /*
356 + * This feeds cpupll_divpmcck which feeds CPU. It should
357 + * not be disabled.
358 + */
359 + .f = CLK_IS_CRITICAL, },
360
361 { .n = "cpupll_divpmcck",
362 .p = "cpupll_fracck",
363 .l = &pll_layout_divpmc,
364 .t = PLL_TYPE_DIV,
365 - .c = 1,
366 + /* This feeds CPU. It should not be disabled. */
367 + .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,
368 .eid = PMC_CPUPLL, },
369 },
370
371 @@ -126,13 +131,22 @@ static const struct {
372 .p = "mainck",
373 .l = &pll_layout_frac,
374 .t = PLL_TYPE_FRAC,
375 - .c = 1, },
376 + /*
377 + * This feeds syspll_divpmcck which may feed critial parts
378 + * of the systems like timers. Therefore it should not be
379 + * disabled.
380 + */
381 + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
382
383 { .n = "syspll_divpmcck",
384 .p = "syspll_fracck",
385 .l = &pll_layout_divpmc,
386 .t = PLL_TYPE_DIV,
387 - .c = 1,
388 + /*
389 + * This may feed critial parts of the systems like timers.
390 + * Therefore it should not be disabled.
391 + */
392 + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
393 .eid = PMC_SYSPLL, },
394 },
395
396 @@ -141,55 +155,71 @@ static const struct {
397 .p = "mainck",
398 .l = &pll_layout_frac,
399 .t = PLL_TYPE_FRAC,
400 - .c = 1, },
401 + /*
402 + * This feeds ddrpll_divpmcck which feeds DDR. It should not
403 + * be disabled.
404 + */
405 + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
406
407 { .n = "ddrpll_divpmcck",
408 .p = "ddrpll_fracck",
409 .l = &pll_layout_divpmc,
410 .t = PLL_TYPE_DIV,
411 - .c = 1, },
412 + /* This feeds DDR. It should not be disabled. */
413 + .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE, },
414 },
415
416 [PLL_ID_IMG] = {
417 { .n = "imgpll_fracck",
418 .p = "mainck",
419 .l = &pll_layout_frac,
420 - .t = PLL_TYPE_FRAC, },
421 + .t = PLL_TYPE_FRAC,
422 + .f = CLK_SET_RATE_GATE, },
423
424 { .n = "imgpll_divpmcck",
425 .p = "imgpll_fracck",
426 .l = &pll_layout_divpmc,
427 - .t = PLL_TYPE_DIV, },
428 + .t = PLL_TYPE_DIV,
429 + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
430 + CLK_SET_RATE_PARENT, },
431 },
432
433 [PLL_ID_BAUD] = {
434 { .n = "baudpll_fracck",
435 .p = "mainck",
436 .l = &pll_layout_frac,
437 - .t = PLL_TYPE_FRAC, },
438 + .t = PLL_TYPE_FRAC,
439 + .f = CLK_SET_RATE_GATE, },
440
441 { .n = "baudpll_divpmcck",
442 .p = "baudpll_fracck",
443 .l = &pll_layout_divpmc,
444 - .t = PLL_TYPE_DIV, },
445 + .t = PLL_TYPE_DIV,
446 + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
447 + CLK_SET_RATE_PARENT, },
448 },
449
450 [PLL_ID_AUDIO] = {
451 { .n = "audiopll_fracck",
452 .p = "main_xtal",
453 .l = &pll_layout_frac,
454 - .t = PLL_TYPE_FRAC, },
455 + .t = PLL_TYPE_FRAC,
456 + .f = CLK_SET_RATE_GATE, },
457
458 { .n = "audiopll_divpmcck",
459 .p = "audiopll_fracck",
460 .l = &pll_layout_divpmc,
461 .t = PLL_TYPE_DIV,
462 + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
463 + CLK_SET_RATE_PARENT,
464 .eid = PMC_AUDIOPMCPLL, },
465
466 { .n = "audiopll_diviock",
467 .p = "audiopll_fracck",
468 .l = &pll_layout_divio,
469 .t = PLL_TYPE_DIV,
470 + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
471 + CLK_SET_RATE_PARENT,
472 .eid = PMC_AUDIOIOPLL, },
473 },
474
475 @@ -197,12 +227,15 @@ static const struct {
476 { .n = "ethpll_fracck",
477 .p = "main_xtal",
478 .l = &pll_layout_frac,
479 - .t = PLL_TYPE_FRAC, },
480 + .t = PLL_TYPE_FRAC,
481 + .f = CLK_SET_RATE_GATE, },
482
483 { .n = "ethpll_divpmcck",
484 .p = "ethpll_fracck",
485 .l = &pll_layout_divpmc,
486 - .t = PLL_TYPE_DIV, },
487 + .t = PLL_TYPE_DIV,
488 + .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
489 + CLK_SET_RATE_PARENT, },
490 },
491 };
492
493 @@ -890,7 +923,7 @@ static void __init sama7g5_pmc_setup(str
494 sama7g5_plls[i][j].p, parent_hw, i,
495 &pll_characteristics,
496 sama7g5_plls[i][j].l,
497 - sama7g5_plls[i][j].c);
498 + sama7g5_plls[i][j].f);
499 break;
500
501 case PLL_TYPE_DIV:
502 @@ -899,7 +932,7 @@ static void __init sama7g5_pmc_setup(str
503 sama7g5_plls[i][j].p, i,
504 &pll_characteristics,
505 sama7g5_plls[i][j].l,
506 - sama7g5_plls[i][j].c);
507 + sama7g5_plls[i][j].f);
508 break;
509
510 default: