xref: /linux/drivers/clk/at91/clk-sam9x60-pll.c (revision b8d312aa075f33282565467662c4628dae0a2aff)
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 
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 
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 
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 
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 
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 
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 
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 
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
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