1 // SPDX-License-Identifier: GPL-2.0
3 * CS2000 -- CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier
5 * Copyright (C) 2015 Renesas Electronics Corporation
6 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
8 #include <linux/clk-provider.h>
9 #include <linux/delay.h>
10 #include <linux/clk.h>
11 #include <linux/i2c.h>
13 #include <linux/module.h>
14 #include <linux/regmap.h>
17 #define RATIO_REG_SIZE 4
20 #define DEVICE_CTRL 0x2
21 #define DEVICE_CFG1 0x3
22 #define DEVICE_CFG2 0x4
23 #define GLOBAL_CFG 0x5
24 #define Ratio_Add(x, nth) (6 + (x * 4) + (nth))
25 #define Ratio_Val(x, nth) ((x >> (24 - (8 * nth))) & 0xFF)
26 #define Val_Ratio(x, nth) ((x & 0xFF) << (24 - (8 * nth)))
27 #define FUNC_CFG1 0x16
28 #define FUNC_CFG2 0x17
31 #define REVISION_MASK (0x7)
32 #define REVISION_B2_B3 (0x4)
33 #define REVISION_C1 (0x6)
36 #define PLL_UNLOCK (1 << 7)
37 #define AUXOUTDIS (1 << 1)
38 #define CLKOUTDIS (1 << 0)
41 #define RSEL(x) (((x) & 0x3) << 3)
42 #define RSEL_MASK RSEL(0x3)
43 #define AUXOUTSRC(x) (((x) & 0x3) << 1)
44 #define AUXOUTSRC_MASK AUXOUTSRC(0x3)
48 #define AUTORMOD (1 << 3)
49 #define LOCKCLK(x) (((x) & 0x3) << 1)
50 #define LOCKCLK_MASK LOCKCLK(0x3)
51 #define FRACNSRC_MASK (1 << 0)
52 #define FRACNSRC_STATIC (0 << 0)
53 #define FRACNSRC_DYNAMIC (1 << 0)
56 #define FREEZE (1 << 7)
60 #define CLKSKIPEN (1 << 7)
61 #define REFCLKDIV(x) (((x) & 0x3) << 3)
62 #define REFCLKDIV_MASK REFCLKDIV(0x3)
65 #define LFRATIO_MASK (1 << 3)
66 #define LFRATIO_20_12 (0 << 3)
67 #define LFRATIO_12_20 (1 << 3)
69 #define CH_SIZE_ERR(ch) ((ch < 0) || (ch >= CH_MAX))
70 #define hw_to_priv(_hw) container_of(_hw, struct cs2000_priv, hw)
71 #define priv_to_client(priv) (priv->client)
72 #define priv_to_dev(priv) (&(priv_to_client(priv)->dev))
78 static bool cs2000_readable_reg(struct device
*dev
, unsigned int reg
)
83 static bool cs2000_writeable_reg(struct device
*dev
, unsigned int reg
)
85 return reg
!= DEVICE_ID
;
88 static bool cs2000_volatile_reg(struct device
*dev
, unsigned int reg
)
90 return reg
== DEVICE_CTRL
;
93 static const struct regmap_config cs2000_regmap_config
= {
96 .max_register
= FUNC_CFG2
,
97 .readable_reg
= cs2000_readable_reg
,
98 .writeable_reg
= cs2000_writeable_reg
,
99 .volatile_reg
= cs2000_volatile_reg
,
104 struct i2c_client
*client
;
107 struct regmap
*regmap
;
114 unsigned long saved_rate
;
115 unsigned long saved_parent_rate
;
118 static const struct of_device_id cs2000_of_match
[] = {
119 { .compatible
= "cirrus,cs2000-cp", },
122 MODULE_DEVICE_TABLE(of
, cs2000_of_match
);
124 static const struct i2c_device_id cs2000_id
[] = {
128 MODULE_DEVICE_TABLE(i2c
, cs2000_id
);
130 static int cs2000_enable_dev_config(struct cs2000_priv
*priv
, bool enable
)
134 ret
= regmap_update_bits(priv
->regmap
, DEVICE_CFG1
, ENDEV1
,
135 enable
? ENDEV1
: 0);
139 ret
= regmap_update_bits(priv
->regmap
, GLOBAL_CFG
, ENDEV2
,
140 enable
? ENDEV2
: 0);
144 ret
= regmap_update_bits(priv
->regmap
, FUNC_CFG1
, CLKSKIPEN
,
145 (enable
&& priv
->clk_skip
) ? CLKSKIPEN
: 0);
152 static int cs2000_ref_clk_bound_rate(struct cs2000_priv
*priv
,
157 if (rate_in
>= 32000000 && rate_in
< 56000000)
159 else if (rate_in
>= 16000000 && rate_in
< 28000000)
161 else if (rate_in
>= 8000000 && rate_in
< 14000000)
166 return regmap_update_bits(priv
->regmap
, FUNC_CFG1
,
171 static int cs2000_wait_pll_lock(struct cs2000_priv
*priv
)
173 struct device
*dev
= priv_to_dev(priv
);
177 for (i
= 0; i
< 256; i
++) {
178 ret
= regmap_read(priv
->regmap
, DEVICE_CTRL
, &val
);
181 if (!(val
& PLL_UNLOCK
))
186 dev_err(dev
, "pll lock failed\n");
191 static int cs2000_clk_out_enable(struct cs2000_priv
*priv
, bool enable
)
193 /* enable both AUX_OUT, CLK_OUT */
194 return regmap_update_bits(priv
->regmap
, DEVICE_CTRL
,
195 (AUXOUTDIS
| CLKOUTDIS
),
197 (AUXOUTDIS
| CLKOUTDIS
));
200 static u32
cs2000_rate_to_ratio(u32 rate_in
, u32 rate_out
, bool lf_ratio
)
203 u32 multiplier
= lf_ratio
? 12 : 20;
206 * ratio = rate_out / rate_in * 2^multiplier
208 * To avoid over flow, rate_out is u64.
209 * The result should be u32.
211 ratio
= (u64
)rate_out
<< multiplier
;
212 do_div(ratio
, rate_in
);
217 static unsigned long cs2000_ratio_to_rate(u32 ratio
, u32 rate_in
, bool lf_ratio
)
220 u32 multiplier
= lf_ratio
? 12 : 20;
223 * ratio = rate_out / rate_in * 2^multiplier
225 * To avoid over flow, rate_out is u64.
226 * The result should be u32 or unsigned long.
229 rate_out
= (u64
)ratio
* rate_in
;
230 return rate_out
>> multiplier
;
233 static int cs2000_ratio_set(struct cs2000_priv
*priv
,
234 int ch
, u32 rate_in
, u32 rate_out
)
243 val
= cs2000_rate_to_ratio(rate_in
, rate_out
, priv
->lf_ratio
);
244 for (i
= 0; i
< RATIO_REG_SIZE
; i
++) {
245 ret
= regmap_write(priv
->regmap
,
255 static u32
cs2000_ratio_get(struct cs2000_priv
*priv
, int ch
)
262 for (i
= 0; i
< RATIO_REG_SIZE
; i
++) {
263 ret
= regmap_read(priv
->regmap
, Ratio_Add(ch
, i
), &tmp
);
267 val
|= Val_Ratio(tmp
, i
);
273 static int cs2000_ratio_select(struct cs2000_priv
*priv
, int ch
)
281 ret
= regmap_update_bits(priv
->regmap
, DEVICE_CFG1
, RSEL_MASK
, RSEL(ch
));
285 fracnsrc
= priv
->dynamic_mode
? FRACNSRC_DYNAMIC
: FRACNSRC_STATIC
;
287 ret
= regmap_update_bits(priv
->regmap
, DEVICE_CFG2
,
288 AUTORMOD
| LOCKCLK_MASK
| FRACNSRC_MASK
,
289 LOCKCLK(ch
) | fracnsrc
);
296 static unsigned long cs2000_recalc_rate(struct clk_hw
*hw
,
297 unsigned long parent_rate
)
299 struct cs2000_priv
*priv
= hw_to_priv(hw
);
300 int ch
= 0; /* it uses ch0 only at this point */
303 ratio
= cs2000_ratio_get(priv
, ch
);
305 return cs2000_ratio_to_rate(ratio
, parent_rate
, priv
->lf_ratio
);
308 static long cs2000_round_rate(struct clk_hw
*hw
, unsigned long rate
,
309 unsigned long *parent_rate
)
311 struct cs2000_priv
*priv
= hw_to_priv(hw
);
314 ratio
= cs2000_rate_to_ratio(*parent_rate
, rate
, priv
->lf_ratio
);
316 return cs2000_ratio_to_rate(ratio
, *parent_rate
, priv
->lf_ratio
);
319 static int cs2000_select_ratio_mode(struct cs2000_priv
*priv
,
321 unsigned long parent_rate
)
324 * From the datasheet:
326 * | It is recommended that the 12.20 High-Resolution format be
327 * | utilized whenever the desired ratio is less than 4096 since
328 * | the output frequency accuracy of the PLL is directly proportional
329 * | to the accuracy of the timing reference clock and the resolution
332 * This mode is only available in dynamic mode.
334 priv
->lf_ratio
= priv
->dynamic_mode
&& ((rate
/ parent_rate
) > 4096);
336 return regmap_update_bits(priv
->regmap
, FUNC_CFG2
, LFRATIO_MASK
,
337 priv
->lf_ratio
? LFRATIO_20_12
: LFRATIO_12_20
);
340 static int __cs2000_set_rate(struct cs2000_priv
*priv
, int ch
,
341 unsigned long rate
, unsigned long parent_rate
)
346 ret
= regmap_update_bits(priv
->regmap
, GLOBAL_CFG
, FREEZE
, FREEZE
);
350 ret
= cs2000_select_ratio_mode(priv
, rate
, parent_rate
);
354 ret
= cs2000_ratio_set(priv
, ch
, parent_rate
, rate
);
358 ret
= cs2000_ratio_select(priv
, ch
);
362 ret
= regmap_update_bits(priv
->regmap
, GLOBAL_CFG
, FREEZE
, 0);
366 priv
->saved_rate
= rate
;
367 priv
->saved_parent_rate
= parent_rate
;
372 static int cs2000_set_rate(struct clk_hw
*hw
,
373 unsigned long rate
, unsigned long parent_rate
)
375 struct cs2000_priv
*priv
= hw_to_priv(hw
);
376 int ch
= 0; /* it uses ch0 only at this point */
378 return __cs2000_set_rate(priv
, ch
, rate
, parent_rate
);
381 static int cs2000_set_saved_rate(struct cs2000_priv
*priv
)
383 int ch
= 0; /* it uses ch0 only at this point */
385 return __cs2000_set_rate(priv
, ch
,
387 priv
->saved_parent_rate
);
390 static int cs2000_enable(struct clk_hw
*hw
)
392 struct cs2000_priv
*priv
= hw_to_priv(hw
);
395 ret
= cs2000_enable_dev_config(priv
, true);
399 ret
= cs2000_clk_out_enable(priv
, true);
403 ret
= cs2000_wait_pll_lock(priv
);
410 static void cs2000_disable(struct clk_hw
*hw
)
412 struct cs2000_priv
*priv
= hw_to_priv(hw
);
414 cs2000_enable_dev_config(priv
, false);
416 cs2000_clk_out_enable(priv
, false);
419 static u8
cs2000_get_parent(struct clk_hw
*hw
)
421 struct cs2000_priv
*priv
= hw_to_priv(hw
);
424 * In dynamic mode, output rates are derived from CLK_IN.
425 * In static mode, CLK_IN is ignored, so we return REF_CLK instead.
427 return priv
->dynamic_mode
? CLK_IN
: REF_CLK
;
430 static const struct clk_ops cs2000_ops
= {
431 .get_parent
= cs2000_get_parent
,
432 .recalc_rate
= cs2000_recalc_rate
,
433 .round_rate
= cs2000_round_rate
,
434 .set_rate
= cs2000_set_rate
,
435 .prepare
= cs2000_enable
,
436 .unprepare
= cs2000_disable
,
439 static int cs2000_clk_get(struct cs2000_priv
*priv
)
441 struct device
*dev
= priv_to_dev(priv
);
442 struct clk
*clk_in
, *ref_clk
;
444 clk_in
= devm_clk_get(dev
, "clk_in");
445 /* not yet provided */
447 return -EPROBE_DEFER
;
449 ref_clk
= devm_clk_get(dev
, "ref_clk");
450 /* not yet provided */
452 return -EPROBE_DEFER
;
454 priv
->clk_in
= clk_in
;
455 priv
->ref_clk
= ref_clk
;
460 static int cs2000_clk_register(struct cs2000_priv
*priv
)
462 struct device
*dev
= priv_to_dev(priv
);
463 struct device_node
*np
= dev
->of_node
;
464 struct clk_init_data init
;
465 const char *name
= np
->name
;
466 static const char *parent_names
[CLK_MAX
];
469 int ch
= 0; /* it uses ch0 only at this point */
472 of_property_read_string(np
, "clock-output-names", &name
);
474 priv
->dynamic_mode
= of_property_read_bool(np
, "cirrus,dynamic-mode");
475 dev_info(dev
, "operating in %s mode\n",
476 priv
->dynamic_mode
? "dynamic" : "static");
478 of_property_read_u32(np
, "cirrus,aux-output-source", &aux_out
);
479 ret
= regmap_update_bits(priv
->regmap
, DEVICE_CFG1
,
480 AUXOUTSRC_MASK
, AUXOUTSRC(aux_out
));
484 priv
->clk_skip
= of_property_read_bool(np
, "cirrus,clock-skip");
486 ref_clk_rate
= clk_get_rate(priv
->ref_clk
);
487 ret
= cs2000_ref_clk_bound_rate(priv
, ref_clk_rate
);
491 if (priv
->dynamic_mode
) {
492 /* Default to low-frequency mode to allow for large ratios */
493 priv
->lf_ratio
= true;
496 * set default rate as 1/1.
497 * otherwise .set_rate which setup ratio
498 * is never called if user requests 1/1 rate
500 ret
= __cs2000_set_rate(priv
, ch
, ref_clk_rate
, ref_clk_rate
);
505 parent_names
[CLK_IN
] = __clk_get_name(priv
->clk_in
);
506 parent_names
[REF_CLK
] = __clk_get_name(priv
->ref_clk
);
509 init
.ops
= &cs2000_ops
;
510 init
.flags
= CLK_SET_RATE_GATE
;
511 init
.parent_names
= parent_names
;
512 init
.num_parents
= ARRAY_SIZE(parent_names
);
514 priv
->hw
.init
= &init
;
516 ret
= clk_hw_register(dev
, &priv
->hw
);
520 ret
= of_clk_add_hw_provider(np
, of_clk_hw_simple_get
, &priv
->hw
);
522 clk_hw_unregister(&priv
->hw
);
529 static int cs2000_version_print(struct cs2000_priv
*priv
)
531 struct device
*dev
= priv_to_dev(priv
);
532 const char *revision
;
536 ret
= regmap_read(priv
->regmap
, DEVICE_ID
, &val
);
540 /* CS2000 should be 0x0 */
544 switch (val
& REVISION_MASK
) {
546 revision
= "B2 / B3";
555 dev_info(dev
, "revision - %s\n", revision
);
560 static void cs2000_remove(struct i2c_client
*client
)
562 struct cs2000_priv
*priv
= i2c_get_clientdata(client
);
563 struct device
*dev
= priv_to_dev(priv
);
564 struct device_node
*np
= dev
->of_node
;
566 of_clk_del_provider(np
);
568 clk_hw_unregister(&priv
->hw
);
571 static int cs2000_probe(struct i2c_client
*client
)
573 struct cs2000_priv
*priv
;
574 struct device
*dev
= &client
->dev
;
577 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
581 priv
->client
= client
;
582 i2c_set_clientdata(client
, priv
);
584 priv
->regmap
= devm_regmap_init_i2c(client
, &cs2000_regmap_config
);
585 if (IS_ERR(priv
->regmap
))
586 return PTR_ERR(priv
->regmap
);
588 ret
= cs2000_clk_get(priv
);
592 ret
= cs2000_clk_register(priv
);
596 ret
= cs2000_version_print(priv
);
603 cs2000_remove(client
);
608 static int __maybe_unused
cs2000_resume(struct device
*dev
)
610 struct cs2000_priv
*priv
= dev_get_drvdata(dev
);
612 return cs2000_set_saved_rate(priv
);
615 static const struct dev_pm_ops cs2000_pm_ops
= {
616 SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL
, cs2000_resume
)
619 static struct i2c_driver cs2000_driver
= {
622 .pm
= &cs2000_pm_ops
,
623 .of_match_table
= cs2000_of_match
,
625 .probe
= cs2000_probe
,
626 .remove
= cs2000_remove
,
627 .id_table
= cs2000_id
,
630 module_i2c_driver(cs2000_driver
);
632 MODULE_DESCRIPTION("CS2000-CP driver");
633 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
634 MODULE_LICENSE("GPL v2");