Merge tag 'u-boot-stm32-20211012' of https://source.denx.de/u-boot/custodians/u-boot-stm
[platform/kernel/u-boot.git] / drivers / clk / at91 / clk-sam9x60-pll.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * SAM9X60's PLL clock support.
4  *
5  * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries
6  *
7  * Author: Claudiu Beznea <claudiu.beznea@microchip.com>
8  *
9  * Based on drivers/clk/at91/clk-sam9x60-pll.c from Linux.
10  *
11  */
12
13 #include <asm/processor.h>
14 #include <common.h>
15 #include <clk-uclass.h>
16 #include <div64.h>
17 #include <dm.h>
18 #include <linux/clk-provider.h>
19 #include <linux/clk/at91_pmc.h>
20 #include <linux/delay.h>
21
22 #include "pmc.h"
23
24 #define UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL       "at91-sam9x60-div-pll-clk"
25 #define UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL      "at91-sam9x60-frac-pll-clk"
26
27 #define PMC_PLL_CTRL0_DIV_MSK   GENMASK(7, 0)
28 #define PMC_PLL_CTRL1_MUL_MSK   GENMASK(31, 24)
29 #define PMC_PLL_CTRL1_FRACR_MSK GENMASK(21, 0)
30
31 #define PLL_DIV_MAX             (FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
32 #define UPLL_DIV                2
33 #define PLL_MUL_MAX             (FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
34
35 #define FCORE_MIN               (600000000)
36 #define FCORE_MAX               (1200000000)
37
38 #define PLL_MAX_ID              7
39
40 struct sam9x60_pll {
41         void __iomem *base;
42         const struct clk_pll_characteristics *characteristics;
43         const struct clk_pll_layout *layout;
44         struct clk clk;
45         u8 id;
46 };
47
48 #define to_sam9x60_pll(_clk)    container_of(_clk, struct sam9x60_pll, clk)
49
50 static inline bool sam9x60_pll_ready(void __iomem *base, int id)
51 {
52         unsigned int status;
53
54         pmc_read(base, AT91_PMC_PLL_ISR0, &status);
55
56         return !!(status & BIT(id));
57 }
58
59 static long sam9x60_frac_pll_compute_mul_frac(u32 *mul, u32 *frac, ulong rate,
60                                               ulong parent_rate)
61 {
62         unsigned long tmprate, remainder;
63         unsigned long nmul = 0;
64         unsigned long nfrac = 0;
65
66         if (rate < FCORE_MIN || rate > FCORE_MAX)
67                 return -ERANGE;
68
69         /*
70          * Calculate the multiplier associated with the current
71          * divider that provide the closest rate to the requested one.
72          */
73         nmul = mult_frac(rate, 1, parent_rate);
74         tmprate = mult_frac(parent_rate, nmul, 1);
75         remainder = rate - tmprate;
76
77         if (remainder) {
78                 nfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * (1 << 22),
79                                               parent_rate);
80
81                 tmprate += DIV_ROUND_CLOSEST_ULL((u64)nfrac * parent_rate,
82                                                  (1 << 22));
83         }
84
85         /* Check if resulted rate is valid.  */
86         if (tmprate < FCORE_MIN || tmprate > FCORE_MAX)
87                 return -ERANGE;
88
89         *mul = nmul - 1;
90         *frac = nfrac;
91
92         return tmprate;
93 }
94
95 static ulong sam9x60_frac_pll_set_rate(struct clk *clk, ulong rate)
96 {
97         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
98         void __iomem *base = pll->base;
99         ulong parent_rate = clk_get_parent_rate(clk);
100         u32 nmul, cmul, nfrac, cfrac, val;
101         bool ready = sam9x60_pll_ready(base, pll->id);
102         long ret;
103
104         if (!parent_rate)
105                 return 0;
106
107         ret = sam9x60_frac_pll_compute_mul_frac(&nmul, &nfrac, rate,
108                                                 parent_rate);
109         if (ret < 0)
110                 return 0;
111
112         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
113                         pll->id);
114         pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
115         cmul = (val & pll->layout->mul_mask) >> pll->layout->mul_shift;
116         cfrac = (val & pll->layout->frac_mask) >> pll->layout->frac_shift;
117
118         /* Check against current values. */
119         if (sam9x60_pll_ready(base, pll->id) &&
120             nmul == cmul && nfrac == cfrac)
121                 return 0;
122
123         /* Update it to hardware. */
124         pmc_write(base, AT91_PMC_PLL_CTRL1,
125                   (nmul << pll->layout->mul_shift) |
126                   (nfrac << pll->layout->frac_shift));
127
128         pmc_update_bits(base, AT91_PMC_PLL_UPDT,
129                         AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
130                         AT91_PMC_PLL_UPDT_UPDATE | pll->id);
131
132         while (ready && !sam9x60_pll_ready(base, pll->id)) {
133                 debug("waiting for pll %u...\n", pll->id);
134                 cpu_relax();
135         }
136
137         return parent_rate * (nmul + 1) + ((u64)parent_rate * nfrac >> 22);
138 }
139
140 static ulong sam9x60_frac_pll_get_rate(struct clk *clk)
141 {
142         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
143         void __iomem *base = pll->base;
144         ulong parent_rate = clk_get_parent_rate(clk);
145         u32 mul, frac, val;
146
147         if (!parent_rate)
148                 return 0;
149
150         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
151                         pll->id);
152         pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
153         mul = (val & pll->layout->mul_mask) >> pll->layout->mul_shift;
154         frac = (val & pll->layout->frac_mask) >> pll->layout->frac_shift;
155
156         return (parent_rate * (mul + 1) + ((u64)parent_rate * frac >> 22));
157 }
158
159 static int sam9x60_frac_pll_enable(struct clk *clk)
160 {
161         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
162         void __iomem *base = pll->base;
163         unsigned int val;
164         ulong crate;
165
166         crate = sam9x60_frac_pll_get_rate(clk);
167         if (crate < FCORE_MIN || crate > FCORE_MAX)
168                 return -ERANGE;
169
170         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
171                         pll->id);
172         pmc_read(base, AT91_PMC_PLL_CTRL1, &val);
173
174         if (sam9x60_pll_ready(base, pll->id))
175                 return 0;
176
177         pmc_update_bits(base, AT91_PMC_PLL_UPDT,
178                         AT91_PMC_PMM_UPDT_STUPTIM_MSK |
179                         AT91_PMC_PLL_UPDT_ID_MSK,
180                         AT91_PMC_PLL_UPDT_STUPTIM(0x3f) | pll->id);
181
182         /* Recommended value for AT91_PMC_PLL_ACR */
183         if (pll->characteristics->upll)
184                 val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;
185         else
186                 val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;
187         pmc_write(base, AT91_PMC_PLL_ACR, val);
188
189         if (pll->characteristics->upll) {
190                 /* Enable the UTMI internal bandgap */
191                 val |= AT91_PMC_PLL_ACR_UTMIBG;
192                 pmc_write(base, AT91_PMC_PLL_ACR, val);
193
194                 udelay(10);
195
196                 /* Enable the UTMI internal regulator */
197                 val |= AT91_PMC_PLL_ACR_UTMIVR;
198                 pmc_write(base, AT91_PMC_PLL_ACR, val);
199
200                 udelay(10);
201
202                 pmc_update_bits(base, AT91_PMC_PLL_UPDT,
203                                 AT91_PMC_PLL_UPDT_UPDATE |
204                                 AT91_PMC_PLL_UPDT_ID_MSK,
205                                 AT91_PMC_PLL_UPDT_UPDATE | pll->id);
206         }
207
208         pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
209                         AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
210                         AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
211
212         pmc_update_bits(base, AT91_PMC_PLL_UPDT,
213                         AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
214                         AT91_PMC_PLL_UPDT_UPDATE | pll->id);
215
216         while (!sam9x60_pll_ready(base, pll->id)) {
217                 debug("waiting for pll %u...\n", pll->id);
218                 cpu_relax();
219         }
220
221         return 0;
222 }
223
224 static int sam9x60_frac_pll_disable(struct clk *clk)
225 {
226         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
227         void __iomem *base = pll->base;
228
229         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
230                         pll->id);
231
232         pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
233                         AT91_PMC_PLL_CTRL0_ENPLL, 0);
234
235         if (pll->characteristics->upll)
236                 pmc_update_bits(base, AT91_PMC_PLL_ACR,
237                                 AT91_PMC_PLL_ACR_UTMIBG |
238                                 AT91_PMC_PLL_ACR_UTMIVR, 0);
239
240         pmc_update_bits(base, AT91_PMC_PLL_UPDT,
241                         AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
242                         AT91_PMC_PLL_UPDT_UPDATE | pll->id);
243
244         return 0;
245 }
246
247 static const struct clk_ops sam9x60_frac_pll_ops = {
248         .enable = sam9x60_frac_pll_enable,
249         .disable = sam9x60_frac_pll_disable,
250         .set_rate = sam9x60_frac_pll_set_rate,
251         .get_rate = sam9x60_frac_pll_get_rate,
252 };
253
254 static int sam9x60_div_pll_enable(struct clk *clk)
255 {
256         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
257         void __iomem *base = pll->base;
258         unsigned int val;
259
260         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
261                         pll->id);
262         pmc_read(base, AT91_PMC_PLL_CTRL0, &val);
263
264         /* Stop if enabled. */
265         if (val & pll->layout->endiv_mask)
266                 return 0;
267
268         pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
269                         pll->layout->endiv_mask,
270                         (1 << pll->layout->endiv_shift));
271
272         pmc_update_bits(base, AT91_PMC_PLL_UPDT,
273                         AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
274                         AT91_PMC_PLL_UPDT_UPDATE | pll->id);
275
276         while (!sam9x60_pll_ready(base, pll->id)) {
277                 debug("waiting for pll %u...\n", pll->id);
278                 cpu_relax();
279         }
280
281         return 0;
282 }
283
284 static int sam9x60_div_pll_disable(struct clk *clk)
285 {
286         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
287         void __iomem *base = pll->base;
288
289         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
290                         pll->id);
291
292         pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
293                         pll->layout->endiv_mask, 0);
294
295         pmc_update_bits(base, AT91_PMC_PLL_UPDT,
296                         AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
297                         AT91_PMC_PLL_UPDT_UPDATE | pll->id);
298
299         return 0;
300 }
301
302 static ulong sam9x60_div_pll_set_rate(struct clk *clk, ulong rate)
303 {
304         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
305         void __iomem *base = pll->base;
306         const struct clk_pll_characteristics *characteristics =
307                                                         pll->characteristics;
308         ulong parent_rate = clk_get_parent_rate(clk);
309         u8 div = DIV_ROUND_CLOSEST_ULL(parent_rate, rate) - 1;
310         ulong req_rate = parent_rate / (div + 1);
311         bool ready = sam9x60_pll_ready(base, pll->id);
312         u32 val;
313
314         if (!parent_rate || div > pll->layout->div_mask ||
315             req_rate < characteristics->output[0].min ||
316             req_rate > characteristics->output[0].max)
317                 return 0;
318
319         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
320                         pll->id);
321         pmc_read(base, AT91_PMC_PLL_CTRL0, &val);
322         /* Compare against current value. */
323         if (div == ((val & pll->layout->div_mask) >> pll->layout->div_shift))
324                 return 0;
325
326         /* Update it to hardware. */
327         pmc_update_bits(base, AT91_PMC_PLL_CTRL0,
328                         pll->layout->div_mask,
329                         div << pll->layout->div_shift);
330
331         pmc_update_bits(base, AT91_PMC_PLL_UPDT,
332                         AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
333                         AT91_PMC_PLL_UPDT_UPDATE | pll->id);
334
335         while (ready && !sam9x60_pll_ready(base, pll->id)) {
336                 debug("waiting for pll %u...\n", pll->id);
337                 cpu_relax();
338         }
339
340         return req_rate;
341 }
342
343 static ulong sam9x60_div_pll_get_rate(struct clk *clk)
344 {
345         struct sam9x60_pll *pll = to_sam9x60_pll(clk);
346         void __iomem *base = pll->base;
347         ulong parent_rate = clk_get_parent_rate(clk);
348         u32 val;
349         u8 div;
350
351         if (!parent_rate)
352                 return 0;
353
354         pmc_update_bits(base, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
355                         pll->id);
356
357         pmc_read(base, AT91_PMC_PLL_CTRL0, &val);
358
359         div = (val & pll->layout->div_mask) >> pll->layout->div_shift;
360
361         return parent_rate / (div + 1);
362 }
363
364 static const struct clk_ops sam9x60_div_pll_ops = {
365         .enable = sam9x60_div_pll_enable,
366         .disable = sam9x60_div_pll_disable,
367         .set_rate = sam9x60_div_pll_set_rate,
368         .get_rate = sam9x60_div_pll_get_rate,
369 };
370
371 static struct clk *
372 sam9x60_clk_register_pll(void __iomem *base, const char *type,
373                          const char *name, const char *parent_name, u8 id,
374                          const struct clk_pll_characteristics *characteristics,
375                          const struct clk_pll_layout *layout, u32 flags)
376 {
377         struct sam9x60_pll *pll;
378         struct clk *clk;
379         int ret;
380
381         if (!base || !type || !name || !parent_name || !characteristics ||
382             !layout || id > PLL_MAX_ID)
383                 return ERR_PTR(-EINVAL);
384
385         pll = kzalloc(sizeof(*pll), GFP_KERNEL);
386         if (!pll)
387                 return ERR_PTR(-ENOMEM);
388
389         pll->id = id;
390         pll->characteristics = characteristics;
391         pll->layout = layout;
392         pll->base = base;
393         clk = &pll->clk;
394         clk->flags = flags;
395
396         ret = clk_register(clk, type, name, parent_name);
397         if (ret) {
398                 kfree(pll);
399                 clk = ERR_PTR(ret);
400         }
401
402         return clk;
403 }
404
405 struct clk *
406 sam9x60_clk_register_div_pll(void __iomem *base, const char *name,
407                              const char *parent_name, u8 id,
408                              const struct clk_pll_characteristics *characteristics,
409                              const struct clk_pll_layout *layout, bool critical)
410 {
411         return sam9x60_clk_register_pll(base,
412                 UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL, name, parent_name, id,
413                 characteristics, layout,
414                 CLK_GET_RATE_NOCACHE | (critical ? CLK_IS_CRITICAL : 0));
415 }
416
417 struct clk *
418 sam9x60_clk_register_frac_pll(void __iomem *base, const char *name,
419                               const char *parent_name, u8 id,
420                               const struct clk_pll_characteristics *characteristics,
421                               const struct clk_pll_layout *layout, bool critical)
422 {
423         return sam9x60_clk_register_pll(base,
424                 UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL, name, parent_name, id,
425                 characteristics, layout,
426                 CLK_GET_RATE_NOCACHE | (critical ? CLK_IS_CRITICAL : 0));
427 }
428
429 U_BOOT_DRIVER(at91_sam9x60_div_pll_clk) = {
430         .name = UBOOT_DM_CLK_AT91_SAM9X60_DIV_PLL,
431         .id = UCLASS_CLK,
432         .ops = &sam9x60_div_pll_ops,
433         .flags = DM_FLAG_PRE_RELOC,
434 };
435
436 U_BOOT_DRIVER(at91_sam9x60_frac_pll_clk) = {
437         .name = UBOOT_DM_CLK_AT91_SAM9X60_FRAC_PLL,
438         .id = UCLASS_CLK,
439         .ops = &sam9x60_frac_pll_ops,
440         .flags = DM_FLAG_PRE_RELOC,
441 };