Skip to contentSkip to conversation

JH7100 Audio Clocks

PATCH Applied Emil Renner Berthing 3 participants 17 messages Jan 26, 2022 – Mar 11, 2022

Subsystems (3)
lore
Share & tools
lore

Emil Renner Berthing

author maintainer
#0 lore raw

cover JH7100 Audio Clocks

This series add support for the audio clocks on the StarFive JH7100 RISC-V SoC, although the first two patches are fixes to the original addition of the basic clock driver. At least the first fix may be considered for 5.17.

It turns out the SoC has several memory ranges for different clocks, but they all share the layout of the control registers. This could be modelled in 3 ways:

1) Model all the clocks as a single peripheral with multiple memory ranges and have a single driver for them all.
2) Model each memory range as different, but related peripherals with a single driver handling all of them.
3) Model each memory range as different peripherals with separate drivers that can share most code.

Although the first option would require less code this series implements the 3rd option. The basic clock driver has to be built-in to boot the SoC, so separate drivers for the other registers means less code needs to be built-in and can be left as loadable modules.

Emil Renner Berthing (7):
clk: starfive: jh7100: Don't round divisor up twice
clk: starfive: jh7100: Handle audio_div clock properly
dt-bindings: clock: Add JH7100 audio clock definitions
dt-bindings: clock: Add starfive,jh7100-audclk bindings
clk: starfive: jh7100: Make hw clock implementation reusable
clk: starfive: jh7100: Support more clock types
clk: starfive: Add JH7100 audio clock driver

 .../clock/starfive,jh7100-audclk.yaml         |  57 ++++++
 MAINTAINERS                                   |   8 +-
 drivers/clk/starfive/Kconfig                  |   8 +
 drivers/clk/starfive/Makefile                 |   1 +
 .../clk/starfive/clk-starfive-jh7100-audio.c  | 170 +++++++++++++++++
 drivers/clk/starfive/clk-starfive-jh7100.c    | 176 +++++++++---------
 drivers/clk/starfive/clk-starfive-jh7100.h    | 112 +++++++++++
 .../dt-bindings/clock/starfive-jh7100-audio.h |  41 ++++
 8 files changed, 482 insertions(+), 91 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-audclk.yaml
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100-audio.c
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100.h
 create mode 100644 include/dt-bindings/clock/starfive-jh7100-audio.h
Signature · 1 line
2.34.1
author maintainer
#1 lore raw

PATCH 1/7 clk: starfive: jh7100: Don't round divisor up twice

The problem is best illustrated by an example. Suppose a consumer wants a 4MHz clock rate from a divider with a 10MHz parent. It would then call

clk_round_rate(clk, 4000000)

which would call into our determine_rate() callback that correctly rounds up and finds that a divisor of 3 gives the highest possible frequency below the requested 4MHz and returns 10000000 / 3 = 3333333Hz.

However the consumer would then call

clk_set_rate(clk, 3333333)

but since 3333333 doesn't divide 10000000 evenly our set_rate() callback would again round the divisor up and set it to 4 which results in an unnecessarily low rate of 2.5MHz.

Fix it by using DIV_ROUND_CLOSEST in the set_rate() callback.

Fixes 4210be668a09 ("clk: starfive: Add JH7100 clock generator driver")
---
 drivers/clk/starfive/clk-starfive-jh7100.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)
drivers/clk/starfive/clk-starfive-jh7100.c +3 -11
index 25d31afa0f87..db6a4dc203af 100644
@@ -399,22 +399,13 @@ static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
 	return div ? parent_rate / div : 0;
 }
 
