2 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/kernel.h>
15 #include <linux/bitops.h>
16 #include <linux/err.h>
17 #include <linux/bug.h>
18 #include <linux/export.h>
19 #include <linux/clk-provider.h>
20 #include <linux/delay.h>
21 #include <linux/regmap.h>
22 #include <linux/math64.h>
24 #include <asm/div64.h>
30 #define CMD_UPDATE BIT(0)
31 #define CMD_ROOT_EN BIT(1)
32 #define CMD_DIRTY_CFG BIT(4)
33 #define CMD_DIRTY_N BIT(5)
34 #define CMD_DIRTY_M BIT(6)
35 #define CMD_DIRTY_D BIT(7)
36 #define CMD_ROOT_OFF BIT(31)
39 #define CFG_SRC_DIV_SHIFT 0
40 #define CFG_SRC_SEL_SHIFT 8
41 #define CFG_SRC_SEL_MASK (0x7 << CFG_SRC_SEL_SHIFT)
42 #define CFG_MODE_SHIFT 12
43 #define CFG_MODE_MASK (0x3 << CFG_MODE_SHIFT)
44 #define CFG_MODE_DUAL_EDGE (0x2 << CFG_MODE_SHIFT)
50 static int clk_rcg2_is_enabled(struct clk_hw
*hw
)
52 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
56 ret
= regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CMD_REG
, &cmd
);
60 return (cmd
& CMD_ROOT_OFF
) == 0;
63 static u8
clk_rcg2_get_parent(struct clk_hw
*hw
)
65 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
66 int num_parents
= __clk_get_num_parents(hw
->clk
);
70 ret
= regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CFG_REG
, &cfg
);
74 cfg
&= CFG_SRC_SEL_MASK
;
75 cfg
>>= CFG_SRC_SEL_SHIFT
;
77 for (i
= 0; i
< num_parents
; i
++)
78 if (cfg
== rcg
->parent_map
[i
])
84 static int update_config(struct clk_rcg2
*rcg
)
88 struct clk_hw
*hw
= &rcg
->clkr
.hw
;
89 const char *name
= __clk_get_name(hw
->clk
);
91 ret
= regmap_update_bits(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CMD_REG
,
92 CMD_UPDATE
, CMD_UPDATE
);
96 /* Wait for update to take effect */
97 for (count
= 500; count
> 0; count
--) {
98 ret
= regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CMD_REG
, &cmd
);
101 if (!(cmd
& CMD_UPDATE
))
106 WARN(1, "%s: rcg didn't update its configuration.", name
);
110 static int clk_rcg2_set_parent(struct clk_hw
*hw
, u8 index
)
112 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
115 ret
= regmap_update_bits(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CFG_REG
,
117 rcg
->parent_map
[index
] << CFG_SRC_SEL_SHIFT
);
121 return update_config(rcg
);
125 * Calculate m/n:d rate
128 * rate = ----------- x ---
132 calc_rate(unsigned long rate
, u32 m
, u32 n
, u32 mode
, u32 hid_div
)
150 clk_rcg2_recalc_rate(struct clk_hw
*hw
, unsigned long parent_rate
)
152 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
153 u32 cfg
, hid_div
, m
= 0, n
= 0, mode
= 0, mask
;
155 regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CFG_REG
, &cfg
);
157 if (rcg
->mnd_width
) {
158 mask
= BIT(rcg
->mnd_width
) - 1;
159 regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ M_REG
, &m
);
161 regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ N_REG
, &n
);
165 mode
= cfg
& CFG_MODE_MASK
;
166 mode
>>= CFG_MODE_SHIFT
;
169 mask
= BIT(rcg
->hid_width
) - 1;
170 hid_div
= cfg
>> CFG_SRC_DIV_SHIFT
;
173 return calc_rate(parent_rate
, m
, n
, mode
, hid_div
);
176 static long _freq_tbl_determine_rate(struct clk_hw
*hw
,
177 const struct freq_tbl
*f
, unsigned long rate
,
178 unsigned long *p_rate
, struct clk
**p
)
180 unsigned long clk_flags
;
182 f
= qcom_find_freq(f
, rate
);
186 clk_flags
= __clk_get_flags(hw
->clk
);
187 *p
= clk_get_parent_by_index(hw
->clk
, f
->src
);
188 if (clk_flags
& CLK_SET_RATE_PARENT
) {
191 rate
*= f
->pre_div
+ 1;
201 rate
= __clk_get_rate(*p
);
208 static long clk_rcg2_determine_rate(struct clk_hw
*hw
, unsigned long rate
,
209 unsigned long *p_rate
, struct clk
**p
)
211 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
213 return _freq_tbl_determine_rate(hw
, rcg
->freq_tbl
, rate
, p_rate
, p
);
216 static int clk_rcg2_configure(struct clk_rcg2
*rcg
, const struct freq_tbl
*f
)
221 if (rcg
->mnd_width
&& f
->n
) {
222 mask
= BIT(rcg
->mnd_width
) - 1;
223 ret
= regmap_update_bits(rcg
->clkr
.regmap
,
224 rcg
->cmd_rcgr
+ M_REG
, mask
, f
->m
);
228 ret
= regmap_update_bits(rcg
->clkr
.regmap
,
229 rcg
->cmd_rcgr
+ N_REG
, mask
, ~(f
->n
- f
->m
));
233 ret
= regmap_update_bits(rcg
->clkr
.regmap
,
234 rcg
->cmd_rcgr
+ D_REG
, mask
, ~f
->n
);
239 mask
= BIT(rcg
->hid_width
) - 1;
240 mask
|= CFG_SRC_SEL_MASK
| CFG_MODE_MASK
;
241 cfg
= f
->pre_div
<< CFG_SRC_DIV_SHIFT
;
242 cfg
|= rcg
->parent_map
[f
->src
] << CFG_SRC_SEL_SHIFT
;
243 if (rcg
->mnd_width
&& f
->n
)
244 cfg
|= CFG_MODE_DUAL_EDGE
;
245 ret
= regmap_update_bits(rcg
->clkr
.regmap
,
246 rcg
->cmd_rcgr
+ CFG_REG
, mask
, cfg
);
250 return update_config(rcg
);
253 static int __clk_rcg2_set_rate(struct clk_hw
*hw
, unsigned long rate
)
255 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
256 const struct freq_tbl
*f
;
258 f
= qcom_find_freq(rcg
->freq_tbl
, rate
);
262 return clk_rcg2_configure(rcg
, f
);
265 static int clk_rcg2_set_rate(struct clk_hw
*hw
, unsigned long rate
,
266 unsigned long parent_rate
)
268 return __clk_rcg2_set_rate(hw
, rate
);
271 static int clk_rcg2_set_rate_and_parent(struct clk_hw
*hw
,
272 unsigned long rate
, unsigned long parent_rate
, u8 index
)
274 return __clk_rcg2_set_rate(hw
, rate
);
277 const struct clk_ops clk_rcg2_ops
= {
278 .is_enabled
= clk_rcg2_is_enabled
,
279 .get_parent
= clk_rcg2_get_parent
,
280 .set_parent
= clk_rcg2_set_parent
,
281 .recalc_rate
= clk_rcg2_recalc_rate
,
282 .determine_rate
= clk_rcg2_determine_rate
,
283 .set_rate
= clk_rcg2_set_rate
,
284 .set_rate_and_parent
= clk_rcg2_set_rate_and_parent
,
286 EXPORT_SYMBOL_GPL(clk_rcg2_ops
);
293 static const struct frac_entry frac_table_675m
[] = { /* link rate of 270M */
294 { 52, 295 }, /* 119 M */
295 { 11, 57 }, /* 130.25 M */
296 { 63, 307 }, /* 138.50 M */
297 { 11, 50 }, /* 148.50 M */
298 { 47, 206 }, /* 154 M */
299 { 31, 100 }, /* 205.25 M */
300 { 107, 269 }, /* 268.50 M */
304 static struct frac_entry frac_table_810m
[] = { /* Link rate of 162M */
305 { 31, 211 }, /* 119 M */
306 { 32, 199 }, /* 130.25 M */
307 { 63, 307 }, /* 138.50 M */
308 { 11, 60 }, /* 148.50 M */
309 { 50, 263 }, /* 154 M */
310 { 31, 120 }, /* 205.25 M */
311 { 119, 359 }, /* 268.50 M */
315 static int clk_edp_pixel_set_rate(struct clk_hw
*hw
, unsigned long rate
,
316 unsigned long parent_rate
)
318 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
319 struct freq_tbl f
= *rcg
->freq_tbl
;
320 const struct frac_entry
*frac
;
322 s64 src_rate
= parent_rate
;
324 u32 mask
= BIT(rcg
->hid_width
) - 1;
327 if (src_rate
== 810000000)
328 frac
= frac_table_810m
;
330 frac
= frac_table_675m
;
332 for (; frac
->num
; frac
++) {
334 request
*= frac
->den
;
335 request
= div_s64(request
, frac
->num
);
336 if ((src_rate
< (request
- delta
)) ||
337 (src_rate
> (request
+ delta
)))
340 regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CFG_REG
,
343 f
.pre_div
>>= CFG_SRC_DIV_SHIFT
;
348 return clk_rcg2_configure(rcg
, &f
);
354 static int clk_edp_pixel_set_rate_and_parent(struct clk_hw
*hw
,
355 unsigned long rate
, unsigned long parent_rate
, u8 index
)
357 /* Parent index is set statically in frequency table */
358 return clk_edp_pixel_set_rate(hw
, rate
, parent_rate
);
361 static long clk_edp_pixel_determine_rate(struct clk_hw
*hw
, unsigned long rate
,
362 unsigned long *p_rate
, struct clk
**p
)
364 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
365 const struct freq_tbl
*f
= rcg
->freq_tbl
;
366 const struct frac_entry
*frac
;
368 s64 src_rate
= *p_rate
;
370 u32 mask
= BIT(rcg
->hid_width
) - 1;
373 /* Force the correct parent */
374 *p
= clk_get_parent_by_index(hw
->clk
, f
->src
);
376 if (src_rate
== 810000000)
377 frac
= frac_table_810m
;
379 frac
= frac_table_675m
;
381 for (; frac
->num
; frac
++) {
383 request
*= frac
->den
;
384 request
= div_s64(request
, frac
->num
);
385 if ((src_rate
< (request
- delta
)) ||
386 (src_rate
> (request
+ delta
)))
389 regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CFG_REG
,
391 hid_div
>>= CFG_SRC_DIV_SHIFT
;
394 return calc_rate(src_rate
, frac
->num
, frac
->den
, !!frac
->den
,
401 const struct clk_ops clk_edp_pixel_ops
= {
402 .is_enabled
= clk_rcg2_is_enabled
,
403 .get_parent
= clk_rcg2_get_parent
,
404 .set_parent
= clk_rcg2_set_parent
,
405 .recalc_rate
= clk_rcg2_recalc_rate
,
406 .set_rate
= clk_edp_pixel_set_rate
,
407 .set_rate_and_parent
= clk_edp_pixel_set_rate_and_parent
,
408 .determine_rate
= clk_edp_pixel_determine_rate
,
410 EXPORT_SYMBOL_GPL(clk_edp_pixel_ops
);
412 static long clk_byte_determine_rate(struct clk_hw
*hw
, unsigned long rate
,
413 unsigned long *p_rate
, struct clk
**p
)
415 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
416 const struct freq_tbl
*f
= rcg
->freq_tbl
;
417 unsigned long parent_rate
, div
;
418 u32 mask
= BIT(rcg
->hid_width
) - 1;
423 *p
= clk_get_parent_by_index(hw
->clk
, f
->src
);
424 *p_rate
= parent_rate
= __clk_round_rate(*p
, rate
);
426 div
= DIV_ROUND_UP((2 * parent_rate
), rate
) - 1;
427 div
= min_t(u32
, div
, mask
);
429 return calc_rate(parent_rate
, 0, 0, 0, div
);
432 static int clk_byte_set_rate(struct clk_hw
*hw
, unsigned long rate
,
433 unsigned long parent_rate
)
435 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
436 struct freq_tbl f
= *rcg
->freq_tbl
;
438 u32 mask
= BIT(rcg
->hid_width
) - 1;
440 div
= DIV_ROUND_UP((2 * parent_rate
), rate
) - 1;
441 div
= min_t(u32
, div
, mask
);
445 return clk_rcg2_configure(rcg
, &f
);
448 static int clk_byte_set_rate_and_parent(struct clk_hw
*hw
,
449 unsigned long rate
, unsigned long parent_rate
, u8 index
)
451 /* Parent index is set statically in frequency table */
452 return clk_byte_set_rate(hw
, rate
, parent_rate
);
455 const struct clk_ops clk_byte_ops
= {
456 .is_enabled
= clk_rcg2_is_enabled
,
457 .get_parent
= clk_rcg2_get_parent
,
458 .set_parent
= clk_rcg2_set_parent
,
459 .recalc_rate
= clk_rcg2_recalc_rate
,
460 .set_rate
= clk_byte_set_rate
,
461 .set_rate_and_parent
= clk_byte_set_rate_and_parent
,
462 .determine_rate
= clk_byte_determine_rate
,
464 EXPORT_SYMBOL_GPL(clk_byte_ops
);
466 static const struct frac_entry frac_table_pixel
[] = {
474 static long clk_pixel_determine_rate(struct clk_hw
*hw
, unsigned long rate
,
475 unsigned long *p_rate
, struct clk
**p
)
477 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
478 unsigned long request
, src_rate
;
480 const struct freq_tbl
*f
= rcg
->freq_tbl
;
481 const struct frac_entry
*frac
= frac_table_pixel
;
482 struct clk
*parent
= *p
= clk_get_parent_by_index(hw
->clk
, f
->src
);
484 for (; frac
->num
; frac
++) {
485 request
= (rate
* frac
->den
) / frac
->num
;
487 src_rate
= __clk_round_rate(parent
, request
);
488 if ((src_rate
< (request
- delta
)) ||
489 (src_rate
> (request
+ delta
)))
493 return (src_rate
* frac
->num
) / frac
->den
;
499 static int clk_pixel_set_rate(struct clk_hw
*hw
, unsigned long rate
,
500 unsigned long parent_rate
)
502 struct clk_rcg2
*rcg
= to_clk_rcg2(hw
);
503 struct freq_tbl f
= *rcg
->freq_tbl
;
504 const struct frac_entry
*frac
= frac_table_pixel
;
505 unsigned long request
, src_rate
;
507 u32 mask
= BIT(rcg
->hid_width
) - 1;
509 struct clk
*parent
= clk_get_parent_by_index(hw
->clk
, f
.src
);
511 for (; frac
->num
; frac
++) {
512 request
= (rate
* frac
->den
) / frac
->num
;
514 src_rate
= __clk_round_rate(parent
, request
);
515 if ((src_rate
< (request
- delta
)) ||
516 (src_rate
> (request
+ delta
)))
519 regmap_read(rcg
->clkr
.regmap
, rcg
->cmd_rcgr
+ CFG_REG
,
522 f
.pre_div
>>= CFG_SRC_DIV_SHIFT
;
527 return clk_rcg2_configure(rcg
, &f
);
532 static int clk_pixel_set_rate_and_parent(struct clk_hw
*hw
, unsigned long rate
,
533 unsigned long parent_rate
, u8 index
)
535 /* Parent index is set statically in frequency table */
536 return clk_pixel_set_rate(hw
, rate
, parent_rate
);
539 const struct clk_ops clk_pixel_ops
= {
540 .is_enabled
= clk_rcg2_is_enabled
,
541 .get_parent
= clk_rcg2_get_parent
,
542 .set_parent
= clk_rcg2_set_parent
,
543 .recalc_rate
= clk_rcg2_recalc_rate
,
544 .set_rate
= clk_pixel_set_rate
,
545 .set_rate_and_parent
= clk_pixel_set_rate_and_parent
,
546 .determine_rate
= clk_pixel_determine_rate
,
548 EXPORT_SYMBOL_GPL(clk_pixel_ops
);