1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2019 Microchip Technology Inc.
4 *
5 */
6
7 #include <linux/bitfield.h>
8 #include <linux/clk-provider.h>
9 #include <linux/clkdev.h>
10 #include <linux/clk/at91_pmc.h>
11 #include <linux/of.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/regmap.h>
14
15 #include "pmc.h"
16
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)
22
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)
26
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)
32
33 #define PMC_PLL_UPDT 0x1c
34 #define PMC_PLL_UPDT_UPDATE BIT(8)
35
36 #define PMC_PLL_ISR0 0xec
37
38 #define PLL_DIV_MAX (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
39 #define UPLL_DIV 2
40 #define PLL_MUL_MAX (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
41
42 #define PLL_MAX_ID 1
43
44 struct sam9x60_pll {
45 struct clk_hw hw;
46 struct regmap *regmap;
47 spinlock_t *lock;
48 const struct clk_pll_characteristics *characteristics;
49 u32 frac;
50 u8 id;
51 u8 div;
52 u16 mul;
53 };
54
55 #define to_sam9x60_pll(hw) container_of(hw, struct sam9x60_pll, hw)
56
sam9x60_pll_ready(struct regmap * regmap,int id)57 static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)
58 {
59 unsigned int status;
60
61 regmap_read(regmap, PMC_PLL_ISR0, &status);
62
63 return !!(status & BIT(id));
64 }
65
sam9x60_pll_prepare(struct clk_hw * hw)66 static int sam9x60_pll_prepare(struct clk_hw *hw)
67 {
68 struct sam9x60_pll *pll = to_sam9x60_pll(hw);
69 struct regmap *regmap = pll->regmap;
70 unsigned long flags;
71 u8 div;
72 u16 mul;
73 u32 val;
74
75 spin_lock_irqsave(pll->lock, flags);
76 regmap_write(regmap, PMC_PLL_UPDT, pll->id);
77
78 regmap_read(regmap, PMC_PLL_CTRL0, &val);
79 div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
80
81 regmap_read(regmap, PMC_PLL_CTRL1, &val);
82 mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
83
84 if (sam9x60_pll_ready(regmap, pll->id) &&
85 (div == pll->div && mul == pll->mul)) {
86 spin_unlock_irqrestore(pll->lock, flags);
87 return 0;
88 }
89
90 /* Recommended value for PMC_PLL_ACR */
91 val = PMC_PLL_ACR_DEFAULT;
92 regmap_write(regmap, PMC_PLL_ACR, val);
93
94 regmap_write(regmap, PMC_PLL_CTRL1,
95 FIELD_PREP(PMC_PLL_CTRL1_MUL_MSK, pll->mul));
96
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);
101
102 udelay(10);
103
104 /* Enable the UTMI internal regulator */
105 val |= PMC_PLL_ACR_UTMIVR;
106 regmap_write(regmap, PMC_PLL_ACR, val);
107
108 udelay(10);
109 }
110
111 regmap_update_bits(regmap, PMC_PLL_UPDT,
112 PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
113
114 regmap_write(regmap, PMC_PLL_CTRL0,
115 PMC_PLL_CTRL0_ENLOCK | PMC_PLL_CTRL0_ENPLL |
116 PMC_PLL_CTRL0_ENPLLCK | pll->div);
117
118 regmap_update_bits(regmap, PMC_PLL_UPDT,
119 PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
120
121 while (!sam9x60_pll_ready(regmap, pll->id))
122 cpu_relax();
123
124 spin_unlock_irqrestore(pll->lock, flags);
125
126 return 0;
127 }
128
sam9x60_pll_is_prepared(struct clk_hw * hw)129 static int sam9x60_pll_is_prepared(struct clk_hw *hw)
130 {
131 struct sam9x60_pll *pll = to_sam9x60_pll(hw);
132
133 return sam9x60_pll_ready(pll->regmap, pll->id);
134 }
135
sam9x60_pll_unprepare(struct clk_hw * hw)136 static void sam9x60_pll_unprepare(struct clk_hw *hw)
137 {
138 struct sam9x60_pll *pll = to_sam9x60_pll(hw);
139 unsigned long flags;
140
141 spin_lock_irqsave(pll->lock, flags);
142
143 regmap_write(pll->regmap, PMC_PLL_UPDT, pll->id);
144
145 regmap_update_bits(pll->regmap, PMC_PLL_CTRL0,
146 PMC_PLL_CTRL0_ENPLLCK, 0);
147
148 regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
149 PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
150
151 regmap_update_bits(pll->regmap, PMC_PLL_CTRL0, PMC_PLL_CTRL0_ENPLL, 0);
152
153 if (pll->characteristics->upll)
154 regmap_update_bits(pll->regmap, PMC_PLL_ACR,
155 PMC_PLL_ACR_UTMIBG | PMC_PLL_ACR_UTMIVR, 0);
156
157 regmap_update_bits(pll->regmap, PMC_PLL_UPDT,
158 PMC_PLL_UPDT_UPDATE, PMC_PLL_UPDT_UPDATE);
159
160 spin_unlock_irqrestore(pll->lock, flags);
161 }
162
sam9x60_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)163 static unsigned long sam9x60_pll_recalc_rate(struct clk_hw *hw,
164 unsigned long parent_rate)
165 {
166 struct sam9x60_pll *pll = to_sam9x60_pll(hw);
167
168 return (parent_rate * (pll->mul + 1)) / (pll->div + 1);
169 }
170
sam9x60_pll_get_best_div_mul(struct sam9x60_pll * pll,unsigned long rate,unsigned long parent_rate,bool update)171 static long sam9x60_pll_get_best_div_mul(struct sam9x60_pll *pll,
172 unsigned long rate,
173 unsigned long parent_rate,
174 bool update)
175 {
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;
184
185 if (rate < characteristics->output[0].min ||
186 rate > characteristics->output[0].max)
187 return -ERANGE;
188
189 if (!pll->characteristics->upll) {
190 mindiv = parent_rate / rate;
191 if (mindiv < 2)
192 mindiv = 2;
193
194 maxdiv = DIV_ROUND_UP(parent_rate * PLL_MUL_MAX, rate);
195 if (maxdiv > PLL_DIV_MAX)
196 maxdiv = PLL_DIV_MAX;
197 } else {
198 mindiv = maxdiv = UPLL_DIV;
199 }
200
201 for (tmpdiv = mindiv; tmpdiv <= maxdiv; tmpdiv++) {
202 unsigned long remainder;
203 unsigned long tmprate;
204 unsigned long tmpmul;
205 unsigned long tmpfrac = 0;
206
207 /*
208 * Calculate the multiplier associated with the current
209 * divider that provide the closest rate to the requested one.
210 */
211 tmpmul = mult_frac(rate, tmpdiv, parent_rate);
212 tmprate = mult_frac(parent_rate, tmpmul, tmpdiv);
213 remainder = rate - tmprate;
214
215 if (remainder) {
216 tmpfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * tmpdiv * (1 << 22),
217 parent_rate);
218
219 tmprate += DIV_ROUND_CLOSEST_ULL((u64)tmpfrac * parent_rate,
220 tmpdiv * (1 << 22));
221
222 if (tmprate > rate)
223 remainder = tmprate - rate;
224 else
225 remainder = rate - tmprate;
226 }
227
228 /*
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.
232 */
233 if (remainder < bestremainder) {
234 bestremainder = remainder;
235 bestdiv = tmpdiv;
236 bestmul = tmpmul;
237 bestrate = tmprate;
238 bestfrac = tmpfrac;
239 }
240
241 /* We've found a perfect match! */
242 if (!remainder)
243 break;
244 }
245
246 /* Check if bestrate is a valid output rate */
247 if (bestrate < characteristics->output[0].min &&
248 bestrate > characteristics->output[0].max)
249 return -ERANGE;
250
251 if (update) {
252 pll->div = bestdiv - 1;
253 pll->mul = bestmul - 1;
254 pll->frac = bestfrac;
255 }
256
257 return bestrate;
258 }
259
sam9x60_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)260 static long sam9x60_pll_round_rate(struct clk_hw *hw, unsigned long rate,
261 unsigned long *parent_rate)
262 {
263 struct sam9x60_pll *pll = to_sam9x60_pll(hw);
264
265 return sam9x60_pll_get_best_div_mul(pll, rate, *parent_rate, false);
266 }
267
sam9x60_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)268 static int sam9x60_pll_set_rate(struct clk_hw *hw, unsigned long rate,
269 unsigned long parent_rate)
270 {
271 struct sam9x60_pll *pll = to_sam9x60_pll(hw);
272
273 return sam9x60_pll_get_best_div_mul(pll, rate, parent_rate, true);
274 }
275
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,
283 };
284
285 struct clk_hw * __init
sam9x60_clk_register_pll(struct regmap * regmap,spinlock_t * lock,const char * name,const char * parent_name,u8 id,const struct clk_pll_characteristics * characteristics)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)
289 {
290 struct sam9x60_pll *pll;
291 struct clk_hw *hw;
292 struct clk_init_data init;
293 unsigned int pllr;
294 int ret;
295
296 if (id > PLL_MAX_ID)
297 return ERR_PTR(-EINVAL);
298
299 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
300 if (!pll)
301 return ERR_PTR(-ENOMEM);
302
303 init.name = name;
304 init.ops = &pll_ops;
305 init.parent_names = &parent_name;
306 init.num_parents = 1;
307 init.flags = CLK_SET_RATE_GATE;
308
309 pll->id = id;
310 pll->hw.init = &init;
311 pll->characteristics = characteristics;
312 pll->regmap = regmap;
313 pll->lock = lock;
314
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);
320
321 hw = &pll->hw;
322 ret = clk_hw_register(NULL, hw);
323 if (ret) {
324 kfree(pll);
325 hw = ERR_PTR(ret);
326 }
327
328 return hw;
329 }
330
331