Commit 8066514d authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge branches 'clk-versa', 'clk-silabs', 'clk-samsung', 'clk-starfive' and...

Merge branches 'clk-versa', 'clk-silabs', 'clk-samsung', 'clk-starfive' and 'clk-sophgo' into clk-next

 - Add glitch free PLL setting support to si5351 clk driver

* clk-versa:
  clk: versaclock3: Drop ret variable
  clk: versaclock3: Add missing space between ')' and '{'
  clk: versaclock3: Use u8 return type for get_parent() callback
  clk: versaclock3: Avoid unnecessary padding
  clk: versaclock3: Update vc3_get_div() to avoid divide by zero

* clk-silabs:
  clk: si5351: allow PLLs to be adjusted without reset
  dt-bindings: clock: si5351: add PLL reset mode property
  dt-bindings: clock: si5351: convert to yaml

* clk-samsung:
  clk: samsung: Improve kernel-doc comments
  clk: samsung: Fix kernel-doc comments

* clk-starfive:
  clk: starfive: jh7100: Add CLK_SET_RATE_PARENT to gmac_tx
  clk: starfive: Add flags argument to JH71X0__MUX macro

* clk-sophgo:
  dt-bindings: clock: sophgo: Add clock controller of CV1800 series SoC
Loading
Loading
Loading
Loading
+0 −126
Original line number Diff line number Diff line
Binding for Silicon Labs Si5351a/b/c programmable i2c clock generator.

Reference
[1] Si5351A/B/C Data Sheet
    https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/Si5351-B.pdf

The Si5351a/b/c are programmable i2c clock generators with up to 8 output
clocks. Si5351a also has a reduced pin-count package (MSOP10) where only
3 output clocks are accessible. The internal structure of the clock
generators can be found in [1].

==I2C device node==

Required properties:
- compatible: shall be one of the following:
	"silabs,si5351a" - Si5351a, QFN20 package
	"silabs,si5351a-msop" - Si5351a, MSOP10 package
	"silabs,si5351b" - Si5351b, QFN20 package
	"silabs,si5351c" - Si5351c, QFN20 package
- reg: i2c device address, shall be 0x60 or 0x61.
- #clock-cells: from common clock binding; shall be set to 1.
- clocks: from common clock binding; list of parent clock
  handles, shall be xtal reference clock or xtal and clkin for
  si5351c only. Corresponding clock input names are "xtal" and
  "clkin" respectively.
- #address-cells: shall be set to 1.
- #size-cells: shall be set to 0.

Optional properties:
- silabs,pll-source: pair of (number, source) for each pll. Allows
  to overwrite clock source of pll A (number=0) or B (number=1).

==Child nodes==

Each of the clock outputs can be overwritten individually by
using a child node to the I2C device node. If a child node for a clock
output is not set, the eeprom configuration is not overwritten.

Required child node properties:
- reg: number of clock output.

Optional child node properties:
- silabs,clock-source: source clock of the output divider stage N, shall be
  0 = multisynth N
  1 = multisynth 0 for output clocks 0-3, else multisynth4
  2 = xtal
  3 = clkin (si5351c only)
- silabs,drive-strength: output drive strength in mA, shall be one of {2,4,6,8}.
- silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth
  divider.
- silabs,pll-master: boolean, multisynth can change pll frequency.
- silabs,pll-reset: boolean, clock output can reset its pll.
- silabs,disable-state : clock output disable state, shall be
  0 = clock output is driven LOW when disabled
  1 = clock output is driven HIGH when disabled
  2 = clock output is FLOATING (HIGH-Z) when disabled
  3 = clock output is NEVER disabled

==Example==

/* 25MHz reference crystal */
ref25: ref25M {
	compatible = "fixed-clock";
	#clock-cells = <0>;
	clock-frequency = <25000000>;
};

