1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2019 Microchip Technology Inc.
7 #include <linux/bitfield.h>
8 #include <linux/clk-provider.h>
9 #include <linux/clkdev.h>
10 #include <linux/clk/at91_pmc.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/regmap.h>
17 #define PMC_PLL_CTRL0 0xc
18 #define PMC_PLL_CTRL0_DIV_MSK GENMASK(7, 0)
19 #define PMC_PLL_CTRL0_ENPLL BIT(28)
20 #define PMC_PLL_CTRL0_ENPLLCK BIT(29)
21 #define PMC_PLL_CTRL0_ENLOCK BIT(31)
23 #define PMC_PLL_CTRL1 0x10
24 #define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)
25 #define PMC_PLL_CTRL1_MUL_MSK GENMASK(30, 24)
27 #define PMC_PLL_ACR 0x18
28 #define PMC_PLL_ACR_DEFAULT 0x1b040010UL
29 #define PMC_PLL_ACR_UTMIVR BIT(12)
30 #define PMC_PLL_ACR_UTMIBG BIT(13)
31 #define PMC_PLL_ACR_LOOP_FILTER_MSK GENMASK(31, 24)
33 #define PMC_PLL_UPDT 0x1c
34 #define PMC_PLL_UPDT_UPDATE BIT(8)
36 #define PMC_PLL_ISR0 0xec
38 #define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
40 #define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
46 struct regmap
*regmap
;
48 const struct clk_pll_characteristics
*characteristics
;
55 #define to_sam9x60_pll(hw) container_of(hw, struct sam9x60_pll, hw)
57 static inline bool sam9x60_pll_ready(struct regmap
*regmap
, int id
)
61 regmap_read(regmap
, PMC_PLL_ISR0
, &status
);
63 return !!(status
& BIT(id
));
66 static int sam9x60_pll_prepare(struct clk_hw
*hw
)
68 struct sam9x60_pll
*pll
= to_sam9x60_pll(hw
);
69 struct regmap
*regmap
= pll
->regmap
;
75 spin_lock_irqsave(pll
->lock
, flags
);
76 regmap_write(regmap
, PMC_PLL_UPDT
, pll
->id
);
78 regmap_read(regmap
, PMC_PLL_CTRL0
, &val
);
79 div
= FIELD_GET(PMC_PLL_CTRL0_DIV_MSK
, val
);
81 regmap_read(regmap
, PMC_PLL_CTRL1
, &val
);
82 mul
= FIELD_GET(PMC_PLL_CTRL1_MUL_MSK
, val
);
84 if (sam9x60_pll_ready(regmap
, pll
->id
) &&
85 (div
== pll
->div
&& mul
== pll
->mul
)) {
86 spin_unlock_irqrestore(pll
->lock
, flags
);
90 /* Recommended value for PMC_PLL_ACR */
91 val
= PMC_PLL_ACR_DEFAULT
;
92 regmap_write(regmap
, PMC_PLL_ACR
, val
);
94 regmap_write(regmap
, PMC_PLL_CTRL1
,
95 FIELD_PREP(PMC_PLL_CTRL1_MUL_MSK
, pll
->mul
));
97 if (pll
->characteristics
->upll
) {
98 /* Enable the UTMI internal bandgap */
99 val
|= PMC_PLL_ACR_UTMIBG
;
100 regmap_write(regmap
, PMC_PLL_ACR
, val
);
104 /* Enable the UTMI internal regulator */
105 val
|= PMC_PLL_ACR_UTMIVR
;
106 regmap_write(regmap
, PMC_PLL_ACR
, val
);
111 regmap_update_bits(regmap
, PMC_PLL_UPDT
,
112 PMC_PLL_UPDT_UPDATE
, PMC_PLL_UPDT_UPDATE
);
114 regmap_write(regmap
, PMC_PLL_CTRL0
,
115 PMC_PLL_CTRL0_ENLOCK
| PMC_PLL_CTRL0_ENPLL
|
116 PMC_PLL_CTRL0_ENPLLCK
| pll
->div
);
118 regmap_update_bits(regmap
, PMC_PLL_UPDT
,
119 PMC_PLL_UPDT_UPDATE
, PMC_PLL_UPDT_UPDATE
);
121 while (!sam9x60_pll_ready(regmap
, pll
->id
))
124 spin_unlock_irqrestore(pll
->lock
, flags
);
129 static int sam9x60_pll_is_prepared(struct clk_hw
*hw
)
131 struct sam9x60_pll
*pll
= to_sam9x60_pll(hw
);
133 return sam9x60_pll_ready(pll
->regmap
, pll
->id
);
136 static void sam9x60_pll_unprepare(struct clk_hw
*hw
)
138 struct sam9x60_pll
*pll
= to_sam9x60_pll(hw
);
141 spin_lock_irqsave(pll
->lock
, flags
);
143 regmap_write(pll
->regmap
, PMC_PLL_UPDT
, pll
->id
);
145 regmap_update_bits(pll
->regmap
, PMC_PLL_CTRL0
,
146 PMC_PLL_CTRL0_ENPLLCK
, 0);
148 regmap_update_bits(pll
->regmap
, PMC_PLL_UPDT
,
149 PMC_PLL_UPDT_UPDATE
, PMC_PLL_UPDT_UPDATE
);
151 regmap_update_bits(pll
->regmap
, PMC_PLL_CTRL0
, PMC_PLL_CTRL0_ENPLL
, 0);
153 if (pll
->characteristics
->upll
)
154 regmap_update_bits(pll
->regmap
, PMC_PLL_ACR
,
155 PMC_PLL_ACR_UTMIBG
| PMC_PLL_ACR_UTMIVR
, 0);
157 regmap_update_bits(pll
->regmap
, PMC_PLL_UPDT
,
158 PMC_PLL_UPDT_UPDATE
, PMC_PLL_UPDT_UPDATE
);
160 spin_unlock_irqrestore(pll
->lock
, flags
);
163 static unsigned long sam9x60_pll_recalc_rate(struct clk_hw
*hw
,
164 unsigned long parent_rate
)
166 struct sam9x60_pll
*pll
= to_sam9x60_pll(hw
);
168 return (parent_rate
* (pll
->mul
+ 1)) / (pll
->div
+ 1);
171 static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll
*pll
,
173 unsigned long parent_rate
,
176 const struct clk_pll_characteristics
*characteristics
=
177 pll
->characteristics
;
178 unsigned long bestremainder
= ULONG_MAX
;
179 unsigned long maxdiv
, mindiv
, tmpdiv
;
180 long bestrate
= -ERANGE
;
181 unsigned long bestdiv
= 0;
182 unsigned long bestmul
= 0;
183 unsigned long bestfrac
= 0;
185 if (rate
< characteristics
->output
[0].min
||
186 rate
> characteristics
->output
[0].max
)
189 if (!pll
->characteristics
->upll
) {
190 mindiv
= parent_rate
/ rate
;
194 maxdiv
= DIV_ROUND_UP(parent_rate
* PLL_MUL_MAX
, rate
);
195 if (maxdiv
> PLL_DIV_MAX
)
196 maxdiv
= PLL_DIV_MAX
;
198 mindiv
= maxdiv
= UPLL_DIV
;
201 for (tmpdiv
= mindiv
; tmpdiv
<= maxdiv
; tmpdiv
++) {
202 unsigned long remainder
;
203 unsigned long tmprate
;
204 unsigned long tmpmul
;
205 unsigned long tmpfrac
= 0;
208 * Calculate the multiplier associated with the current
209 * divider that provide the closest rate to the requested one.
211 tmpmul
= mult_frac(rate
, tmpdiv
, parent_rate
);
212 tmprate
= mult_frac(parent_rate
, tmpmul
, tmpdiv
);
213 remainder
= rate
- tmprate
;
216 tmpfrac
= DIV_ROUND_CLOSEST_ULL((u64
)remainder
* tmpdiv
* (1 << 22),
219 tmprate
+= DIV_ROUND_CLOSEST_ULL((u64
)tmpfrac
* parent_rate
,
223 remainder
= tmprate
- rate
;
225 remainder
= rate
- tmprate
;
229 * Compare the remainder with the best remainder found until
230 * now and elect a new best multiplier/divider pair if the
231 * current remainder is smaller than the best one.
233 if (remainder
< bestremainder
) {
234 bestremainder
= remainder
;
241 /* We've found a perfect match! */
246 /* Check if bestrate is a valid output rate */
247 if (bestrate
< characteristics
->output
[0].min
&&
248 bestrate
> characteristics
->output
[0].max
)
252 pll
->div
= bestdiv
- 1;
253 pll
->mul
= bestmul
- 1;
254 pll
->frac
= bestfrac
;
260 static long sam9x60_pll_round_rate(struct clk_hw
*hw
, unsigned long rate
,
261 unsigned long *parent_rate
)
263 struct sam9x60_pll
*pll
= to_sam9x60_pll(hw
);
265 return sam9x60_pll_get_best_div_mul(pll
, rate
, *parent_rate
, false);
268 static int sam9x60_pll_set_rate(struct clk_hw
*hw
, unsigned long rate
,
269 unsigned long parent_rate
)
271 struct sam9x60_pll
*pll
= to_sam9x60_pll(hw
);
273 return sam9x60_pll_get_best_div_mul(pll
, rate
, parent_rate
, true);
276 static const struct clk_ops pll_ops
= {
277 .prepare
= sam9x60_pll_prepare
,
278 .unprepare
= sam9x60_pll_unprepare
,
279 .is_prepared
= sam9x60_pll_is_prepared
,
280 .recalc_rate
= sam9x60_pll_recalc_rate
,
281 .round_rate
= sam9x60_pll_round_rate
,
282 .set_rate
= sam9x60_pll_set_rate
,
285 struct clk_hw
* __init
286 sam9x60_clk_register_pll(struct regmap
*regmap
, spinlock_t
*lock
,
287 const char *name
, const char *parent_name
, u8 id
,
288 const struct clk_pll_characteristics
*characteristics
)
290 struct sam9x60_pll
*pll
;
292 struct clk_init_data init
;
297 return ERR_PTR(-EINVAL
);
299 pll
= kzalloc(sizeof(*pll
), GFP_KERNEL
);
301 return ERR_PTR(-ENOMEM
);
305 init
.parent_names
= &parent_name
;
306 init
.num_parents
= 1;
307 init
.flags
= CLK_SET_RATE_GATE
;
310 pll
->hw
.init
= &init
;
311 pll
->characteristics
= characteristics
;
312 pll
->regmap
= regmap
;
315 regmap_write(regmap
, PMC_PLL_UPDT
, id
);
316 regmap_read(regmap
, PMC_PLL_CTRL0
, &pllr
);
317 pll
->div
= FIELD_GET(PMC_PLL_CTRL0_DIV_MSK
, pllr
);
318 regmap_read(regmap
, PMC_PLL_CTRL1
, &pllr
);
319 pll
->mul
= FIELD_GET(PMC_PLL_CTRL1_MUL_MSK
, pllr
);
322 ret
= clk_hw_register(NULL
, hw
);