1 // SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause
2 /*
3 * Copyright (C) 2016 Atmel Corporation,
4 * Songjun Wu <songjun.wu@atmel.com>,
5 * Nicolas Ferre <nicolas.ferre@atmel.com>
6 * Copyright (C) 2017 Free Electrons,
7 * Quentin Schulz <quentin.schulz@free-electrons.com>
8 *
9 * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent
10 * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of
11 * its own parent. PMC and PAD can then divide the FRAC rate to best match the
12 * asked rate.
13 *
14 * Traits of FRAC clock:
15 * enable - clk_enable writes nd, fracr parameters and enables PLL
16 * rate - rate is adjustable.
17 * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22))
18 * parent - fixed parent. No clk_set_parent support
19 *
20 * Traits of PMC clock:
21 * enable - clk_enable writes qdpmc, and enables PMC output
22 * rate - rate is adjustable.
23 * clk->rate = parent->rate / (qdpmc + 1)
24 * parent - fixed parent. No clk_set_parent support
25 *
26 * Traits of PAD clock:
27 * enable - clk_enable writes divisors and enables PAD output
28 * rate - rate is adjustable.
29 * clk->rate = parent->rate / (qdaudio * div))
30 * parent - fixed parent. No clk_set_parent support
31 */
32
33 #include <io.h>
34 #include <kernel/delay.h>
35 #include <kernel/panic.h>
36 #include <mm/core_memprot.h>
37 #include <string.h>
38 #include <types_ext.h>
39
40 #include "at91_clk.h"
41
42 #define AUDIO_PLL_DIV_FRAC BIT(22)
43 #define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \
44 AT91_PMC_AUDIO_PLL_ND_OFFSET)
45
46 #define AUDIO_PLL_QDPAD(qd, div) \
47 ((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \
48 AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \
49 (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \
50 AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK))
51
52 #define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \
53 AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
54
55 #define AUDIO_PLL_FOUT_MIN 620000000UL
56 #define AUDIO_PLL_FOUT_MAX 700000000UL
57
58 struct clk_audio_frac {
59 vaddr_t base;
60 uint32_t fracr;
61 uint8_t nd;
62 };
63
64 struct clk_audio_pad {
65 vaddr_t base;
66 uint8_t qdaudio;
67 uint8_t div;
68 };
69
70 struct clk_audio_pmc {
71 vaddr_t base;
72 uint8_t qdpmc;
73 };
74
clk_audio_pll_frac_enable(struct clk * clk)75 static TEE_Result clk_audio_pll_frac_enable(struct clk *clk)
76 {
77 struct clk_audio_frac *frac = clk->priv;
78
79 io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0,
80 AT91_PMC_AUDIO_PLL_RESETN);
81 io_setbits32(frac->base + AT91_PMC_AUDIO_PLL0,
82 AT91_PMC_AUDIO_PLL_RESETN);
83 io_clrsetbits32(frac->base + AT91_PMC_AUDIO_PLL1,
84 AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr);
85
86 /*
87 * reset and enable have to be done in 2 separated writes
88 * for AT91_PMC_AUDIO_PLL0
89 */
90 io_clrsetbits32(frac->base + AT91_PMC_AUDIO_PLL0,
91 AT91_PMC_AUDIO_PLL_PLLEN |
92 AT91_PMC_AUDIO_PLL_ND_MASK,
93 AT91_PMC_AUDIO_PLL_PLLEN |
94 AT91_PMC_AUDIO_PLL_ND(frac->nd));
95
96 return TEE_SUCCESS;
97 }
98
clk_audio_pll_pad_enable(struct clk * clk)99 static TEE_Result clk_audio_pll_pad_enable(struct clk *clk)
100 {
101 struct clk_audio_pad *apad_ck = clk->priv;
102
103 io_clrsetbits32(apad_ck->base + AT91_PMC_AUDIO_PLL1,
104 AT91_PMC_AUDIO_PLL_QDPAD_MASK,
105 AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div));
106 io_clrsetbits32(apad_ck->base + AT91_PMC_AUDIO_PLL0,
107 AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN);
108
109 return TEE_SUCCESS;
110 }
111
clk_audio_pll_pmc_enable(struct clk * clk)112 static TEE_Result clk_audio_pll_pmc_enable(struct clk *clk)
113 {
114 struct clk_audio_pmc *apmc_ck = clk->priv;
115
116 io_clrsetbits32(apmc_ck->base + AT91_PMC_AUDIO_PLL0,
117 AT91_PMC_AUDIO_PLL_PMCEN |
118 AT91_PMC_AUDIO_PLL_QDPMC_MASK,
119 AT91_PMC_AUDIO_PLL_PMCEN |
120 AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc));
121 return TEE_SUCCESS;
122 }
123
clk_audio_pll_frac_disable(struct clk * clk)124 static void clk_audio_pll_frac_disable(struct clk *clk)
125 {
126 struct clk_audio_frac *frac = clk->priv;
127
128 io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0,
129 AT91_PMC_AUDIO_PLL_PLLEN);
130 /* Requires 2 separated writes */
131 io_clrbits32(frac->base + AT91_PMC_AUDIO_PLL0,
132 AT91_PMC_AUDIO_PLL_RESETN);
133 }
134
clk_audio_pll_pad_disable(struct clk * clk)135 static void clk_audio_pll_pad_disable(struct clk *clk)
136 {
137 struct clk_audio_pad *apad_ck = clk->priv;
138
139 io_clrbits32(apad_ck->base + AT91_PMC_AUDIO_PLL0,
140 AT91_PMC_AUDIO_PLL_PADEN);
141 }
142
clk_audio_pll_pmc_disable(struct clk * clk)143 static void clk_audio_pll_pmc_disable(struct clk *clk)
144 {
145 struct clk_audio_pmc *apmc_ck = clk->priv;
146
147 io_clrbits32(apmc_ck->base + AT91_PMC_AUDIO_PLL0,
148 AT91_PMC_AUDIO_PLL_PMCEN);
149 }
150
clk_audio_pll_fout(unsigned long parent_rate,unsigned long nd,unsigned long fracr)151 static unsigned long clk_audio_pll_fout(unsigned long parent_rate,
152 unsigned long nd, unsigned long fracr)
153 {
154 unsigned long long fr = (unsigned long long)parent_rate * fracr;
155
156 fr = UDIV_ROUND_NEAREST(fr, AUDIO_PLL_DIV_FRAC);
157
158 return parent_rate * (nd + 1) + fr;
159 }
160
clk_audio_pll_frac_get_rate(struct clk * clk,unsigned long parent_rate)161 static unsigned long clk_audio_pll_frac_get_rate(struct clk *clk,
162 unsigned long parent_rate)
163 {
164 struct clk_audio_frac *frac = clk->priv;
165
166 return clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr);
167 }
168
clk_audio_pll_pad_get_rate(struct clk * clk,unsigned long parent_rate)169 static unsigned long clk_audio_pll_pad_get_rate(struct clk *clk,
170 unsigned long parent_rate)
171 {
172 struct clk_audio_pad *apad_ck = clk->priv;
173 unsigned long apad_rate = 0;
174
175 if (apad_ck->qdaudio && apad_ck->div)
176 apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div);
177
178 return apad_rate;
179 }
180
clk_audio_pll_pmc_get_rate(struct clk * clk,unsigned long parent_rate)181 static unsigned long clk_audio_pll_pmc_get_rate(struct clk *clk,
182 unsigned long parent_rate)
183 {
184 struct clk_audio_pmc *apmc_ck = clk->priv;
185
186 return parent_rate / (apmc_ck->qdpmc + 1);
187 }
188
clk_audio_pll_frac_compute_frac(unsigned long rate,unsigned long parent_rate,unsigned long * nd,unsigned long * fracr)189 static TEE_Result clk_audio_pll_frac_compute_frac(unsigned long rate,
190 unsigned long parent_rate,
191 unsigned long *nd,
192 unsigned long *fracr)
193 {
194 unsigned long long tmp = 0;
195 unsigned long long rem = 0;
196
197 if (!rate || !parent_rate)
198 return TEE_ERROR_BAD_PARAMETERS;
199
200 tmp = rate;
201 rem = tmp % parent_rate;
202 tmp /= parent_rate;
203 if (!tmp || tmp >= AUDIO_PLL_ND_MAX)
204 return TEE_ERROR_BAD_PARAMETERS;
205
206 *nd = tmp - 1;
207
208 tmp = rem * AUDIO_PLL_DIV_FRAC;
209 tmp = UDIV_ROUND_NEAREST(tmp, parent_rate);
210 if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK)
211 return TEE_ERROR_BAD_PARAMETERS;
212
213 /* we can cast here as we verified the bounds just above */
214 *fracr = (unsigned long)tmp;
215
216 return TEE_SUCCESS;
217 }
218
clk_audio_pll_frac_set_rate(struct clk * clk,unsigned long rate,unsigned long parent_rate)219 static TEE_Result clk_audio_pll_frac_set_rate(struct clk *clk,
220 unsigned long rate,
221 unsigned long parent_rate)
222 {
223 struct clk_audio_frac *frac = clk->priv;
224 unsigned long fracr = 0;
225 unsigned long nd = 0;
226 TEE_Result res = TEE_ERROR_GENERIC;
227
228 if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX)
229 return TEE_ERROR_BAD_PARAMETERS;
230
231 res = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr);
232 if (res)
233 return res;
234
235 frac->nd = nd;
236 frac->fracr = fracr;
237
238 return TEE_SUCCESS;
239 }
240
clk_audio_pll_pad_set_rate(struct clk * clk,unsigned long rate,unsigned long parent_rate)241 static TEE_Result clk_audio_pll_pad_set_rate(struct clk *clk,
242 unsigned long rate,
243 unsigned long parent_rate)
244 {
245 struct clk_audio_pad *apad_ck = clk->priv;
246 uint8_t tmp_div = 1;
247
248 if (!rate)
249 return TEE_ERROR_BAD_PARAMETERS;
250
251 tmp_div = parent_rate / rate;
252 if (tmp_div % 3 == 0) {
253 apad_ck->qdaudio = tmp_div / 3;
254 apad_ck->div = 3;
255 } else {
256 apad_ck->qdaudio = tmp_div / 2;
257 apad_ck->div = 2;
258 }
259
260 return TEE_SUCCESS;
261 }
262
clk_audio_pll_pmc_set_rate(struct clk * clk,unsigned long rate,unsigned long parent_rate)263 static TEE_Result clk_audio_pll_pmc_set_rate(struct clk *clk,
264 unsigned long rate,
265 unsigned long parent_rate)
266 {
267 struct clk_audio_pmc *apmc_ck = clk->priv;
268
269 if (!rate)
270 return TEE_ERROR_BAD_PARAMETERS;
271
272 apmc_ck->qdpmc = parent_rate / rate - 1;
273
274 return TEE_SUCCESS;
275 }
276
277 static const struct clk_ops audio_pll_frac_ops = {
278 .enable = clk_audio_pll_frac_enable,
279 .disable = clk_audio_pll_frac_disable,
280 .get_rate = clk_audio_pll_frac_get_rate,
281 .set_rate = clk_audio_pll_frac_set_rate,
282 };
283
284 static const struct clk_ops audio_pll_pad_ops = {
285 .enable = clk_audio_pll_pad_enable,
286 .disable = clk_audio_pll_pad_disable,
287 .get_rate = clk_audio_pll_pad_get_rate,
288 .set_rate = clk_audio_pll_pad_set_rate,
289 };
290
291 static const struct clk_ops audio_pll_pmc_ops = {
292 .enable = clk_audio_pll_pmc_enable,
293 .disable = clk_audio_pll_pmc_disable,
294 .get_rate = clk_audio_pll_pmc_get_rate,
295 .set_rate = clk_audio_pll_pmc_set_rate,
296 };
297
298 struct clk *
at91_clk_register_audio_pll_frac(struct pmc_data * pmc,const char * name,struct clk * parent)299 at91_clk_register_audio_pll_frac(struct pmc_data *pmc, const char *name,
300 struct clk *parent)
301 {
302 struct clk_audio_frac *frac_ck = NULL;
303 struct clk *clk = NULL;
304
305 clk = clk_alloc(name, &audio_pll_frac_ops, &parent, 1);
306 if (!clk)
307 return NULL;
308
309 frac_ck = calloc(1, sizeof(*frac_ck));
310 if (!frac_ck) {
311 clk_free(clk);
312 return NULL;
313 }
314
315 clk->flags = CLK_SET_RATE_GATE;
316
317 frac_ck->base = pmc->base;
318
319 clk->priv = frac_ck;
320 if (clk_register(clk)) {
321 clk_free(clk);
322 free(frac_ck);
323 return NULL;
324 }
325
326 return clk;
327 }
328
329 struct clk *
at91_clk_register_audio_pll_pad(struct pmc_data * pmc,const char * name,struct clk * parent)330 at91_clk_register_audio_pll_pad(struct pmc_data *pmc, const char *name,
331 struct clk *parent)
332 {
333 struct clk_audio_pad *apad_ck = NULL;
334 struct clk *clk = NULL;
335
336 clk = clk_alloc(name, &audio_pll_pad_ops, &parent, 1);
337 if (!clk)
338 return NULL;
339
340 apad_ck = calloc(1, sizeof(*apad_ck));
341 if (!apad_ck) {
342 clk_free(clk);
343 return NULL;
344 }
345
346 clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
347
348 apad_ck->base = pmc->base;
349
350 clk->priv = apad_ck;
351 if (clk_register(clk)) {
352 clk_free(clk);
353 free(apad_ck);
354 return NULL;
355 }
356
357 return clk;
358 }
359
360 struct clk *
at91_clk_register_audio_pll_pmc(struct pmc_data * pmc,const char * name,struct clk * parent)361 at91_clk_register_audio_pll_pmc(struct pmc_data *pmc, const char *name,
362 struct clk *parent)
363 {
364 struct clk_audio_pmc *apmc_ck = NULL;
365 struct clk *clk = NULL;
366
367 clk = clk_alloc(name, &audio_pll_pmc_ops, &parent, 1);
368 if (!clk)
369 return NULL;
370
371 apmc_ck = calloc(1, sizeof(*apmc_ck));
372 if (!apmc_ck) {
373 clk_free(clk);
374 return NULL;
375 }
376
377 clk->flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
378
379 apmc_ck->base = pmc->base;
380
381 clk->priv = apmc_ck;
382
383 if (clk_register(clk)) {
384 clk_free(clk);
385 free(apmc_ck);
386 return NULL;
387 }
388
389 return clk;
390 }
391