i2c-master-node {

	/* Si5351a msop10 i2c clock generator */
	si5351a: clock-generator@60 {
		compatible = "silabs,si5351a-msop";
		reg = <0x60>;
		#address-cells = <1>;
		#size-cells = <0>;
		#clock-cells = <1>;

		/* connect xtal input to 25MHz reference */
		clocks = <&ref25>;
		clock-names = "xtal";

		/* connect xtal input as source of pll0 and pll1 */
		silabs,pll-source = <0 0>, <1 0>;

		/*
		 * overwrite clkout0 configuration with:
		 * - 8mA output drive strength
		 * - pll0 as clock source of multisynth0
		 * - multisynth0 as clock source of output divider
		 * - multisynth0 can change pll0
		 * - set initial clock frequency of 74.25MHz
		 */
		clkout0 {
			reg = <0>;
			silabs,drive-strength = <8>;
			silabs,multisynth-source = <0>;
			silabs,clock-source = <0>;
			silabs,pll-master;
			clock-frequency = <74250000>;
		};

		/*
		 * overwrite clkout1 configuration with:
		 * - 4mA output drive strength
		 * - pll1 as clock source of multisynth1
		 * - multisynth1 as clock source of output divider
		 * - multisynth1 can change pll1
		 */
		clkout1 {
			reg = <1>;
			silabs,drive-strength = <4>;
			silabs,multisynth-source = <1>;
			silabs,clock-source = <0>;
			pll-master;
		};

		/*
		 * overwrite clkout2 configuration with:
		 * - xtal as clock source of output divider
		 */
		clkout2 {
			reg = <2>;
			silabs,clock-source = <2>;
		};
	};
};
+265 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/silabs,si5351.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Silicon Labs Si5351A/B/C programmable I2C clock generators

description: |
  The Silicon Labs Si5351A/B/C are programmable I2C clock generators with up to
  8 outputs. Si5351A also has a reduced pin-count package (10-MSOP) where only 3
  output clocks are accessible. The internal structure of the clock generators
  can be found in [1].

  [1] Si5351A/B/C Data Sheet
      https://www.skyworksinc.com/-/media/Skyworks/SL/documents/public/data-sheets/Si5351-B.pdf

maintainers:
  - Alvin Šipraga <alsi@bang-olufsen.dk>

properties:
  compatible:
    enum:
      - silabs,si5351a      # Si5351A, 20-QFN package
      - silabs,si5351a-msop # Si5351A, 10-MSOP package
      - silabs,si5351b      # Si5351B, 20-QFN package
      - silabs,si5351c      # Si5351C, 20-QFN package

  reg:
    enum:
      - 0x60
      - 0x61

  "#address-cells":
    const: 1

  "#size-cells":
    const: 0

  "#clock-cells":
    const: 1

  clocks:
    minItems: 1
    maxItems: 2

  clock-names:
    minItems: 1
    items:
      - const: xtal
      - const: clkin

  silabs,pll-source:
    $ref: /schemas/types.yaml#/definitions/uint32-matrix
    description: |
      A list of cell pairs containing a PLL index and its source. Allows to
      overwrite clock source of the internal PLLs.
    items:
      items:
        - description: PLL A (0) or PLL B (1)
          enum: [ 0, 1 ]
        - description: PLL source, XTAL (0) or CLKIN (1, Si5351C only).
          enum: [ 0, 1 ]

  silabs,pll-reset-mode:
    $ref: /schemas/types.yaml#/definitions/uint32-matrix
    minItems: 1
    maxItems: 2
    description: A list of cell pairs containing a PLL index and its reset mode.
    items:
      items:
        - description: PLL A (0) or PLL B (1)
          enum: [ 0, 1 ]
        - description: |
            Reset mode for the PLL. Mode can be one of:

                0 - reset whenever PLL rate is adjusted (default mode)
                1 - do not reset when PLL rate is adjusted

            In mode 1, the PLL is only reset if the silabs,pll-reset is
            specified in one of the clock output child nodes that also sources
            the PLL. This mode may be preferable if output clocks are expected
            to be adjusted without glitches.
          enum: [ 0, 1 ]

