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
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.
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
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>
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(-)
43 diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
44 index b656d25a9767..23cc8297ec4c 100644
45 --- a/drivers/clk/at91/clk-generated.c
46 +++ b/drivers/clk/at91/clk-generated.c
47 @@ -27,6 +27,7 @@ struct clk_generated {
50 const struct clk_pcr_layout *layout;
51 + struct at91_clk_pms pms;
55 @@ -34,25 +35,35 @@ struct clk_generated {
56 #define to_clk_generated(hw) \
57 container_of(hw, struct clk_generated, hw)
59 -static int clk_generated_enable(struct clk_hw *hw)
60 +static int clk_generated_set(struct clk_generated *gck, int status)
62 - struct clk_generated *gck = to_clk_generated(hw);
65 - pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
66 - __func__, gck->gckdiv, gck->parent_id);
67 + unsigned int enable = status ? AT91_PMC_PCR_GCKEN : 0;
69 spin_lock_irqsave(gck->lock, flags);
70 regmap_write(gck->regmap, gck->layout->offset,
71 (gck->id & gck->layout->pid_mask));
72 regmap_update_bits(gck->regmap, gck->layout->offset,
73 AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
74 - gck->layout->cmd | AT91_PMC_PCR_GCKEN,
75 + gck->layout->cmd | enable,
76 field_prep(gck->layout->gckcss_mask, gck->parent_id) |
78 FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
79 - AT91_PMC_PCR_GCKEN);
81 spin_unlock_irqrestore(gck->lock, flags);
86 +static int clk_generated_enable(struct clk_hw *hw)
88 + struct clk_generated *gck = to_clk_generated(hw);
90 + pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
91 + __func__, gck->gckdiv, gck->parent_id);
93 + clk_generated_set(gck, 1);
98 @@ -245,6 +256,23 @@ static int clk_generated_set_rate(struct clk_hw *hw,
102 +static int clk_generated_save_context(struct clk_hw *hw)
104 + struct clk_generated *gck = to_clk_generated(hw);
106 + gck->pms.status = clk_generated_is_enabled(&gck->hw);
111 +static void clk_generated_restore_context(struct clk_hw *hw)
113 + struct clk_generated *gck = to_clk_generated(hw);
115 + if (gck->pms.status)
116 + clk_generated_set(gck, gck->pms.status);
119 static const struct clk_ops generated_ops = {
120 .enable = clk_generated_enable,
121 .disable = clk_generated_disable,
122 @@ -254,6 +282,8 @@ static const struct clk_ops generated_ops = {
123 .get_parent = clk_generated_get_parent,
124 .set_parent = clk_generated_set_parent,
125 .set_rate = clk_generated_set_rate,
126 + .save_context = clk_generated_save_context,
127 + .restore_context = clk_generated_restore_context,
131 @@ -320,8 +350,6 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
136 - pmc_register_id(id);
140 diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
141 index cfae2f59df66..8601b27c1ae0 100644
142 --- a/drivers/clk/at91/clk-main.c
143 +++ b/drivers/clk/at91/clk-main.c
145 struct clk_main_osc {
147 struct regmap *regmap;
148 + struct at91_clk_pms pms;
151 #define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
152 @@ -37,6 +38,7 @@ struct clk_main_rc_osc {
153 struct regmap *regmap;
154 unsigned long frequency;
155 unsigned long accuracy;
156 + struct at91_clk_pms pms;
159 #define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
160 @@ -51,6 +53,7 @@ struct clk_rm9200_main {
161 struct clk_sam9x5_main {
163 struct regmap *regmap;
164 + struct at91_clk_pms pms;
168 @@ -120,10 +123,29 @@ static int clk_main_osc_is_prepared(struct clk_hw *hw)
169 return (status & AT91_PMC_MOSCS) && clk_main_parent_select(tmp);
172 +static int clk_main_osc_save_context(struct clk_hw *hw)
174 + struct clk_main_osc *osc = to_clk_main_osc(hw);
176 + osc->pms.status = clk_main_osc_is_prepared(hw);
181 +static void clk_main_osc_restore_context(struct clk_hw *hw)
183 + struct clk_main_osc *osc = to_clk_main_osc(hw);
185 + if (osc->pms.status)
186 + clk_main_osc_prepare(hw);
189 static const struct clk_ops main_osc_ops = {
190 .prepare = clk_main_osc_prepare,
191 .unprepare = clk_main_osc_unprepare,
192 .is_prepared = clk_main_osc_is_prepared,
193 + .save_context = clk_main_osc_save_context,
194 + .restore_context = clk_main_osc_restore_context,
197 struct clk_hw * __init
198 @@ -240,12 +262,31 @@ static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
199 return osc->accuracy;
202 +static int clk_main_rc_osc_save_context(struct clk_hw *hw)
204 + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
206 + osc->pms.status = clk_main_rc_osc_is_prepared(hw);
211 +static void clk_main_rc_osc_restore_context(struct clk_hw *hw)
213 + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
215 + if (osc->pms.status)
216 + clk_main_rc_osc_prepare(hw);
219 static const struct clk_ops main_rc_osc_ops = {
220 .prepare = clk_main_rc_osc_prepare,
221 .unprepare = clk_main_rc_osc_unprepare,
222 .is_prepared = clk_main_rc_osc_is_prepared,
223 .recalc_rate = clk_main_rc_osc_recalc_rate,
224 .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
225 + .save_context = clk_main_rc_osc_save_context,
226 + .restore_context = clk_main_rc_osc_restore_context,
229 struct clk_hw * __init
230 @@ -465,12 +506,37 @@ static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
231 return clk_main_parent_select(status);
234 +static int clk_sam9x5_main_save_context(struct clk_hw *hw)
236 + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
238 + clkmain->pms.status = clk_main_rc_osc_is_prepared(&clkmain->hw);
239 + clkmain->pms.parent = clk_sam9x5_main_get_parent(&clkmain->hw);
244 +static void clk_sam9x5_main_restore_context(struct clk_hw *hw)
246 + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
249 + ret = clk_sam9x5_main_set_parent(hw, clkmain->pms.parent);
253 + if (clkmain->pms.status)
254 + clk_sam9x5_main_prepare(hw);
257 static const struct clk_ops sam9x5_main_ops = {
258 .prepare = clk_sam9x5_main_prepare,
259 .is_prepared = clk_sam9x5_main_is_prepared,
260 .recalc_rate = clk_sam9x5_main_recalc_rate,
261 .set_parent = clk_sam9x5_main_set_parent,
262 .get_parent = clk_sam9x5_main_get_parent,
263 + .save_context = clk_sam9x5_main_save_context,
264 + .restore_context = clk_sam9x5_main_restore_context,
267 struct clk_hw * __init
268 diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
269 index a80427980bf7..f75549fff023 100644
270 --- a/drivers/clk/at91/clk-master.c
271 +++ b/drivers/clk/at91/clk-master.c
272 @@ -37,6 +37,7 @@ struct clk_master {
274 const struct clk_master_layout *layout;
275 const struct clk_master_characteristics *characteristics;
276 + struct at91_clk_pms pms;
280 @@ -112,10 +113,52 @@ static unsigned long clk_master_div_recalc_rate(struct clk_hw *hw,
284 +static int clk_master_div_save_context(struct clk_hw *hw)
286 + struct clk_master *master = to_clk_master(hw);
287 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
288 + unsigned long flags;
289 + unsigned int mckr, div;
291 + spin_lock_irqsave(master->lock, flags);
292 + regmap_read(master->regmap, master->layout->offset, &mckr);
293 + spin_unlock_irqrestore(master->lock, flags);
295 + mckr &= master->layout->mask;
296 + div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
297 + div = master->characteristics->divisors[div];
299 + master->pms.parent_rate = clk_hw_get_rate(parent_hw);
300 + master->pms.rate = DIV_ROUND_CLOSEST(master->pms.parent_rate, div);
305 +static void clk_master_div_restore_context(struct clk_hw *hw)
307 + struct clk_master *master = to_clk_master(hw);
308 + unsigned long flags;
312 + spin_lock_irqsave(master->lock, flags);
313 + regmap_read(master->regmap, master->layout->offset, &mckr);
314 + spin_unlock_irqrestore(master->lock, flags);
316 + mckr &= master->layout->mask;
317 + div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
318 + div = master->characteristics->divisors[div];
320 + if (div != DIV_ROUND_CLOSEST(master->pms.parent_rate, master->pms.rate))
321 + pr_warn("MCKR DIV not configured properly by firmware!\n");
324 static const struct clk_ops master_div_ops = {
325 .prepare = clk_master_prepare,
326 .is_prepared = clk_master_is_prepared,
327 .recalc_rate = clk_master_div_recalc_rate,
328 + .save_context = clk_master_div_save_context,
329 + .restore_context = clk_master_div_restore_context,
332 static int clk_master_div_set_rate(struct clk_hw *hw, unsigned long rate,
333 @@ -125,7 +168,9 @@ static int clk_master_div_set_rate(struct clk_hw *hw, unsigned long rate,
334 const struct clk_master_characteristics *characteristics =
335 master->characteristics;
337 + unsigned int mckr, tmp;
341 div = DIV_ROUND_CLOSEST(parent_rate, rate);
342 if (div > ARRAY_SIZE(characteristics->divisors))
343 @@ -145,11 +190,24 @@ static int clk_master_div_set_rate(struct clk_hw *hw, unsigned long rate,
346 spin_lock_irqsave(master->lock, flags);
347 - regmap_update_bits(master->regmap, master->layout->offset,
348 - (MASTER_DIV_MASK << MASTER_DIV_SHIFT),
349 - (div << MASTER_DIV_SHIFT));
350 + ret = regmap_read(master->regmap, master->layout->offset, &mckr);
354 + tmp = mckr & master->layout->mask;
355 + tmp = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
359 + mckr &= ~(MASTER_DIV_MASK << MASTER_DIV_SHIFT);
360 + mckr |= (div << MASTER_DIV_SHIFT);
361 + ret = regmap_write(master->regmap, master->layout->offset, mckr);
365 while (!clk_master_ready(master))
368 spin_unlock_irqrestore(master->lock, flags);
371 @@ -197,12 +255,25 @@ static int clk_master_div_determine_rate(struct clk_hw *hw,
375 +static void clk_master_div_restore_context_chg(struct clk_hw *hw)
377 + struct clk_master *master = to_clk_master(hw);
380 + ret = clk_master_div_set_rate(hw, master->pms.rate,
381 + master->pms.parent_rate);
383 + pr_warn("Failed to restore MCK DIV clock\n");
386 static const struct clk_ops master_div_ops_chg = {
387 .prepare = clk_master_prepare,
388 .is_prepared = clk_master_is_prepared,
389 .recalc_rate = clk_master_div_recalc_rate,
390 .determine_rate = clk_master_div_determine_rate,
391 .set_rate = clk_master_div_set_rate,
392 + .save_context = clk_master_div_save_context,
393 + .restore_context = clk_master_div_restore_context_chg,
396 static void clk_sama7g5_master_best_diff(struct clk_rate_request *req,
397 @@ -272,7 +343,8 @@ static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate,
399 struct clk_master *master = to_clk_master(hw);
402 + unsigned int pres, mckr, tmp;
405 pres = DIV_ROUND_CLOSEST(parent_rate, rate);
406 if (pres > MASTER_PRES_MAX)
407 @@ -284,15 +356,27 @@ static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate,
408 pres = ffs(pres) - 1;
410 spin_lock_irqsave(master->lock, flags);
411 - regmap_update_bits(master->regmap, master->layout->offset,
412 - (MASTER_PRES_MASK << master->layout->pres_shift),
413 - (pres << master->layout->pres_shift));
414 + ret = regmap_read(master->regmap, master->layout->offset, &mckr);
418 + mckr &= master->layout->mask;
419 + tmp = (mckr >> master->layout->pres_shift) & MASTER_PRES_MASK;
423 + mckr &= ~(MASTER_PRES_MASK << master->layout->pres_shift);
424 + mckr |= (pres << master->layout->pres_shift);
425 + ret = regmap_write(master->regmap, master->layout->offset, mckr);
429 while (!clk_master_ready(master))
432 spin_unlock_irqrestore(master->lock, flags);
438 static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw,
439 @@ -330,11 +414,68 @@ static u8 clk_master_pres_get_parent(struct clk_hw *hw)
440 return mckr & AT91_PMC_CSS;
443 +static int clk_master_pres_save_context(struct clk_hw *hw)
445 + struct clk_master *master = to_clk_master(hw);
446 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
447 + unsigned long flags;
448 + unsigned int val, pres;
450 + spin_lock_irqsave(master->lock, flags);
451 + regmap_read(master->regmap, master->layout->offset, &val);
452 + spin_unlock_irqrestore(master->lock, flags);
454 + val &= master->layout->mask;
455 + pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
456 + if (pres == MASTER_PRES_MAX && master->characteristics->have_div3_pres)
459 + pres = (1 << pres);
461 + master->pms.parent = val & AT91_PMC_CSS;
462 + master->pms.parent_rate = clk_hw_get_rate(parent_hw);
463 + master->pms.rate = DIV_ROUND_CLOSEST_ULL(master->pms.parent_rate, pres);
468 +static void clk_master_pres_restore_context(struct clk_hw *hw)
470 + struct clk_master *master = to_clk_master(hw);
471 + unsigned long flags;
472 + unsigned int val, pres;
474 + spin_lock_irqsave(master->lock, flags);
475 + regmap_read(master->regmap, master->layout->offset, &val);
476 + spin_unlock_irqrestore(master->lock, flags);
478 + val &= master->layout->mask;
479 + pres = (val >> master->layout->pres_shift) & MASTER_PRES_MASK;
480 + if (pres == MASTER_PRES_MAX && master->characteristics->have_div3_pres)
483 + pres = (1 << pres);
485 + if (master->pms.rate !=
486 + DIV_ROUND_CLOSEST_ULL(master->pms.parent_rate, pres) ||
487 + (master->pms.parent != (val & AT91_PMC_CSS)))
488 + pr_warn("MCKR PRES was not configured properly by firmware!\n");
491 +static void clk_master_pres_restore_context_chg(struct clk_hw *hw)
493 + struct clk_master *master = to_clk_master(hw);
495 + clk_master_pres_set_rate(hw, master->pms.rate, master->pms.parent_rate);
498 static const struct clk_ops master_pres_ops = {
499 .prepare = clk_master_prepare,
500 .is_prepared = clk_master_is_prepared,
501 .recalc_rate = clk_master_pres_recalc_rate,
502 .get_parent = clk_master_pres_get_parent,
503 + .save_context = clk_master_pres_save_context,
504 + .restore_context = clk_master_pres_restore_context,
507 static const struct clk_ops master_pres_ops_chg = {
508 @@ -344,6 +485,8 @@ static const struct clk_ops master_pres_ops_chg = {
509 .recalc_rate = clk_master_pres_recalc_rate,
510 .get_parent = clk_master_pres_get_parent,
511 .set_rate = clk_master_pres_set_rate,
512 + .save_context = clk_master_pres_save_context,
513 + .restore_context = clk_master_pres_restore_context_chg,
516 static struct clk_hw * __init
517 @@ -539,20 +682,21 @@ static int clk_sama7g5_master_set_parent(struct clk_hw *hw, u8 index)
521 -static int clk_sama7g5_master_enable(struct clk_hw *hw)
522 +static void clk_sama7g5_master_set(struct clk_master *master,
523 + unsigned int status)
525 - struct clk_master *master = to_clk_master(hw);
527 unsigned int val, cparent;
528 + unsigned int enable = status ? PMC_MCR_EN : 0;
530 spin_lock_irqsave(master->lock, flags);
532 regmap_write(master->regmap, PMC_MCR, PMC_MCR_ID(master->id));
533 regmap_read(master->regmap, PMC_MCR, &val);
534 regmap_update_bits(master->regmap, PMC_MCR,
535 - PMC_MCR_EN | PMC_MCR_CSS | PMC_MCR_DIV |
536 + enable | PMC_MCR_CSS | PMC_MCR_DIV |
537 PMC_MCR_CMD | PMC_MCR_ID_MSK,
538 - PMC_MCR_EN | (master->parent << PMC_MCR_CSS_SHIFT) |
539 + enable | (master->parent << PMC_MCR_CSS_SHIFT) |
540 (master->div << MASTER_DIV_SHIFT) |
541 PMC_MCR_CMD | PMC_MCR_ID(master->id));
543 @@ -563,6 +707,13 @@ static int clk_sama7g5_master_enable(struct clk_hw *hw)
546 spin_unlock_irqrestore(master->lock, flags);
549 +static int clk_sama7g5_master_enable(struct clk_hw *hw)
551 + struct clk_master *master = to_clk_master(hw);
553 + clk_sama7g5_master_set(master, 1);
557 @@ -620,6 +771,23 @@ static int clk_sama7g5_master_set_rate(struct clk_hw *hw, unsigned long rate,
561 +static int clk_sama7g5_master_save_context(struct clk_hw *hw)
563 + struct clk_master *master = to_clk_master(hw);
565 + master->pms.status = clk_sama7g5_master_is_enabled(hw);
570 +static void clk_sama7g5_master_restore_context(struct clk_hw *hw)
572 + struct clk_master *master = to_clk_master(hw);
574 + if (master->pms.status)
575 + clk_sama7g5_master_set(master, master->pms.status);
578 static const struct clk_ops sama7g5_master_ops = {
579 .enable = clk_sama7g5_master_enable,
580 .disable = clk_sama7g5_master_disable,
581 @@ -629,6 +797,8 @@ static const struct clk_ops sama7g5_master_ops = {
582 .set_rate = clk_sama7g5_master_set_rate,
583 .get_parent = clk_sama7g5_master_get_parent,
584 .set_parent = clk_sama7g5_master_set_parent,
585 + .save_context = clk_sama7g5_master_save_context,
586 + .restore_context = clk_sama7g5_master_restore_context,
589 struct clk_hw * __init
590 diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
591 index 7a27ba8e0577..e14fa5ac734c 100644
592 --- a/drivers/clk/at91/clk-peripheral.c
593 +++ b/drivers/clk/at91/clk-peripheral.c
594 @@ -37,6 +37,7 @@ struct clk_sam9x5_peripheral {
597 const struct clk_pcr_layout *layout;
598 + struct at91_clk_pms pms;
602 @@ -155,10 +156,11 @@ static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
606 -static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
607 +static int clk_sam9x5_peripheral_set(struct clk_sam9x5_peripheral *periph,
608 + unsigned int status)
610 - struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
612 + unsigned int enable = status ? AT91_PMC_PCR_EN : 0;
614 if (periph->id < PERIPHERAL_ID_MIN)
616 @@ -168,15 +170,21 @@ static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
617 (periph->id & periph->layout->pid_mask));
618 regmap_update_bits(periph->regmap, periph->layout->offset,
619 periph->layout->div_mask | periph->layout->cmd |
622 field_prep(periph->layout->div_mask, periph->div) |
623 - periph->layout->cmd |
625 + periph->layout->cmd | enable);
626 spin_unlock_irqrestore(periph->lock, flags);
631 +static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
633 + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
635 + return clk_sam9x5_peripheral_set(periph, 1);
638 static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
640 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
641 @@ -393,6 +401,23 @@ static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw,
645 +static int clk_sam9x5_peripheral_save_context(struct clk_hw *hw)
647 + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
649 + periph->pms.status = clk_sam9x5_peripheral_is_enabled(hw);
654 +static void clk_sam9x5_peripheral_restore_context(struct clk_hw *hw)
656 + struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
658 + if (periph->pms.status)
659 + clk_sam9x5_peripheral_set(periph, periph->pms.status);
662 static const struct clk_ops sam9x5_peripheral_ops = {
663 .enable = clk_sam9x5_peripheral_enable,
664 .disable = clk_sam9x5_peripheral_disable,
665 @@ -400,6 +425,8 @@ static const struct clk_ops sam9x5_peripheral_ops = {
666 .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
667 .round_rate = clk_sam9x5_peripheral_round_rate,
668 .set_rate = clk_sam9x5_peripheral_set_rate,
669 + .save_context = clk_sam9x5_peripheral_save_context,
670 + .restore_context = clk_sam9x5_peripheral_restore_context,
673 static const struct clk_ops sam9x5_peripheral_chg_ops = {
674 @@ -409,6 +436,8 @@ static const struct clk_ops sam9x5_peripheral_chg_ops = {
675 .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
676 .determine_rate = clk_sam9x5_peripheral_determine_rate,
677 .set_rate = clk_sam9x5_peripheral_set_rate,
678 + .save_context = clk_sam9x5_peripheral_save_context,
679 + .restore_context = clk_sam9x5_peripheral_restore_context,
682 struct clk_hw * __init
683 @@ -460,7 +489,6 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
686 clk_sam9x5_peripheral_autodiv(periph);
687 - pmc_register_id(id);
691 diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c
692 index 6ed986d3eee0..249d6a53cedf 100644
693 --- a/drivers/clk/at91/clk-pll.c
694 +++ b/drivers/clk/at91/clk-pll.c
695 @@ -40,6 +40,7 @@ struct clk_pll {
697 const struct clk_pll_layout *layout;
698 const struct clk_pll_characteristics *characteristics;
699 + struct at91_clk_pms pms;
702 static inline bool clk_pll_ready(struct regmap *regmap, int id)
703 @@ -260,6 +261,42 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
707 +static int clk_pll_save_context(struct clk_hw *hw)
709 + struct clk_pll *pll = to_clk_pll(hw);
710 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
712 + pll->pms.parent_rate = clk_hw_get_rate(parent_hw);
713 + pll->pms.rate = clk_pll_recalc_rate(&pll->hw, pll->pms.parent_rate);
714 + pll->pms.status = clk_pll_ready(pll->regmap, PLL_REG(pll->id));
719 +static void clk_pll_restore_context(struct clk_hw *hw)
721 + struct clk_pll *pll = to_clk_pll(hw);
722 + unsigned long calc_rate;
723 + unsigned int pllr, pllr_out, pllr_count;
726 + if (pll->characteristics->out)
727 + out = pll->characteristics->out[pll->range];
729 + regmap_read(pll->regmap, PLL_REG(pll->id), &pllr);
731 + calc_rate = (pll->pms.parent_rate / PLL_DIV(pllr)) *
732 + (PLL_MUL(pllr, pll->layout) + 1);
733 + pllr_count = (pllr >> PLL_COUNT_SHIFT) & PLL_MAX_COUNT;
734 + pllr_out = (pllr >> PLL_OUT_SHIFT) & out;
736 + if (pll->pms.rate != calc_rate ||
737 + pll->pms.status != clk_pll_ready(pll->regmap, PLL_REG(pll->id)) ||
738 + pllr_count != PLL_MAX_COUNT ||
739 + (out && pllr_out != out))
740 + pr_warn("PLLAR was not configured properly by firmware\n");
743 static const struct clk_ops pll_ops = {
744 .prepare = clk_pll_prepare,
745 .unprepare = clk_pll_unprepare,
746 @@ -267,6 +304,8 @@ static const struct clk_ops pll_ops = {
747 .recalc_rate = clk_pll_recalc_rate,
748 .round_rate = clk_pll_round_rate,
749 .set_rate = clk_pll_set_rate,
750 + .save_context = clk_pll_save_context,
751 + .restore_context = clk_pll_restore_context,
754 struct clk_hw * __init
755 diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
756 index fcf8f6a1c2c6..6c4b259d31d3 100644
757 --- a/drivers/clk/at91/clk-programmable.c
758 +++ b/drivers/clk/at91/clk-programmable.c
759 @@ -24,6 +24,7 @@ struct clk_programmable {
762 const struct clk_programmable_layout *layout;
763 + struct at91_clk_pms pms;
766 #define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw)
767 @@ -177,12 +178,38 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate,
771 +static int clk_programmable_save_context(struct clk_hw *hw)
773 + struct clk_programmable *prog = to_clk_programmable(hw);
774 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
776 + prog->pms.parent = clk_programmable_get_parent(hw);
777 + prog->pms.parent_rate = clk_hw_get_rate(parent_hw);
778 + prog->pms.rate = clk_programmable_recalc_rate(hw, prog->pms.parent_rate);
783 +static void clk_programmable_restore_context(struct clk_hw *hw)
785 + struct clk_programmable *prog = to_clk_programmable(hw);
788 + ret = clk_programmable_set_parent(hw, prog->pms.parent);
792 + clk_programmable_set_rate(hw, prog->pms.rate, prog->pms.parent_rate);
795 static const struct clk_ops programmable_ops = {
796 .recalc_rate = clk_programmable_recalc_rate,
797 .determine_rate = clk_programmable_determine_rate,
798 .get_parent = clk_programmable_get_parent,
799 .set_parent = clk_programmable_set_parent,
800 .set_rate = clk_programmable_set_rate,
801 + .save_context = clk_programmable_save_context,
802 + .restore_context = clk_programmable_restore_context,
805 struct clk_hw * __init
806 @@ -221,8 +248,6 @@ at91_clk_register_programmable(struct regmap *regmap,
811 - pmc_register_pck(id);
815 diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c
816 index 1f52409475e9..a73d7c96ce1d 100644
817 --- a/drivers/clk/at91/clk-sam9x60-pll.c
818 +++ b/drivers/clk/at91/clk-sam9x60-pll.c
819 @@ -38,12 +38,14 @@ struct sam9x60_pll_core {
821 struct sam9x60_frac {
822 struct sam9x60_pll_core core;
823 + struct at91_clk_pms pms;
829 struct sam9x60_pll_core core;
830 + struct at91_clk_pms pms;
834 @@ -75,9 +77,8 @@ static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw,
835 DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22));
838 -static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
839 +static int sam9x60_frac_pll_set(struct sam9x60_pll_core *core)
841 - struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
842 struct sam9x60_frac *frac = to_sam9x60_frac(core);
843 struct regmap *regmap = core->regmap;
844 unsigned int val, cfrac, cmul;
845 @@ -141,6 +142,13 @@ static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
849 +static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
851 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
853 + return sam9x60_frac_pll_set(core);
856 static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
858 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
859 @@ -280,6 +288,25 @@ static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
863 +static int sam9x60_frac_pll_save_context(struct clk_hw *hw)
865 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
866 + struct sam9x60_frac *frac = to_sam9x60_frac(core);
868 + frac->pms.status = sam9x60_pll_ready(core->regmap, core->id);
873 +static void sam9x60_frac_pll_restore_context(struct clk_hw *hw)
875 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
876 + struct sam9x60_frac *frac = to_sam9x60_frac(core);
878 + if (frac->pms.status)
879 + sam9x60_frac_pll_set(core);
882 static const struct clk_ops sam9x60_frac_pll_ops = {
883 .prepare = sam9x60_frac_pll_prepare,
884 .unprepare = sam9x60_frac_pll_unprepare,
885 @@ -287,6 +314,8 @@ static const struct clk_ops sam9x60_frac_pll_ops = {
886 .recalc_rate = sam9x60_frac_pll_recalc_rate,
887 .round_rate = sam9x60_frac_pll_round_rate,
888 .set_rate = sam9x60_frac_pll_set_rate,
889 + .save_context = sam9x60_frac_pll_save_context,
890 + .restore_context = sam9x60_frac_pll_restore_context,
893 static const struct clk_ops sam9x60_frac_pll_ops_chg = {
894 @@ -296,11 +325,12 @@ static const struct clk_ops sam9x60_frac_pll_ops_chg = {
895 .recalc_rate = sam9x60_frac_pll_recalc_rate,
896 .round_rate = sam9x60_frac_pll_round_rate,
897 .set_rate = sam9x60_frac_pll_set_rate_chg,
898 + .save_context = sam9x60_frac_pll_save_context,
899 + .restore_context = sam9x60_frac_pll_restore_context,
902 -static int sam9x60_div_pll_prepare(struct clk_hw *hw)
903 +static int sam9x60_div_pll_set(struct sam9x60_pll_core *core)
905 - struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
906 struct sam9x60_div *div = to_sam9x60_div(core);
907 struct regmap *regmap = core->regmap;
909 @@ -334,6 +364,13 @@ static int sam9x60_div_pll_prepare(struct clk_hw *hw)
913 +static int sam9x60_div_pll_prepare(struct clk_hw *hw)
915 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
917 + return sam9x60_div_pll_set(core);
920 static void sam9x60_div_pll_unprepare(struct clk_hw *hw)
922 struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
923 @@ -482,6 +519,25 @@ static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
927 +static int sam9x60_div_pll_save_context(struct clk_hw *hw)
929 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
930 + struct sam9x60_div *div = to_sam9x60_div(core);
932 + div->pms.status = sam9x60_div_pll_is_prepared(hw);
937 +static void sam9x60_div_pll_restore_context(struct clk_hw *hw)
939 + struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
940 + struct sam9x60_div *div = to_sam9x60_div(core);
942 + if (div->pms.status)
943 + sam9x60_div_pll_set(core);
946 static const struct clk_ops sam9x60_div_pll_ops = {
947 .prepare = sam9x60_div_pll_prepare,
948 .unprepare = sam9x60_div_pll_unprepare,
949 @@ -489,6 +545,8 @@ static const struct clk_ops sam9x60_div_pll_ops = {
950 .recalc_rate = sam9x60_div_pll_recalc_rate,
951 .round_rate = sam9x60_div_pll_round_rate,
952 .set_rate = sam9x60_div_pll_set_rate,
953 + .save_context = sam9x60_div_pll_save_context,
954 + .restore_context = sam9x60_div_pll_restore_context,
957 static const struct clk_ops sam9x60_div_pll_ops_chg = {
958 @@ -498,6 +556,8 @@ static const struct clk_ops sam9x60_div_pll_ops_chg = {
959 .recalc_rate = sam9x60_div_pll_recalc_rate,
960 .round_rate = sam9x60_div_pll_round_rate,
961 .set_rate = sam9x60_div_pll_set_rate_chg,
962 + .save_context = sam9x60_div_pll_save_context,
963 + .restore_context = sam9x60_div_pll_restore_context,
966 struct clk_hw * __init
967 diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
968 index f83ec0de86c3..80720fd1a9cf 100644
969 --- a/drivers/clk/at91/clk-system.c
970 +++ b/drivers/clk/at91/clk-system.c
974 struct regmap *regmap;
975 + struct at91_clk_pms pms;
979 @@ -77,10 +78,29 @@ static int clk_system_is_prepared(struct clk_hw *hw)
980 return !!(status & (1 << sys->id));
983 +static int clk_system_save_context(struct clk_hw *hw)
985 + struct clk_system *sys = to_clk_system(hw);
987 + sys->pms.status = clk_system_is_prepared(hw);
992 +static void clk_system_restore_context(struct clk_hw *hw)
994 + struct clk_system *sys = to_clk_system(hw);
996 + if (sys->pms.status)
997 + clk_system_prepare(&sys->hw);
1000 static const struct clk_ops system_ops = {
1001 .prepare = clk_system_prepare,
1002 .unprepare = clk_system_unprepare,
1003 .is_prepared = clk_system_is_prepared,
1004 + .save_context = clk_system_save_context,
1005 + .restore_context = clk_system_restore_context,
1008 struct clk_hw * __init
1009 diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
1010 index 31d5c45e30d7..b0696a928aa9 100644
1011 --- a/drivers/clk/at91/clk-usb.c
1012 +++ b/drivers/clk/at91/clk-usb.c
1014 struct at91sam9x5_clk_usb {
1016 struct regmap *regmap;
1017 + struct at91_clk_pms pms;
1021 @@ -148,12 +149,38 @@ static int at91sam9x5_clk_usb_set_rate(struct clk_hw *hw, unsigned long rate,
1025 +static int at91sam9x5_usb_save_context(struct clk_hw *hw)
1027 + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
1028 + struct clk_hw *parent_hw = clk_hw_get_parent(hw);
1030 + usb->pms.parent = at91sam9x5_clk_usb_get_parent(hw);
1031 + usb->pms.parent_rate = clk_hw_get_rate(parent_hw);
1032 + usb->pms.rate = at91sam9x5_clk_usb_recalc_rate(hw, usb->pms.parent_rate);
1037 +static void at91sam9x5_usb_restore_context(struct clk_hw *hw)
1039 + struct at91sam9x5_clk_usb *usb = to_at91sam9x5_clk_usb(hw);
1042 + ret = at91sam9x5_clk_usb_set_parent(hw, usb->pms.parent);
1046 + at91sam9x5_clk_usb_set_rate(hw, usb->pms.rate, usb->pms.parent_rate);
1049 static const struct clk_ops at91sam9x5_usb_ops = {
1050 .recalc_rate = at91sam9x5_clk_usb_recalc_rate,
1051 .determine_rate = at91sam9x5_clk_usb_determine_rate,
1052 .get_parent = at91sam9x5_clk_usb_get_parent,
1053 .set_parent = at91sam9x5_clk_usb_set_parent,
1054 .set_rate = at91sam9x5_clk_usb_set_rate,
1055 + .save_context = at91sam9x5_usb_save_context,
1056 + .restore_context = at91sam9x5_usb_restore_context,
1059 static int at91sam9n12_clk_usb_enable(struct clk_hw *hw)
1060 diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
1061 index df9f3fc3b6a6..a22c10d9a1b9 100644
1062 --- a/drivers/clk/at91/clk-utmi.c
1063 +++ b/drivers/clk/at91/clk-utmi.c
1064 @@ -23,6 +23,7 @@ struct clk_utmi {
1066 struct regmap *regmap_pmc;
1067 struct regmap *regmap_sfr;
1068 + struct at91_clk_pms pms;
1071 #define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
1072 @@ -113,11 +114,30 @@ static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
1076 +static int clk_utmi_save_context(struct clk_hw *hw)
1078 + struct clk_utmi *utmi = to_clk_utmi(hw);
1080 + utmi->pms.status = clk_utmi_is_prepared(hw);
1085 +static void clk_utmi_restore_context(struct clk_hw *hw)
1087 + struct clk_utmi *utmi = to_clk_utmi(hw);
1089 + if (utmi->pms.status)
1090 + clk_utmi_prepare(hw);
1093 static const struct clk_ops utmi_ops = {
1094 .prepare = clk_utmi_prepare,
1095 .unprepare = clk_utmi_unprepare,
1096 .is_prepared = clk_utmi_is_prepared,
1097 .recalc_rate = clk_utmi_recalc_rate,
1098 + .save_context = clk_utmi_save_context,
1099 + .restore_context = clk_utmi_restore_context,
1102 static struct clk_hw * __init
1103 @@ -232,10 +252,29 @@ static int clk_utmi_sama7g5_is_prepared(struct clk_hw *hw)
1107 +static int clk_utmi_sama7g5_save_context(struct clk_hw *hw)
1109 + struct clk_utmi *utmi = to_clk_utmi(hw);
1111 + utmi->pms.status = clk_utmi_sama7g5_is_prepared(hw);
1116 +static void clk_utmi_sama7g5_restore_context(struct clk_hw *hw)
1118 + struct clk_utmi *utmi = to_clk_utmi(hw);
1120 + if (utmi->pms.status)
1121 + clk_utmi_sama7g5_prepare(hw);
1124 static const struct clk_ops sama7g5_utmi_ops = {
1125 .prepare = clk_utmi_sama7g5_prepare,
1126 .is_prepared = clk_utmi_sama7g5_is_prepared,
1127 .recalc_rate = clk_utmi_recalc_rate,
1128 + .save_context = clk_utmi_sama7g5_save_context,
1129 + .restore_context = clk_utmi_sama7g5_restore_context,
1132 struct clk_hw * __init
1133 diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
1134 index b40035b011d0..b2806946a77a 100644
1135 --- a/drivers/clk/at91/pmc.c
1136 +++ b/drivers/clk/at91/pmc.c
1138 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
1141 +#include <linux/clk.h>
1142 #include <linux/clk-provider.h>
1143 #include <linux/clkdev.h>
1144 #include <linux/clk/at91_pmc.h>
1147 #include <asm/proc-fns.h>
1149 -#include <dt-bindings/clock/at91.h>
1153 #define PMC_MAX_IDS 128
1154 @@ -111,147 +110,19 @@ struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
1158 -static struct regmap *pmcreg;
1160 -static u8 registered_ids[PMC_MAX_IDS];
1161 -static u8 registered_pcks[PMC_MAX_PCKS];
1175 - u32 pcr[PMC_MAX_IDS];
1178 - u32 pckr[PMC_MAX_PCKS];
1182 - * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
1183 - * without alteration in the table, and 0 is for unused clocks.
1185 -void pmc_register_id(u8 id)
1189 - for (i = 0; i < PMC_MAX_IDS; i++) {
1190 - if (registered_ids[i] == 0) {
1191 - registered_ids[i] = id;
1194 - if (registered_ids[i] == id)
1200 - * As Programmable Clock 0 is valid on AT91 chips, there is an offset
1201 - * of 1 between the stored value and the real clock ID.
1203 -void pmc_register_pck(u8 pck)
1207 - for (i = 0; i < PMC_MAX_PCKS; i++) {
1208 - if (registered_pcks[i] == 0) {
1209 - registered_pcks[i] = pck + 1;
1212 - if (registered_pcks[i] == (pck + 1))
1217 -static int pmc_suspend(void)
1218 +static int at91_pmc_suspend(void)
1223 - regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr);
1224 - regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0);
1225 - regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr);
1226 - regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor);
1227 - regmap_read(pmcreg, AT91_CKGR_MCFR, &pmc_cache.mcfr);
1228 - regmap_read(pmcreg, AT91_CKGR_PLLAR, &pmc_cache.pllar);
1229 - regmap_read(pmcreg, AT91_PMC_MCKR, &pmc_cache.mckr);
1230 - regmap_read(pmcreg, AT91_PMC_USB, &pmc_cache.usb);
1231 - regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.imr);
1232 - regmap_read(pmcreg, AT91_PMC_PCSR1, &pmc_cache.pcsr1);
1234 - for (i = 0; registered_ids[i]; i++) {
1235 - regmap_write(pmcreg, AT91_PMC_PCR,
1236 - (registered_ids[i] & AT91_PMC_PCR_PID_MASK));
1237 - regmap_read(pmcreg, AT91_PMC_PCR,
1238 - &pmc_cache.pcr[registered_ids[i]]);
1240 - for (i = 0; registered_pcks[i]; i++) {
1241 - num = registered_pcks[i] - 1;
1242 - regmap_read(pmcreg, AT91_PMC_PCKR(num), &pmc_cache.pckr[num]);
1246 + return clk_save_context();
1249 -static bool pmc_ready(unsigned int mask)
1250 +static void at91_pmc_resume(void)
1252 - unsigned int status;
1254 - regmap_read(pmcreg, AT91_PMC_SR, &status);
1256 - return ((status & mask) == mask) ? 1 : 0;
1259 -static void pmc_resume(void)
1264 - u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
1266 - regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
1267 - if (pmc_cache.mckr != tmp)
1268 - pr_warn("MCKR was not configured properly by the firmware\n");
1269 - regmap_read(pmcreg, AT91_CKGR_PLLAR, &tmp);
1270 - if (pmc_cache.pllar != tmp)
1271 - pr_warn("PLLAR was not configured properly by the firmware\n");
1273 - regmap_write(pmcreg, AT91_PMC_SCER, pmc_cache.scsr);
1274 - regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0);
1275 - regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr);
1276 - regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor);
1277 - regmap_write(pmcreg, AT91_CKGR_MCFR, pmc_cache.mcfr);
1278 - regmap_write(pmcreg, AT91_PMC_USB, pmc_cache.usb);
1279 - regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.imr);
1280 - regmap_write(pmcreg, AT91_PMC_PCER1, pmc_cache.pcsr1);
1282 - for (i = 0; registered_ids[i]; i++) {
1283 - regmap_write(pmcreg, AT91_PMC_PCR,
1284 - pmc_cache.pcr[registered_ids[i]] |
1285 - AT91_PMC_PCR_CMD);
1287 - for (i = 0; registered_pcks[i]; i++) {
1288 - num = registered_pcks[i] - 1;
1289 - regmap_write(pmcreg, AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
1292 - if (pmc_cache.uckr & AT91_PMC_UPLLEN)
1293 - mask |= AT91_PMC_LOCKU;
1295 - while (!pmc_ready(mask))
1297 + clk_restore_context();
1300 static struct syscore_ops pmc_syscore_ops = {
1301 - .suspend = pmc_suspend,
1302 - .resume = pmc_resume,
1303 + .suspend = at91_pmc_suspend,
1304 + .resume = at91_pmc_resume,
1307 static const struct of_device_id sama5d2_pmc_dt_ids[] = {
1308 @@ -271,11 +142,7 @@ static int __init pmc_register_ops(void)
1313 - pmcreg = device_node_to_regmap(np);
1315 - if (IS_ERR(pmcreg))
1316 - return PTR_ERR(pmcreg);
1318 register_syscore_ops(&pmc_syscore_ops);
1320 diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
1321 index a49076c804a9..45df094498ce 100644
1322 --- a/drivers/clk/at91/pmc.h
1323 +++ b/drivers/clk/at91/pmc.h
1325 #include <linux/regmap.h>
1326 #include <linux/spinlock.h>
1328 +#include <dt-bindings/clock/at91.h>
1330 extern spinlock_t pmc_pcr_lock;
1333 @@ -98,6 +100,20 @@ struct clk_pcr_layout {
1338 + * struct at91_clk_pms - Power management state for AT91 clock
1339 + * @rate: clock rate
1340 + * @parent_rate: clock parent rate
1341 + * @status: clock status (enabled or disabled)
1342 + * @parent: clock parent index
1344 +struct at91_clk_pms {
1345 + unsigned long rate;
1346 + unsigned long parent_rate;
1347 + unsigned int status;
1348 + unsigned int parent;
1351 #define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
1352 #define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
1354 @@ -248,12 +264,4 @@ struct clk_hw * __init
1355 at91_clk_sama7g5_register_utmi(struct regmap *regmap, const char *name,
1356 const char *parent_name);
1359 -void pmc_register_id(u8 id);
1360 -void pmc_register_pck(u8 pck);
1362 -static inline void pmc_register_id(u8 id) {}
1363 -static inline void pmc_register_pck(u8 pck) {}
1366 #endif /* __PMC_H_ */