2 * mmp mix(div and mux) clock operation source file
4 * Copyright (C) 2014 Marvell
5 * Chao Xie <chao.xie@marvell.com>
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
12 #include <linux/clk-provider.h>
13 #include <linux/slab.h>
15 #include <linux/err.h>
20 * The mix clock is a clock combined mux and div type clock.
21 * Because the div field and mux field need to be set at same
22 * time, we can not divide it into 2 types of clock
25 #define to_clk_mix(hw) container_of(hw, struct mmp_clk_mix, hw)
27 static unsigned int _get_maxdiv(struct mmp_clk_mix
*mix
)
29 unsigned int div_mask
= (1 << mix
->reg_info
.width_div
) - 1;
30 unsigned int maxdiv
= 0;
31 struct clk_div_table
*clkt
;
33 if (mix
->div_flags
& CLK_DIVIDER_ONE_BASED
)
35 if (mix
->div_flags
& CLK_DIVIDER_POWER_OF_TWO
)
38 for (clkt
= mix
->div_table
; clkt
->div
; clkt
++)
39 if (clkt
->div
> maxdiv
)
46 static unsigned int _get_div(struct mmp_clk_mix
*mix
, unsigned int val
)
48 struct clk_div_table
*clkt
;
50 if (mix
->div_flags
& CLK_DIVIDER_ONE_BASED
)
52 if (mix
->div_flags
& CLK_DIVIDER_POWER_OF_TWO
)
55 for (clkt
= mix
->div_table
; clkt
->div
; clkt
++)
64 static unsigned int _get_mux(struct mmp_clk_mix
*mix
, unsigned int val
)
66 int num_parents
= __clk_get_num_parents(mix
->hw
.clk
);
69 if (mix
->mux_flags
& CLK_MUX_INDEX_BIT
)
71 if (mix
->mux_flags
& CLK_MUX_INDEX_ONE
)
74 for (i
= 0; i
< num_parents
; i
++)
75 if (mix
->mux_table
[i
] == val
)
83 static unsigned int _get_div_val(struct mmp_clk_mix
*mix
, unsigned int div
)
85 struct clk_div_table
*clkt
;
87 if (mix
->div_flags
& CLK_DIVIDER_ONE_BASED
)
89 if (mix
->div_flags
& CLK_DIVIDER_POWER_OF_TWO
)
92 for (clkt
= mix
->div_table
; clkt
->div
; clkt
++)
102 static unsigned int _get_mux_val(struct mmp_clk_mix
*mix
, unsigned int mux
)
105 return mix
->mux_table
[mux
];
110 static void _filter_clk_table(struct mmp_clk_mix
*mix
,
111 struct mmp_clk_mix_clk_table
*table
,
112 unsigned int table_size
)
115 struct mmp_clk_mix_clk_table
*item
;
116 struct clk
*parent
, *clk
;
117 unsigned long parent_rate
;
121 for (i
= 0; i
< table_size
; i
++) {
123 parent
= clk_get_parent_by_index(clk
, item
->parent_index
);
124 parent_rate
= __clk_get_rate(parent
);
125 if (parent_rate
% item
->rate
) {
128 item
->divisor
= parent_rate
/ item
->rate
;
134 static int _set_rate(struct mmp_clk_mix
*mix
, u32 mux_val
, u32 div_val
,
135 unsigned int change_mux
, unsigned int change_div
)
137 struct mmp_clk_mix_reg_info
*ri
= &mix
->reg_info
;
140 int ret
, timeout
= 50;
141 unsigned long flags
= 0;
143 if (!change_mux
&& !change_div
)
147 spin_lock_irqsave(mix
->lock
, flags
);
149 if (mix
->type
== MMP_CLK_MIX_TYPE_V1
150 || mix
->type
== MMP_CLK_MIX_TYPE_V2
)
151 mux_div
= readl(ri
->reg_clk_ctrl
);
153 mux_div
= readl(ri
->reg_clk_sel
);
156 width
= ri
->width_div
;
157 shift
= ri
->shift_div
;
158 mux_div
&= ~MMP_CLK_BITS_MASK(width
, shift
);
159 mux_div
|= MMP_CLK_BITS_SET_VAL(div_val
, width
, shift
);
163 width
= ri
->width_mux
;
164 shift
= ri
->shift_mux
;
165 mux_div
&= ~MMP_CLK_BITS_MASK(width
, shift
);
166 mux_div
|= MMP_CLK_BITS_SET_VAL(mux_val
, width
, shift
);
169 if (mix
->type
== MMP_CLK_MIX_TYPE_V1
) {
170 writel(mux_div
, ri
->reg_clk_ctrl
);
171 } else if (mix
->type
== MMP_CLK_MIX_TYPE_V2
) {
172 mux_div
|= (1 << ri
->bit_fc
);
173 writel(mux_div
, ri
->reg_clk_ctrl
);
176 fc_req
= readl(ri
->reg_clk_ctrl
);
178 if (!(fc_req
& (1 << ri
->bit_fc
)))
183 pr_err("%s:%s cannot do frequency change\n",
184 __func__
, __clk_get_name(mix
->hw
.clk
));
189 fc_req
= readl(ri
->reg_clk_ctrl
);
190 fc_req
|= 1 << ri
->bit_fc
;
191 writel(fc_req
, ri
->reg_clk_ctrl
);
192 writel(mux_div
, ri
->reg_clk_sel
);
193 fc_req
&= ~(1 << ri
->bit_fc
);
199 spin_unlock_irqrestore(mix
->lock
, flags
);
204 static long mmp_clk_mix_determine_rate(struct clk_hw
*hw
, unsigned long rate
,
205 unsigned long *best_parent_rate
,
206 struct clk_hw
**best_parent_clk
)
208 struct mmp_clk_mix
*mix
= to_clk_mix(hw
);
209 struct mmp_clk_mix_clk_table
*item
;
210 struct clk
*parent
, *parent_best
, *mix_clk
;
211 unsigned long parent_rate
, mix_rate
, mix_rate_best
, parent_rate_best
;
212 unsigned long gap
, gap_best
;
221 parent_rate_best
= 0;
226 for (i
= 0; i
< mix
->table_size
; i
++) {
227 item
= &mix
->table
[i
];
228 if (item
->valid
== 0)
230 parent
= clk_get_parent_by_index(mix_clk
,
232 parent_rate
= __clk_get_rate(parent
);
233 mix_rate
= parent_rate
/ item
->divisor
;
234 gap
= abs(mix_rate
- rate
);
235 if (parent_best
== NULL
|| gap
< gap_best
) {
236 parent_best
= parent
;
237 parent_rate_best
= parent_rate
;
238 mix_rate_best
= mix_rate
;
245 for (i
= 0; i
< __clk_get_num_parents(mix_clk
); i
++) {
246 parent
= clk_get_parent_by_index(mix_clk
, i
);
247 parent_rate
= __clk_get_rate(parent
);
248 div_val_max
= _get_maxdiv(mix
);
249 for (j
= 0; j
< div_val_max
; j
++) {
250 div
= _get_div(mix
, j
);
251 mix_rate
= parent_rate
/ div
;
252 gap
= abs(mix_rate
- rate
);
253 if (parent_best
== NULL
|| gap
< gap_best
) {
254 parent_best
= parent
;
255 parent_rate_best
= parent_rate
;
256 mix_rate_best
= mix_rate
;
266 *best_parent_rate
= parent_rate_best
;
267 *best_parent_clk
= __clk_get_hw(parent_best
);
269 return mix_rate_best
;
272 static int mmp_clk_mix_set_rate_and_parent(struct clk_hw
*hw
,
274 unsigned long parent_rate
,
277 struct mmp_clk_mix
*mix
= to_clk_mix(hw
);
279 u32 div_val
, mux_val
;
281 div
= parent_rate
/ rate
;
282 div_val
= _get_div_val(mix
, div
);
283 mux_val
= _get_mux_val(mix
, index
);
285 return _set_rate(mix
, mux_val
, div_val
, 1, 1);
288 static u8
mmp_clk_mix_get_parent(struct clk_hw
*hw
)
290 struct mmp_clk_mix
*mix
= to_clk_mix(hw
);
291 struct mmp_clk_mix_reg_info
*ri
= &mix
->reg_info
;
292 unsigned long flags
= 0;
298 spin_lock_irqsave(mix
->lock
, flags
);
300 if (mix
->type
== MMP_CLK_MIX_TYPE_V1
301 || mix
->type
== MMP_CLK_MIX_TYPE_V2
)
302 mux_div
= readl(ri
->reg_clk_ctrl
);
304 mux_div
= readl(ri
->reg_clk_sel
);
307 spin_unlock_irqrestore(mix
->lock
, flags
);
309 width
= mix
->reg_info
.width_mux
;
310 shift
= mix
->reg_info
.shift_mux
;
312 mux_val
= MMP_CLK_BITS_GET_VAL(mux_div
, width
, shift
);
314 return _get_mux(mix
, mux_val
);
317 static unsigned long mmp_clk_mix_recalc_rate(struct clk_hw
*hw
,
318 unsigned long parent_rate
)
320 struct mmp_clk_mix
*mix
= to_clk_mix(hw
);
321 struct mmp_clk_mix_reg_info
*ri
= &mix
->reg_info
;
322 unsigned long flags
= 0;
328 spin_lock_irqsave(mix
->lock
, flags
);
330 if (mix
->type
== MMP_CLK_MIX_TYPE_V1
331 || mix
->type
== MMP_CLK_MIX_TYPE_V2
)
332 mux_div
= readl(ri
->reg_clk_ctrl
);
334 mux_div
= readl(ri
->reg_clk_sel
);
337 spin_unlock_irqrestore(mix
->lock
, flags
);
339 width
= mix
->reg_info
.width_div
;
340 shift
= mix
->reg_info
.shift_div
;
342 div
= _get_div(mix
, MMP_CLK_BITS_GET_VAL(mux_div
, width
, shift
));
344 return parent_rate
/ div
;
347 static int mmp_clk_set_parent(struct clk_hw
*hw
, u8 index
)
349 struct mmp_clk_mix
*mix
= to_clk_mix(hw
);
350 struct mmp_clk_mix_clk_table
*item
;
352 u32 div_val
, mux_val
;
355 for (i
= 0; i
< mix
->table_size
; i
++) {
356 item
= &mix
->table
[i
];
357 if (item
->valid
== 0)
359 if (item
->parent_index
== index
)
362 if (i
< mix
->table_size
) {
363 div_val
= _get_div_val(mix
, item
->divisor
);
364 mux_val
= _get_mux_val(mix
, item
->parent_index
);
368 mux_val
= _get_mux_val(mix
, index
);
372 return _set_rate(mix
, mux_val
, div_val
, 1, div_val
? 1 : 0);
375 static int mmp_clk_set_rate(struct clk_hw
*hw
, unsigned long rate
,
376 unsigned long best_parent_rate
)
378 struct mmp_clk_mix
*mix
= to_clk_mix(hw
);
379 struct mmp_clk_mix_clk_table
*item
;
380 unsigned long parent_rate
;
381 unsigned int best_divisor
;
382 struct clk
*mix_clk
, *parent
;
385 best_divisor
= best_parent_rate
/ rate
;
389 for (i
= 0; i
< mix
->table_size
; i
++) {
390 item
= &mix
->table
[i
];
391 if (item
->valid
== 0)
393 parent
= clk_get_parent_by_index(mix_clk
,
395 parent_rate
= __clk_get_rate(parent
);
396 if (parent_rate
== best_parent_rate
397 && item
->divisor
== best_divisor
)
400 if (i
< mix
->table_size
)
401 return _set_rate(mix
,
402 _get_mux_val(mix
, item
->parent_index
),
403 _get_div_val(mix
, item
->divisor
),
408 for (i
= 0; i
< __clk_get_num_parents(mix_clk
); i
++) {
409 parent
= clk_get_parent_by_index(mix_clk
, i
);
410 parent_rate
= __clk_get_rate(parent
);
411 if (parent_rate
== best_parent_rate
)
414 if (i
< __clk_get_num_parents(mix_clk
))
415 return _set_rate(mix
, _get_mux_val(mix
, i
),
416 _get_div_val(mix
, best_divisor
), 1, 1);
422 static void mmp_clk_mix_init(struct clk_hw
*hw
)
424 struct mmp_clk_mix
*mix
= to_clk_mix(hw
);
427 _filter_clk_table(mix
, mix
->table
, mix
->table_size
);
430 const struct clk_ops mmp_clk_mix_ops
= {
431 .determine_rate
= mmp_clk_mix_determine_rate
,
432 .set_rate_and_parent
= mmp_clk_mix_set_rate_and_parent
,
433 .set_rate
= mmp_clk_set_rate
,
434 .set_parent
= mmp_clk_set_parent
,
435 .get_parent
= mmp_clk_mix_get_parent
,
436 .recalc_rate
= mmp_clk_mix_recalc_rate
,
437 .init
= mmp_clk_mix_init
,
440 struct clk
*mmp_clk_register_mix(struct device
*dev
,
442 const char **parent_names
,
445 struct mmp_clk_mix_config
*config
,
448 struct mmp_clk_mix
*mix
;
450 struct clk_init_data init
;
453 mix
= kzalloc(sizeof(*mix
), GFP_KERNEL
);
455 pr_err("%s:%s: could not allocate mmp mix clk\n",
457 return ERR_PTR(-ENOMEM
);
461 init
.flags
= flags
| CLK_GET_RATE_NOCACHE
;
462 init
.parent_names
= parent_names
;
463 init
.num_parents
= num_parents
;
464 init
.ops
= &mmp_clk_mix_ops
;
466 memcpy(&mix
->reg_info
, &config
->reg_info
, sizeof(config
->reg_info
));
468 table_bytes
= sizeof(*config
->table
) * config
->table_size
;
469 mix
->table
= kzalloc(table_bytes
, GFP_KERNEL
);
471 pr_err("%s:%s: could not allocate mmp mix table\n",
474 return ERR_PTR(-ENOMEM
);
476 memcpy(mix
->table
, config
->table
, table_bytes
);
477 mix
->table_size
= config
->table_size
;
480 if (config
->mux_table
) {
481 table_bytes
= sizeof(u32
) * num_parents
;
482 mix
->mux_table
= kzalloc(table_bytes
, GFP_KERNEL
);
483 if (!mix
->mux_table
) {
484 pr_err("%s:%s: could not allocate mmp mix mux-table\n",
488 return ERR_PTR(-ENOMEM
);
490 memcpy(mix
->mux_table
, config
->mux_table
, table_bytes
);
493 mix
->div_flags
= config
->div_flags
;
494 mix
->mux_flags
= config
->mux_flags
;
496 mix
->hw
.init
= &init
;
498 if (config
->reg_info
.bit_fc
>= 32)
499 mix
->type
= MMP_CLK_MIX_TYPE_V1
;
500 else if (config
->reg_info
.reg_clk_sel
)
501 mix
->type
= MMP_CLK_MIX_TYPE_V3
;
503 mix
->type
= MMP_CLK_MIX_TYPE_V2
;
504 clk
= clk_register(dev
, &mix
->hw
);
507 kfree(mix
->mux_table
);