patternProperties:
  "^clkout@[0-7]$":
    type: object

    additionalProperties: false

    properties:
      reg:
        description: Clock output number.

      clock-frequency: true

      silabs,clock-source:
        $ref: /schemas/types.yaml#/definitions/uint32
        description: |
          Source clock of the this output's divider stage.

          0 - use multisynth N for this output, where N is the output number
          1 - use either multisynth 0 (if output number is 0-3) or multisynth 4
              (otherwise) for this output
          2 - use XTAL for this output
          3 - use CLKIN for this output (Si5351C only)

      silabs,drive-strength:
        $ref: /schemas/types.yaml#/definitions/uint32
        enum: [ 2, 4, 6, 8 ]
        description: Output drive strength in mA.

      silabs,multisynth-source:
        $ref: /schemas/types.yaml#/definitions/uint32
        enum: [ 0, 1 ]
        description:
          Source PLL A (0) or B (1) for the corresponding multisynth divider.

      silabs,pll-master:
        type: boolean
        description: |
          The frequency of the source PLL is allowed to be changed by the
          multisynth when setting the rate of this clock output.

      silabs,pll-reset:
        type: boolean
        description: Reset the source PLL when enabling this clock output.

      silabs,disable-state:
        $ref: /schemas/types.yaml#/definitions/uint32
        enum: [ 0, 1, 2, 3 ]
        description: |
          Clock output disable state. The state can be one of:

          0 - clock output is driven LOW when disabled
          1 - clock output is driven HIGH when disabled
          2 - clock output is FLOATING (HIGH-Z) when disabled
          3 - clock output is never disabled

    allOf:
      - if:
          properties:
            compatible:
              contains:
                const: silabs,si5351a-msop
        then:
          properties:
            reg:
              maximum: 2
        else:
          properties:
            reg:
              maximum: 7

      - if:
          properties:
            compatible:
              contains:
                const: silabs,si5351c
        then:
          properties:
            silabs,clock-source:
              enum: [ 0, 1, 2, 3 ]
        else:
          properties:
            silabs,clock-source:
              enum: [ 0, 1, 2 ]

    required:
      - reg

allOf:
  - if:
      properties:
        compatible:
          contains:
            enum:
              - silabs,si5351a
              - silabs,si5351a-msop
              - silabs,si5351b
    then:
      properties:
        clocks:
          maxItems: 1
        clock-names:
          maxItems: 1

required:
  - reg
  - "#address-cells"
  - "#size-cells"
  - "#clock-cells"
  - clocks
  - clock-names

unevaluatedProperties: false

examples:
  - |
    i2c {
      #address-cells = <1>;
      #size-cells = <0>;

      clock-generator@60 {
        compatible = "silabs,si5351a-msop";
        reg = <0x60>;
        #address-cells = <1>;
        #size-cells = <0>;
        #clock-cells = <1>;

        /* Connect XTAL input to 25MHz reference */
        clocks = <&ref25>;
        clock-names = "xtal";

        /* Use XTAL input as source of PLL0 and PLL1 */
        silabs,pll-source = <0 0>, <1 0>;

        /* Don't reset PLL1 on rate adjustment */
        silabs,pll-reset-mode = <1 1>;

        /*
         * Overwrite CLK0 configuration with:
         * - 8 mA output drive strength
         * - PLL0 as clock source of multisynth 0
         * - Multisynth 0 as clock source of output divider
         * - Multisynth 0 can change PLL0
         * - Set initial clock frequency of 74.25MHz
         */
        clkout@0 {
          reg = <0>;
          silabs,drive-strength = <8>;
          silabs,multisynth-source = <0>;
          silabs,clock-source = <0>;
          silabs,pll-master;
          clock-frequency = <74250000>;
        };

        /*
         * Overwrite CLK1 configuration with:
         * - 4 mA output drive strength
         * - PLL1 as clock source of multisynth 1
         * - Multisynth 1 as clock source of output divider
         * - Multisynth 1 can change PLL1
         * - Reset PLL1 when enabling this clock output
         */
        clkout@1 {
          reg = <1>;
          silabs,drive-strength = <4>;
          silabs,multisynth-source = <1>;
          silabs,clock-source = <0>;
          silabs,pll-master;
          silabs,pll-reset;
        };

        /*
         * Overwrite CLK2 configuration with:
         * - XTAL as clock source of output divider
         */
        clkout@2 {
          reg = <2>;
          silabs,clock-source = <2>;
        };
      };
    };
