xref: /OK3568_Linux_fs/kernel/drivers/clk/at91/clk-sam9x60-pll.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Copyright (C) 2019 Microchip Technology Inc.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/bitfield.h>
8*4882a593Smuzhiyun #include <linux/clk-provider.h>
9*4882a593Smuzhiyun #include <linux/clkdev.h>
10*4882a593Smuzhiyun #include <linux/clk/at91_pmc.h>
11*4882a593Smuzhiyun #include <linux/of.h>
12*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
13*4882a593Smuzhiyun #include <linux/regmap.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include "pmc.h"
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define	PMC_PLL_CTRL0_DIV_MSK	GENMASK(7, 0)
18*4882a593Smuzhiyun #define	PMC_PLL_CTRL1_MUL_MSK	GENMASK(31, 24)
19*4882a593Smuzhiyun #define	PMC_PLL_CTRL1_FRACR_MSK	GENMASK(21, 0)
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define PLL_DIV_MAX		(FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, UINT_MAX) + 1)
22*4882a593Smuzhiyun #define UPLL_DIV		2
23*4882a593Smuzhiyun #define PLL_MUL_MAX		(FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, UINT_MAX) + 1)
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define FCORE_MIN		(600000000)
26*4882a593Smuzhiyun #define FCORE_MAX		(1200000000)
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun #define PLL_MAX_ID		7
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun struct sam9x60_pll_core {
31*4882a593Smuzhiyun 	struct regmap *regmap;
32*4882a593Smuzhiyun 	spinlock_t *lock;
33*4882a593Smuzhiyun 	const struct clk_pll_characteristics *characteristics;
34*4882a593Smuzhiyun 	const struct clk_pll_layout *layout;
35*4882a593Smuzhiyun 	struct clk_hw hw;
36*4882a593Smuzhiyun 	u8 id;
37*4882a593Smuzhiyun };
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun struct sam9x60_frac {
40*4882a593Smuzhiyun 	struct sam9x60_pll_core core;
41*4882a593Smuzhiyun 	u32 frac;
42*4882a593Smuzhiyun 	u16 mul;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun struct sam9x60_div {
46*4882a593Smuzhiyun 	struct sam9x60_pll_core core;
47*4882a593Smuzhiyun 	u8 div;
48*4882a593Smuzhiyun };
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define to_sam9x60_pll_core(hw)	container_of(hw, struct sam9x60_pll_core, hw)
51*4882a593Smuzhiyun #define to_sam9x60_frac(core)	container_of(core, struct sam9x60_frac, core)
52*4882a593Smuzhiyun #define to_sam9x60_div(core)	container_of(core, struct sam9x60_div, core)
53*4882a593Smuzhiyun 
sam9x60_pll_ready(struct regmap * regmap,int id)54*4882a593Smuzhiyun static inline bool sam9x60_pll_ready(struct regmap *regmap, int id)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	unsigned int status;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	regmap_read(regmap, AT91_PMC_PLL_ISR0, &status);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	return !!(status & BIT(id));
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
sam9x60_frac_pll_ready(struct regmap * regmap,u8 id)63*4882a593Smuzhiyun static bool sam9x60_frac_pll_ready(struct regmap *regmap, u8 id)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	return sam9x60_pll_ready(regmap, id);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
sam9x60_frac_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)68*4882a593Smuzhiyun static unsigned long sam9x60_frac_pll_recalc_rate(struct clk_hw *hw,
69*4882a593Smuzhiyun 						  unsigned long parent_rate)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
72*4882a593Smuzhiyun 	struct sam9x60_frac *frac = to_sam9x60_frac(core);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	return parent_rate * (frac->mul + 1) +
75*4882a593Smuzhiyun 		DIV_ROUND_CLOSEST_ULL((u64)parent_rate * frac->frac, (1 << 22));
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun 
sam9x60_frac_pll_prepare(struct clk_hw * hw)78*4882a593Smuzhiyun static int sam9x60_frac_pll_prepare(struct clk_hw *hw)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
81*4882a593Smuzhiyun 	struct sam9x60_frac *frac = to_sam9x60_frac(core);
82*4882a593Smuzhiyun 	struct regmap *regmap = core->regmap;
83*4882a593Smuzhiyun 	unsigned int val, cfrac, cmul;
84*4882a593Smuzhiyun 	unsigned long flags;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	spin_lock_irqsave(core->lock, flags);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
89*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_ID_MSK, core->id);
90*4882a593Smuzhiyun 	regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
91*4882a593Smuzhiyun 	cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
92*4882a593Smuzhiyun 	cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	if (sam9x60_frac_pll_ready(regmap, core->id) &&
95*4882a593Smuzhiyun 	    (cmul == frac->mul && cfrac == frac->frac))
96*4882a593Smuzhiyun 		goto unlock;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	/* Recommended value for PMC_PLL_ACR */
99*4882a593Smuzhiyun 	if (core->characteristics->upll)
100*4882a593Smuzhiyun 		val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;
101*4882a593Smuzhiyun 	else
102*4882a593Smuzhiyun 		val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;
103*4882a593Smuzhiyun 	regmap_write(regmap, AT91_PMC_PLL_ACR, val);
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	regmap_write(regmap, AT91_PMC_PLL_CTRL1,
106*4882a593Smuzhiyun 		     (frac->mul << core->layout->mul_shift) |
107*4882a593Smuzhiyun 		     (frac->frac << core->layout->frac_shift));
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (core->characteristics->upll) {
110*4882a593Smuzhiyun 		/* Enable the UTMI internal bandgap */
111*4882a593Smuzhiyun 		val |= AT91_PMC_PLL_ACR_UTMIBG;
112*4882a593Smuzhiyun 		regmap_write(regmap, AT91_PMC_PLL_ACR, val);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 		udelay(10);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 		/* Enable the UTMI internal regulator */
117*4882a593Smuzhiyun 		val |= AT91_PMC_PLL_ACR_UTMIVR;
118*4882a593Smuzhiyun 		regmap_write(regmap, AT91_PMC_PLL_ACR, val);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 		udelay(10);
121*4882a593Smuzhiyun 	}
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
124*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
125*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | core->id);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
128*4882a593Smuzhiyun 			   AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL,
129*4882a593Smuzhiyun 			   AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
132*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
133*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | core->id);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	while (!sam9x60_pll_ready(regmap, core->id))
136*4882a593Smuzhiyun 		cpu_relax();
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun unlock:
139*4882a593Smuzhiyun 	spin_unlock_irqrestore(core->lock, flags);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	return 0;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
sam9x60_frac_pll_unprepare(struct clk_hw * hw)144*4882a593Smuzhiyun static void sam9x60_frac_pll_unprepare(struct clk_hw *hw)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
147*4882a593Smuzhiyun 	struct regmap *regmap = core->regmap;
148*4882a593Smuzhiyun 	unsigned long flags;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	spin_lock_irqsave(core->lock, flags);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
153*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_ID_MSK, core->id);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0, AT91_PMC_PLL_CTRL0_ENPLL, 0);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (core->characteristics->upll)
158*4882a593Smuzhiyun 		regmap_update_bits(regmap, AT91_PMC_PLL_ACR,
159*4882a593Smuzhiyun 				   AT91_PMC_PLL_ACR_UTMIBG | AT91_PMC_PLL_ACR_UTMIVR, 0);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
162*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
163*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | core->id);
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	spin_unlock_irqrestore(core->lock, flags);
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
sam9x60_frac_pll_is_prepared(struct clk_hw * hw)168*4882a593Smuzhiyun static int sam9x60_frac_pll_is_prepared(struct clk_hw *hw)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	return sam9x60_pll_ready(core->regmap, core->id);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
sam9x60_frac_pll_compute_mul_frac(struct sam9x60_pll_core * core,unsigned long rate,unsigned long parent_rate,bool update)175*4882a593Smuzhiyun static long sam9x60_frac_pll_compute_mul_frac(struct sam9x60_pll_core *core,
176*4882a593Smuzhiyun 					      unsigned long rate,
177*4882a593Smuzhiyun 					      unsigned long parent_rate,
178*4882a593Smuzhiyun 					      bool update)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	struct sam9x60_frac *frac = to_sam9x60_frac(core);
181*4882a593Smuzhiyun 	unsigned long tmprate, remainder;
182*4882a593Smuzhiyun 	unsigned long nmul = 0;
183*4882a593Smuzhiyun 	unsigned long nfrac = 0;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	if (rate < FCORE_MIN || rate > FCORE_MAX)
186*4882a593Smuzhiyun 		return -ERANGE;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/*
189*4882a593Smuzhiyun 	 * Calculate the multiplier associated with the current
190*4882a593Smuzhiyun 	 * divider that provide the closest rate to the requested one.
191*4882a593Smuzhiyun 	 */
192*4882a593Smuzhiyun 	nmul = mult_frac(rate, 1, parent_rate);
193*4882a593Smuzhiyun 	tmprate = mult_frac(parent_rate, nmul, 1);
194*4882a593Smuzhiyun 	remainder = rate - tmprate;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (remainder) {
197*4882a593Smuzhiyun 		nfrac = DIV_ROUND_CLOSEST_ULL((u64)remainder * (1 << 22),
198*4882a593Smuzhiyun 					      parent_rate);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 		tmprate += DIV_ROUND_CLOSEST_ULL((u64)nfrac * parent_rate,
201*4882a593Smuzhiyun 						 (1 << 22));
202*4882a593Smuzhiyun 	}
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	/* Check if resulted rate is a valid.  */
205*4882a593Smuzhiyun 	if (tmprate < FCORE_MIN || tmprate > FCORE_MAX)
206*4882a593Smuzhiyun 		return -ERANGE;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	if (update) {
209*4882a593Smuzhiyun 		frac->mul = nmul - 1;
210*4882a593Smuzhiyun 		frac->frac = nfrac;
211*4882a593Smuzhiyun 	}
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	return tmprate;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
sam9x60_frac_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)216*4882a593Smuzhiyun static long sam9x60_frac_pll_round_rate(struct clk_hw *hw, unsigned long rate,
217*4882a593Smuzhiyun 					unsigned long *parent_rate)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	return sam9x60_frac_pll_compute_mul_frac(core, rate, *parent_rate, false);
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun 
sam9x60_frac_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)224*4882a593Smuzhiyun static int sam9x60_frac_pll_set_rate(struct clk_hw *hw, unsigned long rate,
225*4882a593Smuzhiyun 				     unsigned long parent_rate)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	return sam9x60_frac_pll_compute_mul_frac(core, rate, parent_rate, true);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun static const struct clk_ops sam9x60_frac_pll_ops = {
233*4882a593Smuzhiyun 	.prepare = sam9x60_frac_pll_prepare,
234*4882a593Smuzhiyun 	.unprepare = sam9x60_frac_pll_unprepare,
235*4882a593Smuzhiyun 	.is_prepared = sam9x60_frac_pll_is_prepared,
236*4882a593Smuzhiyun 	.recalc_rate = sam9x60_frac_pll_recalc_rate,
237*4882a593Smuzhiyun 	.round_rate = sam9x60_frac_pll_round_rate,
238*4882a593Smuzhiyun 	.set_rate = sam9x60_frac_pll_set_rate,
239*4882a593Smuzhiyun };
240*4882a593Smuzhiyun 
sam9x60_div_pll_prepare(struct clk_hw * hw)241*4882a593Smuzhiyun static int sam9x60_div_pll_prepare(struct clk_hw *hw)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
244*4882a593Smuzhiyun 	struct sam9x60_div *div = to_sam9x60_div(core);
245*4882a593Smuzhiyun 	struct regmap *regmap = core->regmap;
246*4882a593Smuzhiyun 	unsigned long flags;
247*4882a593Smuzhiyun 	unsigned int val, cdiv;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	spin_lock_irqsave(core->lock, flags);
250*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
251*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_ID_MSK, core->id);
252*4882a593Smuzhiyun 	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
253*4882a593Smuzhiyun 	cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	/* Stop if enabled an nothing changed. */
256*4882a593Smuzhiyun 	if (!!(val & core->layout->endiv_mask) && cdiv == div->div)
257*4882a593Smuzhiyun 		goto unlock;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
260*4882a593Smuzhiyun 			   core->layout->div_mask | core->layout->endiv_mask,
261*4882a593Smuzhiyun 			   (div->div << core->layout->div_shift) |
262*4882a593Smuzhiyun 			   (1 << core->layout->endiv_shift));
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
265*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
266*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | core->id);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	while (!sam9x60_pll_ready(regmap, core->id))
269*4882a593Smuzhiyun 		cpu_relax();
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun unlock:
272*4882a593Smuzhiyun 	spin_unlock_irqrestore(core->lock, flags);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 	return 0;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
sam9x60_div_pll_unprepare(struct clk_hw * hw)277*4882a593Smuzhiyun static void sam9x60_div_pll_unprepare(struct clk_hw *hw)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
280*4882a593Smuzhiyun 	struct regmap *regmap = core->regmap;
281*4882a593Smuzhiyun 	unsigned long flags;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	spin_lock_irqsave(core->lock, flags);
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
286*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_ID_MSK, core->id);
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_CTRL0,
289*4882a593Smuzhiyun 			   core->layout->endiv_mask, 0);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
292*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MSK,
293*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_UPDATE | core->id);
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	spin_unlock_irqrestore(core->lock, flags);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun 
sam9x60_div_pll_is_prepared(struct clk_hw * hw)298*4882a593Smuzhiyun static int sam9x60_div_pll_is_prepared(struct clk_hw *hw)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
301*4882a593Smuzhiyun 	struct regmap *regmap = core->regmap;
302*4882a593Smuzhiyun 	unsigned long flags;
303*4882a593Smuzhiyun 	unsigned int val;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	spin_lock_irqsave(core->lock, flags);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
308*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_ID_MSK, core->id);
309*4882a593Smuzhiyun 	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	spin_unlock_irqrestore(core->lock, flags);
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	return !!(val & core->layout->endiv_mask);
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
sam9x60_div_pll_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)316*4882a593Smuzhiyun static unsigned long sam9x60_div_pll_recalc_rate(struct clk_hw *hw,
317*4882a593Smuzhiyun 						 unsigned long parent_rate)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
320*4882a593Smuzhiyun 	struct sam9x60_div *div = to_sam9x60_div(core);
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun 	return DIV_ROUND_CLOSEST_ULL(parent_rate, (div->div + 1));
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
sam9x60_div_pll_compute_div(struct sam9x60_pll_core * core,unsigned long * parent_rate,unsigned long rate)325*4882a593Smuzhiyun static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,
326*4882a593Smuzhiyun 					unsigned long *parent_rate,
327*4882a593Smuzhiyun 					unsigned long rate)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun 	const struct clk_pll_characteristics *characteristics =
330*4882a593Smuzhiyun 							core->characteristics;
331*4882a593Smuzhiyun 	struct clk_hw *parent = clk_hw_get_parent(&core->hw);
332*4882a593Smuzhiyun 	unsigned long tmp_rate, tmp_parent_rate, tmp_diff;
333*4882a593Smuzhiyun 	long best_diff = -1, best_rate = -EINVAL;
334*4882a593Smuzhiyun 	u32 divid;
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	if (!rate)
337*4882a593Smuzhiyun 		return 0;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	if (rate < characteristics->output[0].min ||
340*4882a593Smuzhiyun 	    rate > characteristics->output[0].max)
341*4882a593Smuzhiyun 		return -ERANGE;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	for (divid = 1; divid < core->layout->div_mask; divid++) {
344*4882a593Smuzhiyun 		tmp_parent_rate = clk_hw_round_rate(parent, rate * divid);
345*4882a593Smuzhiyun 		if (!tmp_parent_rate)
346*4882a593Smuzhiyun 			continue;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 		tmp_rate = DIV_ROUND_CLOSEST_ULL(tmp_parent_rate, divid);
349*4882a593Smuzhiyun 		tmp_diff = abs(rate - tmp_rate);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 		if (best_diff < 0 || best_diff > tmp_diff) {
352*4882a593Smuzhiyun 			*parent_rate = tmp_parent_rate;
353*4882a593Smuzhiyun 			best_rate = tmp_rate;
354*4882a593Smuzhiyun 			best_diff = tmp_diff;
355*4882a593Smuzhiyun 		}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 		if (!best_diff)
358*4882a593Smuzhiyun 			break;
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	if (best_rate < characteristics->output[0].min ||
362*4882a593Smuzhiyun 	    best_rate > characteristics->output[0].max)
363*4882a593Smuzhiyun 		return -ERANGE;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	return best_rate;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
sam9x60_div_pll_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)368*4882a593Smuzhiyun static long sam9x60_div_pll_round_rate(struct clk_hw *hw, unsigned long rate,
369*4882a593Smuzhiyun 				       unsigned long *parent_rate)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	return sam9x60_div_pll_compute_div(core, parent_rate, rate);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
sam9x60_div_pll_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)376*4882a593Smuzhiyun static int sam9x60_div_pll_set_rate(struct clk_hw *hw, unsigned long rate,
377*4882a593Smuzhiyun 				    unsigned long parent_rate)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	struct sam9x60_pll_core *core = to_sam9x60_pll_core(hw);
380*4882a593Smuzhiyun 	struct sam9x60_div *div = to_sam9x60_div(core);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	div->div = DIV_ROUND_CLOSEST(parent_rate, rate) - 1;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	return 0;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun static const struct clk_ops sam9x60_div_pll_ops = {
388*4882a593Smuzhiyun 	.prepare = sam9x60_div_pll_prepare,
389*4882a593Smuzhiyun 	.unprepare = sam9x60_div_pll_unprepare,
390*4882a593Smuzhiyun 	.is_prepared = sam9x60_div_pll_is_prepared,
391*4882a593Smuzhiyun 	.recalc_rate = sam9x60_div_pll_recalc_rate,
392*4882a593Smuzhiyun 	.round_rate = sam9x60_div_pll_round_rate,
393*4882a593Smuzhiyun 	.set_rate = sam9x60_div_pll_set_rate,
394*4882a593Smuzhiyun };
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun struct clk_hw * __init
sam9x60_clk_register_frac_pll(struct regmap * regmap,spinlock_t * lock,const char * name,const char * parent_name,struct clk_hw * parent_hw,u8 id,const struct clk_pll_characteristics * characteristics,const struct clk_pll_layout * layout,bool critical)397*4882a593Smuzhiyun sam9x60_clk_register_frac_pll(struct regmap *regmap, spinlock_t *lock,
398*4882a593Smuzhiyun 			      const char *name, const char *parent_name,
399*4882a593Smuzhiyun 			      struct clk_hw *parent_hw, u8 id,
400*4882a593Smuzhiyun 			      const struct clk_pll_characteristics *characteristics,
401*4882a593Smuzhiyun 			      const struct clk_pll_layout *layout, bool critical)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	struct sam9x60_frac *frac;
404*4882a593Smuzhiyun 	struct clk_hw *hw;
405*4882a593Smuzhiyun 	struct clk_init_data init;
406*4882a593Smuzhiyun 	unsigned long parent_rate, flags;
407*4882a593Smuzhiyun 	unsigned int val;
408*4882a593Smuzhiyun 	int ret;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	if (id > PLL_MAX_ID || !lock || !parent_hw)
411*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
414*4882a593Smuzhiyun 	if (!frac)
415*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	init.name = name;
418*4882a593Smuzhiyun 	init.parent_names = &parent_name;
419*4882a593Smuzhiyun 	init.num_parents = 1;
420*4882a593Smuzhiyun 	init.ops = &sam9x60_frac_pll_ops;
421*4882a593Smuzhiyun 	init.flags = CLK_SET_RATE_GATE;
422*4882a593Smuzhiyun 	if (critical)
423*4882a593Smuzhiyun 		init.flags |= CLK_IS_CRITICAL;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	frac->core.id = id;
426*4882a593Smuzhiyun 	frac->core.hw.init = &init;
427*4882a593Smuzhiyun 	frac->core.characteristics = characteristics;
428*4882a593Smuzhiyun 	frac->core.layout = layout;
429*4882a593Smuzhiyun 	frac->core.regmap = regmap;
430*4882a593Smuzhiyun 	frac->core.lock = lock;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	spin_lock_irqsave(frac->core.lock, flags);
433*4882a593Smuzhiyun 	if (sam9x60_pll_ready(regmap, id)) {
434*4882a593Smuzhiyun 		regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
435*4882a593Smuzhiyun 				   AT91_PMC_PLL_UPDT_ID_MSK, id);
436*4882a593Smuzhiyun 		regmap_read(regmap, AT91_PMC_PLL_CTRL1, &val);
437*4882a593Smuzhiyun 		frac->mul = FIELD_GET(PMC_PLL_CTRL1_MUL_MSK, val);
438*4882a593Smuzhiyun 		frac->frac = FIELD_GET(PMC_PLL_CTRL1_FRACR_MSK, val);
439*4882a593Smuzhiyun 	} else {
440*4882a593Smuzhiyun 		/*
441*4882a593Smuzhiyun 		 * This means the PLL is not setup by bootloaders. In this
442*4882a593Smuzhiyun 		 * case we need to set the minimum rate for it. Otherwise
443*4882a593Smuzhiyun 		 * a clock child of this PLL may be enabled before setting
444*4882a593Smuzhiyun 		 * its rate leading to enabling this PLL with unsupported
445*4882a593Smuzhiyun 		 * rate. This will lead to PLL not being locked at all.
446*4882a593Smuzhiyun 		 */
447*4882a593Smuzhiyun 		parent_rate = clk_hw_get_rate(parent_hw);
448*4882a593Smuzhiyun 		if (!parent_rate) {
449*4882a593Smuzhiyun 			hw = ERR_PTR(-EINVAL);
450*4882a593Smuzhiyun 			goto free;
451*4882a593Smuzhiyun 		}
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 		ret = sam9x60_frac_pll_compute_mul_frac(&frac->core, FCORE_MIN,
454*4882a593Smuzhiyun 							parent_rate, true);
455*4882a593Smuzhiyun 		if (ret <= 0) {
456*4882a593Smuzhiyun 			hw = ERR_PTR(ret);
457*4882a593Smuzhiyun 			goto free;
458*4882a593Smuzhiyun 		}
459*4882a593Smuzhiyun 	}
460*4882a593Smuzhiyun 	spin_unlock_irqrestore(frac->core.lock, flags);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	hw = &frac->core.hw;
463*4882a593Smuzhiyun 	ret = clk_hw_register(NULL, hw);
464*4882a593Smuzhiyun 	if (ret) {
465*4882a593Smuzhiyun 		kfree(frac);
466*4882a593Smuzhiyun 		hw = ERR_PTR(ret);
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	return hw;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun free:
472*4882a593Smuzhiyun 	spin_unlock_irqrestore(frac->core.lock, flags);
473*4882a593Smuzhiyun 	kfree(frac);
474*4882a593Smuzhiyun 	return hw;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun struct clk_hw * __init
sam9x60_clk_register_div_pll(struct regmap * regmap,spinlock_t * lock,const char * name,const char * parent_name,u8 id,const struct clk_pll_characteristics * characteristics,const struct clk_pll_layout * layout,bool critical)478*4882a593Smuzhiyun sam9x60_clk_register_div_pll(struct regmap *regmap, spinlock_t *lock,
479*4882a593Smuzhiyun 			     const char *name, const char *parent_name, u8 id,
480*4882a593Smuzhiyun 			     const struct clk_pll_characteristics *characteristics,
481*4882a593Smuzhiyun 			     const struct clk_pll_layout *layout, bool critical)
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun 	struct sam9x60_div *div;
484*4882a593Smuzhiyun 	struct clk_hw *hw;
485*4882a593Smuzhiyun 	struct clk_init_data init;
486*4882a593Smuzhiyun 	unsigned long flags;
487*4882a593Smuzhiyun 	unsigned int val;
488*4882a593Smuzhiyun 	int ret;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	if (id > PLL_MAX_ID || !lock)
491*4882a593Smuzhiyun 		return ERR_PTR(-EINVAL);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	div = kzalloc(sizeof(*div), GFP_KERNEL);
494*4882a593Smuzhiyun 	if (!div)
495*4882a593Smuzhiyun 		return ERR_PTR(-ENOMEM);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	init.name = name;
498*4882a593Smuzhiyun 	init.parent_names = &parent_name;
499*4882a593Smuzhiyun 	init.num_parents = 1;
500*4882a593Smuzhiyun 	init.ops = &sam9x60_div_pll_ops;
501*4882a593Smuzhiyun 	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
502*4882a593Smuzhiyun 		     CLK_SET_RATE_PARENT;
503*4882a593Smuzhiyun 	if (critical)
504*4882a593Smuzhiyun 		init.flags |= CLK_IS_CRITICAL;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	div->core.id = id;
507*4882a593Smuzhiyun 	div->core.hw.init = &init;
508*4882a593Smuzhiyun 	div->core.characteristics = characteristics;
509*4882a593Smuzhiyun 	div->core.layout = layout;
510*4882a593Smuzhiyun 	div->core.regmap = regmap;
511*4882a593Smuzhiyun 	div->core.lock = lock;
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	spin_lock_irqsave(div->core.lock, flags);
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	regmap_update_bits(regmap, AT91_PMC_PLL_UPDT,
516*4882a593Smuzhiyun 			   AT91_PMC_PLL_UPDT_ID_MSK, id);
517*4882a593Smuzhiyun 	regmap_read(regmap, AT91_PMC_PLL_CTRL0, &val);
518*4882a593Smuzhiyun 	div->div = FIELD_GET(PMC_PLL_CTRL0_DIV_MSK, val);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	spin_unlock_irqrestore(div->core.lock, flags);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	hw = &div->core.hw;
523*4882a593Smuzhiyun 	ret = clk_hw_register(NULL, hw);
524*4882a593Smuzhiyun 	if (ret) {
525*4882a593Smuzhiyun 		kfree(div);
526*4882a593Smuzhiyun 		hw = ERR_PTR(ret);
527*4882a593Smuzhiyun 	}
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	return hw;
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun 
532