clk: cs2000-cp: add dynamic mode and more features
Subsystems (2)
v3 cover clk: cs2000-cp: add dynamic mode and more features
This version of the patch series addresses typos in v2 and adds support for dynamic mode, configurable clock skip settings and a tranisition to regmap.
The most significant change is the additional support for dynamic mode. Currently, the driver only supports static mode in which the (currently mandatory) CLK_IN clock input is not used by the hardware. With patch 6/9 of this series, that clock is made optional now, and its presence is used to determine the mode of operation.
Existing DTS users have dummy clock hacks in place and need to adopt to this change. I have patches to do that which I intend to post once this series is merged.
Rob, I left your Reviewed-by in 1/9 as that is untouched since v2. I'd much appreciate a review of the other 3 patches that concern dt-bindings.
Thanks,
Daniel
Daniel Mack (9):
dt-bindings: clock: convert cs2000-cp bindings to yaml
dt-bindings: clock: cs2000-cp: Document aux-output-source
dt-bindings: clock: cs2000-cp: make clk_in optional
dt-bindings: clock: cs2000-cp: document cirrus,clock-skip flag
clk: cs2000-cp: Make aux output function controllable
clk: cs2000-cp: add support for dynamic mode
clk: cs2000-cp: make clock skip setting configurable
clk: cs2000-cp: freeze config during register fiddling
clk: cs2000-cp: convert driver to regmap
.../bindings/clock/cirrus,cs2000-cp.yaml | 84 ++++++ .../devicetree/bindings/clock/cs2000-cp.txt | 22 -- drivers/clk/Kconfig | 1 + drivers/clk/clk-cs2000-cp.c | 240 +++++++++++------- include/dt-bindings/clock/cirrus,cs2000-cp.h | 14 + 5 files changed, 253 insertions(+), 108 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml delete mode 100644 Documentation/devicetree/bindings/clock/cs2000-cp.txt create mode 100644 include/dt-bindings/clock/cirrus,cs2000-cp.h
Signature · 1 line
2.31.1
PATCH v3 1/9 dt-bindings: clock: convert cs2000-cp bindings to yaml
The original author of the file was added as maintainer.
--- .../bindings/clock/cirrus,cs2000-cp.yaml | 63 +++++++++++++++++++ .../devicetree/bindings/clock/cs2000-cp.txt | 22 ------- 2 files changed, 63 insertions(+), 22 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml delete mode 100644 Documentation/devicetree/bindings/clock/cs2000-cp.txt
Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml new file +63 -0
@@ -0,0 +1,63 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/cirrus,cs2000-cp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Binding CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier + +maintainers: + - Kuninori Morimoto <[email protected]> + +description: | + The CS2000-CP is an extremely versatile system clocking device that + utilizes a programmable phase lock loop. + + Link: https://www.cirrus.com/products/cs2000/ + +properties: + compatible: + enum: + - cirrus,cs2000-cp + + clocks: + description: + Common clock binding for CLK_IN, XTI/REF_CLK + minItems: 2 + maxItems: 2 + + clock-names: + items: + - const: clk_in + - const: ref_clk + + '#clock-cells': + const: 0 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + i2c@0 { + reg = <0x0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + + clock-controller@4f { + #clock-cells = <0>; + compatible = "cirrus,cs2000-cp"; + reg = <0x4f>; + clocks = <&rcar_sound 0>, <&x12_clk>; + clock-names = "clk_in", "ref_clk"; + }; + };
Documentation/devicetree/bindings/clock/cs2000-cp.txt deleted +0 -22
@@ -1,22 +0,0 @@ -CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier - -Required properties: - -- compatible: "cirrus,cs2000-cp" -- reg: The chip select number on the I2C bus -- clocks: common clock binding for CLK_IN, XTI/REF_CLK -- clock-names: CLK_IN : clk_in, XTI/REF_CLK : ref_clk -- #clock-cells: must be <0> - -Example: - -&i2c2 { - ... - cs2000: clk_multiplier@4f { - #clock-cells = <0>; - compatible = "cirrus,cs2000-cp"; - reg = <0x4f>; - clocks = <&rcar_sound 0>, <&x12_clk>; - clock-names = "clk_in", "ref_clk"; - }; -};
Signature · 1 line
2.31.1
PATCH v3 2/9 dt-bindings: clock: cs2000-cp: Document aux-output-source
In reply to Daniel MackThis new optional property can be used to control the function of the auxiliary output pin. Introduce a new dt-bindings include file that contains the numerical values.
--- .../bindings/clock/cirrus,cs2000-cp.yaml | 14 ++++++++++++++ include/dt-bindings/clock/cirrus,cs2000-cp.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 include/dt-bindings/clock/cirrus,cs2000-cp.h
Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml +14 -0
@@ -37,6 +37,17 @@ properties: reg: maxItems: 1 + cirrus,aux-output-source: + description: + Specifies the function of the auxiliary clock output pin + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # CS2000CP_AUX_OUTPUT_REF_CLK: ref_clk input + - 1 # CS2000CP_AUX_OUTPUT_CLK_IN: clk_in input + - 2 # CS2000CP_AUX_OUTPUT_CLK_OUT: clk_out output + - 3 # CS2000CP_AUX_OUTPUT_PLL_LOCK: pll lock status + default: 0 + required: - compatible - reg
@@ -48,6 +59,8 @@ additionalProperties: false examples: - | + #include <dt-bindings/clock/cirrus,cs2000-cp.h> + i2c@0 { reg = <0x0 0x100>; #address-cells = <1>;
@@ -59,5 +72,6 @@ examples: reg = <0x4f>; clocks = <&rcar_sound 0>, <&x12_clk>; clock-names = "clk_in", "ref_clk"; + cirrus,aux-output-source = <CS2000CP_AUX_OUTPUT_CLK_OUT>; }; };
include/dt-bindings/clock/cirrus,cs2000-cp.h new file +14 -0
@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* +* Copyright (C) 2021 Daniel Mack +*/ + +#ifndef __DT_BINDINGS_CS2000CP_CLK_H +#define __DT_BINDINGS_CS2000CP_CLK_H + +#define CS2000CP_AUX_OUTPUT_REF_CLK 0 +#define CS2000CP_AUX_OUTPUT_CLK_IN 1 +#define CS2000CP_AUX_OUTPUT_CLK_OUT 2 +#define CS2000CP_AUX_OUTPUT_PLL_LOCK 3 + +#endif /* __DT_BINDINGS_CS2000CP_CLK_H */
Signature · 1 line
2.31.1
Re: [PATCH v3 2/9] dt-bindings: clock: cs2000-cp: Document aux-output-source
Quoted 11 lines · Daniel Mack
This new optional property can be used to control the function of the auxiliary output pin. Introduce a new dt-bindings include file that contains the numerical values.
Signed-off-by Daniel Mack <[email protected]>--- .../bindings/clock/cirrus,cs2000-cp.yaml | 14 ++++++++++++++ include/dt-bindings/clock/cirrus,cs2000-cp.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 include/dt-bindings/clock/cirrus,cs2000-cp.h
PATCH v3 3/9 dt-bindings: clock: cs2000-cp: make clk_in optional
In reply to Daniel MackCLK_IN is only used in dynamic mode and is hence optional.
Re-order the clocks so REF_CLK is specified first.
--- .../devicetree/bindings/clock/cirrus,cs2000-cp.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml +6 -5
@@ -22,14 +22,15 @@ properties: clocks: description: - Common clock binding for CLK_IN, XTI/REF_CLK - minItems: 2 + Common clock binding for XTI/REF_CLK, CLK_IN. + CLK_IN is optional and only used in dynamic mode. + minItems: 1 maxItems: 2 clock-names: items: - - const: clk_in - const: ref_clk + - const: clk_in '#clock-cells': const: 0
@@ -70,8 +71,8 @@ examples: #clock-cells = <0>; compatible = "cirrus,cs2000-cp"; reg = <0x4f>; - clocks = <&rcar_sound 0>, <&x12_clk>; - clock-names = "clk_in", "ref_clk"; + clocks = <&x12_clk>, <&rcar_sound 0>; + clock-names = "ref_clk", "clk_in"; cirrus,aux-output-source = <CS2000CP_AUX_OUTPUT_CLK_OUT>; }; };
Signature · 1 line
2.31.1
Rob Herring
maintainerRe: [PATCH v3 3/9] dt-bindings: clock: cs2000-cp: make clk_in optional
Quoted 3 lines · Daniel Mack
CLK_INis only used in dynamic mode and is hence optional.Re-order the clocks so
REF_CLKis specified first.
It's not a compatible change. You can't do that unless you can explain why it doesn't matter.
Quoted 44 lines
Signed-off-by Daniel Mack <[email protected]>--- .../devicetree/bindings/clock/cirrus,cs2000-cp.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml +6
-5@@ -22,14 +22,15 @@ properties: clocks: description: - Common clock binding for CLK_IN, XTI/REF_CLK - minItems: 2 + Common clock binding for XTI/REF_CLK, CLK_IN. + CLK_IN is optional and only used in dynamic mode. + minItems: 1 maxItems: 2 clock-names: items: - - const: clk_in - const: ref_clk + - const: clk_in '#clock-cells': const: 0@@ -70,8 +71,8 @@ examples: #clock-cells = <0>; compatible = "cirrus,cs2000-cp"; reg = <0x4f>; - clocks = <&rcar_sound 0>, <&x12_clk>; - clock-names = "clk_in", "ref_clk"; + clocks = <&x12_clk>, <&rcar_sound 0>; + clock-names = "ref_clk", "clk_in"; cirrus,aux-output-source = <CS2000CP_AUX_OUTPUT_CLK_OUT>; }; };Signature · 1 line
2.31.1
Re: [PATCH v3 3/9] dt-bindings: clock: cs2000-cp: make clk_in optional
Quoted 7 lines · Rob Herring
Quoted 3 lines · Daniel Mack
CLK_INis only used in dynamic mode and is hence optional.Re-order the clocks so
REF_CLKis specified first.It's not a compatible change. You can't do that unless you can explain why it doesn't matter.
Hmm okay. And that rule also applies even if I patch all mainline users?
Daniel
Quoted 45 lines
Quoted 45 lines
Signed-off-by Daniel Mack <[email protected]>--- .../devicetree/bindings/clock/cirrus,cs2000-cp.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml +6
-5@@ -22,14 +22,15 @@ properties: clocks: description: - Common clock binding for CLK_IN, XTI/REF_CLK - minItems: 2 + Common clock binding for XTI/REF_CLK, CLK_IN. + CLK_IN is optional and only used in dynamic mode. + minItems: 1 maxItems: 2 clock-names: items: - - const: clk_in - const: ref_clk + - const: clk_in '#clock-cells': const: 0@@ -70,8 +71,8 @@ examples: #clock-cells = <0>; compatible = "cirrus,cs2000-cp"; reg = <0x4f>; - clocks = <&rcar_sound 0>, <&x12_clk>; - clock-names = "clk_in", "ref_clk"; + clocks = <&x12_clk>, <&rcar_sound 0>; + clock-names = "ref_clk", "clk_in"; cirrus,aux-output-source = <CS2000CP_AUX_OUTPUT_CLK_OUT>; }; };Signature · 1 line
2.31.1
Rob Herring
maintainerRe: [PATCH v3 3/9] dt-bindings: clock: cs2000-cp: make clk_in optional
Quoted 11 lines · Daniel Mack
Quoted 7 lines · Rob Herring
Quoted 3 lines · Daniel Mack
CLK_INis only used in dynamic mode and is hence optional.Re-order the clocks so
REF_CLKis specified first.It's not a compatible change. You can't do that unless you can explain why it doesn't matter.
Hmm okay. And that rule also applies even if I patch all mainline users?
Explaining why you are doing something and the implications of the change, yes that's required for every commit. Whether you can make incompatible changes, that's up to platform maintainers. I only ask that doing that is documented clearly.
Do you know that every user of affected h/w is okay with you requiring them update their dtb?
Rob
Re: [PATCH v3 3/9] dt-bindings: clock: cs2000-cp: make clk_in optional
Quoted 13 lines · Rob Herring
Quoted 11 lines · Daniel Mack
Quoted 7 lines · Rob Herring
Quoted 3 lines · Daniel Mack
CLK_INis only used in dynamic mode and is hence optional.Re-order the clocks so
REF_CLKis specified first.It's not a compatible change. You can't do that unless you can explain why it doesn't matter.
Hmm okay. And that rule also applies even if I patch all mainline users?
Quoted 7 lines
Explaining why you are doing something and the implications of the change, yes that's required for every commit. Whether you can make incompatible changes, that's up to platform maintainers. I only ask that doing that is documented clearly.
Do you know that every user of affected h/w is okay with you requiring them update their dtb?
Alright, I'll rework that to use a new property then for mode selection. and repost.
Thanks,
Daniel
PATCH v3 4/9 dt-bindings: clock: cs2000-cp: document cirrus,clock-skip flag
In reply to Daniel Mack--- .../devicetree/bindings/clock/cirrus,cs2000-cp.yaml | 6 ++++++ 1 file changed, 6 insertions(+)
Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml +6 -0
@@ -49,6 +49,12 @@ properties: - 3 # CS2000CP_AUX_OUTPUT_PLL_LOCK: pll lock status default: 0 + cirrus,clock-skip: + description: + This mode allows the PLL to maintain lock even when CLK_IN + has missing pulses for up to 20 ms. + $ref: /schemas/types.yaml#/definitions/flag + required: - compatible - reg
Signature · 1 line
2.31.1
Re: [PATCH v3 4/9] dt-bindings: clock: cs2000-cp: document cirrus,clock-skip flag
Quoted 5 lines · Daniel Mack
Signed-off-by Daniel Mack <[email protected]>--- .../devicetree/bindings/clock/cirrus,cs2000-cp.yaml | 6 ++++++ 1 file changed, 6 insertions(+)
PATCH v3 5/9 clk: cs2000-cp: Make aux output function controllable
In reply to Daniel MackThe aux output pin can be configured to output either of the two clock inputs, the generated clock or the pll lock status. Allow access to this feature through a new optional device-tree property.
--- drivers/clk/clk-cs2000-cp.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/clk/clk-cs2000-cp.c +9 -0
@@ -39,6 +39,8 @@/* DEVICE_CFG1 */ #define RSEL (x) (((x) & 0x3) << 3)#define RSEL_MASK RSEL(0x3) +#define AUXOUTSRC (x) (((x) & 0x3) << 1) +#define AUXOUTSRC_MASK AUXOUTSRC(0x3)#define ENDEV1 (0x1)/* DEVICE_CFG2 */
@@ -421,12 +423,19 @@ static int cs2000_clk_register(struct cs2000_priv *priv)struct clk_init_data init;const char *name = np->name;static const char *parent_names[CLK_MAX ]; +u32 aux_out =0 ;int ch =0 ;/* it uses ch0 only at this point */ int rate;int ret;of_property_read_string (np,"clock-output-names" , &name); +of_property_read_u32 (np,"cirrus,aux-output-source" , &aux_out); + ret =cs2000_bset (priv,DEVICE_CFG1 , +AUXOUTSRC_MASK ,AUXOUTSRC (aux_out)); +if (ret <0 ) +return ret; +/* * set default rate as 1/1. * otherwise .set_rate which setup ratio
Signature · 1 line
2.31.1
PATCH v3 6/9 clk: cs2000-cp: add support for dynamic mode
In reply to Daniel MackThe CS2000 chip features two input clocks, REF_CLK and CLK_IN. REF_CLK is mandatory, while CLK_IN is optional, depending on the mode of operation.
In static mode, the output clock (CLK_OUT) is directly derived from REF_CLK, and CLK_IN is ignored. In dynamic mode, CLK_IN is used by the digital PLL.
In dynamic mode, a low-frequency ratio configuration that uses a higher multiplier factor.
This patch adds support for dynamic mode and both ratios:
* Make the CLK_IN input clock optional
* If CLK_IN is provided, present it as parent clock
* The low-frequency ratio mode is automatically selected, depending on the presence of CLK_IN and the given input and output rates
--- drivers/clk/clk-cs2000-cp.c | 111 ++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 38 deletions(-)
drivers/clk/clk-cs2000-cp.c +73 -38
@@ -49,7 +49,7 @@#define LOCKCLK_MASK LOCKCLK(0x3)#define FRACNSRC_MASK (1 << 0)#define FRACNSRC_STATIC (0 << 0) -#define FRACNSRC_DYNAMIC (1 << 1) +#define FRACNSRC_DYNAMIC (1 << 0)/* GLOBAL_CFG */ #define ENDEV2 (0x1)
@@ -79,6 +79,8 @@ struct cs2000_priv {struct clk *clk_in;struct clk *ref_clk; +bool lf_ratio; +/* suspend/resume */ unsigned long saved_rate;unsigned long saved_parent_rate;
@@ -134,17 +136,11 @@ static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)if (ret <0 )return ret; -/* FIXME: for Static ratio mode */ - ret =cs2000_bset (priv,FUNC_CFG2 ,LFRATIO_MASK , -LFRATIO_12_20 ); -if (ret <0 ) -return ret; -return 0 ; } -static int cs2000_clk_in_bound_rate (struct cs2000_priv *priv, -u32 rate_in) +static int cs2000_ref_clk_bound_rate (struct cs2000_priv *priv, +u32 rate_in) {u32 val;
@@ -191,35 +187,37 @@ static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable) (AUXOUTDIS | CLKOUTDIS)); } -static u32 cs2000_rate_to_ratio (u32 rate_in,u32 rate_out) +static u32 cs2000_rate_to_ratio (u32 rate_in,u32 rate_out,bool lf_ratio) {u64 ratio; +u32 multiplier = lf_ratio ?12 :20 ;/* -* ratio = rate_out / rate_in * 2^20 +* ratio = rate_out / rate_in * 2^multiplier * * To avoid over flow, rate_out is u64. * The result should be u32. */ - ratio = (u64 )rate_out <<20 ; + ratio = (u64 )rate_out << multiplier;do_div (ratio, rate_in);return ratio; } -static unsigned long cs2000_ratio_to_rate (u32 ratio,u32 rate_in) +static unsigned long cs2000_ratio_to_rate (u32 ratio,u32 rate_in,bool lf_ratio) {u64 rate_out; +u32 multiplier = lf_ratio ?12 :20 ;/* -* ratio = rate_out / rate_in * 2^20 +* ratio = rate_out / rate_in * 2^multiplier * * To avoid over flow, rate_out is u64. * The result should be u32 or unsigned long. */ rate_out = (u64 )ratio * rate_in; -return rate_out >>20 ; +return rate_out >> multiplier; } static int cs2000_ratio_set(struct cs2000_priv *priv,
@@ -232,7 +230,7 @@ static int cs2000_ratio_set(struct cs2000_priv *priv,if (CH_SIZE_ERR (ch))return -EINVAL ; - val =cs2000_rate_to_ratio (rate_in, rate_out); + val =cs2000_rate_to_ratio (rate_in, rate_out, priv->lf_ratio);for (i =0 ; i <RATIO_REG_SIZE ; i++) { ret = cs2000_write(priv, Ratio_Add(ch, i),
@@ -265,22 +263,21 @@ static u32 cs2000_ratio_get(struct cs2000_priv *priv, int ch)static int cs2000_ratio_select (struct cs2000_priv *priv,int ch) {int ret; +u8 fracnsrc;if (CH_SIZE_ERR (ch))return -EINVAL ; -/* -* FIXME -* -* this driver supports static ratio mode only at this point. -*/ ret =cs2000_bset (priv,DEVICE_CFG1 ,RSEL_MASK ,RSEL (ch));if (ret <0 )return ret; +/* Always use dynamic mode when CLK_IN is present */ + fracnsrc = priv->clk_in ?FRACNSRC_DYNAMIC :FRACNSRC_STATIC ; + ret =cs2000_bset (priv,DEVICE_CFG2 , - (AUTORMOD |LOCKCLK_MASK |FRACNSRC_MASK ), - (LOCKCLK (ch) |FRACNSRC_STATIC )); +AUTORMOD |LOCKCLK_MASK |FRACNSRC_MASK , +LOCKCLK (ch) | fracnsrc);if (ret <0 )return ret;
@@ -296,17 +293,40 @@ static unsigned long cs2000_recalc_rate(struct clk_hw *hw, ratio =cs2000_ratio_get (priv, ch); -return cs2000_ratio_to_rate (ratio, parent_rate); +return cs2000_ratio_to_rate (ratio, parent_rate, priv->lf_ratio); }static long cs2000_round_rate (struct clk_hw *hw,unsigned long rate,unsigned long *parent_rate) { +struct cs2000_priv *priv =hw_to_priv (hw);u32 ratio; - ratio =cs2000_rate_to_ratio (*parent_rate, rate); + ratio =cs2000_rate_to_ratio (*parent_rate, rate, priv->lf_ratio); + +return cs2000_ratio_to_rate (ratio, *parent_rate, priv->lf_ratio); +} + +static int cs2000_select_ratio_mode (struct cs2000_priv *priv, +unsigned long rate, +unsigned long parent_rate) +{ +/* +* From the datasheet: +* +* | It is recommended that the 12.20 High-Resolution format be +* | utilized whenever the desired ratio is less than 4096 since +* | the output frequency accuracy of the PLL is directly proportional +* | to the accuracy of the timing reference clock and the resolution +* | of the R_UD. +* +* This mode is only available in dynamic mode (ie, with a CLK_IN input +* present). +*/ + priv->lf_ratio = priv->clk_in && ((rate / parent_rate) >4096 ); -return cs2000_ratio_to_rate (ratio, *parent_rate); +return cs2000_bset (priv,FUNC_CFG2 ,LFRATIO_MASK , + priv->lf_ratio ?LFRATIO_20_12 :LFRATIO_12_20 ); } static int __cs2000_set_rate(struct cs2000_priv *priv, int ch,
@@ -315,7 +335,7 @@ static int __cs2000_set_rate(struct cs2000_priv *priv, int ch, {int ret; - ret =cs2000_clk_in_bound_rate (priv, parent_rate); + ret =cs2000_select_ratio_mode (priv, rate, parent_rate);if (ret <0 )return ret;
@@ -382,8 +402,14 @@ static void cs2000_disable(struct clk_hw *hw)static u8 cs2000_get_parent (struct clk_hw *hw) { -/* always return REF_CLK */ -return REF_CLK ; +struct cs2000_priv *priv =hw_to_priv (hw); + +/* +* If CLK_IN was provided, we're operating in dynamic mode, +* hence output clock rates are derived from that. +*/ + +return priv->clk_in ?CLK_IN :REF_CLK ; }static const struct clk_ops cs2000_ops = {
@@ -400,7 +426,7 @@ static int cs2000_clk_get(struct cs2000_priv *priv)struct device *dev =priv_to_dev (priv);struct clk *clk_in, *ref_clk; - clk_in =devm_clk_get (dev,"clk_in" ); + clk_in =devm_clk_get_optional (dev,"clk_in" );/* not yet provided */ if (IS_ERR (clk_in))return -EPROBE_DEFER ;
@@ -424,8 +450,8 @@ static int cs2000_clk_register(struct cs2000_priv *priv)const char *name = np->name;static const char *parent_names[CLK_MAX ];u32 aux_out =0 ; +int ref_clk_rate;int ch =0 ;/* it uses ch0 only at this point */ -int rate;int ret;of_property_read_string (np,"clock-output-names" , &name);
@@ -436,16 +462,25 @@ static int cs2000_clk_register(struct cs2000_priv *priv)if (ret <0 )return ret; -/* -* set default rate as 1/1. -* otherwise .set_rate which setup ratio -* is never called if user requests 1/1 rate -*/ - rate =clk_get_rate (priv->ref_clk); - ret =__cs2000_set_rate (priv, ch, rate, rate); + ref_clk_rate =clk_get_rate (priv->ref_clk); + ret =cs2000_ref_clk_bound_rate (priv, ref_clk_rate);if (ret <0 )return ret; +if (priv->clk_in) { +/* Default to low-frequency mode to allow for large ratios */ + priv->lf_ratio = true; + }else { +/* +* set default rate as 1/1. +* otherwise .set_rate which setup ratio +* is never called if user requests 1/1 rate +*/ + ret =__cs2000_set_rate (priv, ch, ref_clk_rate, ref_clk_rate); +if (ret <0 ) +return ret; + } + parent_names[CLK_IN ] =__clk_get_name (priv->clk_in); parent_names[REF_CLK ] =__clk_get_name (priv->ref_clk);
Signature · 1 line
2.31.1
PATCH v3 7/9 clk: cs2000-cp: make clock skip setting configurable
In reply to Daniel MackThe clock skip function of this chip is not necessarily desirable in all hardware appliances. This patch makes the feature configurable through a device-tree property.
--- drivers/clk/clk-cs2000-cp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/clk/clk-cs2000-cp.c +4 -1
@@ -80,6 +80,7 @@ struct cs2000_priv {struct clk *ref_clk;bool lf_ratio; +bool clk_skip;/* suspend/resume */ unsigned long saved_rate;
@@ -132,7 +133,7 @@ static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)return ret; ret =cs2000_bset (priv,FUNC_CFG1 ,CLKSKIPEN , - enable ?CLKSKIPEN :0 ); + (enable && priv->clk_skip) ?CLKSKIPEN :0 );if (ret <0 )return ret;
@@ -462,6 +463,8 @@ static int cs2000_clk_register(struct cs2000_priv *priv)if (ret <0 )return ret; + priv->clk_skip =of_property_read_bool (np,"cirrus,clock-skip" ); + ref_clk_rate =clk_get_rate (priv->ref_clk); ret =cs2000_ref_clk_bound_rate (priv, ref_clk_rate);if (ret <0 )
Signature · 1 line
2.31.1
PATCH v3 8/9 clk: cs2000-cp: freeze config during register fiddling
In reply to Daniel MackMake sure to freeze the configuration of the chip during the programming of 32-bit registers. This avoids the processing of invalid intermediate states.
--- drivers/clk/clk-cs2000-cp.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/clk/clk-cs2000-cp.c +9 -0
@@ -52,6 +52,7 @@#define FRACNSRC_DYNAMIC (1 << 0)/* GLOBAL_CFG */ +#define FREEZE (1 << 7)#define ENDEV2 (0x1)/* FUNC_CFG1 */
@@ -336,6 +337,10 @@ static int __cs2000_set_rate(struct cs2000_priv *priv, int ch, {int ret; + ret =cs2000_bset (priv,GLOBAL_CFG ,FREEZE ,FREEZE ); +if (ret <0 ) +return ret; + ret =cs2000_select_ratio_mode (priv, rate, parent_rate);if (ret <0 )return ret;
@@ -348,6 +353,10 @@ static int __cs2000_set_rate(struct cs2000_priv *priv, int ch,if (ret <0 )return ret; + ret =cs2000_bset (priv,GLOBAL_CFG ,FREEZE ,0 ); +if (ret <0 ) +return ret; + priv->saved_rate = rate; priv->saved_parent_rate = parent_rate;
Signature · 1 line
2.31.1
PATCH v3 9/9 clk: cs2000-cp: convert driver to regmap
In reply to Daniel MackRegmap gives us caching, debugging infrastructure and other things for free and does away with open-coded bit-fiddling implementations.
--- drivers/clk/Kconfig | 1 + drivers/clk/clk-cs2000-cp.c | 124 ++++++++++++++++++++---------------- 2 files changed, 69 insertions(+), 56 deletions(-)
drivers/clk/Kconfig +1 -0
@@ -185,6 +185,7 @@ config COMMON_CLK_CDCE925 config COMMON_CLK_CS2000_CP tristate "Clock driver for CS2000 Fractional-N Clock Synthesizer & Clock Multiplier" depends on I2C + select REGMAP_I2C help If you say yes here you get support for the CS2000 clock multiplier.
drivers/clk/clk-cs2000-cp.c +68 -56
242 lines not on this page · raw message
Signature · 1 line
2.31.1