+46 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/sophgo,cv1800-clk.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Sophgo CV1800 Series Clock Controller

maintainers:
  - Inochi Amaoto <inochiama@outlook.com>

properties:
  compatible:
    enum:
      - sophgo,cv1800-clk
      - sophgo,cv1810-clk

  reg:
    maxItems: 1

  clocks:
    maxItems: 1

  "#clock-cells":
    const: 1
    description:
      See <dt-bindings/clock/sophgo,cv1800.h> for valid indices.

required:
  - compatible
  - reg
  - clocks
  - "#clock-cells"

additionalProperties: false

examples:
  - |
    clock-controller@3002000 {
        compatible = "sophgo,cv1800-clk";
        reg = <0x03002000 0x1000>;
        clocks = <&osc>;
        #clock-cells = <1>;
    };

...
+44 −3
Original line number Diff line number Diff line
@@ -506,6 +506,8 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
{
	struct si5351_hw_data *hwdata =
		container_of(hw, struct si5351_hw_data, hw);
	struct si5351_platform_data *pdata =
		hwdata->drvdata->client->dev.platform_data;
	u8 reg = (hwdata->num == 0) ? SI5351_PLLA_PARAMETERS :
		SI5351_PLLB_PARAMETERS;

@@ -518,6 +520,7 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate,
		(hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0);

	/* Do a pll soft reset on the affected pll */
	if (pdata->pll_reset[hwdata->num])
		si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET,
				 hwdata->num == 0 ? SI5351_PLL_RESET_A :
						    SI5351_PLL_RESET_B);
