xref: /linux/drivers/clk/clk-fixed-factor.c (revision cd1cb38836c0fc597718f300f7d19fcea1117a3c)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
4  */
5 #include <linux/module.h>
6 #include <linux/clk-provider.h>
7 #include <linux/slab.h>
8 #include <linux/err.h>
9 #include <linux/of.h>
10 #include <linux/platform_device.h>
11 
12 /*
13  * DOC: basic fixed multiplier and divider clock that cannot gate
14  *
15  * Traits of this clock:
16  * prepare - clk_prepare only ensures that parents are prepared
17  * enable - clk_enable only ensures that parents are enabled
18  * rate - rate is fixed.  clk->rate = parent->rate / div * mult
19  * parent - fixed parent.  No clk_set_parent support
20  */
21 
22 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
23 		unsigned long parent_rate)
24 {
25 	struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
26 	unsigned long long int rate;
27 
28 	rate = (unsigned long long int)parent_rate * fix->mult;
29 	do_div(rate, fix->div);
30 	return (unsigned long)rate;
31 }
32 
33 static int clk_factor_determine_rate(struct clk_hw *hw,
34 				     struct clk_rate_request *req)
35 {
36 	struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
37 
38 	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
39 		unsigned long best_parent;
40 
41 		best_parent = (req->rate / fix->mult) * fix->div;
42 		req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
43 	}
44 
45 	req->rate = (req->best_parent_rate / fix->div) * fix->mult;
46 
47 	return 0;
48 }
49 
50 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long rate,
51 				unsigned long *prate)
52 {
53 	struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
54 
55 	if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
56 		unsigned long best_parent;
57 
58 		best_parent = (rate / fix->mult) * fix->div;
59 		*prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
60 	}
61 
62 	return (*prate / fix->div) * fix->mult;
63 }
64 
65 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
66 				unsigned long parent_rate)
67 {
68 	/*
69 	 * We must report success but we can do so unconditionally because
70 	 * clk_factor_determine_rate returns values that ensure this call is a
71 	 * nop.
72 	 */
73 
74 	return 0;
75 }
76 
77 static unsigned long clk_factor_recalc_accuracy(struct clk_hw *hw,
78 						unsigned long parent_accuracy)
79 {
80 	struct clk_fixed_factor *fix = to_clk_fixed_factor(hw);
81 
82 	if (fix->flags & CLK_FIXED_FACTOR_FIXED_ACCURACY)
83 		return fix->acc;
84 
85 	return parent_accuracy;
86 }
87 
88 const struct clk_ops clk_fixed_factor_ops = {
89 	.determine_rate = clk_factor_determine_rate,
90 	.round_rate = clk_factor_round_rate,
91 	.set_rate = clk_factor_set_rate,
92 	.recalc_rate = clk_factor_recalc_rate,
93 	.recalc_accuracy = clk_factor_recalc_accuracy,
94 };
95 EXPORT_SYMBOL_GPL(clk_fixed_factor_ops);
96 
97 static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void *res)
98 {
99 	struct clk_fixed_factor *fix = res;
100 
101 	/*
102 	 * We can not use clk_hw_unregister_fixed_factor, since it will kfree()
103 	 * the hw, resulting in double free. Just unregister the hw and let
104 	 * devres code kfree() it.
105 	 */
106 	clk_hw_unregister(&fix->hw);
107 }
108 
109 static struct clk_hw *
110 __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
111 		const char *name, const char *parent_name,
112 		const struct clk_hw *parent_hw, const struct clk_parent_data *pdata,
113 		unsigned long flags, unsigned int mult, unsigned int div,
114 		unsigned long acc, unsigned int fixflags, bool devm)
115 {
116 	struct clk_fixed_factor *fix;
117 	struct clk_init_data init = { };
118 	struct clk_hw *hw;
119 	int ret;
120 
121 	/* You can't use devm without a dev */
122 	if (devm && !dev)
123 		return ERR_PTR(-EINVAL);
124 
125 	if (devm)
126 		fix = devres_alloc(devm_clk_hw_register_fixed_factor_release,
127 				sizeof(*fix), GFP_KERNEL);
128 	else
129 		fix = kmalloc(sizeof(*fix), GFP_KERNEL);
130 	if (!fix)
131 		return ERR_PTR(-ENOMEM);
132 
133 	/* struct clk_fixed_factor assignments */
134 	fix->mult = mult;
135 	fix->div = div;
136 	fix->hw.init = &init;
137 	fix->acc = acc;
138 	fix->flags = fixflags;
139 
140 	init.name = name;
141 	init.ops = &clk_fixed_factor_ops;
142 	init.flags = flags;
143 	if (parent_name)
144 		init.parent_names = &parent_name;
145 	else if (parent_hw)
146 		init.parent_hws = &parent_hw;
147 	else
148 		init.parent_data = pdata;
149 	init.num_parents = 1;
150 
151 	hw = &fix->hw;
152 	if (dev)
153 		ret = clk_hw_register(dev, hw);
154 	else
155 		ret = of_clk_hw_register(np, hw);
156 	if (ret) {
157 		if (devm)
158 			devres_free(fix);
159 		else
160 			kfree(fix);
161 		hw = ERR_PTR(ret);
162 	} else if (devm)
163 		devres_add(dev, fix);
164 
165 	return hw;
166 }
167 
168 /**
169  * devm_clk_hw_register_fixed_factor_index - Register a fixed factor clock with
170  * parent from DT index
171  * @dev: device that is registering this clock
172  * @name: name of this clock
173  * @index: index of phandle in @dev 'clocks' property
174  * @flags: fixed factor flags
175  * @mult: multiplier
176  * @div: divider
177  *
178  * Return: Pointer to fixed factor clk_hw structure that was registered or
179  * an error pointer.
180  */
181 struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev,
182 		const char *name, unsigned int index, unsigned long flags,
183 		unsigned int mult, unsigned int div)
184 {
185 	const struct clk_parent_data pdata = { .index = index };
186 
187 	return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, NULL, &pdata,
188 					      flags, mult, div, 0, 0, true);
189 }
190 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_index);
191 
192 /**
193  * devm_clk_hw_register_fixed_factor_parent_hw - Register a fixed factor clock with
194  * pointer to parent clock
195  * @dev: device that is registering this clock
196  * @name: name of this clock
197  * @parent_hw: pointer to parent clk
198  * @flags: fixed factor flags
199  * @mult: multiplier
200  * @div: divider
201  *
202  * Return: Pointer to fixed factor clk_hw structure that was registered or
203  * an error pointer.
204  */
205 struct clk_hw *devm_clk_hw_register_fixed_factor_parent_hw(struct device *dev,
206 		const char *name, const struct clk_hw *parent_hw,
207 		unsigned long flags, unsigned int mult, unsigned int div)
208 {
209 	const struct clk_parent_data pdata = { .index = -1 };
210 
211 	return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, parent_hw,
212 					      &pdata, flags, mult, div, 0, 0, true);
213 }
214 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_parent_hw);
215 
216 struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev,
217 		const char *name, const struct clk_hw *parent_hw,
218 		unsigned long flags, unsigned int mult, unsigned int div)
219 {
220 	const struct clk_parent_data pdata = { .index = -1 };
221 
222 	return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, parent_hw,
223 					      &pdata, flags, mult, div, 0, 0, false);
224 }
225 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_parent_hw);
226 
227 struct clk_hw *clk_hw_register_fixed_factor(struct device *dev,
228 		const char *name, const char *parent_name, unsigned long flags,
229 		unsigned int mult, unsigned int div)
230 {
231 	const struct clk_parent_data pdata = { .index = -1 };
232 
233 	return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL,
234 					      &pdata, flags, mult, div, 0, 0, false);
235 }
236 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor);
237 
238 struct clk_hw *clk_hw_register_fixed_factor_fwname(struct device *dev,
239 		struct device_node *np, const char *name, const char *fw_name,
240 		unsigned long flags, unsigned int mult, unsigned int div)
241 {
242 	const struct clk_parent_data pdata = { .index = -1, .fw_name = fw_name };
243 
244 	return __clk_hw_register_fixed_factor(dev, np, name, NULL, NULL,
245 			&pdata, flags, mult, div, 0, 0, false);
246 }
247 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_fwname);
248 
249 struct clk_hw *clk_hw_register_fixed_factor_with_accuracy_fwname(struct device *dev,
250 		struct device_node *np, const char *name, const char *fw_name,
251 		unsigned long flags, unsigned int mult, unsigned int div,
252 		unsigned long acc)
253 {
254 	const struct clk_parent_data pdata = { .index = -1, .fw_name = fw_name };
255 
256 	return __clk_hw_register_fixed_factor(dev, np, name, NULL, NULL,
257 			&pdata, flags, mult, div, acc,
258 			CLK_FIXED_FACTOR_FIXED_ACCURACY, false);
259 }
260 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_with_accuracy_fwname);
261 
262 struct clk_hw *clk_hw_register_fixed_factor_index(struct device *dev,
263 		const char *name, unsigned int index, unsigned long flags,
264 		unsigned int mult, unsigned int div)
265 {
266 	const struct clk_parent_data pdata = { .index = index };
267 
268 	return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, NULL, &pdata,
269 					      flags, mult, div, 0, 0, false);
270 }
271 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_index);
272 
273 struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
274 		const char *parent_name, unsigned long flags,
275 		unsigned int mult, unsigned int div)
276 {
277 	struct clk_hw *hw;
278 
279 	hw = clk_hw_register_fixed_factor(dev, name, parent_name, flags, mult,
280 					  div);
281 	if (IS_ERR(hw))
282 		return ERR_CAST(hw);
283 	return hw->clk;
284 }
285 EXPORT_SYMBOL_GPL(clk_register_fixed_factor);
286 
287 void clk_unregister_fixed_factor(struct clk *clk)
288 {
289 	struct clk_hw *hw;
290 
291 	hw = __clk_get_hw(clk);
292 	if (!hw)
293 		return;
294 
295 	clk_unregister(clk);
296 	kfree(to_clk_fixed_factor(hw));
297 }
298 EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor);
299 
300 void clk_hw_unregister_fixed_factor(struct clk_hw *hw)
301 {
302 	struct clk_fixed_factor *fix;
303 
304 	fix = to_clk_fixed_factor(hw);
305 
306 	clk_hw_unregister(hw);
307 	kfree(fix);
308 }
309 EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor);
310 
311 struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev,
312 		const char *name, const char *parent_name, unsigned long flags,
313 		unsigned int mult, unsigned int div)
314 {
315 	const struct clk_parent_data pdata = { .index = -1 };
316 
317 	return __clk_hw_register_fixed_factor(dev, NULL, name, parent_name, NULL,
318 			&pdata, flags, mult, div, 0, 0, true);
319 }
320 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor);
321 
322 struct clk_hw *devm_clk_hw_register_fixed_factor_fwname(struct device *dev,
323 		struct device_node *np, const char *name, const char *fw_name,
324 		unsigned long flags, unsigned int mult, unsigned int div)
325 {
326 	const struct clk_parent_data pdata = { .index = -1, .fw_name = fw_name };
327 
328 	return __clk_hw_register_fixed_factor(dev, np, name, NULL, NULL,
329 			&pdata, flags, mult, div, 0, 0, true);
330 }
331 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_fwname);
332 
333 struct clk_hw *devm_clk_hw_register_fixed_factor_with_accuracy_fwname(struct device *dev,
334 		struct device_node *np, const char *name, const char *fw_name,
335 		unsigned long flags, unsigned int mult, unsigned int div,
336 		unsigned long acc)
337 {
338 	const struct clk_parent_data pdata = { .index = -1, .fw_name = fw_name };
339 
340 	return __clk_hw_register_fixed_factor(dev, np, name, NULL, NULL,
341 			&pdata, flags, mult, div, acc,
342 			CLK_FIXED_FACTOR_FIXED_ACCURACY, true);
343 }
344 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_with_accuracy_fwname);
345 
346 #ifdef CONFIG_OF
347 static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node)
348 {
349 	struct clk_hw *hw;
350 	const char *clk_name = node->name;
351 	const struct clk_parent_data pdata = { .index = 0 };
352 	u32 div, mult;
353 	int ret;
354 
355 	if (of_property_read_u32(node, "clock-div", &div)) {
356 		pr_err("%s Fixed factor clock <%pOFn> must have a clock-div property\n",
357 			__func__, node);
358 		return ERR_PTR(-EIO);
359 	}
360 
361 	if (of_property_read_u32(node, "clock-mult", &mult)) {
362 		pr_err("%s Fixed factor clock <%pOFn> must have a clock-mult property\n",
363 			__func__, node);
364 		return ERR_PTR(-EIO);
365 	}
366 
367 	of_property_read_string(node, "clock-output-names", &clk_name);
368 
369 	hw = __clk_hw_register_fixed_factor(NULL, node, clk_name, NULL, NULL,
370 					    &pdata, 0, mult, div, 0, 0, false);
371 	if (IS_ERR(hw)) {
372 		/*
373 		 * Clear OF_POPULATED flag so that clock registration can be
374 		 * attempted again from probe function.
375 		 */
376 		of_node_clear_flag(node, OF_POPULATED);
377 		return ERR_CAST(hw);
378 	}
379 
380 	ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw);
381 	if (ret) {
382 		clk_hw_unregister_fixed_factor(hw);
383 		return ERR_PTR(ret);
384 	}
385 
386 	return hw;
387 }
388 
389 /**
390  * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
391  * @node:	device node for the clock
392  */
393 void __init of_fixed_factor_clk_setup(struct device_node *node)
394 {
395 	_of_fixed_factor_clk_setup(node);
396 }
397 CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock",
398 		of_fixed_factor_clk_setup);
399 
400 static void of_fixed_factor_clk_remove(struct platform_device *pdev)
401 {
402 	struct clk_hw *clk = platform_get_drvdata(pdev);
403 
404 	of_clk_del_provider(pdev->dev.of_node);
405 	clk_hw_unregister_fixed_factor(clk);
406 }
407 
408 static int of_fixed_factor_clk_probe(struct platform_device *pdev)
409 {
410 	struct clk_hw *clk;
411 
412 	/*
413 	 * This function is not executed when of_fixed_factor_clk_setup
414 	 * succeeded.
415 	 */
416 	clk = _of_fixed_factor_clk_setup(pdev->dev.of_node);
417 	if (IS_ERR(clk))
418 		return PTR_ERR(clk);
419 
420 	platform_set_drvdata(pdev, clk);
421 
422 	return 0;
423 }
424 
425 static const struct of_device_id of_fixed_factor_clk_ids[] = {
426 	{ .compatible = "fixed-factor-clock" },
427 	{ }
428 };
429 MODULE_DEVICE_TABLE(of, of_fixed_factor_clk_ids);
430 
431 static struct platform_driver of_fixed_factor_clk_driver = {
432 	.driver = {
433 		.name = "of_fixed_factor_clk",
434 		.of_match_table = of_fixed_factor_clk_ids,
435 	},
436 	.probe = of_fixed_factor_clk_probe,
437 	.remove = of_fixed_factor_clk_remove,
438 };
439 builtin_platform_driver(of_fixed_factor_clk_driver);
440 #endif
441