File Index
Files and directories
Sign in
FILE

clk-sam9x60-pll.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/at91/clk-sam9x60-pll.c C
  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.h>
  9#include <linux/clk-provider.h>
 10#include <linux/clkdev.h>
 11#include <linux/clk/at91_pmc.h>
 12#include <linux/of.h>
 13#include <linux/mfd/syscon.h>
 14#include <linux/regmap.h>
 15
 16#include "pmc.h"
 17
 18#define	PMC_PLL_CTRL0_DIV_MSK	GENMASK(7, 0)
 19#define	PMC_PLL_CTRL1_MUL_MSK	GENMASK(31, 24)
 20#define	PMC_PLL_CTRL1_FRACR_MSK	GENMASK(21, 0)
 21
 22#define PLL_DIV_MAX		(FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
 23#define UPLL_DIV		2
 24#define PLL_MUL_MAX		(FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
 25
 26#define PLL_MAX_ID		9
 27
 28struct sam9x60_pll_core {
 29	struct regmap *regmap;
 30	spinlock_t *lock;
 31	const struct clk_pll_characteristics *characteristics;
 32	const struct clk_pll_layout *layout;
 33	struct clk_hw hw;
 34	u8 id;
 35};
 36
 37struct sam9x60_frac {
 38	struct sam9x60_pll_core core;
 39	struct at91_clk_pms pms;
 40	u32 frac;
 41	u16 mul;
 42};
 43
 44struct sam9x60_div {
 45	struct sam9x60_pll_core core;
 46	struct at91_clk_pms pms;
 47	u8 div;
 48	u8 safe_div;
 49};
 50
 51#define to_sam9x60_pll_core(hw)	container_of(hw, struct sam9x60_pll_core, hw)
 52#define to_sam9x60_frac(core)	container_of(core, struct sam9x60_frac, core)
 53#define to_sam9x60_div(core)	container_of(core, struct sam9x60_div, core)
 54
 55static struct sam9x60_div *notifier_div;
 56
 57static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)
 58{
 59	unsigned int status;
 60
 61	regmap_read(regmap, AT91_PMC_PLL_ISR0, &status);
 62
 63	return !!(status & BIT(id));
 64}
 65
 66static bool sam9x60_frac_pll_ready(struct regmap *regmap, u8 id)
 67{
 68	return sam9x60_pll_ready(regmap, id);
 69}
 70
 71static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw,
 72						  unsigned long parent_rate)
 73{
 74	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
 75	struct sam9x60_frac *frac = to_sam9x60_frac(core);
 76	unsigned long freq;
 77
 78	freq = parent_rate * (frac->mul + 1) +
 79		DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22));
 80
 81	if (core->layout->div2)
 82		freq >>= 1;
 83
 84	return freq;
 85}
 86
 87static int sam9x60_frac_pll_set(struct sam9x60_pll_core *core)
 88{
 89	struct sam9x60_frac *frac = to_sam9x60_frac(core);
 90	struct regmap *regmap = core->regmap;
 91	unsigned int val, cfrac, cmul;
 92	unsigned long flags;
 93
 94	spin_lock_irqsave(core->lock, flags);
 95
 96	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
 97			  AT91_PMC_PLL_UPDT_ID_MSK, core->id);
 98	regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
 99	cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