@@ -1222,6 +1225,44 @@ static int si5351_dt_parse(struct i2c_client *client,
		}
	}

	/*
	 * Parse PLL reset mode. For compatibility with older device trees, the
	 * default is to always reset a PLL after setting its rate.
	 */
	pdata->pll_reset[0] = true;
	pdata->pll_reset[1] = true;

	of_property_for_each_u32(np, "silabs,pll-reset-mode", prop, p, num) {
		if (num >= 2) {
			dev_err(&client->dev,
				"invalid pll %d on pll-reset-mode prop\n", num);
			return -EINVAL;
		}

		p = of_prop_next_u32(prop, p, &val);
		if (!p) {
			dev_err(&client->dev,
				"missing pll-reset-mode for pll %d\n", num);
			return -EINVAL;
		}

		switch (val) {
		case 0:
			/* Reset PLL whenever its rate is adjusted */
			pdata->pll_reset[num] = true;
			break;
		case 1:
			/* Don't reset PLL whenever its rate is adjusted */
			pdata->pll_reset[num] = false;
			break;
		default:
			dev_err(&client->dev,
				"invalid pll-reset-mode %d for pll %d\n", val,
				num);
			return -EINVAL;
		}
	}

	/* per clkout properties */
	for_each_child_of_node(np, child) {
		if (of_property_read_u32(child, "reg", &num)) {
+40 −48
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@
#define VC3_PLL1_M_DIV(n)		((n) & GENMASK(5, 0))

#define VC3_PLL1_VCO_N_DIVIDER		0x9
#define VC3_PLL1_LOOP_FILTER_N_DIV_MSB	0x0a
#define VC3_PLL1_LOOP_FILTER_N_DIV_MSB	0xa

#define VC3_OUT_DIV1_DIV2_CTRL		0xf

@@ -148,16 +148,16 @@ struct vc3_pfd_data {
};

struct vc3_pll_data {
	unsigned long vco_min;
	unsigned long vco_max;
	u8 num;
	u8 int_div_msb_offs;
	u8 int_div_lsb_offs;
	unsigned long vco_min;
	unsigned long vco_max;
};

struct vc3_div_data {
	u8 offs;
	const struct clk_div_table *table;
	u8 offs;
	u8 shift;
	u8 width;
	u8 flags;
@@ -210,7 +210,7 @@ static const struct clk_div_table div3_divs[] = {

static struct clk_hw *clk_out[6];

static unsigned char vc3_pfd_mux_get_parent(struct clk_hw *hw)
static u8 vc3_pfd_mux_get_parent(struct clk_hw *hw)
{
	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
	const struct vc3_clk_data *pfd_mux = vc3->data;
@@ -226,9 +226,8 @@ static int vc3_pfd_mux_set_parent(struct clk_hw *hw, u8 index)
	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
	const struct vc3_clk_data *pfd_mux = vc3->data;

	regmap_update_bits(vc3->regmap, pfd_mux->offs, pfd_mux->bitmsk,
	return regmap_update_bits(vc3->regmap, pfd_mux->offs, pfd_mux->bitmsk,
				  index ? pfd_mux->bitmsk : 0);
	return 0;
}

static const struct clk_ops vc3_pfd_mux_ops = {
@@ -440,7 +439,7 @@ static const struct clk_ops vc3_pll_ops = {
	.set_rate = vc3_pll_set_rate,
};

static unsigned char vc3_div_mux_get_parent(struct clk_hw *hw)
static u8 vc3_div_mux_get_parent(struct clk_hw *hw)
{
	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
	const struct vc3_clk_data *div_mux = vc3->data;
@@ -456,10 +455,8 @@ static int vc3_div_mux_set_parent(struct clk_hw *hw, u8 index)
	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
	const struct vc3_clk_data *div_mux = vc3->data;

	regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk,
	return regmap_update_bits(vc3->regmap, div_mux->offs, div_mux->bitmsk,
				  index ? div_mux->bitmsk : 0);

	return 0;
}

static const struct clk_ops vc3_div_mux_ops = {
@@ -477,7 +474,7 @@ static unsigned int vc3_get_div(const struct clk_div_table *table,
		if (clkt->val == val)
			return clkt->div;

	return 0;
	return 1;
}

static unsigned long vc3_div_recalc_rate(struct clk_hw *hw,
@@ -524,10 +521,9 @@ static int vc3_div_set_rate(struct clk_hw *hw, unsigned long rate,

	value = divider_get_val(rate, parent_rate, div_data->table,
				div_data->width, div_data->flags);
	regmap_update_bits(vc3->regmap, div_data->offs,
	return regmap_update_bits(vc3->regmap, div_data->offs,
				  VC3_DIV_MASK(div_data->width) << div_data->shift,
				  value << div_data->shift);
	return 0;
}

static const struct clk_ops vc3_div_ops = {
@@ -539,11 +535,9 @@ static const struct clk_ops vc3_div_ops = {
static int vc3_clk_mux_determine_rate(struct clk_hw *hw,
				      struct clk_rate_request *req)
{
	int ret;
	int frc;

	ret = clk_mux_determine_rate_flags(hw, req, CLK_SET_RATE_PARENT);
	if (ret) {
	if (clk_mux_determine_rate_flags(hw, req, CLK_SET_RATE_PARENT)) {
		/* The below check is equivalent to (best_parent_rate/rate) */
		if (req->best_parent_rate >= req->rate) {
			frc = DIV_ROUND_CLOSEST_ULL(req->best_parent_rate,
@@ -552,13 +546,12 @@ static int vc3_clk_mux_determine_rate(struct clk_hw *hw,
			return clk_mux_determine_rate_flags(hw, req,
							    CLK_SET_RATE_PARENT);
		}
		ret = 0;
	}

	return ret;
	return 0;
}

static unsigned char vc3_clk_mux_get_parent(struct clk_hw *hw)
static u8 vc3_clk_mux_get_parent(struct clk_hw *hw)
{
	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
	const struct vc3_clk_data *clk_mux = vc3->data;
@@ -574,9 +567,8 @@ static int vc3_clk_mux_set_parent(struct clk_hw *hw, u8 index)
	struct vc3_hw_data *vc3 = container_of(hw, struct vc3_hw_data, hw);
	const struct vc3_clk_data *clk_mux = vc3->data;

	regmap_update_bits(vc3->regmap, clk_mux->offs,
			   clk_mux->bitmsk, index ? clk_mux->bitmsk : 0);
	return 0;
	return regmap_update_bits(vc3->regmap, clk_mux->offs, clk_mux->bitmsk,
				  index ? clk_mux->bitmsk : 0);
}

static const struct clk_ops vc3_clk_mux_ops = {
Loading