1 // SPDX-License-Identifier: GPL-2.0
3 * Common clock framework driver for the Versaclock7 family of timing devices.
5 * Copyright (c) 2022 Renesas Electronics Corporation
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10 #include <linux/bitfield.h>
11 #include <linux/clk.h>
12 #include <linux/clk-provider.h>
13 #include <linux/i2c.h>
14 #include <linux/math64.h>
15 #include <linux/module.h>
17 #include <linux/property.h>
18 #include <linux/regmap.h>
19 #include <linux/swab.h>
22 * 16-bit register address: the lower 8 bits of the register address come
23 * from the offset addr byte and the upper 8 bits come from the page register.
25 #define VC7_PAGE_ADDR 0xFD
26 #define VC7_PAGE_WINDOW 256
27 #define VC7_MAX_REG 0x364
29 /* Maximum number of banks supported by VC7 */
30 #define VC7_NUM_BANKS 7
32 /* Maximum number of FODs supported by VC7 */
35 /* Maximum number of IODs supported by VC7 */
38 /* Maximum number of outputs supported by VC7 */
39 #define VC7_NUM_OUT 12
41 /* VCO valid range is 9.5 GHz to 10.7 GHz */
42 #define VC7_APLL_VCO_MIN 9500000000UL
43 #define VC7_APLL_VCO_MAX 10700000000UL
45 /* APLL denominator is fixed at 2^27 */
46 #define VC7_APLL_DENOMINATOR_BITS 27
48 /* FOD 1st stage denominator is fixed 2^34 */
49 #define VC7_FOD_DENOMINATOR_BITS 34
51 /* IOD can operate between 1kHz and 650MHz */
52 #define VC7_IOD_RATE_MIN 1000UL
53 #define VC7_IOD_RATE_MAX 650000000UL
54 #define VC7_IOD_MIN_DIVISOR 14
55 #define VC7_IOD_MAX_DIVISOR 0x1ffffff /* 25-bit */
57 #define VC7_FOD_RATE_MIN 1000UL
58 #define VC7_FOD_RATE_MAX 650000000UL
59 #define VC7_FOD_1ST_STAGE_RATE_MIN 33000000UL /* 33 MHz */
60 #define VC7_FOD_1ST_STAGE_RATE_MAX 650000000UL /* 650 MHz */
61 #define VC7_FOD_1ST_INT_MAX 324
62 #define VC7_FOD_2ND_INT_MIN 2
63 #define VC7_FOD_2ND_INT_MAX 0x1ffff /* 17-bit */
67 #define VC7_REG_XO_CNFG 0x2C
68 #define VC7_REG_XO_CNFG_COUNT 4
69 #define VC7_REG_XO_IB_H_DIV_SHIFT 24
70 #define VC7_REG_XO_IB_H_DIV_MASK GENMASK(28, VC7_REG_XO_IB_H_DIV_SHIFT)
72 #define VC7_REG_APLL_FB_DIV_FRAC 0x120
73 #define VC7_REG_APLL_FB_DIV_FRAC_COUNT 4
74 #define VC7_REG_APLL_FB_DIV_FRAC_MASK GENMASK(26, 0)
76 #define VC7_REG_APLL_FB_DIV_INT 0x124
77 #define VC7_REG_APLL_FB_DIV_INT_COUNT 2
78 #define VC7_REG_APLL_FB_DIV_INT_MASK GENMASK(9, 0)
80 #define VC7_REG_APLL_CNFG 0x127
81 #define VC7_REG_APLL_EN_DOUBLER BIT(0)
83 #define VC7_REG_OUT_BANK_CNFG(idx) (0x280 + (0x4 * (idx)))
84 #define VC7_REG_OUTPUT_BANK_SRC_MASK GENMASK(2, 0)
86 #define VC7_REG_FOD_INT_CNFG(idx) (0x1E0 + (0x10 * (idx)))
87 #define VC7_REG_FOD_INT_CNFG_COUNT 8
88 #define VC7_REG_FOD_1ST_INT_MASK GENMASK(8, 0)
89 #define VC7_REG_FOD_2ND_INT_SHIFT 9
90 #define VC7_REG_FOD_2ND_INT_MASK GENMASK(25, VC7_REG_FOD_2ND_INT_SHIFT)
91 #define VC7_REG_FOD_FRAC_SHIFT 26
92 #define VC7_REG_FOD_FRAC_MASK GENMASK_ULL(59, VC7_REG_FOD_FRAC_SHIFT)
94 #define VC7_REG_IOD_INT_CNFG(idx) (0x1C0 + (0x8 * (idx)))
95 #define VC7_REG_IOD_INT_CNFG_COUNT 4
96 #define VC7_REG_IOD_INT_MASK GENMASK(24, 0)
98 #define VC7_REG_ODRV_EN(idx) (0x240 + (0x4 * (idx)))
99 #define VC7_REG_OUT_DIS BIT(0)
101 struct vc7_driver_data
;
102 static const struct regmap_config vc7_regmap_config
;
104 /* Supported Renesas VC7 models */
109 struct vc7_chip_info
{
110 const enum vc7_model model
;
111 const unsigned int banks
[VC7_NUM_BANKS
];
112 const unsigned int num_banks
;
113 const unsigned int outputs
[VC7_NUM_OUT
];
114 const unsigned int num_outputs
;
118 * Changing the APLL frequency is currently not supported.
119 * The APLL will consist of an opaque block between the XO and FOD/IODs and
120 * its frequency will be computed based on the current state of the device.
122 struct vc7_apll_data
{
124 struct vc7_driver_data
*vc7
;
128 u32 apll_fb_div_frac
;
131 struct vc7_fod_data
{
133 struct vc7_driver_data
*vc7
;
140 struct vc7_iod_data
{
142 struct vc7_driver_data
*vc7
;
147 struct vc7_out_data
{
149 struct vc7_driver_data
*vc7
;
151 unsigned int out_dis
;
154 struct vc7_driver_data
{
155 struct i2c_client
*client
;
156 struct regmap
*regmap
;
157 const struct vc7_chip_info
*chip_info
;
160 struct vc7_apll_data clk_apll
;
161 struct vc7_fod_data clk_fod
[VC7_NUM_FOD
];
162 struct vc7_iod_data clk_iod
[VC7_NUM_IOD
];
163 struct vc7_out_data clk_out
[VC7_NUM_OUT
];
166 struct vc7_bank_src_map
{
167 enum vc7_bank_src_type
{
172 struct vc7_iod_data
*iod
;
173 struct vc7_fod_data
*fod
;
177 static struct clk_hw
*vc7_of_clk_get(struct of_phandle_args
*clkspec
,
180 struct vc7_driver_data
*vc7
= data
;
181 unsigned int idx
= clkspec
->args
[0];
183 if (idx
>= vc7
->chip_info
->num_outputs
)
184 return ERR_PTR(-EINVAL
);
186 return &vc7
->clk_out
[idx
].hw
;
189 static const unsigned int RC21008A_index_to_output_mapping
[] = {
190 1, 2, 3, 6, 7, 8, 10, 11
193 static int vc7_map_index_to_output(const enum vc7_model model
, const unsigned int i
)
197 return RC21008A_index_to_output_mapping
[i
];
203 /* bank to output mapping, same across all variants */
204 static const unsigned int output_bank_mapping
[] = {
220 * vc7_64_mul_64_to_128() - Multiply two u64 and return an unsigned 128-bit integer
221 * as an upper and lower part.
223 * @left: The left argument.
224 * @right: The right argument.
225 * @hi: The upper 64-bits of the 128-bit product.
226 * @lo: The lower 64-bits of the 128-bit product.
228 * From mul_64_64 in crypto/ecc.c:350 in the linux kernel, accessed in v5.17.2.
230 static void vc7_64_mul_64_to_128(u64 left
, u64 right
, u64
*hi
, u64
*lo
)
232 u64 a0
= left
& 0xffffffffull
;
234 u64 b0
= right
& 0xffffffffull
;
235 u64 b1
= right
>> 32;
246 m3
+= 0x100000000ull
;
248 *lo
= (m0
& 0xffffffffull
) | (m2
<< 32);
249 *hi
= m3
+ (m2
>> 32);
253 * vc7_128_div_64_to_64() - Divides a 128-bit uint by a 64-bit divisor, return a 64-bit quotient.
255 * @numhi: The uppper 64-bits of the dividend.
256 * @numlo: The lower 64-bits of the dividend.
257 * @den: The denominator (divisor).
258 * @r: The remainder, pass NULL if the remainder is not needed.
260 * Originally from libdivide, modified to use kernel u64/u32 types.
262 * See https://github.com/ridiculousfish/libdivide/blob/master/libdivide.h#L471.
264 * Return: The 64-bit quotient of the division.
266 * In case of overflow of division by zero, max(u64) is returned.
268 static u64
vc7_128_div_64_to_64(u64 numhi
, u64 numlo
, u64 den
, u64
*r
)
271 * We work in base 2**32.
272 * A uint32 holds a single digit. A uint64 holds two digits.
273 * Our numerator is conceptually [num3, num2, num1, num0].
274 * Our denominator is [den1, den0].
276 const u64 b
= ((u64
)1 << 32);
278 /* The high and low digits of our computed quotient. */
281 /* The normalization shift factor */
285 * The high and low digits of our denominator (after normalizing).
286 * Also the low 2 digits of our numerator (after normalizing).
288 u32 den1
, den0
, num1
, num0
;
290 /* A partial remainder; */
294 * The estimated quotient, and its corresponding remainder (unrelated
295 * to true remainder).
299 /* Variables used to correct the estimated quotient. */
302 /* Check for overflow and divide by 0. */
310 * Determine the normalization factor. We multiply den by this, so that
311 * its leading digit is at least half b. In binary this means just
312 * shifting left by the number of leading zeros, so that there's a 1 in
315 * We also shift numer by the same amount. This cannot overflow because
316 * numhi < den. The expression (-shift & 63) is the same as (64 -
317 * shift), except it avoids the UB of shifting by 64. The funny bitwise
318 * 'and' ensures that numlo does not get shifted into numhi if shift is
319 * 0. clang 11 has an x86 codegen bug here: see LLVM bug 50118. The
320 * sequence below avoids it.
322 shift
= __builtin_clzll(den
);
325 numhi
|= (numlo
>> (-shift
& 63)) & (-(s64
)shift
>> 63);
329 * Extract the low digits of the numerator and both digits of the
332 num1
= (u32
)(numlo
>> 32);
333 num0
= (u32
)(numlo
& 0xFFFFFFFFu
);
334 den1
= (u32
)(den
>> 32);
335 den0
= (u32
)(den
& 0xFFFFFFFFu
);
338 * We wish to compute q1 = [n3 n2 n1] / [d1 d0].
339 * Estimate q1 as [n3 n2] / [d1], and then correct it.
340 * Note while qhat may be 2 digits, q1 is always 1 digit.
342 qhat
= div64_u64_rem(numhi
, den1
, &rhat
);
344 c2
= rhat
* b
+ num1
;
346 qhat
-= (c1
- c2
> den
) ? 2 : 1;
349 /* Compute the true (partial) remainder. */
350 rem
= numhi
* b
+ num1
- q1
* den
;
353 * We wish to compute q0 = [rem1 rem0 n0] / [d1 d0].
354 * Estimate q0 as [rem1 rem0] / [d1] and correct it.
356 qhat
= div64_u64_rem(rem
, den1
, &rhat
);
358 c2
= rhat
* b
+ num0
;
360 qhat
-= (c1
- c2
> den
) ? 2 : 1;
363 /* Return remainder if requested. */
365 *r
= (rem
* b
+ num0
- q0
* den
) >> shift
;
366 return ((u64
)q1
<< 32) | q0
;
369 static int vc7_get_bank_clk(struct vc7_driver_data
*vc7
,
370 unsigned int bank_idx
,
371 unsigned int output_bank_src
,
372 struct vc7_bank_src_map
*map
)
374 /* Mapping from Table 38 in datasheet */
375 if (bank_idx
== 0 || bank_idx
== 1) {
376 switch (output_bank_src
) {
379 map
->src
.iod
= &vc7
->clk_iod
[0];
383 map
->src
.iod
= &vc7
->clk_iod
[1];
387 map
->src
.fod
= &vc7
->clk_fod
[0];
391 map
->src
.fod
= &vc7
->clk_fod
[1];
396 } else if (bank_idx
== 2) {
397 switch (output_bank_src
) {
400 map
->src
.iod
= &vc7
->clk_iod
[1];
404 map
->src
.fod
= &vc7
->clk_fod
[0];
408 map
->src
.fod
= &vc7
->clk_fod
[1];
413 } else if (bank_idx
== 3) {
414 switch (output_bank_src
) {
417 map
->src
.fod
= &vc7
->clk_fod
[0];
421 map
->src
.fod
= &vc7
->clk_fod
[1];
425 map
->src
.fod
= &vc7
->clk_fod
[2];
430 } else if (bank_idx
== 4) {
431 switch (output_bank_src
) {
433 /* CLKIN1 not supported in this driver */
437 map
->src
.iod
= &vc7
->clk_iod
[2];
441 map
->src
.fod
= &vc7
->clk_fod
[1];
445 map
->src
.fod
= &vc7
->clk_fod
[2];
448 /* CLKIN0 not supported in this driver */
453 } else if (bank_idx
== 5) {
454 switch (output_bank_src
) {
456 /* CLKIN1 not supported in this driver */
459 /* XIN_REFIN not supported in this driver */
463 map
->src
.iod
= &vc7
->clk_iod
[2];
467 map
->src
.iod
= &vc7
->clk_iod
[3];
471 map
->src
.fod
= &vc7
->clk_fod
[1];
475 map
->src
.fod
= &vc7
->clk_fod
[2];
478 /* CLKIN0 not supported in this driver */
483 } else if (bank_idx
== 6) {
484 switch (output_bank_src
) {
486 /* CLKIN1 not supported in this driver */
490 map
->src
.iod
= &vc7
->clk_iod
[2];
494 map
->src
.iod
= &vc7
->clk_iod
[3];
498 map
->src
.fod
= &vc7
->clk_fod
[1];
502 map
->src
.fod
= &vc7
->clk_fod
[2];
505 /* CLKIN0 not supported in this driver */
512 pr_warn("bank_src%d = %d is not supported\n", bank_idx
, output_bank_src
);
516 static int vc7_read_apll(struct vc7_driver_data
*vc7
)
522 err
= regmap_bulk_read(vc7
->regmap
,
525 VC7_REG_XO_CNFG_COUNT
);
527 dev_err(&vc7
->client
->dev
, "failed to read XO_CNFG\n");
531 vc7
->clk_apll
.xo_ib_h_div
= (val32
& VC7_REG_XO_IB_H_DIV_MASK
)
532 >> VC7_REG_XO_IB_H_DIV_SHIFT
;
534 err
= regmap_read(vc7
->regmap
,
538 dev_err(&vc7
->client
->dev
, "failed to read APLL_CNFG\n");
542 vc7
->clk_apll
.en_doubler
= val32
& VC7_REG_APLL_EN_DOUBLER
;
544 err
= regmap_bulk_read(vc7
->regmap
,
545 VC7_REG_APLL_FB_DIV_FRAC
,
547 VC7_REG_APLL_FB_DIV_FRAC_COUNT
);
549 dev_err(&vc7
->client
->dev
, "failed to read APLL_FB_DIV_FRAC\n");
553 vc7
->clk_apll
.apll_fb_div_frac
= val32
& VC7_REG_APLL_FB_DIV_FRAC_MASK
;
555 err
= regmap_bulk_read(vc7
->regmap
,
556 VC7_REG_APLL_FB_DIV_INT
,
558 VC7_REG_APLL_FB_DIV_INT_COUNT
);
560 dev_err(&vc7
->client
->dev
, "failed to read APLL_FB_DIV_INT\n");
564 vc7
->clk_apll
.apll_fb_div_int
= val16
& VC7_REG_APLL_FB_DIV_INT_MASK
;
569 static int vc7_read_fod(struct vc7_driver_data
*vc7
, unsigned int idx
)
574 err
= regmap_bulk_read(vc7
->regmap
,
575 VC7_REG_FOD_INT_CNFG(idx
),
577 VC7_REG_FOD_INT_CNFG_COUNT
);
579 dev_err(&vc7
->client
->dev
, "failed to read FOD%d\n", idx
);
583 vc7
->clk_fod
[idx
].fod_1st_int
= (val
& VC7_REG_FOD_1ST_INT_MASK
);
584 vc7
->clk_fod
[idx
].fod_2nd_int
=
585 (val
& VC7_REG_FOD_2ND_INT_MASK
) >> VC7_REG_FOD_2ND_INT_SHIFT
;
586 vc7
->clk_fod
[idx
].fod_frac
= (val
& VC7_REG_FOD_FRAC_MASK
)
587 >> VC7_REG_FOD_FRAC_SHIFT
;
592 static int vc7_write_fod(struct vc7_driver_data
*vc7
, unsigned int idx
)
598 * FOD dividers are part of an atomic group where fod_1st_int,
599 * fod_2nd_int, and fod_frac must be written together. The new divider
600 * is applied when the MSB of fod_frac is written.
603 err
= regmap_bulk_read(vc7
->regmap
,
604 VC7_REG_FOD_INT_CNFG(idx
),
606 VC7_REG_FOD_INT_CNFG_COUNT
);
608 dev_err(&vc7
->client
->dev
, "failed to read FOD%d\n", idx
);
612 val
= u64_replace_bits(val
,
613 vc7
->clk_fod
[idx
].fod_1st_int
,
614 VC7_REG_FOD_1ST_INT_MASK
);
615 val
= u64_replace_bits(val
,
616 vc7
->clk_fod
[idx
].fod_2nd_int
,
617 VC7_REG_FOD_2ND_INT_MASK
);
618 val
= u64_replace_bits(val
,
619 vc7
->clk_fod
[idx
].fod_frac
,
620 VC7_REG_FOD_FRAC_MASK
);
622 err
= regmap_bulk_write(vc7
->regmap
,
623 VC7_REG_FOD_INT_CNFG(idx
),
627 dev_err(&vc7
->client
->dev
, "failed to write FOD%d\n", idx
);
634 static int vc7_read_iod(struct vc7_driver_data
*vc7
, unsigned int idx
)
639 err
= regmap_bulk_read(vc7
->regmap
,
640 VC7_REG_IOD_INT_CNFG(idx
),
642 VC7_REG_IOD_INT_CNFG_COUNT
);
644 dev_err(&vc7
->client
->dev
, "failed to read IOD%d\n", idx
);
648 vc7
->clk_iod
[idx
].iod_int
= (val
& VC7_REG_IOD_INT_MASK
);
653 static int vc7_write_iod(struct vc7_driver_data
*vc7
, unsigned int idx
)
659 * IOD divider field is atomic and all bits must be written.
660 * The new divider is applied when the MSB of iod_int is written.
663 err
= regmap_bulk_read(vc7
->regmap
,
664 VC7_REG_IOD_INT_CNFG(idx
),
666 VC7_REG_IOD_INT_CNFG_COUNT
);
668 dev_err(&vc7
->client
->dev
, "failed to read IOD%d\n", idx
);
672 val
= u32_replace_bits(val
,
673 vc7
->clk_iod
[idx
].iod_int
,
674 VC7_REG_IOD_INT_MASK
);
676 err
= regmap_bulk_write(vc7
->regmap
,
677 VC7_REG_IOD_INT_CNFG(idx
),
681 dev_err(&vc7
->client
->dev
, "failed to write IOD%d\n", idx
);
688 static int vc7_read_output(struct vc7_driver_data
*vc7
, unsigned int idx
)
691 unsigned int val
, out_num
;
693 out_num
= vc7_map_index_to_output(vc7
->chip_info
->model
, idx
);
694 err
= regmap_read(vc7
->regmap
,
695 VC7_REG_ODRV_EN(out_num
),
698 dev_err(&vc7
->client
->dev
, "failed to read ODRV_EN[%d]\n", idx
);
702 vc7
->clk_out
[idx
].out_dis
= val
& VC7_REG_OUT_DIS
;
707 static int vc7_write_output(struct vc7_driver_data
*vc7
, unsigned int idx
)
710 unsigned int out_num
;
712 out_num
= vc7_map_index_to_output(vc7
->chip_info
->model
, idx
);
713 err
= regmap_write_bits(vc7
->regmap
,
714 VC7_REG_ODRV_EN(out_num
),
716 vc7
->clk_out
[idx
].out_dis
);
719 dev_err(&vc7
->client
->dev
, "failed to write ODRV_EN[%d]\n", idx
);
726 static unsigned long vc7_get_apll_rate(struct vc7_driver_data
*vc7
)
729 unsigned long xtal_rate
;
730 u64 refin_div
, apll_rate
;
732 xtal_rate
= clk_get_rate(vc7
->pin_xin
);
733 err
= vc7_read_apll(vc7
);
735 dev_err(&vc7
->client
->dev
, "unable to read apll\n");
739 /* 0 is bypassed, 1 is reserved */
740 if (vc7
->clk_apll
.xo_ib_h_div
< 2)
741 refin_div
= xtal_rate
;
743 refin_div
= div64_u64(xtal_rate
, vc7
->clk_apll
.xo_ib_h_div
);
745 if (vc7
->clk_apll
.en_doubler
)
748 /* divider = int + (frac / 2^27) */
749 apll_rate
= (refin_div
* vc7
->clk_apll
.apll_fb_div_int
) +
750 ((refin_div
* vc7
->clk_apll
.apll_fb_div_frac
) >> VC7_APLL_DENOMINATOR_BITS
);
752 pr_debug("%s - xo_ib_h_div: %u, apll_fb_div_int: %u, apll_fb_div_frac: %u\n",
753 __func__
, vc7
->clk_apll
.xo_ib_h_div
, vc7
->clk_apll
.apll_fb_div_int
,
754 vc7
->clk_apll
.apll_fb_div_frac
);
755 pr_debug("%s - refin_div: %llu, apll rate: %llu\n",
756 __func__
, refin_div
, apll_rate
);
761 static void vc7_calc_iod_divider(unsigned long rate
, unsigned long parent_rate
,
764 *divider
= DIV_ROUND_UP(parent_rate
, rate
);
765 if (*divider
< VC7_IOD_MIN_DIVISOR
)
766 *divider
= VC7_IOD_MIN_DIVISOR
;
767 if (*divider
> VC7_IOD_MAX_DIVISOR
)
768 *divider
= VC7_IOD_MAX_DIVISOR
;
771 static void vc7_calc_fod_1st_stage(unsigned long rate
, unsigned long parent_rate
,
772 u32
*div_int
, u64
*div_frac
)
776 *div_int
= (u32
)div64_u64_rem(parent_rate
, rate
, &rem
);
777 *div_frac
= div64_u64(rem
<< VC7_FOD_DENOMINATOR_BITS
, rate
);
780 static unsigned long vc7_calc_fod_1st_stage_rate(unsigned long parent_rate
,
781 u32 fod_1st_int
, u64 fod_frac
)
783 u64 numer
, denom
, hi
, lo
, divisor
;
786 denom
= BIT_ULL(VC7_FOD_DENOMINATOR_BITS
);
789 vc7_64_mul_64_to_128(parent_rate
, denom
, &hi
, &lo
);
790 divisor
= ((u64
)fod_1st_int
* denom
) + numer
;
791 return vc7_128_div_64_to_64(hi
, lo
, divisor
, NULL
);
794 return div64_u64(parent_rate
, fod_1st_int
);
797 static unsigned long vc7_calc_fod_2nd_stage_rate(unsigned long parent_rate
,
798 u32 fod_1st_int
, u32 fod_2nd_int
, u64 fod_frac
)
800 unsigned long fod_1st_stage_rate
;
802 fod_1st_stage_rate
= vc7_calc_fod_1st_stage_rate(parent_rate
, fod_1st_int
, fod_frac
);
805 return fod_1st_stage_rate
;
808 * There is a div-by-2 preceding the 2nd stage integer divider
809 * (not shown on block diagram) so the actual 2nd stage integer
812 return div64_u64(fod_1st_stage_rate
>> 1, fod_2nd_int
);
815 static void vc7_calc_fod_divider(unsigned long rate
, unsigned long parent_rate
,
816 u32
*fod_1st_int
, u32
*fod_2nd_int
, u64
*fod_frac
)
818 unsigned int allow_frac
, i
, best_frac_i
;
819 unsigned long first_stage_rate
;
821 vc7_calc_fod_1st_stage(rate
, parent_rate
, fod_1st_int
, fod_frac
);
822 first_stage_rate
= vc7_calc_fod_1st_stage_rate(parent_rate
, *fod_1st_int
, *fod_frac
);
826 /* Do we need the second stage integer divider? */
827 if (first_stage_rate
< VC7_FOD_1ST_STAGE_RATE_MIN
) {
829 best_frac_i
= VC7_FOD_2ND_INT_MIN
;
831 for (i
= VC7_FOD_2ND_INT_MIN
; i
<= VC7_FOD_2ND_INT_MAX
; i
++) {
833 * 1) There is a div-by-2 preceding the 2nd stage integer divider
834 * (not shown on block diagram) so the actual 2nd stage integer
836 * 2) Attempt to find an integer solution first. This means stepping
837 * through each 2nd stage integer and recalculating the 1st stage
838 * until the 1st stage frequency is out of bounds. If no integer
839 * solution is found, use the best fractional solution.
841 vc7_calc_fod_1st_stage(parent_rate
, rate
* 2 * i
, fod_1st_int
, fod_frac
);
842 first_stage_rate
= vc7_calc_fod_1st_stage_rate(parent_rate
,
846 /* Remember the first viable fractional solution */
847 if (best_frac_i
== VC7_FOD_2ND_INT_MIN
&&
848 first_stage_rate
> VC7_FOD_1ST_STAGE_RATE_MIN
) {
852 /* Is the divider viable? Prefer integer solutions over fractional. */
853 if (*fod_1st_int
< VC7_FOD_1ST_INT_MAX
&&
854 first_stage_rate
>= VC7_FOD_1ST_STAGE_RATE_MIN
&&
855 (allow_frac
|| *fod_frac
== 0)) {
860 /* Ran out of divisors or the 1st stage frequency is out of range */
861 if (i
>= VC7_FOD_2ND_INT_MAX
||
862 first_stage_rate
> VC7_FOD_1ST_STAGE_RATE_MAX
) {
866 /* Restore the best frac and rerun the loop for the last time */
867 if (best_frac_i
!= VC7_FOD_2ND_INT_MIN
)
876 static unsigned long vc7_fod_recalc_rate(struct clk_hw
*hw
, unsigned long parent_rate
)
878 struct vc7_fod_data
*fod
= container_of(hw
, struct vc7_fod_data
, hw
);
879 struct vc7_driver_data
*vc7
= fod
->vc7
;
881 unsigned long fod_rate
;
883 err
= vc7_read_fod(vc7
, fod
->num
);
885 dev_err(&vc7
->client
->dev
, "error reading registers for %s\n",
886 clk_hw_get_name(hw
));
890 pr_debug("%s - %s: parent_rate: %lu\n", __func__
, clk_hw_get_name(hw
), parent_rate
);
892 fod_rate
= vc7_calc_fod_2nd_stage_rate(parent_rate
, fod
->fod_1st_int
,
893 fod
->fod_2nd_int
, fod
->fod_frac
);
895 pr_debug("%s - %s: fod_1st_int: %u, fod_2nd_int: %u, fod_frac: %llu\n",
896 __func__
, clk_hw_get_name(hw
),
897 fod
->fod_1st_int
, fod
->fod_2nd_int
, fod
->fod_frac
);
898 pr_debug("%s - %s rate: %lu\n", __func__
, clk_hw_get_name(hw
), fod_rate
);
903 static long vc7_fod_round_rate(struct clk_hw
*hw
, unsigned long rate
, unsigned long *parent_rate
)
905 struct vc7_fod_data
*fod
= container_of(hw
, struct vc7_fod_data
, hw
);
906 unsigned long fod_rate
;
908 pr_debug("%s - %s: requested rate: %lu, parent_rate: %lu\n",
909 __func__
, clk_hw_get_name(hw
), rate
, *parent_rate
);
911 vc7_calc_fod_divider(rate
, *parent_rate
,
912 &fod
->fod_1st_int
, &fod
->fod_2nd_int
, &fod
->fod_frac
);
913 fod_rate
= vc7_calc_fod_2nd_stage_rate(*parent_rate
, fod
->fod_1st_int
,
914 fod
->fod_2nd_int
, fod
->fod_frac
);
916 pr_debug("%s - %s: fod_1st_int: %u, fod_2nd_int: %u, fod_frac: %llu\n",
917 __func__
, clk_hw_get_name(hw
),
918 fod
->fod_1st_int
, fod
->fod_2nd_int
, fod
->fod_frac
);
919 pr_debug("%s - %s rate: %lu\n", __func__
, clk_hw_get_name(hw
), fod_rate
);
924 static int vc7_fod_set_rate(struct clk_hw
*hw
, unsigned long rate
, unsigned long parent_rate
)
926 struct vc7_fod_data
*fod
= container_of(hw
, struct vc7_fod_data
, hw
);
927 struct vc7_driver_data
*vc7
= fod
->vc7
;
928 unsigned long fod_rate
;
930 pr_debug("%s - %s: rate: %lu, parent_rate: %lu\n",
931 __func__
, clk_hw_get_name(hw
), rate
, parent_rate
);
933 if (rate
< VC7_FOD_RATE_MIN
|| rate
> VC7_FOD_RATE_MAX
) {
934 dev_err(&vc7
->client
->dev
,
935 "requested frequency %lu Hz for %s is out of range\n",
936 rate
, clk_hw_get_name(hw
));
940 vc7_write_fod(vc7
, fod
->num
);
942 fod_rate
= vc7_calc_fod_2nd_stage_rate(parent_rate
, fod
->fod_1st_int
,
943 fod
->fod_2nd_int
, fod
->fod_frac
);
945 pr_debug("%s - %s: fod_1st_int: %u, fod_2nd_int: %u, fod_frac: %llu\n",
946 __func__
, clk_hw_get_name(hw
),
947 fod
->fod_1st_int
, fod
->fod_2nd_int
, fod
->fod_frac
);
948 pr_debug("%s - %s rate: %lu\n", __func__
, clk_hw_get_name(hw
), fod_rate
);
953 static const struct clk_ops vc7_fod_ops
= {
954 .recalc_rate
= vc7_fod_recalc_rate
,
955 .round_rate
= vc7_fod_round_rate
,
956 .set_rate
= vc7_fod_set_rate
,
959 static unsigned long vc7_iod_recalc_rate(struct clk_hw
*hw
, unsigned long parent_rate
)
961 struct vc7_iod_data
*iod
= container_of(hw
, struct vc7_iod_data
, hw
);
962 struct vc7_driver_data
*vc7
= iod
->vc7
;
964 unsigned long iod_rate
;
966 err
= vc7_read_iod(vc7
, iod
->num
);
968 dev_err(&vc7
->client
->dev
, "error reading registers for %s\n",
969 clk_hw_get_name(hw
));
973 iod_rate
= div64_u64(parent_rate
, iod
->iod_int
);
975 pr_debug("%s - %s: iod_int: %u\n", __func__
, clk_hw_get_name(hw
), iod
->iod_int
);
976 pr_debug("%s - %s rate: %lu\n", __func__
, clk_hw_get_name(hw
), iod_rate
);
981 static long vc7_iod_round_rate(struct clk_hw
*hw
, unsigned long rate
, unsigned long *parent_rate
)
983 struct vc7_iod_data
*iod
= container_of(hw
, struct vc7_iod_data
, hw
);
984 unsigned long iod_rate
;
986 pr_debug("%s - %s: requested rate: %lu, parent_rate: %lu\n",
987 __func__
, clk_hw_get_name(hw
), rate
, *parent_rate
);
989 vc7_calc_iod_divider(rate
, *parent_rate
, &iod
->iod_int
);
990 iod_rate
= div64_u64(*parent_rate
, iod
->iod_int
);
992 pr_debug("%s - %s: iod_int: %u\n", __func__
, clk_hw_get_name(hw
), iod
->iod_int
);
993 pr_debug("%s - %s rate: %ld\n", __func__
, clk_hw_get_name(hw
), iod_rate
);
998 static int vc7_iod_set_rate(struct clk_hw
*hw
, unsigned long rate
, unsigned long parent_rate
)
1000 struct vc7_iod_data
*iod
= container_of(hw
, struct vc7_iod_data
, hw
);
1001 struct vc7_driver_data
*vc7
= iod
->vc7
;
1002 unsigned long iod_rate
;
1004 pr_debug("%s - %s: rate: %lu, parent_rate: %lu\n",
1005 __func__
, clk_hw_get_name(hw
), rate
, parent_rate
);
1007 if (rate
< VC7_IOD_RATE_MIN
|| rate
> VC7_IOD_RATE_MAX
) {
1008 dev_err(&vc7
->client
->dev
,
1009 "requested frequency %lu Hz for %s is out of range\n",
1010 rate
, clk_hw_get_name(hw
));
1014 vc7_write_iod(vc7
, iod
->num
);
1016 iod_rate
= div64_u64(parent_rate
, iod
->iod_int
);
1018 pr_debug("%s - %s: iod_int: %u\n", __func__
, clk_hw_get_name(hw
), iod
->iod_int
);
1019 pr_debug("%s - %s rate: %ld\n", __func__
, clk_hw_get_name(hw
), iod_rate
);
1024 static const struct clk_ops vc7_iod_ops
= {
1025 .recalc_rate
= vc7_iod_recalc_rate
,
1026 .round_rate
= vc7_iod_round_rate
,
1027 .set_rate
= vc7_iod_set_rate
,
1030 static int vc7_clk_out_prepare(struct clk_hw
*hw
)
1032 struct vc7_out_data
*out
= container_of(hw
, struct vc7_out_data
, hw
);
1033 struct vc7_driver_data
*vc7
= out
->vc7
;
1038 err
= vc7_write_output(vc7
, out
->num
);
1040 dev_err(&vc7
->client
->dev
, "error writing registers for %s\n",
1041 clk_hw_get_name(hw
));
1045 pr_debug("%s - %s: clk prepared\n", __func__
, clk_hw_get_name(hw
));
1050 static void vc7_clk_out_unprepare(struct clk_hw
*hw
)
1052 struct vc7_out_data
*out
= container_of(hw
, struct vc7_out_data
, hw
);
1053 struct vc7_driver_data
*vc7
= out
->vc7
;
1058 err
= vc7_write_output(vc7
, out
->num
);
1060 dev_err(&vc7
->client
->dev
, "error writing registers for %s\n",
1061 clk_hw_get_name(hw
));
1065 pr_debug("%s - %s: clk unprepared\n", __func__
, clk_hw_get_name(hw
));
1068 static int vc7_clk_out_is_enabled(struct clk_hw
*hw
)
1070 struct vc7_out_data
*out
= container_of(hw
, struct vc7_out_data
, hw
);
1071 struct vc7_driver_data
*vc7
= out
->vc7
;
1072 int err
, is_enabled
;
1074 err
= vc7_read_output(vc7
, out
->num
);
1076 dev_err(&vc7
->client
->dev
, "error reading registers for %s\n",
1077 clk_hw_get_name(hw
));
1081 is_enabled
= !out
->out_dis
;
1083 pr_debug("%s - %s: is_enabled=%d\n", __func__
, clk_hw_get_name(hw
), is_enabled
);
1088 static const struct clk_ops vc7_clk_out_ops
= {
1089 .prepare
= vc7_clk_out_prepare
,
1090 .unprepare
= vc7_clk_out_unprepare
,
1091 .is_enabled
= vc7_clk_out_is_enabled
,
1094 static int vc7_probe(struct i2c_client
*client
)
1096 struct vc7_driver_data
*vc7
;
1097 struct clk_init_data clk_init
;
1098 struct vc7_bank_src_map bank_src_map
;
1099 const char *node_name
, *apll_name
;
1100 const char *parent_names
[1];
1101 unsigned int i
, val
, bank_idx
, out_num
;
1102 unsigned long apll_rate
;
1105 vc7
= devm_kzalloc(&client
->dev
, sizeof(*vc7
), GFP_KERNEL
);
1109 i2c_set_clientdata(client
, vc7
);
1110 vc7
->client
= client
;
1111 vc7
->chip_info
= i2c_get_match_data(client
);
1113 vc7
->pin_xin
= devm_clk_get(&client
->dev
, "xin");
1114 if (PTR_ERR(vc7
->pin_xin
) == -EPROBE_DEFER
) {
1115 return dev_err_probe(&client
->dev
, -EPROBE_DEFER
,
1116 "xin not specified\n");
1119 vc7
->regmap
= devm_regmap_init_i2c(client
, &vc7_regmap_config
);
1120 if (IS_ERR(vc7
->regmap
)) {
1121 return dev_err_probe(&client
->dev
, PTR_ERR(vc7
->regmap
),
1122 "failed to allocate register map\n");
1125 if (of_property_read_string(client
->dev
.of_node
, "clock-output-names",
1127 node_name
= client
->dev
.of_node
->name
;
1130 apll_rate
= vc7_get_apll_rate(vc7
);
1131 apll_name
= kasprintf(GFP_KERNEL
, "%s_apll", node_name
);
1132 vc7
->clk_apll
.clk
= clk_register_fixed_rate(&client
->dev
, apll_name
,
1133 __clk_get_name(vc7
->pin_xin
),
1135 kfree(apll_name
); /* ccf made a copy of the name */
1136 if (IS_ERR(vc7
->clk_apll
.clk
)) {
1137 return dev_err_probe(&client
->dev
, PTR_ERR(vc7
->clk_apll
.clk
),
1138 "failed to register apll\n");
1142 for (i
= 0; i
< VC7_NUM_FOD
; i
++) {
1143 memset(&clk_init
, 0, sizeof(clk_init
));
1144 clk_init
.name
= kasprintf(GFP_KERNEL
, "%s_fod%d", node_name
, i
);
1145 clk_init
.ops
= &vc7_fod_ops
;
1146 clk_init
.parent_names
= parent_names
;
1147 parent_names
[0] = __clk_get_name(vc7
->clk_apll
.clk
);
1148 clk_init
.num_parents
= 1;
1149 vc7
->clk_fod
[i
].num
= i
;
1150 vc7
->clk_fod
[i
].vc7
= vc7
;
1151 vc7
->clk_fod
[i
].hw
.init
= &clk_init
;
1152 ret
= devm_clk_hw_register(&client
->dev
, &vc7
->clk_fod
[i
].hw
);
1154 goto err_clk_register
;
1155 kfree(clk_init
.name
); /* ccf made a copy of the name */
1159 for (i
= 0; i
< VC7_NUM_IOD
; i
++) {
1160 memset(&clk_init
, 0, sizeof(clk_init
));
1161 clk_init
.name
= kasprintf(GFP_KERNEL
, "%s_iod%d", node_name
, i
);
1162 clk_init
.ops
= &vc7_iod_ops
;
1163 clk_init
.parent_names
= parent_names
;
1164 parent_names
[0] = __clk_get_name(vc7
->clk_apll
.clk
);
1165 clk_init
.num_parents
= 1;
1166 vc7
->clk_iod
[i
].num
= i
;
1167 vc7
->clk_iod
[i
].vc7
= vc7
;
1168 vc7
->clk_iod
[i
].hw
.init
= &clk_init
;
1169 ret
= devm_clk_hw_register(&client
->dev
, &vc7
->clk_iod
[i
].hw
);
1171 goto err_clk_register
;
1172 kfree(clk_init
.name
); /* ccf made a copy of the name */
1175 /* Register outputs */
1176 for (i
= 0; i
< vc7
->chip_info
->num_outputs
; i
++) {
1177 out_num
= vc7_map_index_to_output(vc7
->chip_info
->model
, i
);
1180 * This driver does not support remapping FOD/IOD to banks.
1181 * The device state is read and the driver is setup to match
1182 * the device's existing mapping.
1184 bank_idx
= output_bank_mapping
[out_num
];
1186 regmap_read(vc7
->regmap
, VC7_REG_OUT_BANK_CNFG(bank_idx
), &val
);
1187 val
&= VC7_REG_OUTPUT_BANK_SRC_MASK
;
1189 memset(&bank_src_map
, 0, sizeof(bank_src_map
));
1190 ret
= vc7_get_bank_clk(vc7
, bank_idx
, val
, &bank_src_map
);
1192 dev_err_probe(&client
->dev
, ret
,
1193 "unable to register output %d\n", i
);
1197 switch (bank_src_map
.type
) {
1199 parent_names
[0] = clk_hw_get_name(&bank_src_map
.src
.fod
->hw
);
1202 parent_names
[0] = clk_hw_get_name(&bank_src_map
.src
.iod
->hw
);
1206 memset(&clk_init
, 0, sizeof(clk_init
));
1207 clk_init
.name
= kasprintf(GFP_KERNEL
, "%s_out%d", node_name
, i
);
1208 clk_init
.ops
= &vc7_clk_out_ops
;
1209 clk_init
.flags
= CLK_SET_RATE_PARENT
;
1210 clk_init
.parent_names
= parent_names
;
1211 clk_init
.num_parents
= 1;
1212 vc7
->clk_out
[i
].num
= i
;
1213 vc7
->clk_out
[i
].vc7
= vc7
;
1214 vc7
->clk_out
[i
].hw
.init
= &clk_init
;
1215 ret
= devm_clk_hw_register(&client
->dev
, &vc7
->clk_out
[i
].hw
);
1217 goto err_clk_register
;
1218 kfree(clk_init
.name
); /* ccf made a copy of the name */
1221 ret
= of_clk_add_hw_provider(client
->dev
.of_node
, vc7_of_clk_get
, vc7
);
1223 dev_err_probe(&client
->dev
, ret
, "unable to add clk provider\n");
1230 dev_err_probe(&client
->dev
, ret
,
1231 "unable to register %s\n", clk_init
.name
);
1232 kfree(clk_init
.name
); /* ccf made a copy of the name */
1234 clk_unregister_fixed_rate(vc7
->clk_apll
.clk
);
1238 static void vc7_remove(struct i2c_client
*client
)
1240 struct vc7_driver_data
*vc7
= i2c_get_clientdata(client
);
1242 of_clk_del_provider(client
->dev
.of_node
);
1243 clk_unregister_fixed_rate(vc7
->clk_apll
.clk
);
1246 static bool vc7_volatile_reg(struct device
*dev
, unsigned int reg
)
1248 if (reg
== VC7_PAGE_ADDR
)
1254 static const struct vc7_chip_info vc7_rc21008a_info
= {
1255 .model
= VC7_RC21008A
,
1260 static struct regmap_range_cfg vc7_range_cfg
[] = {
1263 .range_max
= VC7_MAX_REG
,
1264 .selector_reg
= VC7_PAGE_ADDR
,
1265 .selector_mask
= 0xFF,
1266 .selector_shift
= 0,
1268 .window_len
= VC7_PAGE_WINDOW
,
1271 static const struct regmap_config vc7_regmap_config
= {
1274 .max_register
= VC7_MAX_REG
,
1275 .ranges
= vc7_range_cfg
,
1276 .num_ranges
= ARRAY_SIZE(vc7_range_cfg
),
1277 .volatile_reg
= vc7_volatile_reg
,
1278 .cache_type
= REGCACHE_MAPLE
,
1279 .can_multi_write
= true,
1280 .reg_format_endian
= REGMAP_ENDIAN_LITTLE
,
1281 .val_format_endian
= REGMAP_ENDIAN_LITTLE
,
1284 static const struct i2c_device_id vc7_i2c_id
[] = {
1285 { "rc21008a", .driver_data
= (kernel_ulong_t
)&vc7_rc21008a_info
},
1288 MODULE_DEVICE_TABLE(i2c
, vc7_i2c_id
);
1290 static const struct of_device_id vc7_of_match
[] = {
1291 { .compatible
= "renesas,rc21008a", .data
= &vc7_rc21008a_info
},
1294 MODULE_DEVICE_TABLE(of
, vc7_of_match
);
1296 static struct i2c_driver vc7_i2c_driver
= {
1299 .of_match_table
= vc7_of_match
,
1302 .remove
= vc7_remove
,
1303 .id_table
= vc7_i2c_id
,
1305 module_i2c_driver(vc7_i2c_driver
);
1307 MODULE_LICENSE("GPL");
1308 MODULE_AUTHOR("Alex Helms <alexander.helms.jy@renesas.com");
1309 MODULE_DESCRIPTION("Renesas Versaclock7 common clock framework driver");