100	cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
101
102	if (sam9x60_frac_pll_ready(regmap, core->id) &&
103	    (cmul == frac->mul && cfrac == frac->frac))
104		goto unlock;
105
106	/* Load recommended value for PMC_PLL_ACR */
107	val = core->characteristics->acr;
108	regmap_write(regmap, AT91_PMC_PLL_ACR, val);
109
110	regmap_write(regmap, AT91_PMC_PLL_CTRL1,
111		     (frac->mul << core->layout->mul_shift) |
112		     (frac->frac << core->layout->frac_shift));
113
114	if (core->characteristics->upll) {
115		/* Enable the UTMI internal bandgap */
116		val |= AT91_PMC_PLL_ACR_UTMIBG;
117		regmap_write(regmap, AT91_PMC_PLL_ACR, val);
118
119		udelay(10);
120
121		/* Enable the UTMI internal regulator */
122		val |= AT91_PMC_PLL_ACR_UTMIVR;
123		regmap_write(regmap, AT91_PMC_PLL_ACR, val);
124
125		udelay(10);
126	}
127
128	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
129			  AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
130			  AT91_PMC_PLL_UPDT_UPDATE | core->id);
131
132	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
133			   AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
134			   AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
135
136	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
137			  AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
138			  AT91_PMC_PLL_UPDT_UPDATE | core->id);
139
140	while (!sam9x60_pll_ready(regmap, core->id))
141		cpu_relax();
142
143unlock:
144	spin_unlock_irqrestore(core->lock, flags);
145
146	return 0;
147}
148
149static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
150{
151	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
152
153	return sam9x60_frac_pll_set(core);
154}
155
156static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
157{
158	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
159	struct regmap *regmap = core->regmap;
160	unsigned long flags;
161
162	spin_lock_irqsave(core->lock, flags);
163
164	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
165			  AT91_PMC_PLL_UPDT_ID_MSK, core->id);
166
167	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENPLL, 0);
168
169	if (core->characteristics->upll)
170		regmap_update_bits(regmap, AT91_PMC_PLL_ACR,
171				   AT91_PMC_PLL_ACR_UTMIBG | AT91_PMC_PLL_ACR_UTMIVR, 0);
172
173	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
174			  AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
175			  AT91_PMC_PLL_UPDT_UPDATE | core->id);
176
177	spin_unlock_irqrestore(core->lock, flags);
178}
179
180static int sam9x60_frac_pll_is_prepared(struct clk_hw *hw)
181{
182	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
183
184	return sam9x60_pll_ready(core->regmap, core->id);
185}
186
187static long sam9x60_frac_pll_compute_mul_frac(struct sam9x60_pll_core *core,
188					      unsigned long rate,
189					      unsigned long parent_rate,
190					      bool update)
191{
192	struct sam9x60_frac *frac = to_sam9x60_frac(core);
193	unsigned long tmprate, remainder;
194	unsigned long nmul = 0;
195	unsigned long nfrac = 0;
196
197	if (rate < core->characteristics->core_output[0].min ||
198	    rate > core->characteristics->core_output[0].max)
199		return -ERANGE;
200
201	/*
202	 * Calculate the multiplier associated with the current
203	 * divider that provide the closest rate to the requested one.
204	 */
205	nmul = mult_frac(rate, 1, parent_rate);
206	tmprate = mult_frac(parent_rate, nmul, 1);
207	remainder = rate - tmprate;
208
209	if (remainder) {
210		nfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * (1 << 22),
211					      parent_rate);
212
213		tmprate += DIV_ROUND_CLOSEST_ULL((u64)nfrac * parent_rate,
214						 (1 << 22));
215	}
216
217	/* Check if resulted rate is a valid.  */
218	if (tmprate < core->characteristics->core_output[0].min ||
219	    tmprate > core->characteristics->core_output[0].max)
220		return -ERANGE;
221
222	if (update) {
223		frac->mul = nmul - 1;
224		frac->frac = nfrac;
225	}
226
227	return tmprate;
228}
229
230static int sam9x60_frac_pll_determine_rate(struct clk_hw *hw,
231					   struct clk_rate_request *req)
232{
233	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
234
235	req->rate = sam9x60_frac_pll_compute_mul_frac(core, req->rate,
236						      req->best_parent_rate,
237						      false);
238
239	return 0;
240}
241
242static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,
243				     unsigned long parent_rate)
244{
245	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
246
247	return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
248}
249
250static int sam9x60_frac_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
251					 unsigned long parent_rate)
252{
253	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
254	struct sam9x60_frac *frac = to_sam9x60_frac(core);
255	struct regmap *regmap = core->regmap;
256	unsigned long irqflags;
257	unsigned int val, cfrac, cmul;
258	long ret;
259
260	ret = sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
261	if (ret <= 0)
262		return ret;
263
264	spin_lock_irqsave(core->lock, irqflags);
265
266	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
267			  core->id);
268	regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
269	cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
270	cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
271
272	if (cmul == frac->mul && cfrac == frac->frac)
273		goto unlock;
274
275	regmap_write(regmap, AT91_PMC_PLL_CTRL1,
276		     (frac->mul << core->layout->mul_shift) |
277		     (frac->frac << core->layout->frac_shift));
278
279	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
280			  AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
281			  AT91_PMC_PLL_UPDT_UPDATE | core->id);
282
283	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
284			   AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
285			   AT91_PMC_PLL_CTRL0_ENLOCK |
286			   AT91_PMC_PLL_CTRL0_ENPLL);
287
288	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
289			  AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
290			  AT91_PMC_PLL_UPDT_UPDATE | core->id);
291
292	while (!sam9x60_pll_ready(regmap, core->id))
293		cpu_relax();
294
295unlock:
296	spin_unlock_irqrestore(core->lock, irqflags);
297
298	return ret;
299}
300
301static int sam9x60_frac_pll_save_context(struct clk_hw *hw)
302{
303	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
304	struct sam9x60_frac *frac = to_sam9x60_frac(core);
305
306	frac->pms.status = sam9x60_pll_ready(core->regmap, core->id);
307
308	return 0;
309}
310
311static void sam9x60_frac_pll_restore_context(struct clk_hw *hw)
312{
313	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
314	struct sam9x60_frac *frac = to_sam9x60_frac(core);
315
316	if (frac->pms.status)
317		sam9x60_frac_pll_set(core);
318}
319
320static const struct clk_ops sam9x60_frac_pll_ops = {
321	.prepare = sam9x60_frac_pll_prepare,
322	.unprepare = sam9x60_frac_pll_unprepare,
323	.is_prepared = sam9x60_frac_pll_is_prepared,
324	.recalc_rate = sam9x60_frac_pll_recalc_rate,
325	.determine_rate = sam9x60_frac_pll_determine_rate,
326	.set_rate = sam9x60_frac_pll_set_rate,
327	.save_context = sam9x60_frac_pll_save_context,
328	.restore_context = sam9x60_frac_pll_restore_context,
329};
330
331static const struct clk_ops sam9x60_frac_pll_ops_chg = {
332	.prepare = sam9x60_frac_pll_prepare,
333	.unprepare = sam9x60_frac_pll_unprepare,
334	.is_prepared = sam9x60_frac_pll_is_prepared,
335	.recalc_rate = sam9x60_frac_pll_recalc_rate,
336	.determine_rate = sam9x60_frac_pll_determine_rate,
337	.set_rate = sam9x60_frac_pll_set_rate_chg,
338	.save_context = sam9x60_frac_pll_save_context,
339	.restore_context = sam9x60_frac_pll_restore_context,
340};
341
342/* This function should be called with spinlock acquired.
343 * Warning: this function must be called only if the same PLL ID was set in
344 *          PLL_UPDT register previously.
345 */
346static void sam9x60_div_pll_set_div(struct sam9x60_pll_core *core, u32 div,
347				    bool enable)
348{
349	struct regmap *regmap = core->regmap;
350	u32 ena_msk = enable ? core->layout->endiv_mask : 0;
351	u32 ena_val = enable ? (1 << core->layout->endiv_shift) : 0;
352
353	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
354			   core->layout->div_mask | ena_msk,
355			   (div << core->layout->div_shift) | ena_val);
356
357	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
358			  AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
359			  AT91_PMC_PLL_UPDT_UPDATE | core->id);
360
361	while (!sam9x60_pll_ready(regmap, core->id))
362		cpu_relax();
363}
364
365static int sam9x60_div_pll_set(struct sam9x60_pll_core *core)
366{
367	struct sam9x60_div *div = to_sam9x60_div(core);
368	struct regmap *regmap = core->regmap;
369	unsigned long flags;
370	unsigned int val, cdiv;
371
372	spin_lock_irqsave(core->lock, flags);
373	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
374			  AT91_PMC_PLL_UPDT_ID_MSK, core->id);
375	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
376	cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
377
378	/* Stop if enabled an nothing changed. */
379	if (!!(val & core->layout->endiv_mask) && cdiv == div->div)
380		goto unlock;
381
382	sam9x60_div_pll_set_div(core, div->div, 1);
383
384unlock:
385	spin_unlock_irqrestore(core->lock, flags);
386
387	return 0;
388}
389
390static int sam9x60_div_pll_prepare(struct clk_hw *hw)
391{
392	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
393
394	return sam9x60_div_pll_set(core);
395}
396
397static void sam9x60_div_pll_unprepare(struct clk_hw *hw)
398{
399	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
400	struct regmap *regmap = core->regmap;
401	unsigned long flags;
402
403	spin_lock_irqsave(core->lock, flags);
404
405	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
406			  AT91_PMC_PLL_UPDT_ID_MSK, core->id);
407
408	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
409			   core->layout->endiv_mask, 0);
410
411	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT,
412			  AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
413			  AT91_PMC_PLL_UPDT_UPDATE | core->id);
414
415	spin_unlock_irqrestore(core->lock, flags);
416}
417
418static int sam9x60_div_pll_is_prepared(struct clk_hw *hw)
419{
420	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
421	struct regmap *regmap = core->regmap;
422	unsigned long flags;
423	unsigned int val;
424
425	spin_lock_irqsave(core->lock, flags);
426
427	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
428			   AT91_PMC_PLL_UPDT_ID_MSK, core->id);
429	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
430
431	spin_unlock_irqrestore(core->lock, flags);
432
433	return !!(val & core->layout->endiv_mask);
434}
435
436static unsigned long sam9x60_div_pll_recalc_rate(struct clk_hw *hw,
437						 unsigned long parent_rate)
438{
439	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
440	struct sam9x60_div *div = to_sam9x60_div(core);
441
442	return DIV_ROUND_CLOSEST_ULL(parent_rate, (div->div + 1));
443}
444
445static unsigned long sam9x60_fixed_div_pll_recalc_rate(struct clk_hw *hw,
446						       unsigned long parent_rate)
447{
448	return parent_rate >> 1;
449}
450
451static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,
452					unsigned long *parent_rate,
453					unsigned long rate)
454{
455	const struct clk_pll_characteristics *characteristics =
456							core->characteristics;
457	struct clk_hw *parent = clk_hw_get_parent(&core->hw);
458	unsigned long tmp_rate, tmp_parent_rate, tmp_diff;
459	long best_diff = -1, best_rate = -EINVAL;
460	u32 divid;
461
462	if (!rate)
463		return 0;
464
465	if (rate < characteristics->output[0].min ||
466	    rate > characteristics->output[0].max)
467		return -ERANGE;
468
469	for (divid = 1; divid < core->layout->div_mask; divid++) {
470		tmp_parent_rate = clk_hw_round_rate(parent, rate * divid);
471		if (!tmp_parent_rate)
472			continue;
473
474		tmp_rate = DIV_ROUND_CLOSEST_ULL(tmp_parent_rate, divid);
475		tmp_diff = abs(rate - tmp_rate);
476
477		if (best_diff < 0 || best_diff > tmp_diff) {
478			*parent_rate = tmp_parent_rate;
479			best_rate = tmp_rate;
480			best_diff = tmp_diff;
481		}
482
483		if (!best_diff)
484			break;
485	}
486
487	if (best_rate < characteristics->output[0].min ||
488	    best_rate > characteristics->output[0].max)
489		return -ERANGE;
490
491	return best_rate;
492}
493
494static int sam9x60_div_pll_determine_rate(struct clk_hw *hw,
495					  struct clk_rate_request *req)
496{
497	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
498
499	req->rate = sam9x60_div_pll_compute_div(core, &req->best_parent_rate,
500						req->rate);
501
502	return 0;
503}
504
505static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,
506				    unsigned long parent_rate)
507{
508	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
509	struct sam9x60_div *div = to_sam9x60_div(core);
510
511	div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
512
513	return 0;
514}
515
516static int sam9x60_div_pll_set_rate_chg(struct clk_hw *hw, unsigned long rate,
517					unsigned long parent_rate)
518{
519	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
520	struct sam9x60_div *div = to_sam9x60_div(core);
521	struct regmap *regmap = core->regmap;
522	unsigned long irqflags;
523	unsigned int val, cdiv;
524
525	div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
526
527	spin_lock_irqsave(core->lock, irqflags);
528	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
529			  core->id);
530	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
531	cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
532
533	/* Stop if nothing changed. */
534	if (cdiv == div->div)
535		goto unlock;
536
537	sam9x60_div_pll_set_div(core, div->div, 0);
538
539unlock:
540	spin_unlock_irqrestore(core->lock, irqflags);
541
542	return 0;
543}
544
545static int sam9x60_div_pll_save_context(struct clk_hw *hw)
546{
547	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
548	struct sam9x60_div *div = to_sam9x60_div(core);
549
550	div->pms.status = sam9x60_div_pll_is_prepared(hw);
551
552	return 0;
553}
554
555static void sam9x60_div_pll_restore_context(struct clk_hw *hw)
556{
557	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
558	struct sam9x60_div *div = to_sam9x60_div(core);
559
560	if (div->pms.status)
561		sam9x60_div_pll_set(core);
562}
563
564static int sam9x60_div_pll_notifier_fn(struct notifier_block *notifier,
565				       unsigned long code, void *data)
566{
567	struct sam9x60_div *div = notifier_div;
568	struct sam9x60_pll_core core = div->core;
569	struct regmap *regmap = core.regmap;
570	unsigned long irqflags;
571	u32 val, cdiv;
572	int ret = NOTIFY_DONE;
573
574	if (code != PRE_RATE_CHANGE)
575		return ret;
576
577	/*
578	 * We switch to safe divider to avoid overclocking of other domains
579	 * feed by us while the frac PLL (our parent) is changed.
580	 */
581	div->div = div->safe_div;
582
583	spin_lock_irqsave(core.lock, irqflags);
584	regmap_write_bits(regmap, AT91_PMC_PLL_UPDT, AT91_PMC_PLL_UPDT_ID_MSK,
585			  core.id);
586	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
587	cdiv = (val & core.layout->div_mask) >> core.layout->div_shift;
588
589	/* Stop if nothing changed. */
590	if (cdiv == div->safe_div)
591		goto unlock;
592
593	sam9x60_div_pll_set_div(&core, div->div, 0);
594	ret = NOTIFY_OK;
595
596unlock:
597	spin_unlock_irqrestore(core.lock, irqflags);
598
599	return ret;
600}
601
602static struct notifier_block sam9x60_div_pll_notifier = {
603	.notifier_call = sam9x60_div_pll_notifier_fn,
604};
605
606static const struct clk_ops sam9x60_div_pll_ops = {
607	.prepare = sam9x60_div_pll_prepare,
608	.unprepare = sam9x60_div_pll_unprepare,
609	.is_prepared = sam9x60_div_pll_is_prepared,
610	.recalc_rate = sam9x60_div_pll_recalc_rate,
611	.determine_rate = sam9x60_div_pll_determine_rate,
612	.set_rate = sam9x60_div_pll_set_rate,
613	.save_context = sam9x60_div_pll_save_context,
614	.restore_context = sam9x60_div_pll_restore_context,
615};
616
617static const struct clk_ops sam9x60_div_pll_ops_chg = {
618	.prepare = sam9x60_div_pll_prepare,
619	.unprepare = sam9x60_div_pll_unprepare,
620	.is_prepared = sam9x60_div_pll_is_prepared,
621	.recalc_rate = sam9x60_div_pll_recalc_rate,
622	.determine_rate = sam9x60_div_pll_determine_rate,
623	.set_rate = sam9x60_div_pll_set_rate_chg,
624	.save_context = sam9x60_div_pll_save_context,
625	.restore_context = sam9x60_div_pll_restore_context,
626};
627
628static const struct clk_ops sam9x60_fixed_div_pll_ops = {
629	.prepare = sam9x60_div_pll_prepare,
630	.unprepare = sam9x60_div_pll_unprepare,
631	.is_prepared = sam9x60_div_pll_is_prepared,
632	.recalc_rate = sam9x60_fixed_div_pll_recalc_rate,
633	.determine_rate = sam9x60_div_pll_determine_rate,
634	.save_context = sam9x60_div_pll_save_context,
635	.restore_context = sam9x60_div_pll_restore_context,
636};
637
638struct clk_hw * __init
639sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
640			      const char *name, const char *parent_name,
641			      struct clk_hw *parent_hw, u8 id,
642			      const struct clk_pll_characteristics *characteristics,
643			      const struct clk_pll_layout *layout, u32 flags)
644{
645	struct sam9x60_frac *frac;
646	struct clk_hw *hw;
647	struct clk_init_data init = {};
648	unsigned long parent_rate, irqflags;
649	unsigned int val;
650	int ret;
651
652	if (id > PLL_MAX_ID || !lock || !parent_hw)
653		return ERR_PTR(-EINVAL);
654
655	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
656	if (!frac)
657		return ERR_PTR(-ENOMEM);
658
659	init.name = name;
660	if (parent_name)
661		init.parent_names = &parent_name;
662	else
663		init.parent_hws = (const struct clk_hw **)&parent_hw;
664	init.num_parents = 1;
665	if (flags & CLK_SET_RATE_GATE)
666		init.ops = &sam9x60_frac_pll_ops;
667	else
668		init.ops = &sam9x60_frac_pll_ops_chg;
669
670	init.flags = flags;
671
672	frac->core.id = id;
673	frac->core.hw.init = &init;
674	frac->core.characteristics = characteristics;
675	frac->core.layout = layout;
676	frac->core.regmap = regmap;
677	frac->core.lock = lock;
678
679	spin_lock_irqsave(frac->core.lock, irqflags);
680	if (sam9x60_pll_ready(regmap, id)) {
681		regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
682				   AT91_PMC_PLL_UPDT_ID_MSK, id);
683		regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
684		frac->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
685		frac->frac = FIELD_GET(PMC_PLL_CTRL1_FRACR_MSK, val);
686	} else {
687		/*
688		 * This means the PLL is not setup by bootloaders. In this
689		 * case we need to set the minimum rate for it. Otherwise
690		 * a clock child of this PLL may be enabled before setting
691		 * its rate leading to enabling this PLL with unsupported
692		 * rate. This will lead to PLL not being locked at all.
693		 */
694		parent_rate = clk_hw_get_rate(parent_hw);
695		if (!parent_rate) {
696			hw = ERR_PTR(-EINVAL);
697			goto free;
698		}
699
700		ret = sam9x60_frac_pll_compute_mul_frac(&frac->core,
701							characteristics->core_output[0].min,
702							parent_rate, true);
703		if (ret < 0) {
704			hw = ERR_PTR(ret);
705			goto free;
706		}
707	}
708	spin_unlock_irqrestore(frac->core.lock, irqflags);
709
710	hw = &frac->core.hw;
711	ret = clk_hw_register(NULL, hw);
712	if (ret) {
713		kfree(frac);
714		hw = ERR_PTR(ret);
715	}
716
717	return hw;
718
719free:
720	spin_unlock_irqrestore(frac->core.lock, irqflags);
721	kfree(frac);
722	return hw;
723}
724
725struct clk_hw * __init
726sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
727			     const char *name, const char *parent_name,
728			     struct clk_hw *parent_hw, u8 id,
729			     const struct clk_pll_characteristics *characteristics,
730			     const struct clk_pll_layout *layout, u32 flags,
731			     u32 safe_div)
732{
733	struct sam9x60_div *div;
734	struct clk_hw *hw;
735	struct clk_init_data init = {};
736	unsigned long irqflags;
737	unsigned int val;
738	int ret;
739
740	/* We only support one changeable PLL. */
741	if (id > PLL_MAX_ID || !lock || (safe_div && notifier_div))
742		return ERR_PTR(-EINVAL);
743
744	if (safe_div >= PLL_DIV_MAX)
745		safe_div = PLL_DIV_MAX - 1;
746
747	div = kzalloc(sizeof(*div), GFP_KERNEL);
748	if (!div)
749		return ERR_PTR(-ENOMEM);
750
751	init.name = name;
752	if (parent_hw)
753		init.parent_hws = (const struct clk_hw **)&parent_hw;
754	else
755		init.parent_names = &parent_name;
756	init.num_parents = 1;
757
758	if (layout->div2)
759		init.ops = &sam9x60_fixed_div_pll_ops;
760	else if (flags & CLK_SET_RATE_GATE)
761		init.ops = &sam9x60_div_pll_ops;
762	else
763		init.ops = &sam9x60_div_pll_ops_chg;
764
765	init.flags = flags;
766
767	div->core.id = id;
768	div->core.hw.init = &init;
769	div->core.characteristics = characteristics;
770	div->core.layout = layout;
771	div->core.regmap = regmap;
772	div->core.lock = lock;
773	div->safe_div = safe_div;
774
775	spin_lock_irqsave(div->core.lock, irqflags);
776
777	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
778			   AT91_PMC_PLL_UPDT_ID_MSK, id);
779	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
780	div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
781
782	spin_unlock_irqrestore(div->core.lock, irqflags);
783
784	hw = &div->core.hw;
785	ret = clk_hw_register(NULL, hw);
786	if (ret) {
787		kfree(div);
788		hw = ERR_PTR(ret);
789	} else if (div->safe_div) {
790		notifier_div = div;
791		clk_notifier_register(hw->clk, &sam9x60_div_pll_notifier);
792	}
793
794	return hw;
795}
796
~/ Read-only file preview.