-static unsigned long jh7100_clk_bestdiv(struct jh7100_clk *clk,
-					unsigned long rate, unsigned long parent)
-{
-	unsigned long max = clk->max_div;
-	unsigned long div = DIV_ROUND_UP(parent, rate);
-
-	return min(div, max);
-}
-
 static int jh7100_clk_determine_rate(struct clk_hw *hw,
 				     struct clk_rate_request *req)
 {
 	struct jh7100_clk *clk = jh7100_clk_from(hw);
 	unsigned long parent = req->best_parent_rate;
 	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
-	unsigned long div = jh7100_clk_bestdiv(clk, rate, parent);
+	unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div);
 	unsigned long result = parent / div;
 
 	/*
@@ -442,7 +433,8 @@ static int jh7100_clk_set_rate(struct clk_hw *hw,
 			       unsigned long parent_rate)
 {
 	struct jh7100_clk *clk = jh7100_clk_from(hw);
-	unsigned long div = jh7100_clk_bestdiv(clk, rate, parent_rate);
+	unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate),
+				  1UL, (unsigned long)clk->max_div);
 
 	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
 	return 0;
Signature · 1 line
2.34.1
maintainer Applied
#2 lore raw

Re: [PATCH v1 1/7] clk: starfive: jh7100: Don't round divisor up twice

Quoting Emil Renner Berthing (2022-01-26 09:39:47)

Quoted 18 lines

The problem is best illustrated by an example. Suppose a consumer wants a 4MHz clock rate from a divider with a 10MHz parent. It would then call

clk_round_rate(clk, 4000000)

which would call into our determine_rate() callback that correctly rounds up and finds that a divisor of 3 gives the highest possible frequency below the requested 4MHz and returns 10000000 / 3 = 3333333Hz.

However the consumer would then call

clk_set_rate(clk, 3333333)

but since 3333333 doesn't divide 10000000 evenly our set_rate() callback would again round the divisor up and set it to 4 which results in an unnecessarily low rate of 2.5MHz.

Quoted 5 lines

Fix it by using DIV_ROUND_CLOSEST in the set_rate() callback.

Fixes 4210be668a09 ("clk: starfive: Add JH7100 clock generator driver")

---

Applied to clk-next

author maintainer
#3 lore raw

PATCH 2/7 clk: starfive: jh7100: Handle audio_div clock properly

In reply to Emil Renner Berthing

It turns out the audio_div clock is a fractional divider where the lowest byte of the ctrl register is the integer part of the divider and the 2nd byte is the number of 100th added to the divider.

The children of this clock is used by the audio peripherals for their sample rate clock, so round to the closest possible rate rather than always rounding down like regular dividers.

Fixes 4210be668a09 ("clk: starfive: Add JH7100 clock generator driver")
---
 drivers/clk/starfive/clk-starfive-jh7100.c | 68 +++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)
drivers/clk/starfive/clk-starfive-jh7100.c +67 -1
index db6a4dc203af..4b59338b5d7d 100644
@@ -32,6 +32,13 @@
 #define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
 #define JH7100_CLK_MUX_SHIFT	24
 #define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
+#define JH7100_CLK_FRAC_MASK	GENMASK(15, 8)
+#define JH7100_CLK_FRAC_SHIFT	8
+#define JH7100_CLK_INT_MASK	GENMASK(7, 0)
+
+/* fractional divider min/max */
+#define JH7100_CLK_FRAC_MIN	100UL
+#define JH7100_CLK_FRAC_MAX	25599UL
 
 /* clock data */
 #define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = {		\
@@ -55,6 +62,13 @@
 	.parents = { [0] = _parent },					\
 }
 
+#define JH7100_FDIV(_idx, _name, _parent) [_idx] = {			\
+	.name = _name,							\
+	.flags = 0,							\
+	.max = JH7100_CLK_FRAC_MAX,					\
+	.parents = { [0] = _parent },					\
+}
+
 #define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = {		\
 	.name = _name,							\
 	.flags = 0,							\
@@ -225,7 +239,7 @@ static const struct {
 	JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 2,
 		    JH7100_CLK_OSC_SYS,
 		    JH7100_CLK_USBPHY_PLLDIV25M),
-	JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", 131072, JH7100_CLK_AUDIO_ROOT),
+	JH7100_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT),
 	JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", 0, JH7100_CLK_AUDIO_DIV),
 	JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", 0, JH7100_CLK_OSC_AUD),
 	JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", 0, 4, JH7100_CLK_VIN_ROOT),
@@ -440,6 +454,49 @@ static int jh7100_clk_set_rate(struct clk_hw *hw,
 	return 0;
 }
 
