1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Driver for IDT Versaclock 5/6
5 * Derived from code Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
10 #include <clk-uclass.h>
14 #include <dm/device_compat.h>
16 #include <linux/clk-provider.h>
17 #include <linux/kernel.h>
18 #include <linux/math64.h>
20 #include <dt-bindings/clock/versaclock.h>
22 /* VersaClock5 registers */
23 #define VC5_OTP_CONTROL 0x00
25 /* Factory-reserved register block */
26 #define VC5_RSVD_DEVICE_ID 0x01
27 #define VC5_RSVD_ADC_GAIN_7_0 0x02
28 #define VC5_RSVD_ADC_GAIN_15_8 0x03
29 #define VC5_RSVD_ADC_OFFSET_7_0 0x04
30 #define VC5_RSVD_ADC_OFFSET_15_8 0x05
31 #define VC5_RSVD_TEMPY 0x06
32 #define VC5_RSVD_OFFSET_TBIN 0x07
33 #define VC5_RSVD_GAIN 0x08
34 #define VC5_RSVD_TEST_NP 0x09
35 #define VC5_RSVD_UNUSED 0x0a
36 #define VC5_RSVD_BANDGAP_TRIM_UP 0x0b
37 #define VC5_RSVD_BANDGAP_TRIM_DN 0x0c
38 #define VC5_RSVD_CLK_R_12_CLK_AMP_4 0x0d
39 #define VC5_RSVD_CLK_R_34_CLK_AMP_4 0x0e
40 #define VC5_RSVD_CLK_AMP_123 0x0f
42 /* Configuration register block */
43 #define VC5_PRIM_SRC_SHDN 0x10
44 #define VC5_PRIM_SRC_SHDN_EN_XTAL BIT(7)
45 #define VC5_PRIM_SRC_SHDN_EN_CLKIN BIT(6)
46 #define VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ BIT(3)
47 #define VC5_PRIM_SRC_SHDN_SP BIT(1)
48 #define VC5_PRIM_SRC_SHDN_EN_GBL_SHDN BIT(0)
50 #define VC5_VCO_BAND 0x11
51 #define VC5_XTAL_X1_LOAD_CAP 0x12
52 #define VC5_XTAL_X2_LOAD_CAP 0x13
53 #define VC5_REF_DIVIDER 0x15
54 #define VC5_REF_DIVIDER_SEL_PREDIV2 BIT(7)
55 #define VC5_REF_DIVIDER_REF_DIV(n) ((n) & 0x3f)
57 #define VC5_VCO_CTRL_AND_PREDIV 0x16
58 #define VC5_VCO_CTRL_AND_PREDIV_BYPASS_PREDIV BIT(7)
60 #define VC5_FEEDBACK_INT_DIV 0x17
61 #define VC5_FEEDBACK_INT_DIV_BITS 0x18
62 #define VC5_FEEDBACK_FRAC_DIV(n) (0x19 + (n))
63 #define VC5_RC_CONTROL0 0x1e
64 #define VC5_RC_CONTROL1 0x1f
65 /* Register 0x20 is factory reserved */
67 /* Output divider control for divider 1,2,3,4 */
68 #define VC5_OUT_DIV_CONTROL(idx) (0x21 + ((idx) * 0x10))
69 #define VC5_OUT_DIV_CONTROL_RESET BIT(7)
70 #define VC5_OUT_DIV_CONTROL_SELB_NORM BIT(3)
71 #define VC5_OUT_DIV_CONTROL_SEL_EXT BIT(2)
72 #define VC5_OUT_DIV_CONTROL_INT_MODE BIT(1)
73 #define VC5_OUT_DIV_CONTROL_EN_FOD BIT(0)
75 #define VC5_OUT_DIV_FRAC(idx, n) (0x22 + ((idx) * 0x10) + (n))
76 #define VC5_OUT_DIV_FRAC4_OD_SCEE BIT(1)
78 #define VC5_OUT_DIV_STEP_SPREAD(idx, n) (0x26 + ((idx) * 0x10) + (n))
79 #define VC5_OUT_DIV_SPREAD_MOD(idx, n) (0x29 + ((idx) * 0x10) + (n))
80 #define VC5_OUT_DIV_SKEW_INT(idx, n) (0x2b + ((idx) * 0x10) + (n))
81 #define VC5_OUT_DIV_INT(idx, n) (0x2d + ((idx) * 0x10) + (n))
82 #define VC5_OUT_DIV_SKEW_FRAC(idx) (0x2f + ((idx) * 0x10))
83 /* Registers 0x30, 0x40, 0x50 are factory reserved */
85 /* Clock control register for clock 1,2 */
86 #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n))
87 #define VC5_CLK_OUTPUT_CFG0_CFG_SHIFT 5
88 #define VC5_CLK_OUTPUT_CFG0_CFG_MASK GENMASK(7, VC5_CLK_OUTPUT_CFG0_CFG_SHIFT)
90 #define VC5_CLK_OUTPUT_CFG0_CFG_LVPECL (VC5_LVPECL)
91 #define VC5_CLK_OUTPUT_CFG0_CFG_CMOS (VC5_CMOS)
92 #define VC5_CLK_OUTPUT_CFG0_CFG_HCSL33 (VC5_HCSL33)
93 #define VC5_CLK_OUTPUT_CFG0_CFG_LVDS (VC5_LVDS)
94 #define VC5_CLK_OUTPUT_CFG0_CFG_CMOS2 (VC5_CMOS2)
95 #define VC5_CLK_OUTPUT_CFG0_CFG_CMOSD (VC5_CMOSD)
96 #define VC5_CLK_OUTPUT_CFG0_CFG_HCSL25 (VC5_HCSL25)
98 #define VC5_CLK_OUTPUT_CFG0_PWR_SHIFT 3
99 #define VC5_CLK_OUTPUT_CFG0_PWR_MASK GENMASK(4, VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
100 #define VC5_CLK_OUTPUT_CFG0_PWR_18 (0 << VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
101 #define VC5_CLK_OUTPUT_CFG0_PWR_25 (2 << VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
102 #define VC5_CLK_OUTPUT_CFG0_PWR_33 (3 << VC5_CLK_OUTPUT_CFG0_PWR_SHIFT)
103 #define VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT 0
104 #define VC5_CLK_OUTPUT_CFG0_SLEW_MASK GENMASK(1, VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
105 #define VC5_CLK_OUTPUT_CFG0_SLEW_80 (0 << VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
106 #define VC5_CLK_OUTPUT_CFG0_SLEW_85 (1 << VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
107 #define VC5_CLK_OUTPUT_CFG0_SLEW_90 (2 << VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
108 #define VC5_CLK_OUTPUT_CFG0_SLEW_100 (3 << VC5_CLK_OUTPUT_CFG0_SLEW_SHIFT)
109 #define VC5_CLK_OUTPUT_CFG1_EN_CLKBUF BIT(0)
111 #define VC5_CLK_OE_SHDN 0x68
112 #define VC5_CLK_OS_SHDN 0x69
114 #define VC5_GLOBAL_REGISTER 0x76
115 #define VC5_GLOBAL_REGISTER_GLOBAL_RESET BIT(5)
117 /* PLL/VCO runs between 2.5 GHz and 3.0 GHz */
118 #define VC5_PLL_VCO_MIN 2500000000UL
119 #define VC5_PLL_VCO_MAX 3000000000UL
121 /* VC5 Input mux settings */
122 #define VC5_MUX_IN_XIN BIT(0)
123 #define VC5_MUX_IN_CLKIN BIT(1)
125 /* Maximum number of clk_out supported by this driver */
126 #define VC5_MAX_CLK_OUT_NUM 5
128 /* Maximum number of FODs supported by this driver */
129 #define VC5_MAX_FOD_NUM 4
131 /* flags to describe chip features */
132 /* chip has built-in oscilator */
133 #define VC5_HAS_INTERNAL_XTAL BIT(0)
134 /* chip has PFD requency doubler */
135 #define VC5_HAS_PFD_FREQ_DBL BIT(1)
137 /* Supported IDT VC5 models. */
147 /* Structure to describe features of a particular VC5 model */
148 struct vc5_chip_info
{
149 const enum vc5_model model
;
150 const unsigned int clk_fod_cnt
;
151 const unsigned int clk_out_cnt
;
155 struct vc5_driver_data
;
159 struct vc5_driver_data
*vc5
;
165 struct vc5_out_data
{
167 struct vc5_driver_data
*vc5
;
169 unsigned int clk_output_cfg0
;
170 unsigned int clk_output_cfg0_mask
;
173 struct vc5_driver_data
{
175 const struct vc5_chip_info
*chip_info
;
178 struct clk
*pin_clkin
;
179 unsigned char clk_mux_ins
;
183 struct vc5_hw_data clk_pll
;
184 struct vc5_hw_data clk_fod
[VC5_MAX_FOD_NUM
];
185 struct vc5_out_data clk_out
[VC5_MAX_CLK_OUT_NUM
];
188 static const struct vc5_chip_info idt_5p49v5923_info
= {
189 .model
= IDT_VC5_5P49V5923
,
195 static const struct vc5_chip_info idt_5p49v5925_info
= {
196 .model
= IDT_VC5_5P49V5925
,
202 static const struct vc5_chip_info idt_5p49v5933_info
= {
203 .model
= IDT_VC5_5P49V5933
,
206 .flags
= VC5_HAS_INTERNAL_XTAL
,
209 static const struct vc5_chip_info idt_5p49v5935_info
= {
210 .model
= IDT_VC5_5P49V5935
,
213 .flags
= VC5_HAS_INTERNAL_XTAL
,
216 static const struct vc5_chip_info idt_5p49v6901_info
= {
217 .model
= IDT_VC6_5P49V6901
,
220 .flags
= VC5_HAS_PFD_FREQ_DBL
,
223 static const struct vc5_chip_info idt_5p49v6965_info
= {
224 .model
= IDT_VC6_5P49V6965
,
230 static int vc5_update_bits(struct udevice
*dev
, unsigned int reg
, unsigned int mask
,
236 ret
= dm_i2c_read(dev
, reg
, &cache
, 1);
242 ret
= dm_i2c_write(dev
, reg
, (uchar
*)&cache
, 1);
247 static unsigned long vc5_mux_get_rate(struct clk
*hw
)
249 return clk_get_rate(clk_get_parent(hw
));
252 static int vc5_mux_set_parent(struct clk
*hw
, unsigned char index
)
254 struct vc5_driver_data
*vc5
= container_of(hw
, struct vc5_driver_data
, clk_mux
);
255 const u8 mask
= VC5_PRIM_SRC_SHDN_EN_XTAL
| VC5_PRIM_SRC_SHDN_EN_CLKIN
;
258 if (index
> 1 || !vc5
->clk_mux_ins
)
261 if (vc5
->clk_mux_ins
== (VC5_MUX_IN_CLKIN
| VC5_MUX_IN_XIN
)) {
263 src
= VC5_PRIM_SRC_SHDN_EN_XTAL
;
265 src
= VC5_PRIM_SRC_SHDN_EN_CLKIN
;
270 if (vc5
->clk_mux_ins
== VC5_MUX_IN_XIN
)
271 src
= VC5_PRIM_SRC_SHDN_EN_XTAL
;
272 else if (vc5
->clk_mux_ins
== VC5_MUX_IN_CLKIN
)
273 src
= VC5_PRIM_SRC_SHDN_EN_CLKIN
;
274 else /* Invalid; should have been caught by vc5_probe() */
278 return vc5_update_bits(vc5
->i2c
, VC5_PRIM_SRC_SHDN
, mask
, src
);
281 static const struct clk_ops vc5_mux_ops
= {
282 .get_rate
= vc5_mux_get_rate
,
285 static unsigned long vc5_pfd_round_rate(struct clk
*hw
, unsigned long rate
)
287 struct clk
*clk_parent
= clk_get_parent(hw
);
288 unsigned long parent_rate
= clk_get_rate(clk_parent
);
291 /* PLL cannot operate with input clock above 50 MHz. */
295 /* CLKIN within range of PLL input, feed directly to PLL. */
296 if (parent_rate
<= 50000000)
299 idiv
= DIV_ROUND_UP(parent_rate
, rate
);
303 return parent_rate
/ idiv
;
306 static unsigned long vc5_pfd_recalc_rate(struct clk
*hw
)
308 struct vc5_driver_data
*vc5
=
309 container_of(hw
, struct vc5_driver_data
, clk_pfd
);
310 unsigned int prediv
, div
;
311 struct clk
*clk_parent
= clk_get_parent(hw
);
312 unsigned long parent_rate
= clk_get_rate(clk_parent
);
314 dm_i2c_read(vc5
->i2c
, VC5_VCO_CTRL_AND_PREDIV
, (uchar
*)&prediv
, 1);
316 /* The bypass_prediv is set, PLL fed from Ref_in directly. */
317 if (prediv
& VC5_VCO_CTRL_AND_PREDIV_BYPASS_PREDIV
)
320 dm_i2c_read(vc5
->i2c
, VC5_REF_DIVIDER
, (uchar
*)&div
, 1);
322 /* The Sel_prediv2 is set, PLL fed from prediv2 (Ref_in / 2) */
323 if (div
& VC5_REF_DIVIDER_SEL_PREDIV2
)
324 return parent_rate
/ 2;
326 return parent_rate
/ VC5_REF_DIVIDER_REF_DIV(div
);
329 static unsigned long vc5_pfd_set_rate(struct clk
*hw
, unsigned long rate
)
331 struct vc5_driver_data
*vc5
=
332 container_of(hw
, struct vc5_driver_data
, clk_pfd
);
335 struct clk
*clk_parent
= clk_get_parent(hw
);
336 unsigned long parent_rate
= clk_get_rate(clk_parent
);
338 /* CLKIN within range of PLL input, feed directly to PLL. */
339 if (parent_rate
<= 50000000) {
340 vc5_update_bits(vc5
->i2c
, VC5_VCO_CTRL_AND_PREDIV
,
341 VC5_VCO_CTRL_AND_PREDIV_BYPASS_PREDIV
,
342 VC5_VCO_CTRL_AND_PREDIV_BYPASS_PREDIV
);
343 vc5_update_bits(vc5
->i2c
, VC5_REF_DIVIDER
, 0xff, 0x00);
347 idiv
= DIV_ROUND_UP(parent_rate
, rate
);
349 /* We have dedicated div-2 predivider. */
351 div
= VC5_REF_DIVIDER_SEL_PREDIV2
;
353 div
= VC5_REF_DIVIDER_REF_DIV(idiv
);
355 vc5_update_bits(vc5
->i2c
, VC5_REF_DIVIDER
, 0xff, div
);
356 vc5_update_bits(vc5
->i2c
, VC5_VCO_CTRL_AND_PREDIV
,
357 VC5_VCO_CTRL_AND_PREDIV_BYPASS_PREDIV
, 0);
362 static const struct clk_ops vc5_pfd_ops
= {
363 .round_rate
= vc5_pfd_round_rate
,
364 .get_rate
= vc5_pfd_recalc_rate
,
365 .set_rate
= vc5_pfd_set_rate
,
369 * VersaClock5 PLL/VCO
371 static unsigned long vc5_pll_recalc_rate(struct clk
*hw
)
373 struct vc5_hw_data
*hwdata
= container_of(hw
, struct vc5_hw_data
, hw
);
374 struct vc5_driver_data
*vc
= hwdata
->vc5
;
375 struct clk
*clk_parent
= clk_get_parent(hw
);
376 unsigned long parent_rate
= clk_get_rate(clk_parent
);
377 u32 div_int
, div_frc
;
380 dm_i2c_read(vc
->i2c
, VC5_FEEDBACK_INT_DIV
, fb
, 5);
382 div_int
= (fb
[0] << 4) | (fb
[1] >> 4);
383 div_frc
= (fb
[2] << 16) | (fb
[3] << 8) | fb
[4];
385 /* The PLL divider has 12 integer bits and 24 fractional bits */
386 return (parent_rate
* div_int
) + ((parent_rate
* div_frc
) >> 24);
389 static unsigned long vc5_pll_round_rate(struct clk
*hw
, unsigned long rate
)
391 struct clk
*clk_parent
= clk_get_parent(hw
);
392 unsigned long parent_rate
= clk_get_rate(clk_parent
);
393 struct vc5_hw_data
*hwdata
= container_of(hw
, struct vc5_hw_data
, hw
);
397 if (rate
< VC5_PLL_VCO_MIN
)
398 rate
= VC5_PLL_VCO_MIN
;
399 if (rate
> VC5_PLL_VCO_MAX
)
400 rate
= VC5_PLL_VCO_MAX
;
402 /* Determine integer part, which is 12 bit wide */
403 div_int
= rate
/ parent_rate
;
405 rate
= parent_rate
* 0xfff;
407 /* Determine best fractional part, which is 24 bit wide */
408 div_frc
= rate
% parent_rate
;
409 div_frc
*= BIT(24) - 1;
410 do_div(div_frc
, parent_rate
);
412 hwdata
->div_int
= div_int
;
413 hwdata
->div_frc
= (u32
)div_frc
;
415 return (parent_rate
* div_int
) + ((parent_rate
* div_frc
) >> 24);
418 static unsigned long vc5_pll_set_rate(struct clk
*hw
, unsigned long rate
)
420 struct vc5_hw_data
*hwdata
= container_of(hw
, struct vc5_hw_data
, hw
);
421 struct vc5_driver_data
*vc5
= hwdata
->vc5
;
424 fb
[0] = hwdata
->div_int
>> 4;
425 fb
[1] = hwdata
->div_int
<< 4;
426 fb
[2] = hwdata
->div_frc
>> 16;
427 fb
[3] = hwdata
->div_frc
>> 8;
428 fb
[4] = hwdata
->div_frc
;
430 return dm_i2c_write(vc5
->i2c
, VC5_FEEDBACK_INT_DIV
, fb
, 5);
433 static const struct clk_ops vc5_pll_ops
= {
434 .round_rate
= vc5_pll_round_rate
,
435 .get_rate
= vc5_pll_recalc_rate
,
436 .set_rate
= vc5_pll_set_rate
,
439 static unsigned long vc5_fod_recalc_rate(struct clk
*hw
)
441 struct vc5_hw_data
*hwdata
= container_of(hw
, struct vc5_hw_data
, hw
);
442 struct vc5_driver_data
*vc
= hwdata
->vc5
;
443 struct clk
*parent
= &vc
->clk_pll
.hw
;
444 unsigned long parent_rate
= vc5_pll_recalc_rate(parent
);
446 /* VCO frequency is divided by two before entering FOD */
447 u32 f_in
= parent_rate
/ 2;
448 u32 div_int
, div_frc
;
452 dm_i2c_read(vc
->i2c
, VC5_OUT_DIV_INT(hwdata
->num
, 0), od_int
, 2);
453 dm_i2c_read(vc
->i2c
, VC5_OUT_DIV_FRAC(hwdata
->num
, 0), od_frc
, 4);
455 div_int
= (od_int
[0] << 4) | (od_int
[1] >> 4);
456 div_frc
= (od_frc
[0] << 22) | (od_frc
[1] << 14) |
457 (od_frc
[2] << 6) | (od_frc
[3] >> 2);
459 /* Avoid division by zero if the output is not configured. */
460 if (div_int
== 0 && div_frc
== 0)
463 /* The PLL divider has 12 integer bits and 30 fractional bits */
464 return div64_u64((u64
)f_in
<< 24ULL, ((u64
)div_int
<< 24ULL) + div_frc
);
467 static unsigned long vc5_fod_round_rate(struct clk
*hw
, unsigned long rate
)
469 struct vc5_hw_data
*hwdata
= container_of(hw
, struct vc5_hw_data
, hw
);
470 struct vc5_driver_data
*vc
= hwdata
->vc5
;
471 struct clk
*parent
= &vc
->clk_pll
.hw
;
472 unsigned long parent_rate
= vc5_pll_recalc_rate(parent
);
474 /* VCO frequency is divided by two before entering FOD */
475 u32 f_in
= parent_rate
/ 2;
479 /* Determine integer part, which is 12 bit wide */
480 div_int
= f_in
/ rate
;
483 * WARNING: The clock chip does not output signal if the integer part
484 * of the divider is 0xfff and fractional part is non-zero.
485 * Clamp the divider at 0xffe to keep the code simple.
487 if (div_int
> 0xffe) {
489 rate
= f_in
/ div_int
;
492 /* Determine best fractional part, which is 30 bit wide */
493 div_frc
= f_in
% rate
;
495 do_div(div_frc
, rate
);
497 hwdata
->div_int
= div_int
;
498 hwdata
->div_frc
= (u32
)div_frc
;
500 return div64_u64((u64
)f_in
<< 24ULL, ((u64
)div_int
<< 24ULL) + div_frc
);
503 static unsigned long vc5_fod_set_rate(struct clk
*hw
, unsigned long rate
)
505 struct vc5_hw_data
*hwdata
= container_of(hw
, struct vc5_hw_data
, hw
);
506 struct vc5_driver_data
*vc5
= hwdata
->vc5
;
509 hwdata
->div_frc
>> 22, hwdata
->div_frc
>> 14,
510 hwdata
->div_frc
>> 6, hwdata
->div_frc
<< 2,
513 hwdata
->div_int
>> 4, hwdata
->div_int
<< 4,
517 dm_i2c_write(vc5
->i2c
, VC5_OUT_DIV_FRAC(hwdata
->num
, 0), data
, 14);
520 * Toggle magic bit in undocumented register for unknown reason.
521 * This is what the IDT timing commander tool does and the chip
522 * datasheet somewhat implies this is needed, but the register
523 * and the bit is not documented.
525 vc5_update_bits(vc5
->i2c
, VC5_GLOBAL_REGISTER
,
526 VC5_GLOBAL_REGISTER_GLOBAL_RESET
, 0);
527 vc5_update_bits(vc5
->i2c
, VC5_GLOBAL_REGISTER
,
528 VC5_GLOBAL_REGISTER_GLOBAL_RESET
,
529 VC5_GLOBAL_REGISTER_GLOBAL_RESET
);
534 static const struct clk_ops vc5_fod_ops
= {
535 .round_rate
= vc5_fod_round_rate
,
536 .get_rate
= vc5_fod_recalc_rate
,
537 .set_rate
= vc5_fod_set_rate
,
540 static int vc5_clk_out_prepare(struct clk
*hw
)
543 struct vc5_driver_data
*vc5
;
544 struct vc5_out_data
*hwdata
;
546 const u8 mask
= VC5_OUT_DIV_CONTROL_SELB_NORM
|
547 VC5_OUT_DIV_CONTROL_SEL_EXT
|
548 VC5_OUT_DIV_CONTROL_EN_FOD
;
552 uclass_get_device_by_name(UCLASS_CLK
, clk_hw_get_name(hw
), &dev
);
553 vc5
= dev_get_priv(dev
);
554 hwdata
= &vc5
->clk_out
[hw
->id
];
557 * If the input mux is disabled, enable it first and
558 * select source from matching FOD.
561 dm_i2c_read(vc5
->i2c
, VC5_OUT_DIV_CONTROL(hwdata
->num
), (uchar
*)&src
, 1);
563 if ((src
& mask
) == 0) {
564 src
= VC5_OUT_DIV_CONTROL_RESET
| VC5_OUT_DIV_CONTROL_EN_FOD
;
565 ret
= vc5_update_bits(vc5
->i2c
,
566 VC5_OUT_DIV_CONTROL(hwdata
->num
),
567 mask
| VC5_OUT_DIV_CONTROL_RESET
, src
);
572 /* Enable the clock buffer */
573 vc5_update_bits(vc5
->i2c
, VC5_CLK_OUTPUT_CFG(hwdata
->num
, 1),
574 VC5_CLK_OUTPUT_CFG1_EN_CLKBUF
,
575 VC5_CLK_OUTPUT_CFG1_EN_CLKBUF
);
576 if (hwdata
->clk_output_cfg0_mask
) {
577 vc5_update_bits(vc5
->i2c
, VC5_CLK_OUTPUT_CFG(hwdata
->num
, 0),
578 hwdata
->clk_output_cfg0_mask
,
579 hwdata
->clk_output_cfg0
);
585 static int vc5_clk_out_unprepare(struct clk
*hw
)
588 struct vc5_driver_data
*vc5
;
589 struct vc5_out_data
*hwdata
;
592 uclass_get_device_by_name(UCLASS_CLK
, clk_hw_get_name(hw
), &dev
);
593 vc5
= dev_get_priv(dev
);
594 hwdata
= &vc5
->clk_out
[hw
->id
];
596 /* Disable the clock buffer */
597 ret
= vc5_update_bits(vc5
->i2c
, VC5_CLK_OUTPUT_CFG(hwdata
->num
, 1),
598 VC5_CLK_OUTPUT_CFG1_EN_CLKBUF
, 0);
603 static int vc5_clk_out_set_parent(struct vc5_driver_data
*vc
, u8 num
, u8 index
)
605 const u8 mask
= VC5_OUT_DIV_CONTROL_RESET
|
606 VC5_OUT_DIV_CONTROL_SELB_NORM
|
607 VC5_OUT_DIV_CONTROL_SEL_EXT
|
608 VC5_OUT_DIV_CONTROL_EN_FOD
;
609 const u8 extclk
= VC5_OUT_DIV_CONTROL_SELB_NORM
|
610 VC5_OUT_DIV_CONTROL_SEL_EXT
;
611 u8 src
= VC5_OUT_DIV_CONTROL_RESET
;
614 src
|= VC5_OUT_DIV_CONTROL_EN_FOD
;
618 return vc5_update_bits(vc
->i2c
, VC5_OUT_DIV_CONTROL(num
), mask
, src
);
621 static unsigned long vc5_clk_out_set_rate(struct clk
*hw
, unsigned long rate
)
624 struct vc5_driver_data
*vc
;
627 uclass_get_device_by_name(UCLASS_CLK
, clk_hw_get_name(hw
), &dev
);
628 vc
= dev_get_priv(dev
);
629 parent
= clk_get_parent(&vc
->clk_out
[hw
->id
].hw
);
631 /* setting the output rate really means setting the parent FOD rate */
632 return clk_set_rate(parent
, clk_round_rate(parent
, rate
));
635 static unsigned long vc5_clk_out_get_rate(struct clk
*hw
)
637 return clk_get_parent_rate(hw
);
640 static const struct clk_ops vc5_clk_out_ops
= {
641 .enable
= vc5_clk_out_prepare
,
642 .disable
= vc5_clk_out_unprepare
,
643 .set_rate
= vc5_clk_out_set_rate
,
644 .get_rate
= vc5_clk_out_get_rate
,
647 static const struct clk_ops vc5_clk_out_sel_ops
= {
648 .enable
= vc5_clk_out_prepare
,
649 .disable
= vc5_clk_out_unprepare
,
650 .get_rate
= vc5_clk_out_get_rate
,
653 static const struct clk_ops vc5_clk_ops
= {
654 .enable
= vc5_clk_out_prepare
,
655 .disable
= vc5_clk_out_unprepare
,
656 .set_rate
= vc5_clk_out_set_rate
,
657 .get_rate
= vc5_clk_out_get_rate
,
660 static int vc5_map_index_to_output(const enum vc5_model model
,
661 const unsigned int n
)
664 case IDT_VC5_5P49V5933
:
665 return (n
== 0) ? 0 : 3;
666 case IDT_VC5_5P49V5923
:
667 case IDT_VC5_5P49V5925
:
668 case IDT_VC5_5P49V5935
:
669 case IDT_VC6_5P49V6901
:
670 case IDT_VC6_5P49V6965
:
676 static int vc5_update_mode(ofnode np_output
,
677 struct vc5_out_data
*clk_out
)
681 if (!ofnode_read_u32(np_output
, "idt,mode", &value
)) {
682 clk_out
->clk_output_cfg0_mask
|= VC5_CLK_OUTPUT_CFG0_CFG_MASK
;
684 case VC5_CLK_OUTPUT_CFG0_CFG_LVPECL
:
685 case VC5_CLK_OUTPUT_CFG0_CFG_CMOS
:
686 case VC5_CLK_OUTPUT_CFG0_CFG_HCSL33
:
687 case VC5_CLK_OUTPUT_CFG0_CFG_LVDS
:
688 case VC5_CLK_OUTPUT_CFG0_CFG_CMOS2
:
689 case VC5_CLK_OUTPUT_CFG0_CFG_CMOSD
:
690 case VC5_CLK_OUTPUT_CFG0_CFG_HCSL25
:
691 clk_out
->clk_output_cfg0
|=
692 value
<< VC5_CLK_OUTPUT_CFG0_CFG_SHIFT
;
702 static int vc5_update_power(ofnode np_output
, struct vc5_out_data
*clk_out
)
706 if (!ofnode_read_u32(np_output
, "idt,voltage-microvolt", &value
)) {
707 clk_out
->clk_output_cfg0_mask
|= VC5_CLK_OUTPUT_CFG0_PWR_MASK
;
710 clk_out
->clk_output_cfg0
|= VC5_CLK_OUTPUT_CFG0_PWR_18
;
713 clk_out
->clk_output_cfg0
|= VC5_CLK_OUTPUT_CFG0_PWR_25
;
716 clk_out
->clk_output_cfg0
|= VC5_CLK_OUTPUT_CFG0_PWR_33
;
725 static int vc5_map_cap_value(u32 femtofarads
)
730 * The datasheet explicitly states 9000 - 25000 with 0.5pF
731 * steps, but the Programmer's guide shows the steps are 0.430pF.
732 * After getting feedback from Renesas, the .5pF steps were the
733 * goal, but 430nF was the actual values.
734 * Because of this, the actual range goes to 22760 instead of 25000
736 if (femtofarads
< 9000 || femtofarads
> 22760)
740 * The Programmer's guide shows XTAL[5:0] but in reality,
741 * XTAL[0] and XTAL[1] are both LSB which makes the math
742 * strange. With clarfication from Renesas, setting the
743 * values should be simpler by ignoring XTAL[0]
745 mapped_value
= DIV_ROUND_CLOSEST(femtofarads
- 9000, 430);
748 * Since the calculation ignores XTAL[0], there is one
749 * special case where mapped_value = 32. In reality, this means
750 * the real mapped value should be 111111b. In other cases,
751 * the mapped_value needs to be shifted 1 to the left.
753 if (mapped_value
> 31)
761 static int vc5_update_cap_load(ofnode node
, struct vc5_driver_data
*vc5
)
766 if (!ofnode_read_u32(node
, "idt,xtal-load-femtofarads", &value
)) {
767 mapped_value
= vc5_map_cap_value(value
);
769 if (mapped_value
< 0)
773 * The mapped_value is really the high 6 bits of
774 * VC5_XTAL_X1_LOAD_CAP and VC5_XTAL_X2_LOAD_CAP, so
775 * shift the value 2 places.
777 vc5_update_bits(vc5
->i2c
, VC5_XTAL_X1_LOAD_CAP
, ~0x03, mapped_value
<< 2);
778 vc5_update_bits(vc5
->i2c
, VC5_XTAL_X2_LOAD_CAP
, ~0x03, mapped_value
<< 2);
784 static int vc5_update_slew(ofnode np_output
, struct vc5_out_data
*clk_out
)
788 if (!ofnode_read_u32(np_output
, "idt,slew-percent", &value
)) {
789 clk_out
->clk_output_cfg0_mask
|= VC5_CLK_OUTPUT_CFG0_SLEW_MASK
;
793 clk_out
->clk_output_cfg0
|= VC5_CLK_OUTPUT_CFG0_SLEW_80
;
796 clk_out
->clk_output_cfg0
|= VC5_CLK_OUTPUT_CFG0_SLEW_85
;
799 clk_out
->clk_output_cfg0
|= VC5_CLK_OUTPUT_CFG0_SLEW_90
;
802 clk_out
->clk_output_cfg0
|=
803 VC5_CLK_OUTPUT_CFG0_SLEW_100
;
812 static int vc5_get_output_config(struct udevice
*dev
,
813 struct vc5_out_data
*clk_out
)
819 sprintf(child_name
, "OUT%d", clk_out
->num
+ 1);
821 np_output
= dev_read_subnode(dev
, child_name
);
823 if (!ofnode_valid(np_output
)) {
824 dev_dbg(dev
, "Invalid clock output configuration OUT%d\n",
829 ret
= vc5_update_mode(np_output
, clk_out
);
833 ret
= vc5_update_power(np_output
, clk_out
);
837 ret
= vc5_update_slew(np_output
, clk_out
);
842 static char *versaclock_get_name(const char *dev_name
, const char *clk_name
, int index
)
848 length
= snprintf(NULL
, 0, "%s.%s", dev_name
, clk_name
) + 1;
850 length
= snprintf(NULL
, 0, "%s.%s%d", dev_name
, clk_name
, index
) + 1;
852 buf
= malloc(length
);
857 snprintf(buf
, length
, "%s.%s", dev_name
, clk_name
);
859 snprintf(buf
, length
, "%s.%s%d", dev_name
, clk_name
, index
);
864 int versaclock_probe(struct udevice
*dev
)
866 struct vc5_driver_data
*vc5
= dev_get_priv(dev
);
867 struct vc5_chip_info
*chip
= (void *)dev_get_driver_data(dev
);
868 unsigned int n
, idx
= 0;
869 char *mux_name
, *pfd_name
, *pll_name
, *outsel_name
;
870 char *out_name
[VC5_MAX_CLK_OUT_NUM
];
871 char *fod_name
[VC5_MAX_FOD_NUM
];
875 val
= (u64
)dev_read_addr_ptr(dev
);
876 ret
= i2c_get_chip(dev
->parent
, val
, 1, &vc5
->i2c
);
879 dev_dbg(dev
, "I2C probe failed.\n");
883 vc5
->chip_info
= chip
;
884 vc5
->pin_xin
= devm_clk_get(dev
, "xin");
886 if (IS_ERR(vc5
->pin_xin
))
887 dev_dbg(dev
, "failed to get xin clock\n");
889 ret
= clk_enable(vc5
->pin_xin
);
891 dev_dbg(dev
, "failed to enable XIN clock\n");
893 vc5
->pin_clkin
= devm_clk_get(dev
, "clkin");
895 /* Register clock input mux */
896 if (!IS_ERR(vc5
->pin_xin
)) {
897 vc5
->clk_mux_ins
|= VC5_MUX_IN_XIN
;
898 } else if (vc5
->chip_info
->flags
& VC5_HAS_INTERNAL_XTAL
) {
899 if (IS_ERR(vc5
->pin_xin
))
900 return PTR_ERR(vc5
->pin_xin
);
901 vc5
->clk_mux_ins
|= VC5_MUX_IN_XIN
;
904 mux_name
= versaclock_get_name(dev
->name
, "mux", -1);
905 if (IS_ERR(mux_name
))
906 return PTR_ERR(mux_name
);
908 clk_register(&vc5
->clk_mux
, "versaclock-mux", mux_name
, vc5
->pin_xin
->dev
->name
);
910 if (!IS_ERR(vc5
->pin_xin
))
911 vc5_mux_set_parent(&vc5
->clk_mux
, 1);
913 vc5_mux_set_parent(&vc5
->clk_mux
, 0);
915 /* Configure Optional Loading Capacitance for external XTAL */
916 if (!(vc5
->chip_info
->flags
& VC5_HAS_INTERNAL_XTAL
)) {
917 ret
= vc5_update_cap_load(dev_ofnode(dev
), vc5
);
919 dev_dbg(dev
, "failed to vc5_update_cap_load\n");
923 pfd_name
= versaclock_get_name(dev
->name
, "pfd", -1);
924 if (IS_ERR(pfd_name
)) {
925 ret
= PTR_ERR(pfd_name
);
929 ret
= clk_register(&vc5
->clk_pfd
, "versaclock-pfd", pfd_name
, vc5
->clk_mux
.dev
->name
);
934 vc5
->clk_pll
.num
= 0;
935 vc5
->clk_pll
.vc5
= vc5
;
936 pll_name
= versaclock_get_name(dev
->name
, "pll", -1);
937 if (IS_ERR(pll_name
)) {
938 ret
= PTR_ERR(pll_name
);
942 ret
= clk_register(&vc5
->clk_pll
.hw
, "versaclock-pll", pll_name
, vc5
->clk_pfd
.dev
->name
);
947 for (n
= 0; n
< vc5
->chip_info
->clk_fod_cnt
; n
++) {
948 fod_name
[n
] = versaclock_get_name(dev
->name
, "fod", n
);
949 if (IS_ERR(pll_name
)) {
950 ret
= PTR_ERR(fod_name
[n
]);
953 idx
= vc5_map_index_to_output(vc5
->chip_info
->model
, n
);
954 vc5
->clk_fod
[n
].num
= idx
;
955 vc5
->clk_fod
[n
].vc5
= vc5
;
956 ret
= clk_register(&vc5
->clk_fod
[n
].hw
, "versaclock-fod", fod_name
[n
],
957 vc5
->clk_pll
.hw
.dev
->name
);
962 /* Register MUX-connected OUT0_I2C_SELB output */
963 vc5
->clk_out
[0].num
= idx
;
964 vc5
->clk_out
[0].vc5
= vc5
;
965 outsel_name
= versaclock_get_name(dev
->name
, "out0_sel_i2cb", -1);
966 if (IS_ERR(outsel_name
)) {
967 ret
= PTR_ERR(outsel_name
);
971 ret
= clk_register(&vc5
->clk_out
[0].hw
, "versaclock-outsel", outsel_name
,
972 vc5
->clk_mux
.dev
->name
);
976 /* Register FOD-connected OUTx outputs */
977 for (n
= 1; n
< vc5
->chip_info
->clk_out_cnt
; n
++) {
978 idx
= vc5_map_index_to_output(vc5
->chip_info
->model
, n
- 1);
979 out_name
[n
] = versaclock_get_name(dev
->name
, "out", n
);
980 if (IS_ERR(out_name
[n
])) {
981 ret
= PTR_ERR(out_name
[n
]);
984 vc5
->clk_out
[n
].num
= idx
;
985 vc5
->clk_out
[n
].vc5
= vc5
;
986 ret
= clk_register(&vc5
->clk_out
[n
].hw
, "versaclock-out", out_name
[n
],
987 vc5
->clk_fod
[idx
].hw
.dev
->name
);
990 vc5_clk_out_set_parent(vc5
, idx
, 0);
992 /* Fetch Clock Output configuration from DT (if specified) */
993 ret
= vc5_get_output_config(dev
, &vc5
->clk_out
[n
]);
995 dev_dbg(dev
, "failed to vc5_get_output_config()\n");
1003 for (n
= 1; n
< vc5
->chip_info
->clk_out_cnt
; n
++) {
1004 clk_free(&vc5
->clk_out
[n
].hw
);
1008 clk_free(&vc5
->clk_out
[0].hw
);
1011 for (n
= 0; n
< vc5
->chip_info
->clk_fod_cnt
; n
++) {
1012 clk_free(&vc5
->clk_fod
[n
].hw
);
1016 clk_free(&vc5
->clk_pll
.hw
);
1019 clk_free(&vc5
->clk_pfd
);
1022 clk_free(&vc5
->clk_mux
);
1028 static const struct udevice_id versaclock_ids
[] = {
1029 { .compatible
= "idt,5p49v5923", .data
= (ulong
)&idt_5p49v5923_info
},
1030 { .compatible
= "idt,5p49v5925", .data
= (ulong
)&idt_5p49v5925_info
},
1031 { .compatible
= "idt,5p49v5933", .data
= (ulong
)&idt_5p49v5933_info
},
1032 { .compatible
= "idt,5p49v5935", .data
= (ulong
)&idt_5p49v5935_info
},
1033 { .compatible
= "idt,5p49v6901", .data
= (ulong
)&idt_5p49v6901_info
},
1034 { .compatible
= "idt,5p49v6965", .data
= (ulong
)&idt_5p49v6965_info
},
1038 U_BOOT_DRIVER(versaclock
) = {
1039 .name
= "versaclock",
1041 .ops
= &vc5_clk_ops
,
1042 .of_match
= versaclock_ids
,
1043 .probe
= versaclock_probe
,
1044 .priv_auto
= sizeof(struct vc5_driver_data
),
1047 U_BOOT_DRIVER(versaclock_mux
) = {
1048 .name
= "versaclock-mux",
1050 .ops
= &vc5_mux_ops
,
1053 U_BOOT_DRIVER(versaclock_pfd
) = {
1054 .name
= "versaclock-pfd",
1056 .ops
= &vc5_pfd_ops
,
1059 U_BOOT_DRIVER(versaclock_pll
) = {
1060 .name
= "versaclock-pll",
1062 .ops
= &vc5_pll_ops
,
1065 U_BOOT_DRIVER(versaclock_fod
) = {
1066 .name
= "versaclock-fod",
1068 .ops
= &vc5_fod_ops
,
1071 U_BOOT_DRIVER(versaclock_out
) = {
1072 .name
= "versaclock-out",
1074 .ops
= &vc5_clk_out_ops
,
1077 U_BOOT_DRIVER(versaclock_outsel
) = {
1078 .name
= "versaclock-outsel",
1080 .ops
= &vc5_clk_out_sel_ops
,