5d399f6535e8ee79d1422123de00c33c781a3c49
[openwrt/openwrt.git] / target / linux / at91 / patches-5.15 / 234-clk-at91-re-factor-clocks-suspend-resume.patch
1 From 65bb4687b2a5c6f02f44345540c3389d6e7523e7 Mon Sep 17 00:00:00 2001
2 From: Claudiu Beznea <claudiu.beznea@microchip.com>
3 Date: Mon, 11 Oct 2021 14:27:05 +0300
4 Subject: [PATCH 234/247] clk: at91: re-factor clocks suspend/resume
5
6 SAMA5D2 and SAMA7G5 have a special power saving mode (backup mode) where
7 most of the SoC's components are powered off (including PMC). Resuming
8 from this mode is done with the help of bootloader. Peripherals are not
9 aware of the power saving mode thus most of them are disabling clocks in
10 proper suspend API and re-enable them in resume API without taking into
11 account the previously setup rate. Moreover some of the peripherals are
12 acting as wakeup sources and are not disabling the clocks in this
13 scenario, when suspending. Since backup mode cuts the power for
14 peripherals, in resume part these clocks needs to be re-configured.
15
16 The initial PMC suspend/resume code was designed only for SAMA5D2's PMC
17 (as it was the only one supporting backup mode). SAMA7G supports also
18 backup mode and its PMC is different (few new functionalities, different
19 registers offsets, different offsets in registers for each
20 functionalities). To address both SAMA5D2 and SAMA7G5 PMC add
21 .save_context()/.resume_context() support to each clocks driver and call
22 this from PMC driver.
23
24 Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
25 Link: https://lore.kernel.org/r/20211011112719.3951784-2-claudiu.beznea@microchip.com
26 Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
27 Signed-off-by: Stephen Boyd <sboyd@kernel.org>
28 ---
29 drivers/clk/at91/clk-generated.c | 46 +++++--
30 drivers/clk/at91/clk-main.c | 66 ++++++++++
31 drivers/clk/at91/clk-master.c | 194 ++++++++++++++++++++++++++--
32 drivers/clk/at91/clk-peripheral.c | 40 +++++-
33 drivers/clk/at91/clk-pll.c | 39 ++++++
34 drivers/clk/at91/clk-programmable.c | 29 ++++-
35 drivers/clk/at91/clk-sam9x60-pll.c | 68 +++++++++-
36 drivers/clk/at91/clk-system.c | 20 +++
37 drivers/clk/at91/clk-usb.c | 27 ++++
38 drivers/clk/at91/clk-utmi.c | 39 ++++++
39 drivers/clk/at91/pmc.c | 147 +--------------------
40 drivers/clk/at91/pmc.h | 24 ++--
41 12 files changed, 558 insertions(+), 181 deletions(-)
42
43 --- a/drivers/clk/at91/clk-generated.c
44 +++ b/drivers/clk/at91/clk-generated.c
45 @@ -27,6 +27,7 @@ struct clk_generated {
46 u32 id;
47 u32 gckdiv;
48 const struct clk_pcr_layout *layout;
49 + struct at91_clk_pms pms;
50 u8 parent_id;
51 int chg_pid;
52 };
53 @@ -34,25 +35,35 @@ struct clk_generated {
54 #define to_clk_generated(hw) \
55 container_of(hw, struct clk_generated, hw)
56
57 -static int clk_generated_enable(struct clk_hw *hw)
58 +static int clk_generated_set(struct clk_generated *gck, int status)
59 {
60 - struct clk_generated *gck = to_clk_generated(hw);
61 unsigned long flags;
62 -
63 - pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
64 - __func__, gck->gckdiv, gck->parent_id);
65 + unsigned int enable = status ? AT91_PMC_PCR_GCKEN : 0;
66
67 spin_lock_irqsave(gck->lock, flags);
68 regmap_write(gck->regmap, gck->layout->offset,
69 (gck->id & gck->layout->pid_mask));
70 regmap_update_bits(gck->regmap, gck->layout->offset,
71 AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
72 - gck->layout->cmd | AT91_PMC_PCR_GCKEN,
73 + gck->layout->cmd | enable,
74 field_prep(gck->layout->gckcss_mask, gck->parent_id) |
75 gck->layout->cmd |
76 FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
77 - AT91_PMC_PCR_GCKEN);
78 + enable);
79 spin_unlock_irqrestore(gck->lock, flags);
80 +
81 + return 0;
82 +}
83 +
84 +static int clk_generated_enable(struct clk_hw *hw)
85 +{
86 + struct clk_generated *gck = to_clk_generated(hw);
87 +
88 + pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
89 + __func__, gck->gckdiv, gck->parent_id);
90 +
91 + clk_generated_set(gck, 1);
92 +
93 return 0;
94 }
95
96 @@ -249,6 +260,23 @@ static int clk_generated_set_rate(struct
97 return 0;
98 }
99
100 +static int clk_generated_save_context(struct clk_hw *hw)
101 +{
102 + struct clk_generated *gck = to_clk_generated(hw);
103 +
104 + gck->pms.status = clk_generated_is_enabled(&gck->hw);
105 +
106 + return 0;
107 +}
108 +
109 +static void clk_generated_restore_context(struct clk_hw *hw)
110 +{
111 + struct clk_generated *gck = to_clk_generated(hw);
112 +
113 + if (gck->pms.status)
114 + clk_generated_set(gck, gck->pms.status);
115 +}
116 +
117 static const struct clk_ops generated_ops = {
118 .enable = clk_generated_enable,
119 .disable = clk_generated_disable,
120 @@ -258,6 +286,8 @@ static const struct clk_ops generated_op
121 .get_parent = clk_generated_get_parent,
122 .set_parent = clk_generated_set_parent,
123 .set_rate = clk_generated_set_rate,
124 + .save_context = clk_generated_save_context,
125 + .restore_context = clk_generated_restore_context,
126 };
127
128 /**
129 @@ -324,8 +354,6 @@ at91_clk_register_generated(struct regma
130 if (ret) {
131 kfree(gck);
132 hw = ERR_PTR(ret);
133 - } else {
134 - pmc_register_id(id);
135 }
136
137 return hw;
138 --- a/drivers/clk/at91/clk-main.c
139 +++ b/drivers/clk/at91/clk-main.c
140 @@ -28,6 +28,7 @@
141 struct clk_main_osc {
142 struct clk_hw hw;
143 struct regmap *regmap;
144 + struct at91_clk_pms pms;
145 };
146
147 #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
148 @@ -37,6 +38,7 @@ struct clk_main_rc_osc {
149 struct regmap *regmap;
150 unsigned long frequency;
151 unsigned long accuracy;
152 + struct at91_clk_pms pms;
153 };
154
155 #define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
156 @@ -51,6 +53,7 @@ struct clk_rm9200_main {
157 struct clk_sam9x5_main {
158 struct clk_hw hw;
159 struct regmap *regmap;
160 + struct at91_clk_pms pms;
161 u8 parent;
162 };
163
164 @@ -120,10 +123,29 @@ static int clk_main_osc_is_prepared(stru
165 return (status & AT91_PMC_MOSCS) && clk_main_parent_select(tmp);
166 }
167
168 +static int clk_main_osc_save_context(struct clk_hw *hw)
169 +{
170 + struct clk_main_osc *osc = to_clk_main_osc(hw);
171 +
172 + osc->pms.status = clk_main_osc_is_prepared(hw);
173 +
174 + return 0;
175 +}
176 +
177 +static void clk_main_osc_restore_context(struct clk_hw *hw)
178 +{
179 + struct clk_main_osc *osc = to_clk_main_osc(hw);
180 +
181 + if (osc->pms.status)
182 + clk_main_osc_prepare(hw);
183 +}
184 +
185 static const struct clk_ops main_osc_ops = {
186 .prepare = clk_main_osc_prepare,
187 .unprepare = clk_main_osc_unprepare,
188 .is_prepared = clk_main_osc_is_prepared,
189 + .save_context = clk_main_osc_save_context,
190 + .restore_context = clk_main_osc_restore_context,
191 };
192
193 struct clk_hw * __init
194 @@ -240,12 +262,31 @@ static unsigned long clk_main_rc_osc_rec
195 return osc->accuracy;
196 }
197
198 +static int clk_main_rc_osc_save_context(struct clk_hw *hw)
199 +{
200 + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
201 +
202 + osc->pms.status = clk_main_rc_osc_is_prepared(hw);
203 +
204 + return 0;
205 +}
206 +
207 +static void clk_main_rc_osc_restore_context(struct clk_hw *hw)
208 +{
209 + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
210 +
211 + if (osc->pms.status)
212 + clk_main_rc_osc_prepare(hw);
213 +}
214 +
215 static const struct clk_ops main_rc_osc_ops = {
216 .prepare = clk_main_rc_osc_prepare,
217 .unprepare = clk_main_rc_osc_unprepare,
218 .is_prepared = clk_main_rc_osc_is_prepared,
219 .recalc_rate = clk_main_rc_osc_recalc_rate,
220 .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
221 + .save_context = clk_main_rc_osc_save_context,
222 + .restore_context = clk_main_rc_osc_restore_context,
223 };
224
225 struct clk_hw * __init
226 @@ -465,12 +506,37 @@ static u8 clk_sam9x5_main_get_parent(str
227 return clk_main_parent_select(status);
228 }
229
230 +static int clk_sam9x5_main_save_context(struct clk_hw *hw)
231 +{
232 + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
233 +
234 + clkmain->pms.status = clk_main_rc_osc_is_prepared(&clkmain->hw);
235 + clkmain->pms.parent = clk_sam9x5_main_get_parent(&clkmain->hw);
236 +
237 + return 0;
238 +}
239 +
240 +static void clk_sam9x5_main_restore_context(struct clk_hw *hw)
241 +{
242 + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
243 + int ret;
244 +
245 + ret = clk_sam9x5_main_set_parent(hw, clkmain->pms.parent);
246 + if (ret)
247 + return;
248 +
249 + if (clkmain->pms.status)
250 + clk_sam9x5_main_prepare(hw);
251 +}
252 +
253 static const struct clk_ops sam9x5_main_ops = {
254 .prepare = clk_sam9x5_main_prepare,
255 .is_prepared = clk_sam9x5_main_is_prepared,
256 .recalc_rate = clk_sam9x5_main_recalc_rate,
257 .set_parent = clk_sam9x5_main_set_parent,
258 .get_parent = clk_sam9x5_main_get_parent,
259 + .save_context = clk_sam9x5_main_save_context,
260 + .restore_context = clk_sam9x5_main_restore_context,
261 };
262
263 struct clk_hw * __init
264 --- a/drivers/clk/at91/clk-master.c
265 +++ b/drivers/clk/at91/clk-master.c
266 @@ -37,6 +37,7 @@ struct clk_master {
267 spinlock_t *lock;
268 const struct clk_master_layout *layout;
269 const struct clk_master_characteristics *characteristics;
270 + struct at91_clk_pms pms;
271 u32 *mux_table;
272 u32 mckr;
273 int chg_pid;
274 @@ -112,10 +113,52 @@ static unsigned long clk_master_div_reca
275 return rate;
276 }
277
278 +static int clk_master_div_save_context(struct clk_hw *hw)
279 +{
280 + struct clk_master *master = to_clk_master(hw);
281 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
282 + unsigned long flags;
283 + unsigned int mckr, div;
284 +
285 + spin_lock_irqsave(master->lock, flags);
286 + regmap_read(master->regmap, master->layout->offset, &mckr);
287 + spin_unlock_irqrestore(master->lock, flags);
288 +
289 + mckr &= master->layout->mask;
290 + div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
291 + div = master->characteristics->divisors[div];
292 +
293 + master->pms.parent_rate = clk_hw_get_rate(parent_hw);
294 + master->pms.rate = DIV_ROUND_CLOSEST(master->pms.parent_rate, div);
295 +
296 + return 0;
297 +}
298 +
299 +static void clk_master_div_restore_context(struct clk_hw *hw)
300 +{
301 + struct clk_master *master = to_clk_master(hw);
302 + unsigned long flags;
303 + unsigned int mckr;
304 + u8 div;
305 +
306 + spin_lock_irqsave(master->lock, flags);
307 + regmap_read(master->regmap, master->layout->offset, &mckr);
308 + spin_unlock_irqrestore(master->lock, flags);
309 +
310 + mckr &= master->layout->mask;
311 + div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
312 + div = master->characteristics->divisors[div];
313 +
314 + if (div != DIV_ROUND_CLOSEST(master->pms.parent_rate, master->pms.rate))
315 + pr_warn("MCKR DIV not configured properly by firmware!\n");
316 +}
317 +
318 static const struct clk_ops master_div_ops = {
319 .prepare = clk_master_prepare,
320 .is_prepared = clk_master_is_prepared,
321 .recalc_rate = clk_master_div_recalc_rate,
322 + .save_context = clk_master_div_save_context,
323 + .restore_context = clk_master_div_restore_context,
324 };
325
326 static int clk_master_div_set_rate(struct clk_hw *hw, unsigned long rate,
327 @@ -125,7 +168,9 @@ static int clk_master_div_set_rate(struc
328 const struct clk_master_characteristics *characteristics =
329 master->characteristics;
330 unsigned long flags;
331 + unsigned int mckr, tmp;
332 int div, i;
333 + int ret;
334
335 div = DIV_ROUND_CLOSEST(parent_rate, rate);
336 if (div > ARRAY_SIZE(characteristics->divisors))
337 @@ -145,11 +190,24 @@ static int clk_master_div_set_rate(struc
338 return -EINVAL;
339
340 spin_lock_irqsave(master->lock, flags);
341 - regmap_update_bits(master->regmap, master->layout->offset,
342 - (MASTER_DIV_MASK << MASTER_DIV_SHIFT),
343 - (div << MASTER_DIV_SHIFT));
344 + ret = regmap_read(master->regmap, master->layout->offset, &mckr);
345 + if (ret)
346 + goto unlock;
347 +
348 + tmp = mckr & master->layout->mask;
349 + tmp = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
350 + if (tmp == div)
351 + goto unlock;
352 +
353 + mckr &= ~(MASTER_DIV_MASK << MASTER_DIV_SHIFT);
354 + mckr |= (div << MASTER_DIV_SHIFT);
355 + ret = regmap_write(master->regmap, master->layout->offset, mckr);
356 + if (ret)
357 + goto unlock;
358 +
359 while (!clk_master_ready(master))
360 cpu_relax();
361 +unlock:
362 spin_unlock_irqrestore(master->lock, flags);
363
364 return 0;
365 @@ -197,12 +255,25 @@ static int clk_master_div_determine_rate
366 return 0;
367 }
368
369 +static void clk_master_div_restore_context_chg(struct clk_hw *hw)
370 +{
371 + struct clk_master *master = to_clk_master(hw);
372 + int ret;
373 +
374 + ret = clk_master_div_set_rate(hw, master->pms.rate,
375 + master->pms.parent_rate);
376 + if (ret)
377 + pr_warn("Failed to restore MCK DIV clock\n");
378 +}
379 +
380 static const struct clk_ops master_div_ops_chg = {
381 .prepare = clk_master_prepare,
382 .is_prepared = clk_master_is_prepared,
383 .recalc_rate = clk_master_div_recalc_rate,
384 .determine_rate = clk_master_div_determine_rate,
385 .set_rate = clk_master_div_set_rate,
386 + .save_context = clk_master_div_save_context,
387 + .restore_context = clk_master_div_restore_context_chg,
388 };
389
390 static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
391 @@ -272,7 +343,8 @@ static int clk_master_pres_set_rate(stru
392 {
393 struct clk_master *master = to_clk_master(hw);
394 unsigned long flags;
395 - unsigned int pres;
396 + unsigned int pres, mckr, tmp;
397 + int ret;
398
399 pres = DIV_ROUND_CLOSEST(parent_rate, rate);
400 if (pres > MASTER_PRES_MAX)
401 @@ -284,15 +356,27 @@ static int clk_master_pres_set_rate(stru
402 pres = ffs(pres) - 1;
403
404 spin_lock_irqsave(master->lock, flags);
405 - regmap_update_bits(master->regmap, master->layout->offset,
406 - (MASTER_PRES_MASK << master->layout->pres_shift),
407 - (pres << master->layout->pres_shift));
408 + ret = regmap_read(master->regmap, master->layout->offset, &mckr);
409 + if (ret)
410 + goto unlock;
411 +
412 + mckr &= master->layout->mask;
413 + tmp = (mckr >> master->layout->pres_shift) & MASTER_PRES_MASK;
414 + if (pres == tmp)
415 + goto unlock;
416 +
417 + mckr &= ~(MASTER_PRES_MASK << master->layout->pres_shift);
418 + mckr |= (pres << master->layout->pres_shift);
419 + ret = regmap_write(master->regmap, master->layout->offset, mckr);
420 + if (ret)
421 + goto unlock;
422
423 while (!clk_master_ready(master))
424 cpu_relax();
425 +unlock:
426 spin_unlock_irqrestore(master->lock, flags);
427
428 - return 0;
429 + return ret;
430 }
431
432 static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw,
433 @@ -330,11 +414,68 @@ static u8 clk_master_pres_get_parent(str
434 return mckr & AT91_PMC_CSS;
435 }
436
437 +static int clk_master_pres_save_context(struct clk_hw *hw)
438 +{
439 + struct clk_master *master = to_clk_master(hw);
440 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
441 + unsigned long flags;
442 + unsigned int val, pres;
443 +
444 + spin_lock_irqsave(master->lock, flags);
445 + regmap_read(master->regmap, master->layout->offset, &val);
446 + spin_unlock_irqrestore(master->lock, flags);
447 +
448 + val &= master->layout->mask;
449 + pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
450 + if (pres == MASTER_PRES_MAX && master->characteristics->have_div3_pres)
451 + pres = 3;
452 + else
453 + pres = (1 << pres);
454 +
455 + master->pms.parent = val & AT91_PMC_CSS;
456 + master->pms.parent_rate = clk_hw_get_rate(parent_hw);
457 + master->pms.rate = DIV_ROUND_CLOSEST_ULL(master->pms.parent_rate, pres);
458 +
459 + return 0;
460 +}
461 +
462 +static void clk_master_pres_restore_context(struct clk_hw *hw)
463 +{
464 + struct clk_master *master = to_clk_master(hw);
465 + unsigned long flags;
466 + unsigned int val, pres;
467 +
468 + spin_lock_irqsave(master->lock, flags);
469 + regmap_read(master->regmap, master->layout->offset, &val);
470 + spin_unlock_irqrestore(master->lock, flags);
471 +
472 + val &= master->layout->mask;
473 + pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
474 + if (pres == MASTER_PRES_MAX && master->characteristics->have_div3_pres)
475 + pres = 3;
476 + else
477 + pres = (1 << pres);
478 +
479 + if (master->pms.rate !=
480 + DIV_ROUND_CLOSEST_ULL(master->pms.parent_rate, pres) ||
481 + (master->pms.parent != (val & AT91_PMC_CSS)))
482 + pr_warn("MCKR PRES was not configured properly by firmware!\n");
483 +}
484 +
485 +static void clk_master_pres_restore_context_chg(struct clk_hw *hw)
486 +{
487 + struct clk_master *master = to_clk_master(hw);
488 +
489 + clk_master_pres_set_rate(hw, master->pms.rate, master->pms.parent_rate);
490 +}
491 +
492 static const struct clk_ops master_pres_ops = {
493 .prepare = clk_master_prepare,
494 .is_prepared = clk_master_is_prepared,
495 .recalc_rate = clk_master_pres_recalc_rate,
496 .get_parent = clk_master_pres_get_parent,
497 + .save_context = clk_master_pres_save_context,
498 + .restore_context = clk_master_pres_restore_context,
499 };
500
501 static const struct clk_ops master_pres_ops_chg = {
502 @@ -344,6 +485,8 @@ static const struct clk_ops master_pres_
503 .recalc_rate = clk_master_pres_recalc_rate,
504 .get_parent = clk_master_pres_get_parent,
505 .set_rate = clk_master_pres_set_rate,
506 + .save_context = clk_master_pres_save_context,
507 + .restore_context = clk_master_pres_restore_context_chg,
508 };
509
510 static struct clk_hw * __init
511 @@ -539,20 +682,21 @@ static int clk_sama7g5_master_set_parent
512 return 0;
513 }
514
515 -static int clk_sama7g5_master_enable(struct clk_hw *hw)
516 +static void clk_sama7g5_master_set(struct clk_master *master,
517 + unsigned int status)
518 {
519 - struct clk_master *master = to_clk_master(hw);
520 unsigned long flags;
521 unsigned int val, cparent;
522 + unsigned int enable = status ? PMC_MCR_EN : 0;
523
524 spin_lock_irqsave(master->lock, flags);
525
526 regmap_write(master->regmap, PMC_MCR, PMC_MCR_ID(master->id));
527 regmap_read(master->regmap, PMC_MCR, &val);
528 regmap_update_bits(master->regmap, PMC_MCR,
529 - PMC_MCR_EN | PMC_MCR_CSS | PMC_MCR_DIV |
530 + enable | PMC_MCR_CSS | PMC_MCR_DIV |
531 PMC_MCR_CMD | PMC_MCR_ID_MSK,
532 - PMC_MCR_EN | (master->parent << PMC_MCR_CSS_SHIFT) |
533 + enable | (master->parent << PMC_MCR_CSS_SHIFT) |
534 (master->div << MASTER_DIV_SHIFT) |
535 PMC_MCR_CMD | PMC_MCR_ID(master->id));
536
537 @@ -563,6 +707,13 @@ static int clk_sama7g5_master_enable(str
538 cpu_relax();
539
540 spin_unlock_irqrestore(master->lock, flags);
541 +}
542 +
543 +static int clk_sama7g5_master_enable(struct clk_hw *hw)
544 +{
545 + struct clk_master *master = to_clk_master(hw);
546 +
547 + clk_sama7g5_master_set(master, 1);
548
549 return 0;
550 }
551 @@ -620,6 +771,23 @@ static int clk_sama7g5_master_set_rate(s
552 return 0;
553 }
554
555 +static int clk_sama7g5_master_save_context(struct clk_hw *hw)
556 +{
557 + struct clk_master *master = to_clk_master(hw);
558 +
559 + master->pms.status = clk_sama7g5_master_is_enabled(hw);
560 +
561 + return 0;
562 +}
563 +
564 +static void clk_sama7g5_master_restore_context(struct clk_hw *hw)
565 +{
566 + struct clk_master *master = to_clk_master(hw);
567 +
568 + if (master->pms.status)
569 + clk_sama7g5_master_set(master, master->pms.status);
570 +}
571 +
572 static const struct clk_ops sama7g5_master_ops = {
573 .enable = clk_sama7g5_master_enable,
574 .disable = clk_sama7g5_master_disable,
575 @@ -629,6 +797,8 @@ static const struct clk_ops sama7g5_mast
576 .set_rate = clk_sama7g5_master_set_rate,
577 .get_parent = clk_sama7g5_master_get_parent,
578 .set_parent = clk_sama7g5_master_set_parent,
579 + .save_context = clk_sama7g5_master_save_context,
580 + .restore_context = clk_sama7g5_master_restore_context,
581 };
582
583 struct clk_hw * __init
584 --- a/drivers/clk/at91/clk-peripheral.c
585 +++ b/drivers/clk/at91/clk-peripheral.c
586 @@ -37,6 +37,7 @@ struct clk_sam9x5_peripheral {
587 u32 id;
588 u32 div;
589 const struct clk_pcr_layout *layout;
590 + struct at91_clk_pms pms;
591 bool auto_div;
592 int chg_pid;
593 };
594 @@ -155,10 +156,11 @@ static void clk_sam9x5_peripheral_autodi
595 periph->div = shift;
596 }
597
598 -static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
599 +static int clk_sam9x5_peripheral_set(struct clk_sam9x5_peripheral *periph,
600 + unsigned int status)
601 {
602 - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
603 unsigned long flags;
604 + unsigned int enable = status ? AT91_PMC_PCR_EN : 0;
605
606 if (periph->id < PERIPHERAL_ID_MIN)
607 return 0;
608 @@ -168,15 +170,21 @@ static int clk_sam9x5_peripheral_enable(
609 (periph->id & periph->layout->pid_mask));
610 regmap_update_bits(periph->regmap, periph->layout->offset,
611 periph->layout->div_mask | periph->layout->cmd |
612 - AT91_PMC_PCR_EN,
613 + enable,
614 field_prep(periph->layout->div_mask, periph->div) |
615 - periph->layout->cmd |
616 - AT91_PMC_PCR_EN);
617 + periph->layout->cmd | enable);
618 spin_unlock_irqrestore(periph->lock, flags);
619
620 return 0;
621 }
622
623 +static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
624 +{
625 + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
626 +
627 + return clk_sam9x5_peripheral_set(periph, 1);
628 +}
629 +
630 static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
631 {
632 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
633 @@ -393,6 +401,23 @@ static int clk_sam9x5_peripheral_set_rat
634 return -EINVAL;
635 }
636
637 +static int clk_sam9x5_peripheral_save_context(struct clk_hw *hw)
638 +{
639 + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
640 +
641 + periph->pms.status = clk_sam9x5_peripheral_is_enabled(hw);
642 +
643 + return 0;
644 +}
645 +
646 +static void clk_sam9x5_peripheral_restore_context(struct clk_hw *hw)
647 +{
648 + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
649 +
650 + if (periph->pms.status)
651 + clk_sam9x5_peripheral_set(periph, periph->pms.status);
652 +}
653 +
654 static const struct clk_ops sam9x5_peripheral_ops = {
655 .enable = clk_sam9x5_peripheral_enable,
656 .disable = clk_sam9x5_peripheral_disable,
657 @@ -400,6 +425,8 @@ static const struct clk_ops sam9x5_perip
658 .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
659 .round_rate = clk_sam9x5_peripheral_round_rate,
660 .set_rate = clk_sam9x5_peripheral_set_rate,
661 + .save_context = clk_sam9x5_peripheral_save_context,
662 + .restore_context = clk_sam9x5_peripheral_restore_context,
663 };
664
665 static const struct clk_ops sam9x5_peripheral_chg_ops = {
666 @@ -409,6 +436,8 @@ static const struct clk_ops sam9x5_perip
667 .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
668 .determine_rate = clk_sam9x5_peripheral_determine_rate,
669 .set_rate = clk_sam9x5_peripheral_set_rate,
670 + .save_context = clk_sam9x5_peripheral_save_context,
671 + .restore_context = clk_sam9x5_peripheral_restore_context,
672 };
673
674 struct clk_hw * __init
675 @@ -460,7 +489,6 @@ at91_clk_register_sam9x5_peripheral(stru
676 hw = ERR_PTR(ret);
677 } else {
678 clk_sam9x5_peripheral_autodiv(periph);
679 - pmc_register_id(id);
680 }
681
682 return hw;
683 --- a/drivers/clk/at91/clk-pll.c
684 +++ b/drivers/clk/at91/clk-pll.c
685 @@ -40,6 +40,7 @@ struct clk_pll {
686 u16 mul;
687 const struct clk_pll_layout *layout;
688 const struct clk_pll_characteristics *characteristics;
689 + struct at91_clk_pms pms;
690 };
691
692 static inline bool clk_pll_ready(struct regmap *regmap, int id)
693 @@ -260,6 +261,42 @@ static int clk_pll_set_rate(struct clk_h
694 return 0;
695 }
696
697 +static int clk_pll_save_context(struct clk_hw *hw)
698 +{
699 + struct clk_pll *pll = to_clk_pll(hw);
700 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
701 +
702 + pll->pms.parent_rate = clk_hw_get_rate(parent_hw);
703 + pll->pms.rate = clk_pll_recalc_rate(&pll->hw, pll->pms.parent_rate);
704 + pll->pms.status = clk_pll_ready(pll->regmap, PLL_REG(pll->id));
705 +
706 + return 0;
707 +}
708 +
709 +static void clk_pll_restore_context(struct clk_hw *hw)
710 +{
711 + struct clk_pll *pll = to_clk_pll(hw);
712 + unsigned long calc_rate;
713 + unsigned int pllr, pllr_out, pllr_count;
714 + u8 out = 0;
715 +
716 + if (pll->characteristics->out)
717 + out = pll->characteristics->out[pll->range];
718 +
719 + regmap_read(pll->regmap, PLL_REG(pll->id), &pllr);
720 +
721 + calc_rate = (pll->pms.parent_rate / PLL_DIV(pllr)) *
722 + (PLL_MUL(pllr, pll->layout) + 1);
723 + pllr_count = (pllr >> PLL_COUNT_SHIFT) & PLL_MAX_COUNT;
724 + pllr_out = (pllr >> PLL_OUT_SHIFT) & out;
725 +
726 + if (pll->pms.rate != calc_rate ||
727 + pll->pms.status != clk_pll_ready(pll->regmap, PLL_REG(pll->id)) ||
728 + pllr_count != PLL_MAX_COUNT ||
729 + (out && pllr_out != out))
730 + pr_warn("PLLAR was not configured properly by firmware\n");
731 +}
732 +
733 static const struct clk_ops pll_ops = {
734 .prepare = clk_pll_prepare,
735 .unprepare = clk_pll_unprepare,
736 @@ -267,6 +304,8 @@ static const struct clk_ops pll_ops = {
737 .recalc_rate = clk_pll_recalc_rate,
738 .round_rate = clk_pll_round_rate,
739 .set_rate = clk_pll_set_rate,
740 + .save_context = clk_pll_save_context,
741 + .restore_context = clk_pll_restore_context,
742 };
743
744 struct clk_hw * __init
745 --- a/drivers/clk/at91/clk-programmable.c
746 +++ b/drivers/clk/at91/clk-programmable.c
747 @@ -24,6 +24,7 @@ struct clk_programmable {
748 u32 *mux_table;
749 u8 id;
750 const struct clk_programmable_layout *layout;
751 + struct at91_clk_pms pms;
752 };
753
754 #define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw)
755 @@ -177,12 +178,38 @@ static int clk_programmable_set_rate(str
756 return 0;
757 }
758
759 +static int clk_programmable_save_context(struct clk_hw *hw)
760 +{
761 + struct clk_programmable *prog = to_clk_programmable(hw);
762 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
763 +
764 + prog->pms.parent = clk_programmable_get_parent(hw);
765 + prog->pms.parent_rate = clk_hw_get_rate(parent_hw);
766 + prog->pms.rate = clk_programmable_recalc_rate(hw, prog->pms.parent_rate);
767 +
768 + return 0;
769 +}
770 +
771 +static void clk_programmable_restore_context(struct clk_hw *hw)
772 +{
773 + struct clk_programmable *prog = to_clk_programmable(hw);
774 + int ret;
775 +
776 + ret = clk_programmable_set_parent(hw, prog->pms.parent);
777 + if (ret)
778 + return;
779 +
780 + clk_programmable_set_rate(hw, prog->pms.rate, prog->pms.parent_rate);
781 +}
782 +
783 static const struct clk_ops programmable_ops = {
784 .recalc_rate = clk_programmable_recalc_rate,
785 .determine_rate = clk_programmable_determine_rate,
786 .get_parent = clk_programmable_get_parent,
787 .set_parent = clk_programmable_set_parent,
788 .set_rate = clk_programmable_set_rate,
789 + .save_context = clk_programmable_save_context,
790 + .restore_context = clk_programmable_restore_context,
791 };
792
793 struct clk_hw * __init
794 @@ -221,8 +248,6 @@ at91_clk_register_programmable(struct re
795 if (ret) {
796 kfree(prog);
797 hw = ERR_PTR(ret);
798 - } else {
799 - pmc_register_pck(id);
800 }
801
802 return hw;
803 --- a/drivers/clk/at91/clk-sam9x60-pll.c
804 +++ b/drivers/clk/at91/clk-sam9x60-pll.c
805 @@ -38,12 +38,14 @@ struct sam9x60_pll_core {
806
807 struct sam9x60_frac {
808 struct sam9x60_pll_core core;
809 + struct at91_clk_pms pms;
810 u32 frac;
811 u16 mul;
812 };
813
814 struct sam9x60_div {
815 struct sam9x60_pll_core core;
816 + struct at91_clk_pms pms;
817 u8 div;
818 };
819
820 @@ -75,9 +77,8 @@ static unsigned long sam9x60_frac_pll_re
821 DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22));
822 }
823
824 -static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
825 +static int sam9x60_frac_pll_set(struct sam9x60_pll_core *core)
826 {
827 - struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
828 struct sam9x60_frac *frac = to_sam9x60_frac(core);
829 struct regmap *regmap = core->regmap;
830 unsigned int val, cfrac, cmul;
831 @@ -141,6 +142,13 @@ unlock:
832 return 0;
833 }
834
835 +static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
836 +{
837 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
838 +
839 + return sam9x60_frac_pll_set(core);
840 +}
841 +
842 static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
843 {
844 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
845 @@ -280,6 +288,25 @@ unlock:
846 return ret;
847 }
848
849 +static int sam9x60_frac_pll_save_context(struct clk_hw *hw)
850 +{
851 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
852 + struct sam9x60_frac *frac = to_sam9x60_frac(core);
853 +
854 + frac->pms.status = sam9x60_pll_ready(core->regmap, core->id);
855 +
856 + return 0;
857 +}
858 +
859 +static void sam9x60_frac_pll_restore_context(struct clk_hw *hw)
860 +{
861 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
862 + struct sam9x60_frac *frac = to_sam9x60_frac(core);
863 +
864 + if (frac->pms.status)
865 + sam9x60_frac_pll_set(core);
866 +}
867 +
868 static const struct clk_ops sam9x60_frac_pll_ops = {
869 .prepare = sam9x60_frac_pll_prepare,
870 .unprepare = sam9x60_frac_pll_unprepare,
871 @@ -287,6 +314,8 @@ static const struct clk_ops sam9x60_frac
872 .recalc_rate = sam9x60_frac_pll_recalc_rate,
873 .round_rate = sam9x60_frac_pll_round_rate,
874 .set_rate = sam9x60_frac_pll_set_rate,
875 + .save_context = sam9x60_frac_pll_save_context,
876 + .restore_context = sam9x60_frac_pll_restore_context,
877 };
878
879 static const struct clk_ops sam9x60_frac_pll_ops_chg = {
880 @@ -296,11 +325,12 @@ static const struct clk_ops sam9x60_frac
881 .recalc_rate = sam9x60_frac_pll_recalc_rate,
882 .round_rate = sam9x60_frac_pll_round_rate,
883 .set_rate = sam9x60_frac_pll_set_rate_chg,
884 + .save_context = sam9x60_frac_pll_save_context,
885 + .restore_context = sam9x60_frac_pll_restore_context,
886 };
887
888 -static int sam9x60_div_pll_prepare(struct clk_hw *hw)
889 +static int sam9x60_div_pll_set(struct sam9x60_pll_core *core)
890 {
891 - struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
892 struct sam9x60_div *div = to_sam9x60_div(core);
893 struct regmap *regmap = core->regmap;
894 unsigned long flags;
895 @@ -334,6 +364,13 @@ unlock:
896 return 0;
897 }
898
899 +static int sam9x60_div_pll_prepare(struct clk_hw *hw)
900 +{
901 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
902 +
903 + return sam9x60_div_pll_set(core);
904 +}
905 +
906 static void sam9x60_div_pll_unprepare(struct clk_hw *hw)
907 {
908 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
909 @@ -482,6 +519,25 @@ unlock:
910 return 0;
911 }
912
913 +static int sam9x60_div_pll_save_context(struct clk_hw *hw)
914 +{
915 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
916 + struct sam9x60_div *div = to_sam9x60_div(core);
917 +
918 + div->pms.status = sam9x60_div_pll_is_prepared(hw);
919 +
920 + return 0;
921 +}
922 +
923 +static void sam9x60_div_pll_restore_context(struct clk_hw *hw)
924 +{
925 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
926 + struct sam9x60_div *div = to_sam9x60_div(core);
927 +
928 + if (div->pms.status)
929 + sam9x60_div_pll_set(core);
930 +}
931 +
932 static const struct clk_ops sam9x60_div_pll_ops = {
933 .prepare = sam9x60_div_pll_prepare,
934 .unprepare = sam9x60_div_pll_unprepare,
935 @@ -489,6 +545,8 @@ static const struct clk_ops sam9x60_div_
936 .recalc_rate = sam9x60_div_pll_recalc_rate,
937 .round_rate = sam9x60_div_pll_round_rate,
938 .set_rate = sam9x60_div_pll_set_rate,
939 + .save_context = sam9x60_div_pll_save_context,
940 + .restore_context = sam9x60_div_pll_restore_context,
941 };
942
943 static const struct clk_ops sam9x60_div_pll_ops_chg = {
944 @@ -498,6 +556,8 @@ static const struct clk_ops sam9x60_div_
945 .recalc_rate = sam9x60_div_pll_recalc_rate,
946 .round_rate = sam9x60_div_pll_round_rate,
947 .set_rate = sam9x60_div_pll_set_rate_chg,
948 + .save_context = sam9x60_div_pll_save_context,
949 + .restore_context = sam9x60_div_pll_restore_context,
950 };
951
952 struct clk_hw * __init
953 --- a/drivers/clk/at91/clk-system.c
954 +++ b/drivers/clk/at91/clk-system.c
955 @@ -20,6 +20,7 @@
956 struct clk_system {
957 struct clk_hw hw;
958 struct regmap *regmap;
959 + struct at91_clk_pms pms;
960 u8 id;
961 };
962
963 @@ -77,10 +78,29 @@ static int clk_system_is_prepared(struct
964 return !!(status & (1 << sys->id));
965 }
966
967 +static int clk_system_save_context(struct clk_hw *hw)
968 +{
969 + struct clk_system *sys = to_clk_system(hw);
970 +
971 + sys->pms.status = clk_system_is_prepared(hw);
972 +
973 + return 0;
974 +}
975 +
976 +static void clk_system_restore_context(struct clk_hw *hw)
977 +{
978 + struct clk_system *sys = to_clk_system(hw);
979 +
980 + if (sys->pms.status)
981 + clk_system_prepare(&sys->hw);
982 +}
983 +
984 static const struct clk_ops system_ops = {
985 .prepare = clk_system_prepare,
986 .unprepare = clk_system_unprepare,
987 .is_prepared = clk_system_is_prepared,
988 + .save_context = clk_system_save_context,
989 + .restore_context = clk_system_restore_context,
990 };
991
992 struct clk_hw * __init
993 --- a/drivers/clk/at91/clk-usb.c
994 +++ b/drivers/clk/at91/clk-usb.c
995 @@ -24,6 +24,7 @@
996 struct at91sam9x5_clk_usb {
997 struct clk_hw hw;
998 struct regmap *regmap;
999 + struct at91_clk_pms pms;
1000 u32 usbs_mask;
1001 u8 num_parents;
1002 };
1003 @@ -148,12 +149,38 @@ static int at91sam9x5_clk_usb_set_rate(s
1004 return 0;
1005 }
1006
1007 +static int at91sam9x5_usb_save_context(struct clk_hw *hw)
1008 +{
1009 + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
1010 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
1011 +
1012 + usb->pms.parent = at91sam9x5_clk_usb_get_parent(hw);
1013 + usb->pms.parent_rate = clk_hw_get_rate(parent_hw);
1014 + usb->pms.rate = at91sam9x5_clk_usb_recalc_rate(hw, usb->pms.parent_rate);
1015 +
1016 + return 0;
1017 +}
1018 +
1019 +static void at91sam9x5_usb_restore_context(struct clk_hw *hw)
1020 +{
1021 + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
1022 + int ret;
1023 +
1024 + ret = at91sam9x5_clk_usb_set_parent(hw, usb->pms.parent);
1025 + if (ret)
1026 + return;
1027 +
1028 + at91sam9x5_clk_usb_set_rate(hw, usb->pms.rate, usb->pms.parent_rate);
1029 +}
1030 +
1031 static const struct clk_ops at91sam9x5_usb_ops = {
1032 .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
1033 .determine_rate = at91sam9x5_clk_usb_determine_rate,
1034 .get_parent = at91sam9x5_clk_usb_get_parent,
1035 .set_parent = at91sam9x5_clk_usb_set_parent,
1036 .set_rate = at91sam9x5_clk_usb_set_rate,
1037 + .save_context = at91sam9x5_usb_save_context,
1038 + .restore_context = at91sam9x5_usb_restore_context,
1039 };
1040
1041 static int at91sam9n12_clk_usb_enable(struct clk_hw *hw)
1042 --- a/drivers/clk/at91/clk-utmi.c
1043 +++ b/drivers/clk/at91/clk-utmi.c
1044 @@ -23,6 +23,7 @@ struct clk_utmi {
1045 struct clk_hw hw;
1046 struct regmap *regmap_pmc;
1047 struct regmap *regmap_sfr;
1048 + struct at91_clk_pms pms;
1049 };
1050
1051 #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
1052 @@ -113,11 +114,30 @@ static unsigned long clk_utmi_recalc_rat
1053 return UTMI_RATE;
1054 }
1055
1056 +static int clk_utmi_save_context(struct clk_hw *hw)
1057 +{
1058 + struct clk_utmi *utmi = to_clk_utmi(hw);
1059 +
1060 + utmi->pms.status = clk_utmi_is_prepared(hw);
1061 +
1062 + return 0;
1063 +}
1064 +
1065 +static void clk_utmi_restore_context(struct clk_hw *hw)
1066 +{
1067 + struct clk_utmi *utmi = to_clk_utmi(hw);
1068 +
1069 + if (utmi->pms.status)
1070 + clk_utmi_prepare(hw);
1071 +}
1072 +
1073 static const struct clk_ops utmi_ops = {
1074 .prepare = clk_utmi_prepare,
1075 .unprepare = clk_utmi_unprepare,
1076 .is_prepared = clk_utmi_is_prepared,
1077 .recalc_rate = clk_utmi_recalc_rate,
1078 + .save_context = clk_utmi_save_context,
1079 + .restore_context = clk_utmi_restore_context,
1080 };
1081
1082 static struct clk_hw * __init
1083 @@ -232,10 +252,29 @@ static int clk_utmi_sama7g5_is_prepared(
1084 return 0;
1085 }
1086
1087 +static int clk_utmi_sama7g5_save_context(struct clk_hw *hw)
1088 +{
1089 + struct clk_utmi *utmi = to_clk_utmi(hw);
1090 +
1091 + utmi->pms.status = clk_utmi_sama7g5_is_prepared(hw);
1092 +
1093 + return 0;
1094 +}
1095 +
1096 +static void clk_utmi_sama7g5_restore_context(struct clk_hw *hw)
1097 +{
1098 + struct clk_utmi *utmi = to_clk_utmi(hw);
1099 +
1100 + if (utmi->pms.status)
1101 + clk_utmi_sama7g5_prepare(hw);
1102 +}
1103 +
1104 static const struct clk_ops sama7g5_utmi_ops = {
1105 .prepare = clk_utmi_sama7g5_prepare,
1106 .is_prepared = clk_utmi_sama7g5_is_prepared,
1107 .recalc_rate = clk_utmi_recalc_rate,
1108 + .save_context = clk_utmi_sama7g5_save_context,
1109 + .restore_context = clk_utmi_sama7g5_restore_context,
1110 };
1111
1112 struct clk_hw * __init
1113 --- a/drivers/clk/at91/pmc.c
1114 +++ b/drivers/clk/at91/pmc.c
1115 @@ -3,6 +3,7 @@
1116 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
1117 */
1118
1119 +#include <linux/clk.h>
1120 #include <linux/clk-provider.h>
1121 #include <linux/clkdev.h>
1122 #include <linux/clk/at91_pmc.h>
1123 @@ -14,8 +15,6 @@
1124
1125 #include <asm/proc-fns.h>
1126
1127 -#include <dt-bindings/clock/at91.h>
1128 -
1129 #include "pmc.h"
1130
1131 #define PMC_MAX_IDS 128
1132 @@ -111,147 +110,19 @@ struct pmc_data *pmc_data_allocate(unsig
1133 }
1134
1135 #ifdef CONFIG_PM
1136 -static struct regmap *pmcreg;
1137 -
1138 -static u8 registered_ids[PMC_MAX_IDS];
1139 -static u8 registered_pcks[PMC_MAX_PCKS];
1140 -
1141 -static struct
1142 -{
1143 - u32 scsr;
1144 - u32 pcsr0;
1145 - u32 uckr;
1146 - u32 mor;
1147 - u32 mcfr;
1148 - u32 pllar;
1149 - u32 mckr;
1150 - u32 usb;
1151 - u32 imr;
1152 - u32 pcsr1;
1153 - u32 pcr[PMC_MAX_IDS];
1154 - u32 audio_pll0;
1155 - u32 audio_pll1;
1156 - u32 pckr[PMC_MAX_PCKS];
1157 -} pmc_cache;
1158 -
1159 -/*
1160 - * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
1161 - * without alteration in the table, and 0 is for unused clocks.
1162 - */
1163 -void pmc_register_id(u8 id)
1164 +static int at91_pmc_suspend(void)
1165 {
1166 - int i;
1167 -
1168 - for (i = 0; i < PMC_MAX_IDS; i++) {
1169 - if (registered_ids[i] == 0) {
1170 - registered_ids[i] = id;
1171 - break;
1172 - }
1173 - if (registered_ids[i] == id)
1174 - break;
1175 - }
1176 + return clk_save_context();
1177 }
1178
1179 -/*
1180 - * As Programmable Clock 0 is valid on AT91 chips, there is an offset
1181 - * of 1 between the stored value and the real clock ID.
1182 - */
1183 -void pmc_register_pck(u8 pck)
1184 +static void at91_pmc_resume(void)
1185 {
1186 - int i;
1187 -
1188 - for (i = 0; i < PMC_MAX_PCKS; i++) {
1189 - if (registered_pcks[i] == 0) {
1190 - registered_pcks[i] = pck + 1;
1191 - break;
1192 - }
1193 - if (registered_pcks[i] == (pck + 1))
1194 - break;
1195 - }
1196 -}
1197 -
1198 -static int pmc_suspend(void)
1199 -{
1200 - int i;
1201 - u8 num;
1202 -
1203 - regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr);
1204 - regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0);
1205 - regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr);
1206 - regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor);
1207 - regmap_read(pmcreg, AT91_CKGR_MCFR, &pmc_cache.mcfr);
1208 - regmap_read(pmcreg, AT91_CKGR_PLLAR, &pmc_cache.pllar);
1209 - regmap_read(pmcreg, AT91_PMC_MCKR, &pmc_cache.mckr);
1210 - regmap_read(pmcreg, AT91_PMC_USB, &pmc_cache.usb);
1211 - regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.imr);
1212 - regmap_read(pmcreg, AT91_PMC_PCSR1, &pmc_cache.pcsr1);
1213 -
1214 - for (i = 0; registered_ids[i]; i++) {
1215 - regmap_write(pmcreg, AT91_PMC_PCR,
1216 - (registered_ids[i] & AT91_PMC_PCR_PID_MASK));
1217 - regmap_read(pmcreg, AT91_PMC_PCR,
1218 - &pmc_cache.pcr[registered_ids[i]]);
1219 - }
1220 - for (i = 0; registered_pcks[i]; i++) {
1221 - num = registered_pcks[i] - 1;
1222 - regmap_read(pmcreg, AT91_PMC_PCKR(num), &pmc_cache.pckr[num]);
1223 - }
1224 -
1225 - return 0;
1226 -}
1227 -
1228 -static bool pmc_ready(unsigned int mask)
1229 -{
1230 - unsigned int status;
1231 -
1232 - regmap_read(pmcreg, AT91_PMC_SR, &status);
1233 -
1234 - return ((status & mask) == mask) ? 1 : 0;
1235 -}
1236 -
1237 -static void pmc_resume(void)
1238 -{
1239 - int i;
1240 - u8 num;
1241 - u32 tmp;
1242 - u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
1243 -
1244 - regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
1245 - if (pmc_cache.mckr != tmp)
1246 - pr_warn("MCKR was not configured properly by the firmware\n");
1247 - regmap_read(pmcreg, AT91_CKGR_PLLAR, &tmp);
1248 - if (pmc_cache.pllar != tmp)
1249 - pr_warn("PLLAR was not configured properly by the firmware\n");
1250 -
1251 - regmap_write(pmcreg, AT91_PMC_SCER, pmc_cache.scsr);
1252 - regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0);
1253 - regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr);
1254 - regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor);
1255 - regmap_write(pmcreg, AT91_CKGR_MCFR, pmc_cache.mcfr);
1256 - regmap_write(pmcreg, AT91_PMC_USB, pmc_cache.usb);
1257 - regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.imr);
1258 - regmap_write(pmcreg, AT91_PMC_PCER1, pmc_cache.pcsr1);
1259 -
1260 - for (i = 0; registered_ids[i]; i++) {
1261 - regmap_write(pmcreg, AT91_PMC_PCR,
1262 - pmc_cache.pcr[registered_ids[i]] |
1263 - AT91_PMC_PCR_CMD);
1264 - }
1265 - for (i = 0; registered_pcks[i]; i++) {
1266 - num = registered_pcks[i] - 1;
1267 - regmap_write(pmcreg, AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
1268 - }
1269 -
1270 - if (pmc_cache.uckr & AT91_PMC_UPLLEN)
1271 - mask |= AT91_PMC_LOCKU;
1272 -
1273 - while (!pmc_ready(mask))
1274 - cpu_relax();
1275 + clk_restore_context();
1276 }
1277
1278 static struct syscore_ops pmc_syscore_ops = {
1279 - .suspend = pmc_suspend,
1280 - .resume = pmc_resume,
1281 + .suspend = at91_pmc_suspend,
1282 + .resume = at91_pmc_resume,
1283 };
1284
1285 static const struct of_device_id sama5d2_pmc_dt_ids[] = {
1286 @@ -271,11 +142,7 @@ static int __init pmc_register_ops(void)
1287 of_node_put(np);
1288 return -ENODEV;
1289 }
1290 -
1291 - pmcreg = device_node_to_regmap(np);
1292 of_node_put(np);
1293 - if (IS_ERR(pmcreg))
1294 - return PTR_ERR(pmcreg);
1295
1296 register_syscore_ops(&pmc_syscore_ops);
1297
1298 --- a/drivers/clk/at91/pmc.h
1299 +++ b/drivers/clk/at91/pmc.h
1300 @@ -13,6 +13,8 @@
1301 #include <linux/regmap.h>
1302 #include <linux/spinlock.h>
1303
1304 +#include <dt-bindings/clock/at91.h>
1305 +
1306 extern spinlock_t pmc_pcr_lock;
1307
1308 struct pmc_data {
1309 @@ -98,6 +100,20 @@ struct clk_pcr_layout {
1310 u32 pid_mask;
1311 };
1312
1313 +/**
1314 + * struct at91_clk_pms - Power management state for AT91 clock
1315 + * @rate: clock rate
1316 + * @parent_rate: clock parent rate
1317 + * @status: clock status (enabled or disabled)
1318 + * @parent: clock parent index
1319 + */
1320 +struct at91_clk_pms {
1321 + unsigned long rate;
1322 + unsigned long parent_rate;
1323 + unsigned int status;
1324 + unsigned int parent;
1325 +};
1326 +
1327 #define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
1328 #define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
1329
1330 @@ -248,12 +264,4 @@ struct clk_hw * __init
1331 at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name,
1332 const char *parent_name);
1333
1334 -#ifdef CONFIG_PM
1335 -void pmc_register_id(u8 id);
1336 -void pmc_register_pck(u8 pck);
1337 -#else
1338 -static inline void pmc_register_id(u8 id) {}
1339 -static inline void pmc_register_pck(u8 pck) {}
1340 -#endif
1341 -
1342 #endif /* __PMC_H_ */