1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
5 #include <linux/module.h>
6 #include <linux/clk-provider.h>
7 #include <linux/slab.h>
10 #include <linux/platform_device.h>
13 * DOC: basic fixed multiplier and divider clock that cannot gate
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
22 static unsigned long clk_factor_recalc_rate(struct clk_hw
*hw
,
23 unsigned long parent_rate
)
25 struct clk_fixed_factor
*fix
= to_clk_fixed_factor(hw
);
26 unsigned long long int rate
;
28 rate
= (unsigned long long int)parent_rate
* fix
->mult
;
29 do_div(rate
, fix
->div
);
30 return (unsigned long)rate
;
33 static long clk_factor_round_rate(struct clk_hw
*hw
, unsigned long rate
,
36 struct clk_fixed_factor
*fix
= to_clk_fixed_factor(hw
);
38 if (clk_hw_get_flags(hw
) & CLK_SET_RATE_PARENT
) {
39 unsigned long best_parent
;
41 best_parent
= (rate
/ fix
->mult
) * fix
->div
;
42 *prate
= clk_hw_round_rate(clk_hw_get_parent(hw
), best_parent
);
45 return (*prate
/ fix
->div
) * fix
->mult
;
48 static int clk_factor_set_rate(struct clk_hw
*hw
, unsigned long rate
,
49 unsigned long parent_rate
)
52 * We must report success but we can do so unconditionally because
53 * clk_factor_round_rate returns values that ensure this call is a
60 static unsigned long clk_factor_recalc_accuracy(struct clk_hw
*hw
,
61 unsigned long parent_accuracy
)
63 struct clk_fixed_factor
*fix
= to_clk_fixed_factor(hw
);
65 if (fix
->flags
& CLK_FIXED_FACTOR_FIXED_ACCURACY
)
68 return parent_accuracy
;
71 const struct clk_ops clk_fixed_factor_ops
= {
72 .round_rate
= clk_factor_round_rate
,
73 .set_rate
= clk_factor_set_rate
,
74 .recalc_rate
= clk_factor_recalc_rate
,
75 .recalc_accuracy
= clk_factor_recalc_accuracy
,
77 EXPORT_SYMBOL_GPL(clk_fixed_factor_ops
);
79 static void devm_clk_hw_register_fixed_factor_release(struct device
*dev
, void *res
)
81 struct clk_fixed_factor
*fix
= res
;
84 * We can not use clk_hw_unregister_fixed_factor, since it will kfree()
85 * the hw, resulting in double free. Just unregister the hw and let
86 * devres code kfree() it.
88 clk_hw_unregister(&fix
->hw
);
91 static struct clk_hw
*
92 __clk_hw_register_fixed_factor(struct device
*dev
, struct device_node
*np
,
93 const char *name
, const char *parent_name
,
94 const struct clk_hw
*parent_hw
, const struct clk_parent_data
*pdata
,
95 unsigned long flags
, unsigned int mult
, unsigned int div
,
96 unsigned long acc
, unsigned int fixflags
, bool devm
)
98 struct clk_fixed_factor
*fix
;
99 struct clk_init_data init
= { };
103 /* You can't use devm without a dev */
105 return ERR_PTR(-EINVAL
);
108 fix
= devres_alloc(devm_clk_hw_register_fixed_factor_release
,
109 sizeof(*fix
), GFP_KERNEL
);
111 fix
= kmalloc(sizeof(*fix
), GFP_KERNEL
);
113 return ERR_PTR(-ENOMEM
);
115 /* struct clk_fixed_factor assignments */
118 fix
->hw
.init
= &init
;
120 fix
->flags
= fixflags
;
123 init
.ops
= &clk_fixed_factor_ops
;
126 init
.parent_names
= &parent_name
;
128 init
.parent_hws
= &parent_hw
;
130 init
.parent_data
= pdata
;
131 init
.num_parents
= 1;
135 ret
= clk_hw_register(dev
, hw
);
137 ret
= of_clk_hw_register(np
, hw
);
145 devres_add(dev
, fix
);
151 * devm_clk_hw_register_fixed_factor_index - Register a fixed factor clock with
152 * parent from DT index
153 * @dev: device that is registering this clock
154 * @name: name of this clock
155 * @index: index of phandle in @dev 'clocks' property
156 * @flags: fixed factor flags
160 * Return: Pointer to fixed factor clk_hw structure that was registered or
163 struct clk_hw
*devm_clk_hw_register_fixed_factor_index(struct device
*dev
,
164 const char *name
, unsigned int index
, unsigned long flags
,
165 unsigned int mult
, unsigned int div
)
167 const struct clk_parent_data pdata
= { .index
= index
};
169 return __clk_hw_register_fixed_factor(dev
, NULL
, name
, NULL
, NULL
, &pdata
,
170 flags
, mult
, div
, 0, 0, true);
172 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_index
);
175 * devm_clk_hw_register_fixed_factor_parent_hw - Register a fixed factor clock with
176 * pointer to parent clock
177 * @dev: device that is registering this clock
178 * @name: name of this clock
179 * @parent_hw: pointer to parent clk
180 * @flags: fixed factor flags
184 * Return: Pointer to fixed factor clk_hw structure that was registered or
187 struct clk_hw
*devm_clk_hw_register_fixed_factor_parent_hw(struct device
*dev
,
188 const char *name
, const struct clk_hw
*parent_hw
,
189 unsigned long flags
, unsigned int mult
, unsigned int div
)
191 const struct clk_parent_data pdata
= { .index
= -1 };
193 return __clk_hw_register_fixed_factor(dev
, NULL
, name
, NULL
, parent_hw
,
194 &pdata
, flags
, mult
, div
, 0, 0, true);
196 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_parent_hw
);
198 struct clk_hw
*clk_hw_register_fixed_factor_parent_hw(struct device
*dev
,
199 const char *name
, const struct clk_hw
*parent_hw
,
200 unsigned long flags
, unsigned int mult
, unsigned int div
)
202 const struct clk_parent_data pdata
= { .index
= -1 };
204 return __clk_hw_register_fixed_factor(dev
, NULL
, name
, NULL
, parent_hw
,
205 &pdata
, flags
, mult
, div
, 0, 0, false);
207 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_parent_hw
);
209 struct clk_hw
*clk_hw_register_fixed_factor(struct device
*dev
,
210 const char *name
, const char *parent_name
, unsigned long flags
,
211 unsigned int mult
, unsigned int div
)
213 const struct clk_parent_data pdata
= { .index
= -1 };
215 return __clk_hw_register_fixed_factor(dev
, NULL
, name
, parent_name
, NULL
,
216 &pdata
, flags
, mult
, div
, 0, 0, false);
218 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor
);
220 struct clk_hw
*clk_hw_register_fixed_factor_fwname(struct device
*dev
,
221 struct device_node
*np
, const char *name
, const char *fw_name
,
222 unsigned long flags
, unsigned int mult
, unsigned int div
)
224 const struct clk_parent_data pdata
= { .index
= -1, .fw_name
= fw_name
};
226 return __clk_hw_register_fixed_factor(dev
, np
, name
, NULL
, NULL
,
227 &pdata
, flags
, mult
, div
, 0, 0, false);
229 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_fwname
);
231 struct clk_hw
*clk_hw_register_fixed_factor_with_accuracy_fwname(struct device
*dev
,
232 struct device_node
*np
, const char *name
, const char *fw_name
,
233 unsigned long flags
, unsigned int mult
, unsigned int div
,
236 const struct clk_parent_data pdata
= { .index
= -1, .fw_name
= fw_name
};
238 return __clk_hw_register_fixed_factor(dev
, np
, name
, NULL
, NULL
,
239 &pdata
, flags
, mult
, div
, acc
,
240 CLK_FIXED_FACTOR_FIXED_ACCURACY
, false);
242 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_with_accuracy_fwname
);
244 struct clk_hw
*clk_hw_register_fixed_factor_index(struct device
*dev
,
245 const char *name
, unsigned int index
, unsigned long flags
,
246 unsigned int mult
, unsigned int div
)
248 const struct clk_parent_data pdata
= { .index
= index
};
250 return __clk_hw_register_fixed_factor(dev
, NULL
, name
, NULL
, NULL
, &pdata
,
251 flags
, mult
, div
, 0, 0, false);
253 EXPORT_SYMBOL_GPL(clk_hw_register_fixed_factor_index
);
255 struct clk
*clk_register_fixed_factor(struct device
*dev
, const char *name
,
256 const char *parent_name
, unsigned long flags
,
257 unsigned int mult
, unsigned int div
)
261 hw
= clk_hw_register_fixed_factor(dev
, name
, parent_name
, flags
, mult
,
267 EXPORT_SYMBOL_GPL(clk_register_fixed_factor
);
269 void clk_unregister_fixed_factor(struct clk
*clk
)
273 hw
= __clk_get_hw(clk
);
278 kfree(to_clk_fixed_factor(hw
));
280 EXPORT_SYMBOL_GPL(clk_unregister_fixed_factor
);
282 void clk_hw_unregister_fixed_factor(struct clk_hw
*hw
)
284 struct clk_fixed_factor
*fix
;
286 fix
= to_clk_fixed_factor(hw
);
288 clk_hw_unregister(hw
);
291 EXPORT_SYMBOL_GPL(clk_hw_unregister_fixed_factor
);
293 struct clk_hw
*devm_clk_hw_register_fixed_factor(struct device
*dev
,
294 const char *name
, const char *parent_name
, unsigned long flags
,
295 unsigned int mult
, unsigned int div
)
297 const struct clk_parent_data pdata
= { .index
= -1 };
299 return __clk_hw_register_fixed_factor(dev
, NULL
, name
, parent_name
, NULL
,
300 &pdata
, flags
, mult
, div
, 0, 0, true);
302 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor
);
304 struct clk_hw
*devm_clk_hw_register_fixed_factor_fwname(struct device
*dev
,
305 struct device_node
*np
, const char *name
, const char *fw_name
,
306 unsigned long flags
, unsigned int mult
, unsigned int div
)
308 const struct clk_parent_data pdata
= { .index
= -1, .fw_name
= fw_name
};
310 return __clk_hw_register_fixed_factor(dev
, np
, name
, NULL
, NULL
,
311 &pdata
, flags
, mult
, div
, 0, 0, true);
313 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_fwname
);
315 struct clk_hw
*devm_clk_hw_register_fixed_factor_with_accuracy_fwname(struct device
*dev
,
316 struct device_node
*np
, const char *name
, const char *fw_name
,
317 unsigned long flags
, unsigned int mult
, unsigned int div
,
320 const struct clk_parent_data pdata
= { .index
= -1, .fw_name
= fw_name
};
322 return __clk_hw_register_fixed_factor(dev
, np
, name
, NULL
, NULL
,
323 &pdata
, flags
, mult
, div
, acc
,
324 CLK_FIXED_FACTOR_FIXED_ACCURACY
, true);
326 EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_with_accuracy_fwname
);
329 static struct clk_hw
*_of_fixed_factor_clk_setup(struct device_node
*node
)
332 const char *clk_name
= node
->name
;
333 const struct clk_parent_data pdata
= { .index
= 0 };
337 if (of_property_read_u32(node
, "clock-div", &div
)) {
338 pr_err("%s Fixed factor clock <%pOFn> must have a clock-div property\n",
340 return ERR_PTR(-EIO
);
343 if (of_property_read_u32(node
, "clock-mult", &mult
)) {
344 pr_err("%s Fixed factor clock <%pOFn> must have a clock-mult property\n",
346 return ERR_PTR(-EIO
);
349 of_property_read_string(node
, "clock-output-names", &clk_name
);
351 hw
= __clk_hw_register_fixed_factor(NULL
, node
, clk_name
, NULL
, NULL
,
352 &pdata
, 0, mult
, div
, 0, 0, false);
355 * Clear OF_POPULATED flag so that clock registration can be
356 * attempted again from probe function.
358 of_node_clear_flag(node
, OF_POPULATED
);
362 ret
= of_clk_add_hw_provider(node
, of_clk_hw_simple_get
, hw
);
364 clk_hw_unregister_fixed_factor(hw
);
372 * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
373 * @node: device node for the clock
375 void __init
of_fixed_factor_clk_setup(struct device_node
*node
)
377 _of_fixed_factor_clk_setup(node
);
379 CLK_OF_DECLARE(fixed_factor_clk
, "fixed-factor-clock",
380 of_fixed_factor_clk_setup
);
382 static void of_fixed_factor_clk_remove(struct platform_device
*pdev
)
384 struct clk_hw
*clk
= platform_get_drvdata(pdev
);
386 of_clk_del_provider(pdev
->dev
.of_node
);
387 clk_hw_unregister_fixed_factor(clk
);
390 static int of_fixed_factor_clk_probe(struct platform_device
*pdev
)
395 * This function is not executed when of_fixed_factor_clk_setup
398 clk
= _of_fixed_factor_clk_setup(pdev
->dev
.of_node
);
402 platform_set_drvdata(pdev
, clk
);
407 static const struct of_device_id of_fixed_factor_clk_ids
[] = {
408 { .compatible
= "fixed-factor-clock" },
411 MODULE_DEVICE_TABLE(of
, of_fixed_factor_clk_ids
);
413 static struct platform_driver of_fixed_factor_clk_driver
= {
415 .name
= "of_fixed_factor_clk",
416 .of_match_table
= of_fixed_factor_clk_ids
,
418 .probe
= of_fixed_factor_clk_probe
,
419 .remove
= of_fixed_factor_clk_remove
,
421 builtin_platform_driver(of_fixed_factor_clk_driver
);