1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved.
6 #include <linux/clk-provider.h>
7 #include <linux/device.h>
9 #include <linux/slab.h>
11 static u8
clk_composite_get_parent(struct clk_hw
*hw
)
13 struct clk_composite
*composite
= to_clk_composite(hw
);
14 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
15 struct clk_hw
*mux_hw
= composite
->mux_hw
;
17 __clk_hw_set_clk(mux_hw
, hw
);
19 return mux_ops
->get_parent(mux_hw
);
22 static int clk_composite_set_parent(struct clk_hw
*hw
, u8 index
)
24 struct clk_composite
*composite
= to_clk_composite(hw
);
25 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
26 struct clk_hw
*mux_hw
= composite
->mux_hw
;
28 __clk_hw_set_clk(mux_hw
, hw
);
30 return mux_ops
->set_parent(mux_hw
, index
);
33 static unsigned long clk_composite_recalc_rate(struct clk_hw
*hw
,
34 unsigned long parent_rate
)
36 struct clk_composite
*composite
= to_clk_composite(hw
);
37 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
38 struct clk_hw
*rate_hw
= composite
->rate_hw
;
40 __clk_hw_set_clk(rate_hw
, hw
);
42 return rate_ops
->recalc_rate(rate_hw
, parent_rate
);
45 static int clk_composite_determine_rate_for_parent(struct clk_hw
*rate_hw
,
46 struct clk_rate_request
*req
,
47 struct clk_hw
*parent_hw
,
48 const struct clk_ops
*rate_ops
)
52 req
->best_parent_hw
= parent_hw
;
53 req
->best_parent_rate
= clk_hw_get_rate(parent_hw
);
55 if (rate_ops
->determine_rate
)
56 return rate_ops
->determine_rate(rate_hw
, req
);
58 rate
= rate_ops
->round_rate(rate_hw
, req
->rate
,
59 &req
->best_parent_rate
);
68 static int clk_composite_determine_rate(struct clk_hw
*hw
,
69 struct clk_rate_request
*req
)
71 struct clk_composite
*composite
= to_clk_composite(hw
);
72 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
73 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
74 struct clk_hw
*rate_hw
= composite
->rate_hw
;
75 struct clk_hw
*mux_hw
= composite
->mux_hw
;
76 struct clk_hw
*parent
;
77 unsigned long rate_diff
;
78 unsigned long best_rate_diff
= ULONG_MAX
;
79 unsigned long best_rate
= 0;
82 if (rate_hw
&& rate_ops
&&
83 (rate_ops
->determine_rate
|| rate_ops
->round_rate
) &&
84 mux_hw
&& mux_ops
&& mux_ops
->set_parent
) {
85 req
->best_parent_hw
= NULL
;
87 if (clk_hw_get_flags(hw
) & CLK_SET_RATE_NO_REPARENT
) {
88 struct clk_rate_request tmp_req
;
90 parent
= clk_hw_get_parent(mux_hw
);
92 clk_hw_forward_rate_request(hw
, req
, parent
, &tmp_req
, req
->rate
);
93 ret
= clk_composite_determine_rate_for_parent(rate_hw
,
100 req
->rate
= tmp_req
.rate
;
101 req
->best_parent_hw
= tmp_req
.best_parent_hw
;
102 req
->best_parent_rate
= tmp_req
.best_parent_rate
;
107 for (i
= 0; i
< clk_hw_get_num_parents(mux_hw
); i
++) {
108 struct clk_rate_request tmp_req
;
110 parent
= clk_hw_get_parent_by_index(mux_hw
, i
);
114 clk_hw_forward_rate_request(hw
, req
, parent
, &tmp_req
, req
->rate
);
115 ret
= clk_composite_determine_rate_for_parent(rate_hw
,
122 if (req
->rate
>= tmp_req
.rate
)
123 rate_diff
= req
->rate
- tmp_req
.rate
;
125 rate_diff
= tmp_req
.rate
- req
->rate
;
127 if (!rate_diff
|| !req
->best_parent_hw
128 || best_rate_diff
> rate_diff
) {
129 req
->best_parent_hw
= parent
;
130 req
->best_parent_rate
= tmp_req
.best_parent_rate
;
131 best_rate_diff
= rate_diff
;
132 best_rate
= tmp_req
.rate
;
139 req
->rate
= best_rate
;
141 } else if (rate_hw
&& rate_ops
&& rate_ops
->determine_rate
) {
142 __clk_hw_set_clk(rate_hw
, hw
);
143 return rate_ops
->determine_rate(rate_hw
, req
);
144 } else if (mux_hw
&& mux_ops
&& mux_ops
->determine_rate
) {
145 __clk_hw_set_clk(mux_hw
, hw
);
146 return mux_ops
->determine_rate(mux_hw
, req
);
148 pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
153 static long clk_composite_round_rate(struct clk_hw
*hw
, unsigned long rate
,
154 unsigned long *prate
)
156 struct clk_composite
*composite
= to_clk_composite(hw
);
157 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
158 struct clk_hw
*rate_hw
= composite
->rate_hw
;
160 __clk_hw_set_clk(rate_hw
, hw
);
162 return rate_ops
->round_rate(rate_hw
, rate
, prate
);
165 static int clk_composite_set_rate(struct clk_hw
*hw
, unsigned long rate
,
166 unsigned long parent_rate
)
168 struct clk_composite
*composite
= to_clk_composite(hw
);
169 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
170 struct clk_hw
*rate_hw
= composite
->rate_hw
;
172 __clk_hw_set_clk(rate_hw
, hw
);
174 return rate_ops
->set_rate(rate_hw
, rate
, parent_rate
);
177 static int clk_composite_set_rate_and_parent(struct clk_hw
*hw
,
179 unsigned long parent_rate
,
182 struct clk_composite
*composite
= to_clk_composite(hw
);
183 const struct clk_ops
*rate_ops
= composite
->rate_ops
;
184 const struct clk_ops
*mux_ops
= composite
->mux_ops
;
185 struct clk_hw
*rate_hw
= composite
->rate_hw
;
186 struct clk_hw
*mux_hw
= composite
->mux_hw
;
187 unsigned long temp_rate
;
189 __clk_hw_set_clk(rate_hw
, hw
);
190 __clk_hw_set_clk(mux_hw
, hw
);
192 temp_rate
= rate_ops
->recalc_rate(rate_hw
, parent_rate
);
193 if (temp_rate
> rate
) {
194 rate_ops
->set_rate(rate_hw
, rate
, parent_rate
);
195 mux_ops
->set_parent(mux_hw
, index
);
197 mux_ops
->set_parent(mux_hw
, index
);
198 rate_ops
->set_rate(rate_hw
, rate
, parent_rate
);
204 static int clk_composite_is_enabled(struct clk_hw
*hw
)
206 struct clk_composite
*composite
= to_clk_composite(hw
);
207 const struct clk_ops
*gate_ops
= composite
->gate_ops
;
208 struct clk_hw
*gate_hw
= composite
->gate_hw
;
210 __clk_hw_set_clk(gate_hw
, hw
);
212 return gate_ops
->is_enabled(gate_hw
);
215 static int clk_composite_enable(struct clk_hw
*hw
)
217 struct clk_composite
*composite
= to_clk_composite(hw
);
218 const struct clk_ops
*gate_ops
= composite
->gate_ops
;
219 struct clk_hw
*gate_hw
= composite
->gate_hw
;
221 __clk_hw_set_clk(gate_hw
, hw
);
223 return gate_ops
->enable(gate_hw
);
226 static void clk_composite_disable(struct clk_hw
*hw
)
228 struct clk_composite
*composite
= to_clk_composite(hw
);
229 const struct clk_ops
*gate_ops
= composite
->gate_ops
;
230 struct clk_hw
*gate_hw
= composite
->gate_hw
;
232 __clk_hw_set_clk(gate_hw
, hw
);
234 gate_ops
->disable(gate_hw
);
237 static struct clk_hw
*__clk_hw_register_composite(struct device
*dev
,
238 const char *name
, const char * const *parent_names
,
239 const struct clk_parent_data
*pdata
, int num_parents
,
240 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
241 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
242 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
246 struct clk_init_data init
= {};
247 struct clk_composite
*composite
;
248 struct clk_ops
*clk_composite_ops
;
251 composite
= kzalloc(sizeof(*composite
), GFP_KERNEL
);
253 return ERR_PTR(-ENOMEM
);
258 init
.parent_names
= parent_names
;
260 init
.parent_data
= pdata
;
261 init
.num_parents
= num_parents
;
264 clk_composite_ops
= &composite
->ops
;
266 if (mux_hw
&& mux_ops
) {
267 if (!mux_ops
->get_parent
) {
268 hw
= ERR_PTR(-EINVAL
);
272 composite
->mux_hw
= mux_hw
;
273 composite
->mux_ops
= mux_ops
;
274 clk_composite_ops
->get_parent
= clk_composite_get_parent
;
275 if (mux_ops
->set_parent
)
276 clk_composite_ops
->set_parent
= clk_composite_set_parent
;
277 if (mux_ops
->determine_rate
)
278 clk_composite_ops
->determine_rate
= clk_composite_determine_rate
;
281 if (rate_hw
&& rate_ops
) {
282 if (!rate_ops
->recalc_rate
) {
283 hw
= ERR_PTR(-EINVAL
);
286 clk_composite_ops
->recalc_rate
= clk_composite_recalc_rate
;
288 if (rate_ops
->determine_rate
)
289 clk_composite_ops
->determine_rate
=
290 clk_composite_determine_rate
;
291 else if (rate_ops
->round_rate
)
292 clk_composite_ops
->round_rate
=
293 clk_composite_round_rate
;
295 /* .set_rate requires either .round_rate or .determine_rate */
296 if (rate_ops
->set_rate
) {
297 if (rate_ops
->determine_rate
|| rate_ops
->round_rate
)
298 clk_composite_ops
->set_rate
=
299 clk_composite_set_rate
;
301 WARN(1, "%s: missing round_rate op is required\n",
305 composite
->rate_hw
= rate_hw
;
306 composite
->rate_ops
= rate_ops
;
309 if (mux_hw
&& mux_ops
&& rate_hw
&& rate_ops
) {
310 if (mux_ops
->set_parent
&& rate_ops
->set_rate
)
311 clk_composite_ops
->set_rate_and_parent
=
312 clk_composite_set_rate_and_parent
;
315 if (gate_hw
&& gate_ops
) {
316 if (!gate_ops
->is_enabled
|| !gate_ops
->enable
||
317 !gate_ops
->disable
) {
318 hw
= ERR_PTR(-EINVAL
);
322 composite
->gate_hw
= gate_hw
;
323 composite
->gate_ops
= gate_ops
;
324 clk_composite_ops
->is_enabled
= clk_composite_is_enabled
;
325 clk_composite_ops
->enable
= clk_composite_enable
;
326 clk_composite_ops
->disable
= clk_composite_disable
;
329 init
.ops
= clk_composite_ops
;
330 composite
->hw
.init
= &init
;
332 ret
= clk_hw_register(dev
, hw
);
338 if (composite
->mux_hw
)
339 composite
->mux_hw
->clk
= hw
->clk
;
341 if (composite
->rate_hw
)
342 composite
->rate_hw
->clk
= hw
->clk
;
344 if (composite
->gate_hw
)
345 composite
->gate_hw
->clk
= hw
->clk
;
354 struct clk_hw
*clk_hw_register_composite(struct device
*dev
, const char *name
,
355 const char * const *parent_names
, int num_parents
,
356 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
357 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
358 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
361 return __clk_hw_register_composite(dev
, name
, parent_names
, NULL
,
362 num_parents
, mux_hw
, mux_ops
,
363 rate_hw
, rate_ops
, gate_hw
,
366 EXPORT_SYMBOL_GPL(clk_hw_register_composite
);
368 struct clk_hw
*clk_hw_register_composite_pdata(struct device
*dev
,
370 const struct clk_parent_data
*parent_data
,
372 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
373 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
374 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
377 return __clk_hw_register_composite(dev
, name
, NULL
, parent_data
,
378 num_parents
, mux_hw
, mux_ops
,
379 rate_hw
, rate_ops
, gate_hw
,
383 struct clk
*clk_register_composite(struct device
*dev
, const char *name
,
384 const char * const *parent_names
, int num_parents
,
385 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
386 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
387 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
392 hw
= clk_hw_register_composite(dev
, name
, parent_names
, num_parents
,
393 mux_hw
, mux_ops
, rate_hw
, rate_ops
, gate_hw
, gate_ops
,
399 EXPORT_SYMBOL_GPL(clk_register_composite
);
401 struct clk
*clk_register_composite_pdata(struct device
*dev
, const char *name
,
402 const struct clk_parent_data
*parent_data
,
404 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
405 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
406 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
411 hw
= clk_hw_register_composite_pdata(dev
, name
, parent_data
,
412 num_parents
, mux_hw
, mux_ops
, rate_hw
, rate_ops
,
413 gate_hw
, gate_ops
, flags
);
419 void clk_unregister_composite(struct clk
*clk
)
421 struct clk_composite
*composite
;
424 hw
= __clk_get_hw(clk
);
428 composite
= to_clk_composite(hw
);
434 void clk_hw_unregister_composite(struct clk_hw
*hw
)
436 struct clk_composite
*composite
;
438 composite
= to_clk_composite(hw
);
440 clk_hw_unregister(hw
);
443 EXPORT_SYMBOL_GPL(clk_hw_unregister_composite
);
445 static void devm_clk_hw_release_composite(struct device
*dev
, void *res
)
447 clk_hw_unregister_composite(*(struct clk_hw
**)res
);
450 static struct clk_hw
*__devm_clk_hw_register_composite(struct device
*dev
,
451 const char *name
, const char * const *parent_names
,
452 const struct clk_parent_data
*pdata
, int num_parents
,
453 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
454 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
455 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
458 struct clk_hw
**ptr
, *hw
;
460 ptr
= devres_alloc(devm_clk_hw_release_composite
, sizeof(*ptr
),
463 return ERR_PTR(-ENOMEM
);
465 hw
= __clk_hw_register_composite(dev
, name
, parent_names
, pdata
,
466 num_parents
, mux_hw
, mux_ops
, rate_hw
,
467 rate_ops
, gate_hw
, gate_ops
, flags
);
471 devres_add(dev
, ptr
);
479 struct clk_hw
*devm_clk_hw_register_composite_pdata(struct device
*dev
,
481 const struct clk_parent_data
*parent_data
,
483 struct clk_hw
*mux_hw
, const struct clk_ops
*mux_ops
,
484 struct clk_hw
*rate_hw
, const struct clk_ops
*rate_ops
,
485 struct clk_hw
*gate_hw
, const struct clk_ops
*gate_ops
,
488 return __devm_clk_hw_register_composite(dev
, name
, NULL
, parent_data
,
489 num_parents
, mux_hw
, mux_ops
,
490 rate_hw
, rate_ops
, gate_hw
,