+static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw,
+						 unsigned long parent_rate)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 reg = jh7100_clk_reg_get(clk);
+	unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) +
+			       ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT);
+
+	return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0;
+}
+
+static int jh7100_clk_frac_determine_rate(struct clk_hw *hw,
+					  struct clk_rate_request *req)
+{
+	unsigned long parent100 = 100 * req->best_parent_rate;
+	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
+	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate),
+				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
+	unsigned long result = parent100 / div100;
+
+	/* clamp the result as in jh7100_clk_determine_rate() above */
+	if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX)
+		result = parent100 / (div100 + 1);
+	if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN)
+		result = parent100 / (div100 - 1);
+
+	req->rate = result;
+	return 0;
+}
+
+static int jh7100_clk_frac_set_rate(struct clk_hw *hw,
+				    unsigned long rate,
+				    unsigned long parent_rate)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate),
+				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
+	u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100);
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value);
+	return 0;
+}
+
 static u8 jh7100_clk_get_parent(struct clk_hw *hw)
 {
 	struct jh7100_clk *clk = jh7100_clk_from(hw);
@@ -526,6 +583,13 @@ static const struct clk_ops jh7100_clk_div_ops = {
 	.debug_init = jh7100_clk_debug_init,
 };
 
+static const struct clk_ops jh7100_clk_fdiv_ops = {
+	.recalc_rate = jh7100_clk_frac_recalc_rate,
+	.determine_rate = jh7100_clk_frac_determine_rate,
+	.set_rate = jh7100_clk_frac_set_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
 static const struct clk_ops jh7100_clk_gdiv_ops = {
 	.enable = jh7100_clk_enable,
 	.disable = jh7100_clk_disable,
@@ -564,6 +628,8 @@ static const struct clk_ops *__init jh7100_clk_ops(u32 max)
 	if (max & JH7100_CLK_DIV_MASK) {
 		if (max & JH7100_CLK_ENABLE)
 			return &jh7100_clk_gdiv_ops;
+		if (max == JH7100_CLK_FRAC_MAX)
+			return &jh7100_clk_fdiv_ops;
 		return &jh7100_clk_div_ops;
 	}
 
Signature · 1 line
2.34.1
maintainer Applied
#4 lore raw

Re: [PATCH v1 2/7] clk: starfive: jh7100: Handle audio_div clock properly

Quoting Emil Renner Berthing (2022-01-26 09:39:48)

Quoted 11 lines

It turns out the audio_div clock is a fractional divider where the lowest byte of the ctrl register is the integer part of the divider and the 2nd byte is the number of 100th added to the divider.

The children of this clock is used by the audio peripherals for their sample rate clock, so round to the closest possible rate rather than always rounding down like regular dividers.

Fixes 4210be668a09 ("clk: starfive: Add JH7100 clock generator driver")

---

Applied to clk-next

author maintainer
#5 lore raw

PATCH 3/7 dt-bindings: clock: Add JH7100 audio clock definitions

In reply to Emil Renner Berthing

Add all clock outputs for the StarFive JH7100 audio clock generator.

---
 .../dt-bindings/clock/starfive-jh7100-audio.h | 41 +++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 include/dt-bindings/clock/starfive-jh7100-audio.h
include/dt-bindings/clock/starfive-jh7100-audio.h new file +41 -0
new file mode 100644
index 000000000000..fbb4eae6572b
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7100_AUDIO_H__
+#define __DT_BINDINGS_CLOCK_STARFIVE_JH7100_AUDIO_H__
+
+#define JH7100_AUDCLK_ADC_MCLK		0
+#define JH7100_AUDCLK_I2S1_MCLK		1
+#define JH7100_AUDCLK_I2SADC_APB	2
+#define JH7100_AUDCLK_I2SADC_BCLK	3
+#define JH7100_AUDCLK_I2SADC_BCLK_N	4
+#define JH7100_AUDCLK_I2SADC_LRCLK	5
+#define JH7100_AUDCLK_PDM_APB		6
+#define JH7100_AUDCLK_PDM_MCLK		7
+#define JH7100_AUDCLK_I2SVAD_APB	8
+#define JH7100_AUDCLK_SPDIF		9
+#define JH7100_AUDCLK_SPDIF_APB		10
+#define JH7100_AUDCLK_PWMDAC_APB	11
+#define JH7100_AUDCLK_DAC_MCLK		12
+#define JH7100_AUDCLK_I2SDAC_APB	13
+#define JH7100_AUDCLK_I2SDAC_BCLK	14
+#define JH7100_AUDCLK_I2SDAC_BCLK_N	15
+#define JH7100_AUDCLK_I2SDAC_LRCLK	16
+#define JH7100_AUDCLK_I2S1_APB		17
+#define JH7100_AUDCLK_I2S1_BCLK		18
+#define JH7100_AUDCLK_I2S1_BCLK_N	19
+#define JH7100_AUDCLK_I2S1_LRCLK	20
+#define JH7100_AUDCLK_I2SDAC16K_APB	21
+#define JH7100_AUDCLK_APB0_BUS		22
+#define JH7100_AUDCLK_DMA1P_AHB		23
+#define JH7100_AUDCLK_USB_APB		24
+#define JH7100_AUDCLK_USB_LPM		25
+#define JH7100_AUDCLK_USB_STB		26
+#define JH7100_AUDCLK_APB_EN		27
+#define JH7100_AUDCLK_VAD_MEM		28
+
+#define JH7100_AUDCLK_END		29
+
+#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7100_AUDIO_H__ */
Signature · 1 line
2.34.1
maintainer Acked-by on v1 3/7
#6 lore raw

Re: [PATCH v1 3/7] dt-bindings: clock: Add JH7100 audio clock definitions

Quoted 8 lines · Emil Renner Berthing

Add all clock outputs for the StarFive JH7100 audio clock generator.

---
 .../dt-bindings/clock/starfive-jh7100-audio.h | 41 +++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 include/dt-bindings/clock/starfive-jh7100-audio.h
author maintainer
#8 lore raw

PATCH 4/7 dt-bindings: clock: Add starfive,jh7100-audclk bindings

In reply to Emil Renner Berthing

Add bindings for the audio clocks on the StarFive JH7100 RISC-V SoC.

---
 .../clock/starfive,jh7100-audclk.yaml         | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-audclk.yaml
Documentation/devicetree/bindings/clock/starfive,jh7100-audclk.yaml new file +57 -0
new file mode 100644
index 000000000000..8f49a1ae03f1
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/starfive,jh7100-audclk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7100 Audio Clock Generator
+
+maintainers:
+  - Emil Renner Berthing <[email protected]>
+
+properties:
+  compatible:
+    const: starfive,jh7100-audclk
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Audio source clock
+      - description: External 12.288MHz clock
+      - description: Domain 7 AHB bus clock
+
+  clock-names:
+    items:
+      - const: audio_src
+      - const: audio_12288
+      - const: dom7ahb_bus
+
+  '#clock-cells':
+    const: 1
+    description:
+      See <dt-bindings/clock/starfive-jh7100-audio.h> for valid indices.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/starfive-jh7100.h>
+
+    clock-controller@10480000 {
+            compatible = "starfive,jh7100-audclk";
+            reg = <0x10480000 0x10000>;
+            clocks = <&clkgen JH7100_CLK_AUDIO_SRC>,
+                     <&clkgen JH7100_CLK_AUDIO_12288>,
+                     <&clkgen JH7100_CLK_DOM7AHB_BUS>;
+            clock-names = "audio_src", "audio_12288", "dom7ahb_bus";
+            #clock-cells = <1>;
+    };
Signature · 1 line
2.34.1
maintainer Reviewed-by on v1 4/7
#9 lore raw

Re: [PATCH v1 4/7] dt-bindings: clock: Add starfive,jh7100-audclk bindings

Quoted 8 lines · Emil Renner Berthing

Add bindings for the audio clocks on the StarFive JH7100 RISC-V SoC.

---
 .../clock/starfive,jh7100-audclk.yaml         | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-audclk.yaml
author maintainer
#11 lore raw

PATCH 5/7 clk: starfive: jh7100: Make hw clock implementation reusable

In reply to Emil Renner Berthing

The JH7100 has additional audio and video clocks at different memory ranges, but they use the same register layout. Add a header and export the starfive_jh7100_clk_ops function so the clock implementation can be reused by drivers handling these clocks.

---
 drivers/clk/starfive/clk-starfive-jh7100.c | 96 ++-------------------
 drivers/clk/starfive/clk-starfive-jh7100.h | 97 ++++++++++++++++++++++
 2 files changed, 104 insertions(+), 89 deletions(-)
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100.h
drivers/clk/starfive/clk-starfive-jh7100.c +7 -89
index 4b59338b5d7d..a6708f9ebf4c 100644
@@ -20,83 +20,15 @@
 
 #include <dt-bindings/clock/starfive-jh7100.h>
 
+#include "clk-starfive-jh7100.h"
+
 /* external clocks */
 #define JH7100_CLK_OSC_SYS		(JH7100_CLK_END + 0)
 #define JH7100_CLK_OSC_AUD		(JH7100_CLK_END + 1)
 #define JH7100_CLK_GMAC_RMII_REF	(JH7100_CLK_END + 2)
 #define JH7100_CLK_GMAC_GR_MII_RX	(JH7100_CLK_END + 3)
 
-/* register fields */
-#define JH7100_CLK_ENABLE	BIT(31)
-#define JH7100_CLK_INVERT	BIT(30)
-#define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
-#define JH7100_CLK_MUX_SHIFT	24
-#define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
-#define JH7100_CLK_FRAC_MASK	GENMASK(15, 8)
-#define JH7100_CLK_FRAC_SHIFT	8
-#define JH7100_CLK_INT_MASK	GENMASK(7, 0)
-
-/* fractional divider min/max */
-#define JH7100_CLK_FRAC_MIN	100UL
-#define JH7100_CLK_FRAC_MAX	25599UL
-
-/* clock data */
-#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = {		\
-	.name = _name,							\
-	.flags = CLK_SET_RATE_PARENT | (_flags),			\
-	.max = JH7100_CLK_ENABLE,					\
-	.parents = { [0] = _parent },					\
-}
-
-#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = {		\
-	.name = _name,							\
-	.flags = 0,							\
-	.max = _max,							\
-	.parents = { [0] = _parent },					\
-}
-
-#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = {	\
-	.name = _name,							\
-	.flags = _flags,						\
-	.max = JH7100_CLK_ENABLE | (_max),				\
-	.parents = { [0] = _parent },					\
-}
-
-#define JH7100_FDIV(_idx, _name, _parent) [_idx] = {			\
-	.name = _name,							\
-	.flags = 0,							\
-	.max = JH7100_CLK_FRAC_MAX,					\
-	.parents = { [0] = _parent },					\
-}
-
-#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = {		\
-	.name = _name,							\
-	.flags = 0,							\
-	.max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT,		\
-	.parents = { __VA_ARGS__ },					\
-}
-
-#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = {	\
-	.name = _name,							\
-	.flags = _flags,						\
-	.max = JH7100_CLK_ENABLE |					\
-		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT),		\
-	.parents = { __VA_ARGS__ },					\
-}
-
-#define JH7100__INV(_idx, _name, _parent) [_idx] = {			\
-	.name = _name,							\
-	.flags = CLK_SET_RATE_PARENT,					\
-	.max = JH7100_CLK_INVERT,					\
-	.parents = { [0] = _parent },					\
-}
-
-static const struct {
-	const char *name;
-	unsigned long flags;
-	u32 max;
-	u8 parents[4];
-} jh7100_clk_data[] __initconst = {
+static const struct jh7100_clk_data jh7100_clk_data[] __initconst = {
 	JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4,
 		    JH7100_CLK_OSC_SYS,
 		    JH7100_CLK_PLL0_OUT,
@@ -337,21 +269,6 @@ static const struct {
 	JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS),
 };
 
-struct jh7100_clk {
-	struct clk_hw hw;
-	unsigned int idx;
-	unsigned int max_div;
-};
-
-struct jh7100_clk_priv {
-	/* protect clk enable and set rate/parent from happening at the same time */
-	spinlock_t rmw_lock;
-	struct device *dev;
-	void __iomem *base;
-	struct clk_hw *pll[3];
-	struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
-};
-
 static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
 {
 	return container_of(hw, struct jh7100_clk, hw);
@@ -623,7 +540,7 @@ static const struct clk_ops jh7100_clk_inv_ops = {
 	.debug_init = jh7100_clk_debug_init,
 };
 
-static const struct clk_ops *__init jh7100_clk_ops(u32 max)
+const struct clk_ops *starfive_jh7100_clk_ops(u32 max)
 {
 	if (max & JH7100_CLK_DIV_MASK) {
 		if (max & JH7100_CLK_ENABLE)
@@ -644,6 +561,7 @@ static const struct clk_ops *__init jh7100_clk_ops(u32 max)
 
 	return &jh7100_clk_inv_ops;
 }
+EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops);
 
 static struct clk_hw *jh7100_clk_get(struct of_phandle_args *clkspec, void *data)
 {
@@ -665,7 +583,7 @@ static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
 	unsigned int idx;
 	int ret;
 
-	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg, JH7100_CLK_PLL0_OUT), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
@@ -695,7 +613,7 @@ static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
 		struct clk_parent_data parents[4] = {};
 		struct clk_init_data init = {
 			.name = jh7100_clk_data[idx].name,
-			.ops = jh7100_clk_ops(max),
+			.ops = starfive_jh7100_clk_ops(max),
 			.parent_data = parents,
 			.num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1,
 			.flags = jh7100_clk_data[idx].flags,
drivers/clk/starfive/clk-starfive-jh7100.h new file +97 -0

97 lines not on this page · raw message

Signature · 1 line
2.34.1
maintainer Applied
#12 lore raw

Re: [PATCH v1 5/7] clk: starfive: jh7100: Make hw clock implementation reusable

Quoting Emil Renner Berthing (2022-01-26 09:39:51)

Quoted 7 lines

The JH7100 has additional audio and video clocks at different memory ranges, but they use the same register layout. Add a header and export the starfive_jh7100_clk_ops function so the clock implementation can be reused by drivers handling these clocks.

---

Applied to clk-next

author maintainer
#13 lore raw

PATCH 6/7 clk: starfive: jh7100: Support more clock types

In reply to Emil Renner Berthing

Unlike the system clocks there are audio clocks that combine both multiplexer/divider and gate/multiplexer/divider, so add support for that.

---
 drivers/clk/starfive/clk-starfive-jh7100.c | 26 ++++++++++++++++++++++
 drivers/clk/starfive/clk-starfive-jh7100.h | 15 +++++++++++++
 2 files changed, 41 insertions(+)
drivers/clk/starfive/clk-starfive-jh7100.c +26 -0
index a6708f9ebf4c..691aeebc7092 100644
@@ -534,6 +534,27 @@ static const struct clk_ops jh7100_clk_gmux_ops = {
 	.debug_init = jh7100_clk_debug_init,
 };
 
+static const struct clk_ops jh7100_clk_mdiv_ops = {
+	.recalc_rate = jh7100_clk_recalc_rate,
+	.determine_rate = jh7100_clk_determine_rate,
+	.get_parent = jh7100_clk_get_parent,
+	.set_parent = jh7100_clk_set_parent,
+	.set_rate = jh7100_clk_set_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_gmd_ops = {
+	.enable = jh7100_clk_enable,
+	.disable = jh7100_clk_disable,
+	.is_enabled = jh7100_clk_is_enabled,
+	.recalc_rate = jh7100_clk_recalc_rate,
+	.determine_rate = jh7100_clk_determine_rate,
+	.get_parent = jh7100_clk_get_parent,
+	.set_parent = jh7100_clk_set_parent,
+	.set_rate = jh7100_clk_set_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
 static const struct clk_ops jh7100_clk_inv_ops = {
 	.get_phase = jh7100_clk_get_phase,
 	.set_phase = jh7100_clk_set_phase,
@@ -543,6 +564,11 @@ static const struct clk_ops jh7100_clk_inv_ops = {
 const struct clk_ops *starfive_jh7100_clk_ops(u32 max)
 {
 	if (max & JH7100_CLK_DIV_MASK) {
+		if (max & JH7100_CLK_MUX_MASK) {
+			if (max & JH7100_CLK_ENABLE)
+				return &jh7100_clk_gmd_ops;
+			return &jh7100_clk_mdiv_ops;
+		}
 		if (max & JH7100_CLK_ENABLE)
 			return &jh7100_clk_gdiv_ops;
 		if (max == JH7100_CLK_FRAC_MAX)
drivers/clk/starfive/clk-starfive-jh7100.h +15 -0
index 8eccd8c0a746..f116be5740a5 100644
@@ -70,6 +70,21 @@ struct jh7100_clk_data {
 	.parents = { __VA_ARGS__ },						\
 }
 
+#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = {		\
+	.name = _name,								\
+	.flags = 0,								\
+	.max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
+	.parents = { __VA_ARGS__ },						\
+}
+
+#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = {	\
+	.name = _name,								\
+	.flags = _flags,							\
+	.max = JH7100_CLK_ENABLE |						\
+		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
+	.parents = { __VA_ARGS__ },						\
+}
+
 #define JH7100__INV(_idx, _name, _parent) [_idx] = {				\
 	.name = _name,								\
 	.flags = CLK_SET_RATE_PARENT,						\
Signature · 1 line
2.34.1
maintainer Applied
#14 lore raw

Re: [PATCH v1 6/7] clk: starfive: jh7100: Support more clock types

Quoting Emil Renner Berthing (2022-01-26 09:39:52)

Quoted 6 lines

Unlike the system clocks there are audio clocks that combine both multiplexer/divider and gate/multiplexer/divider, so add support for that.

---

Applied to clk-next

author maintainer
#15 lore raw

PATCH 7/7 clk: starfive: Add JH7100 audio clock driver

In reply to Emil Renner Berthing

Add a driver for the audio clocks on the Starfive JH7100 RISC-V SoC.

---
 MAINTAINERS                                   |   8 +-
 drivers/clk/starfive/Kconfig                  |   8 +
 drivers/clk/starfive/Makefile                 |   1 +
 .../clk/starfive/clk-starfive-jh7100-audio.c  | 170 ++++++++++++++++++
 4 files changed, 183 insertions(+), 4 deletions(-)
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100-audio.c
MAINTAINERS +4 -4
index ea3e6c914384..19a855f3fdca 100644
@@ -18376,12 +18376,12 @@ M:	Ion Badulescu <[email protected]>
 S:	Odd Fixes
 F:	drivers/net/ethernet/adaptec/starfire*
 
-STARFIVE JH7100 CLOCK DRIVER
+STARFIVE JH7100 CLOCK DRIVERS
 M:	Emil Renner Berthing <[email protected]>
 S:	Maintained
-F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
-F:	drivers/clk/starfive/clk-starfive-jh7100.c
-F:	include/dt-bindings/clock/starfive-jh7100.h
+F:	Documentation/devicetree/bindings/clock/starfive,jh7100-*.yaml
+F:	drivers/clk/starfive/clk-starfive-jh7100*
+F:	include/dt-bindings/clock/starfive-jh7100*.h
 
 STARFIVE JH7100 PINCTRL DRIVER
 M:	Emil Renner Berthing <[email protected]>
drivers/clk/starfive/Kconfig +8 -0
index c0fa9d5e641f..003bd2d56ce7 100644
@@ -7,3 +7,11 @@ config CLK_STARFIVE_JH7100
 	help
 	  Say yes here to support the clock controller on the StarFive JH7100
 	  SoC.
+
+config CLK_STARFIVE_JH7100_AUDIO
+	tristate "StarFive JH7100 audio clock support"
+	depends on CLK_STARFIVE_JH7100
+	default m if SOC_STARFIVE
+	help
+	  Say Y or M here to support the audio clocks on the StarFive JH7100
+	  SoC.
drivers/clk/starfive/Makefile +1 -0
index 09759cc73530..0fa8ecb9ec1c 100644
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 # StarFive Clock
 obj-$(CONFIG_CLK_STARFIVE_JH7100)	+= clk-starfive-jh7100.o
+obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO)	+= clk-starfive-jh7100-audio.o
drivers/clk/starfive/clk-starfive-jh7100-audio.c new file +170 -0

170 lines not on this page · raw message

Signature · 1 line
2.34.1
maintainer Applied
#16 lore raw

Re: [PATCH v1 7/7] clk: starfive: Add JH7100 audio clock driver

Quoting Emil Renner Berthing (2022-01-26 09:39:53)

Quoted 4 lines

Add a driver for the audio clocks on the Starfive JH7100 RISC-V SoC.

---

Applied to clk-next