1 | /* SPDX-License-Identifier: GPL-2.0 |
2 | * |
3 | * Clock Tree for the Texas Instruments TLV320AIC32x4 |
4 | * |
5 | * Copyright 2019 Annaliese McDermond |
6 | * |
7 | * Author: Annaliese McDermond <nh6z@nh6z.net> |
8 | */ |
9 | |
10 | #include <linux/clk-provider.h> |
11 | #include <linux/clkdev.h> |
12 | #include <linux/regmap.h> |
13 | #include <linux/device.h> |
14 | |
15 | #include "tlv320aic32x4.h" |
16 | |
17 | #define to_clk_aic32x4(_hw) container_of(_hw, struct clk_aic32x4, hw) |
18 | struct clk_aic32x4 { |
19 | struct clk_hw hw; |
20 | struct device *dev; |
21 | struct regmap *regmap; |
22 | unsigned int reg; |
23 | }; |
24 | |
25 | /* |
26 | * struct clk_aic32x4_pll_muldiv - Multiplier/divider settings |
27 | * @p: Divider |
28 | * @r: first multiplier |
29 | * @j: integer part of second multiplier |
30 | * @d: decimal part of second multiplier |
31 | */ |
32 | struct clk_aic32x4_pll_muldiv { |
33 | u8 p; |
34 | u16 r; |
35 | u8 j; |
36 | u16 d; |
37 | }; |
38 | |
39 | struct aic32x4_clkdesc { |
40 | const char *name; |
41 | const char * const *parent_names; |
42 | unsigned int num_parents; |
43 | const struct clk_ops *ops; |
44 | unsigned int reg; |
45 | }; |
46 | |
47 | static int clk_aic32x4_pll_prepare(struct clk_hw *hw) |
48 | { |
49 | struct clk_aic32x4 *pll = to_clk_aic32x4(hw); |
50 | |
51 | return regmap_update_bits(map: pll->regmap, AIC32X4_PLLPR, |
52 | AIC32X4_PLLEN, AIC32X4_PLLEN); |
53 | } |
54 | |
55 | static void clk_aic32x4_pll_unprepare(struct clk_hw *hw) |
56 | { |
57 | struct clk_aic32x4 *pll = to_clk_aic32x4(hw); |
58 | |
59 | regmap_update_bits(map: pll->regmap, AIC32X4_PLLPR, |
60 | AIC32X4_PLLEN, val: 0); |
61 | } |
62 | |
63 | static int clk_aic32x4_pll_is_prepared(struct clk_hw *hw) |
64 | { |
65 | struct clk_aic32x4 *pll = to_clk_aic32x4(hw); |
66 | |
67 | unsigned int val; |
68 | int ret; |
69 | |
70 | ret = regmap_read(map: pll->regmap, AIC32X4_PLLPR, val: &val); |
71 | if (ret < 0) |
72 | return ret; |
73 | |
74 | return !!(val & AIC32X4_PLLEN); |
75 | } |
76 | |
77 | static int clk_aic32x4_pll_get_muldiv(struct clk_aic32x4 *pll, |
78 | struct clk_aic32x4_pll_muldiv *settings) |
79 | { |
80 | /* Change to use regmap_bulk_read? */ |
81 | unsigned int val; |
82 | int ret; |
83 | |
84 | ret = regmap_read(map: pll->regmap, AIC32X4_PLLPR, val: &val); |
85 | if (ret < 0) |
86 | return ret; |
87 | settings->r = val & AIC32X4_PLL_R_MASK; |
88 | settings->p = (val & AIC32X4_PLL_P_MASK) >> AIC32X4_PLL_P_SHIFT; |
89 | |
90 | ret = regmap_read(map: pll->regmap, AIC32X4_PLLJ, val: &val); |
91 | if (ret < 0) |
92 | return ret; |
93 | settings->j = val; |
94 | |
95 | ret = regmap_read(map: pll->regmap, AIC32X4_PLLDMSB, val: &val); |
96 | if (ret < 0) |
97 | return ret; |
98 | settings->d = val << 8; |
99 | |
100 | ret = regmap_read(map: pll->regmap, AIC32X4_PLLDLSB, val: &val); |
101 | if (ret < 0) |
102 | return ret; |
103 | settings->d |= val; |
104 | |
105 | return 0; |
106 | } |
107 | |
108 | static int clk_aic32x4_pll_set_muldiv(struct clk_aic32x4 *pll, |
109 | struct clk_aic32x4_pll_muldiv *settings) |
110 | { |
111 | int ret; |
112 | /* Change to use regmap_bulk_write for some if not all? */ |
113 | |
114 | ret = regmap_update_bits(map: pll->regmap, AIC32X4_PLLPR, |
115 | AIC32X4_PLL_R_MASK, val: settings->r); |
116 | if (ret < 0) |
117 | return ret; |
118 | |
119 | ret = regmap_update_bits(map: pll->regmap, AIC32X4_PLLPR, |
120 | AIC32X4_PLL_P_MASK, |
121 | val: settings->p << AIC32X4_PLL_P_SHIFT); |
122 | if (ret < 0) |
123 | return ret; |
124 | |
125 | ret = regmap_write(map: pll->regmap, AIC32X4_PLLJ, val: settings->j); |
126 | if (ret < 0) |
127 | return ret; |
128 | |
129 | ret = regmap_write(map: pll->regmap, AIC32X4_PLLDMSB, val: (settings->d >> 8)); |
130 | if (ret < 0) |
131 | return ret; |
132 | ret = regmap_write(map: pll->regmap, AIC32X4_PLLDLSB, val: (settings->d & 0xff)); |
133 | if (ret < 0) |
134 | return ret; |
135 | |
136 | return 0; |
137 | } |
138 | |
139 | static unsigned long clk_aic32x4_pll_calc_rate( |
140 | struct clk_aic32x4_pll_muldiv *settings, |
141 | unsigned long parent_rate) |
142 | { |
143 | u64 rate; |
144 | /* |
145 | * We scale j by 10000 to account for the decimal part of P and divide |
146 | * it back out later. |
147 | */ |
148 | rate = (u64) parent_rate * settings->r * |
149 | ((settings->j * 10000) + settings->d); |
150 | |
151 | return (unsigned long) DIV_ROUND_UP_ULL(rate, settings->p * 10000); |
152 | } |
153 | |
154 | static int clk_aic32x4_pll_calc_muldiv(struct clk_aic32x4_pll_muldiv *settings, |
155 | unsigned long rate, unsigned long parent_rate) |
156 | { |
157 | u64 multiplier; |
158 | |
159 | settings->p = parent_rate / AIC32X4_MAX_PLL_CLKIN + 1; |
160 | if (settings->p > 8) |
161 | return -1; |
162 | |
163 | /* |
164 | * We scale this figure by 10000 so that we can get the decimal part |
165 | * of the multiplier. This is because we can't do floating point |
166 | * math in the kernel. |
167 | */ |
168 | multiplier = (u64) rate * settings->p * 10000; |
169 | do_div(multiplier, parent_rate); |
170 | |
171 | /* |
172 | * J can't be over 64, so R can scale this. |
173 | * R can't be greater than 4. |
174 | */ |
175 | settings->r = ((u32) multiplier / 640000) + 1; |
176 | if (settings->r > 4) |
177 | return -1; |
178 | do_div(multiplier, settings->r); |
179 | |
180 | /* |
181 | * J can't be < 1. |
182 | */ |
183 | if (multiplier < 10000) |
184 | return -1; |
185 | |
186 | /* Figure out the integer part, J, and the fractional part, D. */ |
187 | settings->j = (u32) multiplier / 10000; |
188 | settings->d = (u32) multiplier % 10000; |
189 | |
190 | return 0; |
191 | } |
192 | |
193 | static unsigned long clk_aic32x4_pll_recalc_rate(struct clk_hw *hw, |
194 | unsigned long parent_rate) |
195 | { |
196 | struct clk_aic32x4 *pll = to_clk_aic32x4(hw); |
197 | struct clk_aic32x4_pll_muldiv settings; |
198 | int ret; |
199 | |
200 | ret = clk_aic32x4_pll_get_muldiv(pll, settings: &settings); |
201 | if (ret < 0) |
202 | return 0; |
203 | |
204 | return clk_aic32x4_pll_calc_rate(settings: &settings, parent_rate); |
205 | } |
206 | |
207 | static int clk_aic32x4_pll_determine_rate(struct clk_hw *hw, |
208 | struct clk_rate_request *req) |
209 | { |
210 | struct clk_aic32x4_pll_muldiv settings; |
211 | int ret; |
212 | |
213 | ret = clk_aic32x4_pll_calc_muldiv(settings: &settings, rate: req->rate, parent_rate: req->best_parent_rate); |
214 | if (ret < 0) |
215 | return -EINVAL; |
216 | |
217 | req->rate = clk_aic32x4_pll_calc_rate(settings: &settings, parent_rate: req->best_parent_rate); |
218 | |
219 | return 0; |
220 | } |
221 | |
222 | static int clk_aic32x4_pll_set_rate(struct clk_hw *hw, |
223 | unsigned long rate, |
224 | unsigned long parent_rate) |
225 | { |
226 | struct clk_aic32x4 *pll = to_clk_aic32x4(hw); |
227 | struct clk_aic32x4_pll_muldiv settings; |
228 | int ret; |
229 | |
230 | ret = clk_aic32x4_pll_calc_muldiv(settings: &settings, rate, parent_rate); |
231 | if (ret < 0) |
232 | return -EINVAL; |
233 | |
234 | ret = clk_aic32x4_pll_set_muldiv(pll, settings: &settings); |
235 | if (ret) |
236 | return ret; |
237 | |
238 | /* 10ms is the delay to wait before the clocks are stable */ |
239 | msleep(msecs: 10); |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | static int clk_aic32x4_pll_set_parent(struct clk_hw *hw, u8 index) |
245 | { |
246 | struct clk_aic32x4 *pll = to_clk_aic32x4(hw); |
247 | |
248 | return regmap_update_bits(map: pll->regmap, |
249 | AIC32X4_CLKMUX, |
250 | AIC32X4_PLL_CLKIN_MASK, |
251 | val: index << AIC32X4_PLL_CLKIN_SHIFT); |
252 | } |
253 | |
254 | static u8 clk_aic32x4_pll_get_parent(struct clk_hw *hw) |
255 | { |
256 | struct clk_aic32x4 *pll = to_clk_aic32x4(hw); |
257 | unsigned int val; |
258 | |
259 | regmap_read(map: pll->regmap, AIC32X4_PLLPR, val: &val); |
260 | |
261 | return (val & AIC32X4_PLL_CLKIN_MASK) >> AIC32X4_PLL_CLKIN_SHIFT; |
262 | } |
263 | |
264 | |
265 | static const struct clk_ops aic32x4_pll_ops = { |
266 | .prepare = clk_aic32x4_pll_prepare, |
267 | .unprepare = clk_aic32x4_pll_unprepare, |
268 | .is_prepared = clk_aic32x4_pll_is_prepared, |
269 | .recalc_rate = clk_aic32x4_pll_recalc_rate, |
270 | .determine_rate = clk_aic32x4_pll_determine_rate, |
271 | .set_rate = clk_aic32x4_pll_set_rate, |
272 | .set_parent = clk_aic32x4_pll_set_parent, |
273 | .get_parent = clk_aic32x4_pll_get_parent, |
274 | }; |
275 | |
276 | static int clk_aic32x4_codec_clkin_set_parent(struct clk_hw *hw, u8 index) |
277 | { |
278 | struct clk_aic32x4 *mux = to_clk_aic32x4(hw); |
279 | |
280 | return regmap_update_bits(map: mux->regmap, |
281 | AIC32X4_CLKMUX, |
282 | AIC32X4_CODEC_CLKIN_MASK, val: index << AIC32X4_CODEC_CLKIN_SHIFT); |
283 | } |
284 | |
285 | static u8 clk_aic32x4_codec_clkin_get_parent(struct clk_hw *hw) |
286 | { |
287 | struct clk_aic32x4 *mux = to_clk_aic32x4(hw); |
288 | unsigned int val; |
289 | |
290 | regmap_read(map: mux->regmap, AIC32X4_CLKMUX, val: &val); |
291 | |
292 | return (val & AIC32X4_CODEC_CLKIN_MASK) >> AIC32X4_CODEC_CLKIN_SHIFT; |
293 | } |
294 | |
295 | static const struct clk_ops aic32x4_codec_clkin_ops = { |
296 | .determine_rate = clk_hw_determine_rate_no_reparent, |
297 | .set_parent = clk_aic32x4_codec_clkin_set_parent, |
298 | .get_parent = clk_aic32x4_codec_clkin_get_parent, |
299 | }; |
300 | |
301 | static int clk_aic32x4_div_prepare(struct clk_hw *hw) |
302 | { |
303 | struct clk_aic32x4 *div = to_clk_aic32x4(hw); |
304 | |
305 | return regmap_update_bits(map: div->regmap, reg: div->reg, |
306 | AIC32X4_DIVEN, AIC32X4_DIVEN); |
307 | } |
308 | |
309 | static void clk_aic32x4_div_unprepare(struct clk_hw *hw) |
310 | { |
311 | struct clk_aic32x4 *div = to_clk_aic32x4(hw); |
312 | |
313 | regmap_update_bits(map: div->regmap, reg: div->reg, |
314 | AIC32X4_DIVEN, val: 0); |
315 | } |
316 | |
317 | static int clk_aic32x4_div_set_rate(struct clk_hw *hw, unsigned long rate, |
318 | unsigned long parent_rate) |
319 | { |
320 | struct clk_aic32x4 *div = to_clk_aic32x4(hw); |
321 | u8 divisor; |
322 | |
323 | divisor = DIV_ROUND_UP(parent_rate, rate); |
324 | if (divisor > AIC32X4_DIV_MAX) |
325 | return -EINVAL; |
326 | |
327 | return regmap_update_bits(map: div->regmap, reg: div->reg, |
328 | AIC32X4_DIV_MASK, val: divisor); |
329 | } |
330 | |
331 | static int clk_aic32x4_div_determine_rate(struct clk_hw *hw, |
332 | struct clk_rate_request *req) |
333 | { |
334 | unsigned long divisor; |
335 | |
336 | divisor = DIV_ROUND_UP(req->best_parent_rate, req->rate); |
337 | if (divisor > AIC32X4_DIV_MAX) |
338 | return -EINVAL; |
339 | |
340 | req->rate = DIV_ROUND_UP(req->best_parent_rate, divisor); |
341 | return 0; |
342 | } |
343 | |
344 | static unsigned long clk_aic32x4_div_recalc_rate(struct clk_hw *hw, |
345 | unsigned long parent_rate) |
346 | { |
347 | struct clk_aic32x4 *div = to_clk_aic32x4(hw); |
348 | unsigned int val; |
349 | int err; |
350 | |
351 | err = regmap_read(map: div->regmap, reg: div->reg, val: &val); |
352 | if (err) |
353 | return 0; |
354 | |
355 | val &= AIC32X4_DIV_MASK; |
356 | if (!val) |
357 | val = AIC32X4_DIV_MAX; |
358 | |
359 | return DIV_ROUND_UP(parent_rate, val); |
360 | } |
361 | |
362 | static const struct clk_ops aic32x4_div_ops = { |
363 | .prepare = clk_aic32x4_div_prepare, |
364 | .unprepare = clk_aic32x4_div_unprepare, |
365 | .set_rate = clk_aic32x4_div_set_rate, |
366 | .determine_rate = clk_aic32x4_div_determine_rate, |
367 | .recalc_rate = clk_aic32x4_div_recalc_rate, |
368 | }; |
369 | |
370 | static int clk_aic32x4_bdiv_set_parent(struct clk_hw *hw, u8 index) |
371 | { |
372 | struct clk_aic32x4 *mux = to_clk_aic32x4(hw); |
373 | |
374 | return regmap_update_bits(map: mux->regmap, AIC32X4_IFACE3, |
375 | AIC32X4_BDIVCLK_MASK, val: index); |
376 | } |
377 | |
378 | static u8 clk_aic32x4_bdiv_get_parent(struct clk_hw *hw) |
379 | { |
380 | struct clk_aic32x4 *mux = to_clk_aic32x4(hw); |
381 | unsigned int val; |
382 | |
383 | regmap_read(map: mux->regmap, AIC32X4_IFACE3, val: &val); |
384 | |
385 | return val & AIC32X4_BDIVCLK_MASK; |
386 | } |
387 | |
388 | static const struct clk_ops aic32x4_bdiv_ops = { |
389 | .prepare = clk_aic32x4_div_prepare, |
390 | .unprepare = clk_aic32x4_div_unprepare, |
391 | .set_parent = clk_aic32x4_bdiv_set_parent, |
392 | .get_parent = clk_aic32x4_bdiv_get_parent, |
393 | .set_rate = clk_aic32x4_div_set_rate, |
394 | .determine_rate = clk_aic32x4_div_determine_rate, |
395 | .recalc_rate = clk_aic32x4_div_recalc_rate, |
396 | }; |
397 | |
398 | static struct aic32x4_clkdesc aic32x4_clkdesc_array[] = { |
399 | { |
400 | .name = "pll" , |
401 | .parent_names = |
402 | (const char* []) { "mclk" , "bclk" , "gpio" , "din" }, |
403 | .num_parents = 4, |
404 | .ops = &aic32x4_pll_ops, |
405 | .reg = 0, |
406 | }, |
407 | { |
408 | .name = "codec_clkin" , |
409 | .parent_names = |
410 | (const char *[]) { "mclk" , "bclk" , "gpio" , "pll" }, |
411 | .num_parents = 4, |
412 | .ops = &aic32x4_codec_clkin_ops, |
413 | .reg = 0, |
414 | }, |
415 | { |
416 | .name = "ndac" , |
417 | .parent_names = (const char * []) { "codec_clkin" }, |
418 | .num_parents = 1, |
419 | .ops = &aic32x4_div_ops, |
420 | .reg = AIC32X4_NDAC, |
421 | }, |
422 | { |
423 | .name = "mdac" , |
424 | .parent_names = (const char * []) { "ndac" }, |
425 | .num_parents = 1, |
426 | .ops = &aic32x4_div_ops, |
427 | .reg = AIC32X4_MDAC, |
428 | }, |
429 | { |
430 | .name = "nadc" , |
431 | .parent_names = (const char * []) { "codec_clkin" }, |
432 | .num_parents = 1, |
433 | .ops = &aic32x4_div_ops, |
434 | .reg = AIC32X4_NADC, |
435 | }, |
436 | { |
437 | .name = "madc" , |
438 | .parent_names = (const char * []) { "nadc" }, |
439 | .num_parents = 1, |
440 | .ops = &aic32x4_div_ops, |
441 | .reg = AIC32X4_MADC, |
442 | }, |
443 | { |
444 | .name = "bdiv" , |
445 | .parent_names = |
446 | (const char *[]) { "ndac" , "mdac" , "nadc" , "madc" }, |
447 | .num_parents = 4, |
448 | .ops = &aic32x4_bdiv_ops, |
449 | .reg = AIC32X4_BCLKN, |
450 | }, |
451 | }; |
452 | |
453 | static struct clk *aic32x4_register_clk(struct device *dev, |
454 | struct aic32x4_clkdesc *desc) |
455 | { |
456 | struct clk_init_data init; |
457 | struct clk_aic32x4 *priv; |
458 | const char *devname = dev_name(dev); |
459 | |
460 | init.ops = desc->ops; |
461 | init.name = desc->name; |
462 | init.parent_names = desc->parent_names; |
463 | init.num_parents = desc->num_parents; |
464 | init.flags = 0; |
465 | |
466 | priv = devm_kzalloc(dev, size: sizeof(struct clk_aic32x4), GFP_KERNEL); |
467 | if (priv == NULL) |
468 | return (struct clk *) -ENOMEM; |
469 | |
470 | priv->dev = dev; |
471 | priv->hw.init = &init; |
472 | priv->regmap = dev_get_regmap(dev, NULL); |
473 | priv->reg = desc->reg; |
474 | |
475 | clk_hw_register_clkdev(&priv->hw, desc->name, devname); |
476 | return devm_clk_register(dev, hw: &priv->hw); |
477 | } |
478 | |
479 | int aic32x4_register_clocks(struct device *dev, const char *mclk_name) |
480 | { |
481 | int i; |
482 | |
483 | /* |
484 | * These lines are here to preserve the current functionality of |
485 | * the driver with regard to the DT. These should eventually be set |
486 | * by DT nodes so that the connections can be set up in configuration |
487 | * rather than code. |
488 | */ |
489 | aic32x4_clkdesc_array[0].parent_names = |
490 | (const char* []) { mclk_name, "bclk" , "gpio" , "din" }; |
491 | aic32x4_clkdesc_array[1].parent_names = |
492 | (const char *[]) { mclk_name, "bclk" , "gpio" , "pll" }; |
493 | |
494 | for (i = 0; i < ARRAY_SIZE(aic32x4_clkdesc_array); ++i) |
495 | aic32x4_register_clk(dev, desc: &aic32x4_clkdesc_array[i]); |
496 | |
497 | return 0; |
498 | } |
499 | EXPORT_SYMBOL_GPL(aic32x4_register_clocks); |
500 | |