xref: /openbmc/linux/drivers/clk/ti/dpll.c (revision afc98d90)
1 /*
2  * OMAP DPLL clock support
3  *
4  * Copyright (C) 2013 Texas Instruments, Inc.
5  *
6  * Tero Kristo <t-kristo@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13  * kind, whether express or implied; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17 
18 #include <linux/clk-provider.h>
19 #include <linux/slab.h>
20 #include <linux/err.h>
21 #include <linux/of.h>
22 #include <linux/of_address.h>
23 #include <linux/clk/ti.h>
24 
25 #undef pr_fmt
26 #define pr_fmt(fmt) "%s: " fmt, __func__
27 
28 #define DPLL_HAS_AUTOIDLE	0x1
29 
30 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
31 	defined(CONFIG_SOC_DRA7XX)
32 static const struct clk_ops dpll_m4xen_ck_ops = {
33 	.enable		= &omap3_noncore_dpll_enable,
34 	.disable	= &omap3_noncore_dpll_disable,
35 	.recalc_rate	= &omap4_dpll_regm4xen_recalc,
36 	.round_rate	= &omap4_dpll_regm4xen_round_rate,
37 	.set_rate	= &omap3_noncore_dpll_set_rate,
38 	.get_parent	= &omap2_init_dpll_parent,
39 };
40 #endif
41 
42 static const struct clk_ops dpll_core_ck_ops = {
43 	.recalc_rate	= &omap3_dpll_recalc,
44 	.get_parent	= &omap2_init_dpll_parent,
45 };
46 
47 #ifdef CONFIG_ARCH_OMAP3
48 static const struct clk_ops omap3_dpll_core_ck_ops = {
49 	.get_parent	= &omap2_init_dpll_parent,
50 	.recalc_rate	= &omap3_dpll_recalc,
51 	.round_rate	= &omap2_dpll_round_rate,
52 };
53 #endif
54 
55 static const struct clk_ops dpll_ck_ops = {
56 	.enable		= &omap3_noncore_dpll_enable,
57 	.disable	= &omap3_noncore_dpll_disable,
58 	.recalc_rate	= &omap3_dpll_recalc,
59 	.round_rate	= &omap2_dpll_round_rate,
60 	.set_rate	= &omap3_noncore_dpll_set_rate,
61 	.get_parent	= &omap2_init_dpll_parent,
62 };
63 
64 static const struct clk_ops dpll_no_gate_ck_ops = {
65 	.recalc_rate	= &omap3_dpll_recalc,
66 	.get_parent	= &omap2_init_dpll_parent,
67 	.round_rate	= &omap2_dpll_round_rate,
68 	.set_rate	= &omap3_noncore_dpll_set_rate,
69 };
70 
71 #ifdef CONFIG_ARCH_OMAP3
72 static const struct clk_ops omap3_dpll_ck_ops = {
73 	.enable		= &omap3_noncore_dpll_enable,
74 	.disable	= &omap3_noncore_dpll_disable,
75 	.get_parent	= &omap2_init_dpll_parent,
76 	.recalc_rate	= &omap3_dpll_recalc,
77 	.set_rate	= &omap3_noncore_dpll_set_rate,
78 	.round_rate	= &omap2_dpll_round_rate,
79 };
80 
81 static const struct clk_ops omap3_dpll_per_ck_ops = {
82 	.enable		= &omap3_noncore_dpll_enable,
83 	.disable	= &omap3_noncore_dpll_disable,
84 	.get_parent	= &omap2_init_dpll_parent,
85 	.recalc_rate	= &omap3_dpll_recalc,
86 	.set_rate	= &omap3_dpll4_set_rate,
87 	.round_rate	= &omap2_dpll_round_rate,
88 };
89 #endif
90 
91 static const struct clk_ops dpll_x2_ck_ops = {
92 	.recalc_rate	= &omap3_clkoutx2_recalc,
93 };
94 
95 /**
96  * ti_clk_register_dpll - low level registration of a DPLL clock
97  * @hw: hardware clock definition for the clock
98  * @node: device node for the clock
99  *
100  * Finalizes DPLL registration process. In case a failure (clk-ref or
101  * clk-bypass is missing), the clock is added to retry list and
102  * the initialization is retried on later stage.
103  */
104 static void __init ti_clk_register_dpll(struct clk_hw *hw,
105 					struct device_node *node)
106 {
107 	struct clk_hw_omap *clk_hw = to_clk_hw_omap(hw);
108 	struct dpll_data *dd = clk_hw->dpll_data;
109 	struct clk *clk;
110 
111 	dd->clk_ref = of_clk_get(node, 0);
112 	dd->clk_bypass = of_clk_get(node, 1);
113 
114 	if (IS_ERR(dd->clk_ref) || IS_ERR(dd->clk_bypass)) {
115 		pr_debug("clk-ref or clk-bypass missing for %s, retry later\n",
116 			 node->name);
117 		if (!ti_clk_retry_init(node, hw, ti_clk_register_dpll))
118 			return;
119 
120 		goto cleanup;
121 	}
122 
123 	/* register the clock */
124 	clk = clk_register(NULL, &clk_hw->hw);
125 
126 	if (!IS_ERR(clk)) {
127 		omap2_init_clk_hw_omap_clocks(clk);
128 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
129 		kfree(clk_hw->hw.init->parent_names);
130 		kfree(clk_hw->hw.init);
131 		return;
132 	}
133 
134 cleanup:
135 	kfree(clk_hw->dpll_data);
136 	kfree(clk_hw->hw.init->parent_names);
137 	kfree(clk_hw->hw.init);
138 	kfree(clk_hw);
139 }
140 
141 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
142 	defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX)
143 /**
144  * ti_clk_register_dpll_x2 - Registers a DPLLx2 clock
145  * @node: device node for this clock
146  * @ops: clk_ops for this clock
147  * @hw_ops: clk_hw_ops for this clock
148  *
149  * Initializes a DPLL x 2 clock from device tree data.
150  */
151 static void ti_clk_register_dpll_x2(struct device_node *node,
152 				    const struct clk_ops *ops,
153 				    const struct clk_hw_omap_ops *hw_ops)
154 {
155 	struct clk *clk;
156 	struct clk_init_data init = { NULL };
157 	struct clk_hw_omap *clk_hw;
158 	const char *name = node->name;
159 	const char *parent_name;
160 
161 	parent_name = of_clk_get_parent_name(node, 0);
162 	if (!parent_name) {
163 		pr_err("%s must have parent\n", node->name);
164 		return;
165 	}
166 
167 	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
168 	if (!clk_hw)
169 		return;
170 
171 	clk_hw->ops = hw_ops;
172 	clk_hw->hw.init = &init;
173 
174 	init.name = name;
175 	init.ops = ops;
176 	init.parent_names = &parent_name;
177 	init.num_parents = 1;
178 
179 	/* register the clock */
180 	clk = clk_register(NULL, &clk_hw->hw);
181 
182 	if (IS_ERR(clk)) {
183 		kfree(clk_hw);
184 	} else {
185 		omap2_init_clk_hw_omap_clocks(clk);
186 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
187 	}
188 }
189 #endif
190 
191 /**
192  * of_ti_dpll_setup - Setup function for OMAP DPLL clocks
193  * @node: device node containing the DPLL info
194  * @ops: ops for the DPLL
195  * @ddt: DPLL data template to use
196  * @init_flags: flags for controlling init types
197  *
198  * Initializes a DPLL clock from device tree data.
199  */
200 static void __init of_ti_dpll_setup(struct device_node *node,
201 				    const struct clk_ops *ops,
202 				    const struct dpll_data *ddt,
203 				    u8 init_flags)
204 {
205 	struct clk_hw_omap *clk_hw = NULL;
206 	struct clk_init_data *init = NULL;
207 	const char **parent_names = NULL;
208 	struct dpll_data *dd = NULL;
209 	int i;
210 	u8 dpll_mode = 0;
211 
212 	dd = kzalloc(sizeof(*dd), GFP_KERNEL);
213 	clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
214 	init = kzalloc(sizeof(*init), GFP_KERNEL);
215 	if (!dd || !clk_hw || !init)
216 		goto cleanup;
217 
218 	memcpy(dd, ddt, sizeof(*dd));
219 
220 	clk_hw->dpll_data = dd;
221 	clk_hw->ops = &clkhwops_omap3_dpll;
222 	clk_hw->hw.init = init;
223 	clk_hw->flags = MEMMAP_ADDRESSING;
224 
225 	init->name = node->name;
226 	init->ops = ops;
227 
228 	init->num_parents = of_clk_get_parent_count(node);
229 	if (init->num_parents < 1) {
230 		pr_err("%s must have parent(s)\n", node->name);
231 		goto cleanup;
232 	}
233 
234 	parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);
235 	if (!parent_names)
236 		goto cleanup;
237 
238 	for (i = 0; i < init->num_parents; i++)
239 		parent_names[i] = of_clk_get_parent_name(node, i);
240 
241 	init->parent_names = parent_names;
242 
243 	dd->control_reg = ti_clk_get_reg_addr(node, 0);
244 	dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
245 	dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
246 
247 	if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg)
248 		goto cleanup;
249 
250 	if (init_flags & DPLL_HAS_AUTOIDLE) {
251 		dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
252 		if (!dd->autoidle_reg)
253 			goto cleanup;
254 	}
255 
256 	if (of_property_read_bool(node, "ti,low-power-stop"))
257 		dpll_mode |= 1 << DPLL_LOW_POWER_STOP;
258 
259 	if (of_property_read_bool(node, "ti,low-power-bypass"))
260 		dpll_mode |= 1 << DPLL_LOW_POWER_BYPASS;
261 
262 	if (of_property_read_bool(node, "ti,lock"))
263 		dpll_mode |= 1 << DPLL_LOCKED;
264 
265 	if (dpll_mode)
266 		dd->modes = dpll_mode;
267 
268 	ti_clk_register_dpll(&clk_hw->hw, node);
269 	return;
270 
271 cleanup:
272 	kfree(dd);
273 	kfree(parent_names);
274 	kfree(init);
275 	kfree(clk_hw);
276 }
277 
278 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
279 	defined(CONFIG_SOC_DRA7XX)
280 static void __init of_ti_omap4_dpll_x2_setup(struct device_node *node)
281 {
282 	ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, &clkhwops_omap4_dpllmx);
283 }
284 CLK_OF_DECLARE(ti_omap4_dpll_x2_clock, "ti,omap4-dpll-x2-clock",
285 	       of_ti_omap4_dpll_x2_setup);
286 #endif
287 
288 #ifdef CONFIG_SOC_AM33XX
289 static void __init of_ti_am3_dpll_x2_setup(struct device_node *node)
290 {
291 	ti_clk_register_dpll_x2(node, &dpll_x2_ck_ops, NULL);
292 }
293 CLK_OF_DECLARE(ti_am3_dpll_x2_clock, "ti,am3-dpll-x2-clock",
294 	       of_ti_am3_dpll_x2_setup);
295 #endif
296 
297 #ifdef CONFIG_ARCH_OMAP3
298 static void __init of_ti_omap3_dpll_setup(struct device_node *node)
299 {
300 	const struct dpll_data dd = {
301 		.idlest_mask = 0x1,
302 		.enable_mask = 0x7,
303 		.autoidle_mask = 0x7,
304 		.mult_mask = 0x7ff << 8,
305 		.div1_mask = 0x7f,
306 		.max_multiplier = 2047,
307 		.max_divider = 128,
308 		.min_divider = 1,
309 		.freqsel_mask = 0xf0,
310 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
311 	};
312 
313 	of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
314 }
315 CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
316 	       of_ti_omap3_dpll_setup);
317 
318 static void __init of_ti_omap3_core_dpll_setup(struct device_node *node)
319 {
320 	const struct dpll_data dd = {
321 		.idlest_mask = 0x1,
322 		.enable_mask = 0x7,
323 		.autoidle_mask = 0x7,
324 		.mult_mask = 0x7ff << 16,
325 		.div1_mask = 0x7f << 8,
326 		.max_multiplier = 2047,
327 		.max_divider = 128,
328 		.min_divider = 1,
329 		.freqsel_mask = 0xf0,
330 	};
331 
332 	of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
333 }
334 CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock",
335 	       of_ti_omap3_core_dpll_setup);
336 
337 static void __init of_ti_omap3_per_dpll_setup(struct device_node *node)
338 {
339 	const struct dpll_data dd = {
340 		.idlest_mask = 0x1 << 1,
341 		.enable_mask = 0x7 << 16,
342 		.autoidle_mask = 0x7 << 3,
343 		.mult_mask = 0x7ff << 8,
344 		.div1_mask = 0x7f,
345 		.max_multiplier = 2047,
346 		.max_divider = 128,
347 		.min_divider = 1,
348 		.freqsel_mask = 0xf00000,
349 		.modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
350 	};
351 
352 	of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
353 }
354 CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock",
355 	       of_ti_omap3_per_dpll_setup);
356 
357 static void __init of_ti_omap3_per_jtype_dpll_setup(struct device_node *node)
358 {
359 	const struct dpll_data dd = {
360 		.idlest_mask = 0x1 << 1,
361 		.enable_mask = 0x7 << 16,
362 		.autoidle_mask = 0x7 << 3,
363 		.mult_mask = 0xfff << 8,
364 		.div1_mask = 0x7f,
365 		.max_multiplier = 4095,
366 		.max_divider = 128,
367 		.min_divider = 1,
368 		.sddiv_mask = 0xff << 24,
369 		.dco_mask = 0xe << 20,
370 		.flags = DPLL_J_TYPE,
371 		.modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
372 	};
373 
374 	of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
375 }
376 CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock",
377 	       of_ti_omap3_per_jtype_dpll_setup);
378 #endif
379 
380 static void __init of_ti_omap4_dpll_setup(struct device_node *node)
381 {
382 	const struct dpll_data dd = {
383 		.idlest_mask = 0x1,
384 		.enable_mask = 0x7,
385 		.autoidle_mask = 0x7,
386 		.mult_mask = 0x7ff << 8,
387 		.div1_mask = 0x7f,
388 		.max_multiplier = 2047,
389 		.max_divider = 128,
390 		.min_divider = 1,
391 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
392 	};
393 
394 	of_ti_dpll_setup(node, &dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
395 }
396 CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock",
397 	       of_ti_omap4_dpll_setup);
398 
399 static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
400 {
401 	const struct dpll_data dd = {
402 		.idlest_mask = 0x1,
403 		.enable_mask = 0x7,
404 		.autoidle_mask = 0x7,
405 		.mult_mask = 0x7ff << 8,
406 		.div1_mask = 0x7f,
407 		.max_multiplier = 2047,
408 		.max_divider = 128,
409 		.min_divider = 1,
410 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
411 	};
412 
413 	of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
414 }
415 CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock",
416 	       of_ti_omap4_core_dpll_setup);
417 
418 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
419 	defined(CONFIG_SOC_DRA7XX)
420 static void __init of_ti_omap4_m4xen_dpll_setup(struct device_node *node)
421 {
422 	const struct dpll_data dd = {
423 		.idlest_mask = 0x1,
424 		.enable_mask = 0x7,
425 		.autoidle_mask = 0x7,
426 		.mult_mask = 0x7ff << 8,
427 		.div1_mask = 0x7f,
428 		.max_multiplier = 2047,
429 		.max_divider = 128,
430 		.min_divider = 1,
431 		.m4xen_mask = 0x800,
432 		.lpmode_mask = 1 << 10,
433 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
434 	};
435 
436 	of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
437 }
438 CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock",
439 	       of_ti_omap4_m4xen_dpll_setup);
440 
441 static void __init of_ti_omap4_jtype_dpll_setup(struct device_node *node)
442 {
443 	const struct dpll_data dd = {
444 		.idlest_mask = 0x1,
445 		.enable_mask = 0x7,
446 		.autoidle_mask = 0x7,
447 		.mult_mask = 0xfff << 8,
448 		.div1_mask = 0xff,
449 		.max_multiplier = 4095,
450 		.max_divider = 256,
451 		.min_divider = 1,
452 		.sddiv_mask = 0xff << 24,
453 		.flags = DPLL_J_TYPE,
454 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
455 	};
456 
457 	of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
458 }
459 CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock",
460 	       of_ti_omap4_jtype_dpll_setup);
461 #endif
462 
463 static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
464 {
465 	const struct dpll_data dd = {
466 		.idlest_mask = 0x1,
467 		.enable_mask = 0x7,
468 		.autoidle_mask = 0x7,
469 		.mult_mask = 0x7ff << 8,
470 		.div1_mask = 0x7f,
471 		.max_multiplier = 2047,
472 		.max_divider = 128,
473 		.min_divider = 1,
474 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
475 	};
476 
477 	of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
478 }
479 CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock",
480 	       of_ti_am3_no_gate_dpll_setup);
481 
482 static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
483 {
484 	const struct dpll_data dd = {
485 		.idlest_mask = 0x1,
486 		.enable_mask = 0x7,
487 		.autoidle_mask = 0x7,
488 		.mult_mask = 0x7ff << 8,
489 		.div1_mask = 0x7f,
490 		.max_multiplier = 4095,
491 		.max_divider = 256,
492 		.min_divider = 2,
493 		.flags = DPLL_J_TYPE,
494 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
495 	};
496 
497 	of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
498 }
499 CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock",
500 	       of_ti_am3_jtype_dpll_setup);
501 
502 static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
503 {
504 	const struct dpll_data dd = {
505 		.idlest_mask = 0x1,
506 		.enable_mask = 0x7,
507 		.autoidle_mask = 0x7,
508 		.mult_mask = 0x7ff << 8,
509 		.div1_mask = 0x7f,
510 		.max_multiplier = 2047,
511 		.max_divider = 128,
512 		.min_divider = 1,
513 		.flags = DPLL_J_TYPE,
514 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
515 	};
516 
517 	of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
518 }
519 CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock,
520 	       "ti,am3-dpll-no-gate-j-type-clock",
521 	       of_ti_am3_no_gate_jtype_dpll_setup);
522 
523 static void __init of_ti_am3_dpll_setup(struct device_node *node)
524 {
525 	const struct dpll_data dd = {
526 		.idlest_mask = 0x1,
527 		.enable_mask = 0x7,
528 		.autoidle_mask = 0x7,
529 		.mult_mask = 0x7ff << 8,
530 		.div1_mask = 0x7f,
531 		.max_multiplier = 2047,
532 		.max_divider = 128,
533 		.min_divider = 1,
534 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
535 	};
536 
537 	of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
538 }
539 CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup);
540 
541 static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
542 {
543 	const struct dpll_data dd = {
544 		.idlest_mask = 0x1,
545 		.enable_mask = 0x7,
546 		.autoidle_mask = 0x7,
547 		.mult_mask = 0x7ff << 8,
548 		.div1_mask = 0x7f,
549 		.max_multiplier = 2047,
550 		.max_divider = 128,
551 		.min_divider = 1,
552 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
553 	};
554 
555 	of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, 0);
556 }
557 CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock",
558 	       of_ti_am3_core_dpll_setup);
559