linux-watchdog.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver
@ 2022-11-04 16:18 Jonathan Neuschäfer
  2022-11-04 16:18 ` [PATCH v5 1/6] dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks Jonathan Neuschäfer
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-11-04 16:18 UTC (permalink / raw)
  To: linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Daniel Lezcano, Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck,
	Guenter Roeck

This series adds support for the clock and reset controller in the Nuvoton
WPCM450 SoC. This means that the clock rates for peripherals will be calculated
automatically based on the clock tree as it was preconfigured by the bootloader.
The 24 MHz dummy clock, that is currently in the devicetree, is no longer needed.
Somewhat unfortunately, this also means that there is a breaking change once
the devicetree starts relying on the clock driver, but I find it acceptable in
this case, because WPCM450 is still at a somewhat early stage.


Upstreaming plan (although other suggestions are welcome):

Once reviewed,

- The ARM/dts changes should go through Joel Stanley's bmc tree
- The clocksource/timer changes should probably go via Daniel Lezcano and TIP
- The clock controller bindings and driver should go through the clk tree
- It probably makes sense to delay the final ARM/dts patch ("ARM: dts:
  wpcm450: Switch clocks to clock controller") until next cycle to make
  sure it is merged after the clock driver.


v5:
- Dropped patch 2 (watchdog: npcm: Enable clock if provided), which
  was since merged upstream
- Added patch 2 (clocksource: timer-npcm7xx: Enable timer 1 clock before use) again,
  because I wasn't able to find it in linux-next
- Switched the driver to using struct clk_parent_data
- Rebased on 6.1-rc3

v4:
- https://lore.kernel.org/lkml/20220610072141.347795-1-j.neuschaefer@gmx.net/
- Leave WDT clock running during after restart handler
- Fix reset controller initialization
- Dropped patch 2/7 (clocksource: timer-npcm7xx: Enable timer 1 clock before use),
  as it was applied by Daniel Lezcano

v3:
- https://lore.kernel.org/lkml/20220508194333.2170161-1-j.neuschaefer@gmx.net/
- Changed "refclk" string to "ref"
- Fixed some dead code in the driver
- Added clk_prepare_enable call to the watchdog restart handler
- Added a few review tags

v2:
- https://lore.kernel.org/lkml/20220429172030.398011-1-j.neuschaefer@gmx.net/
- various small improvements

v1:
- https://lore.kernel.org/lkml/20220422183012.444674-1-j.neuschaefer@gmx.net/

Jonathan Neuschäfer (6):
  dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks
  clocksource: timer-npcm7xx: Enable timer 1 clock before use
  dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
  ARM: dts: wpcm450: Add clock controller node
  clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
  [NOT FOR MERGE] ARM: dts: wpcm450: Switch clocks to clock controller

 .../bindings/clock/nuvoton,wpcm450-clk.yaml   |  66 +++
 .../bindings/timer/nuvoton,npcm7xx-timer.yaml |   8 +-
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi        |  29 +-
 drivers/clk/Makefile                          |   1 +
 drivers/clk/clk-wpcm450.c                     | 375 ++++++++++++++++++
 drivers/clocksource/timer-npcm7xx.c           |  10 +
 drivers/reset/Kconfig                         |   2 +-
 .../dt-bindings/clock/nuvoton,wpcm450-clk.h   |  67 ++++
 8 files changed, 549 insertions(+), 9 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/nuvoton,wpcm450-clk.yaml
 create mode 100644 drivers/clk/clk-wpcm450.c
 create mode 100644 include/dt-bindings/clock/nuvoton,wpcm450-clk.h

--
2.35.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v5 1/6] dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks
  2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
@ 2022-11-04 16:18 ` Jonathan Neuschäfer
  2022-11-04 16:18 ` [PATCH v5 2/6] clocksource: timer-npcm7xx: Enable timer 1 clock before use Jonathan Neuschäfer
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-11-04 16:18 UTC (permalink / raw)
  To: linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Daniel Lezcano, Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck,
	Guenter Roeck, Rob Herring, Krzysztof Kozlowski

The timer module contains multiple timers. In the WPCM450 SoC, each timer
runs off a clock can be gated individually. To model this correctly, the
timer node in the devicetree needs to take multiple clock inputs.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-by: Rob Herring <robh@kernel.org>
---

v4-5:
- no changes

v3:
- Add R-b tag

v2:
- no changes
---
 .../devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml  | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml b/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml
index 737af78ad70c3..d53e1bb98b8a6 100644
--- a/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml
@@ -25,7 +25,13 @@ properties:
       - description: The timer interrupt of timer 0

   clocks:
-    maxItems: 1
+    items:
+      - description: The reference clock for timer 0
+      - description: The reference clock for timer 1
+      - description: The reference clock for timer 2
+      - description: The reference clock for timer 3
+      - description: The reference clock for timer 4
+    minItems: 1

 required:
   - compatible
--
2.35.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 2/6] clocksource: timer-npcm7xx: Enable timer 1 clock before use
  2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
  2022-11-04 16:18 ` [PATCH v5 1/6] dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks Jonathan Neuschäfer
@ 2022-11-04 16:18 ` Jonathan Neuschäfer
  2022-11-04 16:18 ` [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-11-04 16:18 UTC (permalink / raw)
  To: linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Daniel Lezcano, Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck,
	Guenter Roeck

In the WPCM450 SoC, the clocks for each timer can be gated individually.
To prevent the timer 1 clock from being gated, enable it explicitly.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

Daniel Lezcano mentioned that he applied this patch, but I wasn't able
to find it in linux-next, so I'm sending it again.

v5:
- no changes relative to v3

v4:
- not included

v3:
- no changes

v2:
- Provide context in pr_warn message

v1:
- https://lore.kernel.org/lkml/20220422183012.444674-3-j.neuschaefer@gmx.net/
---
 drivers/clocksource/timer-npcm7xx.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clocksource/timer-npcm7xx.c b/drivers/clocksource/timer-npcm7xx.c
index a00520cbb660a..9af30af5f989a 100644
--- a/drivers/clocksource/timer-npcm7xx.c
+++ b/drivers/clocksource/timer-npcm7xx.c
@@ -188,6 +188,7 @@ static void __init npcm7xx_clocksource_init(void)

 static int __init npcm7xx_timer_init(struct device_node *np)
 {
+	struct clk *clk;
 	int ret;

 	ret = timer_of_init(np, &npcm7xx_to);
@@ -199,6 +200,15 @@ static int __init npcm7xx_timer_init(struct device_node *np)
 	npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
 		(NPCM7XX_Tx_MIN_PRESCALE + 1);

+	/* Enable the clock for timer1, if it exists */
+	clk = of_clk_get(np, 1);
+	if (clk) {
+		if (!IS_ERR(clk))
+			clk_prepare_enable(clk);
+		else
+			pr_warn("%pOF: Failed to get clock for timer1: %pe", np, clk);
+	}
+
 	npcm7xx_clocksource_init();
 	npcm7xx_clockevents_init();

--
2.35.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
  2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
  2022-11-04 16:18 ` [PATCH v5 1/6] dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks Jonathan Neuschäfer
  2022-11-04 16:18 ` [PATCH v5 2/6] clocksource: timer-npcm7xx: Enable timer 1 clock before use Jonathan Neuschäfer
@ 2022-11-04 16:18 ` Jonathan Neuschäfer
  2022-12-09 20:21   ` Stephen Boyd
  2022-11-04 16:18 ` [PATCH v5 4/6] ARM: dts: wpcm450: Add clock controller node Jonathan Neuschäfer
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-11-04 16:18 UTC (permalink / raw)
  To: linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Daniel Lezcano, Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck,
	Guenter Roeck, Krzysztof Kozlowski, Krzysztof Kozlowski

The Nuvoton WPCM450 SoC has a combined clock and reset controller.
Add a devicetree binding for it, as well as definitions for the bit
numbers used by it.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
v5:
- no changes

v4:
- https://lore.kernel.org/lkml/20220610072141.347795-4-j.neuschaefer@gmx.net/
- Add R-b tag

v3:
- Change clock-output-names and clock-names from "refclk" to "ref", suggested
  by Krzysztof Kozlowski

v2:
- https://lore.kernel.org/lkml/20220429172030.398011-5-j.neuschaefer@gmx.net/
- Various improvements, suggested by Krzysztof Kozlowski

v1:
- https://lore.kernel.org/lkml/20220422183012.444674-5-j.neuschaefer@gmx.net/
---
 .../bindings/clock/nuvoton,wpcm450-clk.yaml   | 66 ++++++++++++++++++
 .../dt-bindings/clock/nuvoton,wpcm450-clk.h   | 67 +++++++++++++++++++
 2 files changed, 133 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/nuvoton,wpcm450-clk.yaml
 create mode 100644 include/dt-bindings/clock/nuvoton,wpcm450-clk.h

diff --git a/Documentation/devicetree/bindings/clock/nuvoton,wpcm450-clk.yaml b/Documentation/devicetree/bindings/clock/nuvoton,wpcm450-clk.yaml
new file mode 100644
index 0000000000000..525024a58df4c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nuvoton,wpcm450-clk.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/nuvoton,wpcm450-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton WPCM450 clock controller
+
+maintainers:
+  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+
+description:
+  The clock controller of the Nuvoton WPCM450 SoC supplies clocks and resets to
+  the rest of the chip.
+
+properties:
+  compatible:
+    const: nuvoton,wpcm450-clk
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Reference clock oscillator (should be 48 MHz)
+
+  clock-names:
+    items:
+      - const: ref
+
+  '#clock-cells':
+    const: 1
+
+  '#reset-cells':
+    const: 1
+
+additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+examples:
+  - |
+    #include <dt-bindings/clock/nuvoton,wpcm450-clk.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    refclk: clock-48mhz {
+      /* 48 MHz reference oscillator */
+      compatible = "fixed-clock";
+      clock-output-names = "ref";
+      clock-frequency = <48000000>;
+      #clock-cells = <0>;
+    };
+
+    clk: clock-controller@b0000200 {
+      reg = <0xb0000200 0x100>;
+      compatible = "nuvoton,wpcm450-clk";
+      clocks = <&refclk>;
+      clock-names = "ref";
+      #clock-cells = <1>;
+      #reset-cells = <1>;
+    };
diff --git a/include/dt-bindings/clock/nuvoton,wpcm450-clk.h b/include/dt-bindings/clock/nuvoton,wpcm450-clk.h
new file mode 100644
index 0000000000000..86e1c895921b7
--- /dev/null
+++ b/include/dt-bindings/clock/nuvoton,wpcm450-clk.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef _DT_BINDINGS_CLOCK_NUVOTON_WPCM450_CLK_H
+#define _DT_BINDINGS_CLOCK_NUVOTON_WPCM450_CLK_H
+
+/* Clocks based on CLKEN bits */
+#define WPCM450_CLK_FIU            0
+#define WPCM450_CLK_XBUS           1
+#define WPCM450_CLK_KCS            2
+#define WPCM450_CLK_SHM            4
+#define WPCM450_CLK_USB1           5
+#define WPCM450_CLK_EMC0           6
+#define WPCM450_CLK_EMC1           7
+#define WPCM450_CLK_USB0           8
+#define WPCM450_CLK_PECI           9
+#define WPCM450_CLK_AES           10
+#define WPCM450_CLK_UART0         11
+#define WPCM450_CLK_UART1         12
+#define WPCM450_CLK_SMB2          13
+#define WPCM450_CLK_SMB3          14
+#define WPCM450_CLK_SMB4          15
+#define WPCM450_CLK_SMB5          16
+#define WPCM450_CLK_HUART         17
+#define WPCM450_CLK_PWM           18
+#define WPCM450_CLK_TIMER0        19
+#define WPCM450_CLK_TIMER1        20
+#define WPCM450_CLK_TIMER2        21
+#define WPCM450_CLK_TIMER3        22
+#define WPCM450_CLK_TIMER4        23
+#define WPCM450_CLK_MFT0          24
+#define WPCM450_CLK_MFT1          25
+#define WPCM450_CLK_WDT           26
+#define WPCM450_CLK_ADC           27
+#define WPCM450_CLK_SDIO          28
+#define WPCM450_CLK_SSPI          29
+#define WPCM450_CLK_SMB0          30
+#define WPCM450_CLK_SMB1          31
+
+/* Other clocks */
+#define WPCM450_CLK_USBPHY        32
+
+#define WPCM450_NUM_CLKS          33
+
+/* Resets based on IPSRST bits */
+#define WPCM450_RESET_FIU          0
+#define WPCM450_RESET_EMC0         6
+#define WPCM450_RESET_EMC1         7
+#define WPCM450_RESET_USB0         8
+#define WPCM450_RESET_USB1         9
+#define WPCM450_RESET_AES_PECI    10
+#define WPCM450_RESET_UART        11
+#define WPCM450_RESET_MC          12
+#define WPCM450_RESET_SMB2        13
+#define WPCM450_RESET_SMB3        14
+#define WPCM450_RESET_SMB4        15
+#define WPCM450_RESET_SMB5        16
+#define WPCM450_RESET_PWM         18
+#define WPCM450_RESET_TIMER       19
+#define WPCM450_RESET_ADC         27
+#define WPCM450_RESET_SDIO        28
+#define WPCM450_RESET_SSPI        29
+#define WPCM450_RESET_SMB0        30
+#define WPCM450_RESET_SMB1        31
+
+#define WPCM450_NUM_RESETS        32
+
+#endif /* _DT_BINDINGS_CLOCK_NUVOTON_WPCM450_CLK_H */
--
2.35.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 4/6] ARM: dts: wpcm450: Add clock controller node
  2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
                   ` (2 preceding siblings ...)
  2022-11-04 16:18 ` [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
@ 2022-11-04 16:18 ` Jonathan Neuschäfer
  2022-11-04 16:18 ` [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-11-04 16:18 UTC (permalink / raw)
  To: linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Daniel Lezcano, Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck,
	Guenter Roeck, Krzysztof Kozlowski

This declares the clock controller and the necessary 48 Mhz reference
clock in the WPCM450 device. Switching devices over to the clock
controller is intentionally done in a separate patch to give time for
the clock controller driver to land.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

v4-5:
- no changes

v3:
- Change clock-output-names and clock-names from "refclk" to "ref"

v2:
- https://lore.kernel.org/lkml/20220429172030.398011-6-j.neuschaefer@gmx.net/
- no changes
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index b9b669cd632f1..332cc222c7dc5 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -37,6 +37,14 @@ clk24m: clock-24mhz {
 		#clock-cells = <0>;
 	};

+	refclk: clock-48mhz {
+		/* 48 MHz reference oscillator */
+		compatible = "fixed-clock";
+		clock-output-names = "ref";
+		clock-frequency = <48000000>;
+		#clock-cells = <0>;
+	};
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -49,6 +57,15 @@ gcr: syscon@b0000000 {
 			reg = <0xb0000000 0x200>;
 		};

+		clk: clock-controller@b0000200 {
+			compatible = "nuvoton,wpcm450-clk";
+			reg = <0xb0000200 0x100>;
+			clocks = <&refclk>;
+			clock-names = "ref";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
 		serial0: serial@b8000000 {
 			compatible = "nuvoton,wpcm450-uart";
 			reg = <0xb8000000 0x20>;
--
2.35.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
  2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
                   ` (3 preceding siblings ...)
  2022-11-04 16:18 ` [PATCH v5 4/6] ARM: dts: wpcm450: Add clock controller node Jonathan Neuschäfer
@ 2022-11-04 16:18 ` Jonathan Neuschäfer
  2022-12-09 20:21   ` Stephen Boyd
  2022-12-12  7:30   ` Tomer Maimon
  2022-11-04 16:18 ` [PATCH v5 6/6] [NOT FOR MERGE] ARM: dts: wpcm450: Switch clocks to clock controller Jonathan Neuschäfer
  2022-11-22  1:40 ` [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Joel Stanley
  6 siblings, 2 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-11-04 16:18 UTC (permalink / raw)
  To: linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Daniel Lezcano, Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck,
	Guenter Roeck

This driver implements the following features w.r.t. the clock and reset
controller in the WPCM450 SoC:

- It calculates the rates for all clocks managed by the clock controller
- It leaves the clock tree mostly unchanged, except that it enables/
  disables clock gates based on usage.
- It exposes the reset lines managed by the controller using the
  Generic Reset Controller subsystem

NOTE: If the driver and the corresponding devicetree node are present,
      the driver will disable "unused" clocks. This is problem until
      the clock relations are properly declared in the devicetree (in a
      later patch). Until then, the clk_ignore_unused kernel parameter
      can be used as a workaround.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

v5:
- Switch to using clk_parent_data

v4:
- https://lore.kernel.org/lkml/20220610072141.347795-6-j.neuschaefer@gmx.net/
- Fix reset controller initialization

v3:
- https://lore.kernel.org/lkml/20220508194333.2170161-7-j.neuschaefer@gmx.net/
- Change reference clock name from "refclk" to "ref"
- Remove unused variable in return path of wpcm450_clk_register_pll
- Remove unused divisor tables

v2:
- https://lore.kernel.org/lkml/20220429172030.398011-7-j.neuschaefer@gmx.net/
- no changes
---
 drivers/clk/Makefile      |   1 +
 drivers/clk/clk-wpcm450.c | 375 ++++++++++++++++++++++++++++++++++++++
 drivers/reset/Kconfig     |   2 +-
 3 files changed, 377 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/clk-wpcm450.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index e3ca0d058a256..b58352d4d615d 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_COMMON_CLK_RS9_PCIE)	+= clk-renesas-pcie.o
 obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
 obj-$(CONFIG_COMMON_CLK_VC7)		+= clk-versaclock7.o
 obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
+obj-$(CONFIG_ARCH_WPCM450)		+= clk-wpcm450.o
 obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o

 # please keep this section sorted lexicographically by directory path name
diff --git a/drivers/clk/clk-wpcm450.c b/drivers/clk/clk-wpcm450.c
new file mode 100644
index 0000000000000..b5e81b3b6b982
--- /dev/null
+++ b/drivers/clk/clk-wpcm450.c
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Nuvoton WPCM450 clock and reset controller driver.
+ *
+ * Copyright (C) 2022 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/reset-controller.h>
+#include <linux/reset/reset-simple.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/nuvoton,wpcm450-clk.h>
+
+struct wpcm450_clk_pll {
+	struct clk_hw hw;
+	void __iomem *pllcon;
+	u8 flags;
+};
+
+#define to_wpcm450_clk_pll(_hw) container_of(_hw, struct wpcm450_clk_pll, hw)
+
+#define PLLCON_FBDV	GENMASK(24, 16)
+#define PLLCON_PRST	BIT(13)
+#define PLLCON_PWDEN	BIT(12)
+#define PLLCON_OTDV	GENMASK(10, 8)
+#define PLLCON_INDV	GENMASK(5, 0)
+
+static unsigned long wpcm450_clk_pll_recalc_rate(struct clk_hw *hw,
+						 unsigned long parent_rate)
+{
+	struct wpcm450_clk_pll *pll = to_wpcm450_clk_pll(hw);
+	unsigned long fbdv, indv, otdv;
+	u64 rate;
+	u32 pllcon;
+
+	if (parent_rate == 0) {
+		pr_err("%s: parent rate is zero", __func__);
+		return 0;
+	}
+
+	pllcon = readl_relaxed(pll->pllcon);
+
+	indv = FIELD_GET(PLLCON_INDV, pllcon) + 1;
+	fbdv = FIELD_GET(PLLCON_FBDV, pllcon) + 1;
+	otdv = FIELD_GET(PLLCON_OTDV, pllcon) + 1;
+
+	rate = (u64)parent_rate * fbdv;
+	do_div(rate, indv * otdv);
+
+	return rate;
+}
+
+static int wpcm450_clk_pll_is_enabled(struct clk_hw *hw)
+{
+	struct wpcm450_clk_pll *pll = to_wpcm450_clk_pll(hw);
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->pllcon);
+
+	return !(pllcon & PLLCON_PRST);
+}
+
+static void wpcm450_clk_pll_disable(struct clk_hw *hw)
+{
+	struct wpcm450_clk_pll *pll = to_wpcm450_clk_pll(hw);
+	u32 pllcon;
+
+	pllcon = readl_relaxed(pll->pllcon);
+	pllcon |= PLLCON_PRST | PLLCON_PWDEN;
+	writel(pllcon, pll->pllcon);
+}
+
+static const struct clk_ops wpcm450_clk_pll_ops = {
+	.recalc_rate = wpcm450_clk_pll_recalc_rate,
+	.is_enabled = wpcm450_clk_pll_is_enabled,
+	.disable = wpcm450_clk_pll_disable
+};
+
+static struct clk_hw *
+wpcm450_clk_register_pll(void __iomem *pllcon, const char *name,
+			 const struct clk_parent_data *parent, unsigned long flags)
+{
+	struct wpcm450_clk_pll *pll;
+	struct clk_init_data init = {};
+	int ret;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &wpcm450_clk_pll_ops;
+	init.parent_data = parent;
+	init.num_parents = 1;
+	init.flags = flags;
+
+	pll->pllcon = pllcon;
+	pll->hw.init = &init;
+
+	ret = clk_hw_register(NULL, &pll->hw);
+	if (ret) {
+		kfree(pll);
+		return ERR_PTR(ret);
+	}
+
+	return &pll->hw;
+}
+
+#define REG_CLKEN	0x00
+#define REG_CLKSEL	0x04
+#define REG_CLKDIV	0x08
+#define REG_PLLCON0	0x0c
+#define REG_PLLCON1	0x10
+#define REG_PMCON	0x14
+#define REG_IRQWAKECON	0x18
+#define REG_IRQWAKEFLAG	0x1c
+#define REG_IPSRST	0x20
+
+struct wpcm450_pll_data {
+	const char *name;
+	struct clk_parent_data parent;
+	unsigned int reg;
+	unsigned long flags;
+};
+
+static const struct wpcm450_pll_data pll_data[] = {
+	{ "pll0", { .name = "ref" }, REG_PLLCON0, 0 },
+	{ "pll1", { .name = "ref" }, REG_PLLCON1, 0 },
+};
+
+struct wpcm450_clksel_data {
+	const char *name;
+	const struct clk_parent_data *parents;
+	unsigned int num_parents;
+	const u32 *table;
+	int shift;
+	int width;
+	int index;
+	unsigned long flags;
+};
+
+static const u32 parent_table[] = { 0, 1, 2 };
+
+static const struct clk_parent_data default_parents[] = {
+	{ .name = "pll0" },
+	{ .name = "pll1" },
+	{ .name = "ref" },
+};
+
+static const struct clk_parent_data huart_parents[] = {
+	{ .name = "ref" },
+	{ .name = "refdiv2" },
+};
+
+static const struct wpcm450_clksel_data clksel_data[] = {
+	{ "cpusel", default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 0, 2, -1, CLK_IS_CRITICAL },
+	{ "clkout", default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 2, 2, -1, 0 },
+	{ "usbphy", default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 6, 2, -1, 0 },
+	{ "uartsel", default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 8, 2, WPCM450_CLK_USBPHY, 0 },
+	{ "huartsel", huart_parents, ARRAY_SIZE(huart_parents),
+		parent_table, 10, 1, -1, 0 },
+};
+
+static const struct clk_div_table div_fixed2[] = {
+	{ .val = 0, .div = 2 },
+	{ }
+};
+
+struct wpcm450_clkdiv_data {
+	const char *name;
+	struct clk_parent_data parent;
+	int div_flags;
+	const struct clk_div_table *table;
+	int shift;
+	int width;
+	unsigned long flags;
+};
+
+static struct wpcm450_clkdiv_data clkdiv_data_early[] = {
+	{ "refdiv2", { .name = "ref" }, 0, div_fixed2, 0, 0 },
+};
+
+static const struct wpcm450_clkdiv_data clkdiv_data[] = {
+	{ "cpu", { .name = "cpusel" }, 0, div_fixed2, 0, 0, CLK_IS_CRITICAL },
+	{ "adcdiv", { .name = "ref" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 28, 2, 0 },
+	{ "apb", { .name = "ahb" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 26, 2, 0 },
+	{ "ahb", { .name = "cpu" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 24, 2, 0 },
+	{ "uart", { .name = "uartsel" }, 0, NULL, 16, 4, 0 },
+	{ "ahb3", { .name = "ahb" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 8, 2, 0 },
+};
+
+struct wpcm450_clken_data {
+	const char *name;
+	struct clk_parent_data parent;
+	int bitnum;
+	unsigned long flags;
+};
+
+static const struct wpcm450_clken_data clken_data[] = {
+	{ "fiu", { .name = "ahb3" }, WPCM450_CLK_FIU, 0 },
+	{ "xbus", { .name = "ahb3" }, WPCM450_CLK_XBUS, 0 },
+	{ "kcs", { .name = "apb" }, WPCM450_CLK_KCS, 0 },
+	{ "shm", { .name = "ahb3" }, WPCM450_CLK_SHM, 0 },
+	{ "usb1", { .name = "ahb" }, WPCM450_CLK_USB1, 0 },
+	{ "emc0", { .name = "ahb" }, WPCM450_CLK_EMC0, 0 },
+	{ "emc1", { .name = "ahb" }, WPCM450_CLK_EMC1, 0 },
+	{ "usb0", { .name = "ahb" }, WPCM450_CLK_USB0, 0 },
+	{ "peci", { .name = "apb" }, WPCM450_CLK_PECI, 0 },
+	{ "aes", { .name = "apb" }, WPCM450_CLK_AES, 0 },
+	{ "uart0", { .name = "uart" }, WPCM450_CLK_UART0, 0 },
+	{ "uart1", { .name = "uart" }, WPCM450_CLK_UART1, 0 },
+	{ "smb2", { .name = "apb" }, WPCM450_CLK_SMB2, 0 },
+	{ "smb3", { .name = "apb" }, WPCM450_CLK_SMB3, 0 },
+	{ "smb4", { .name = "apb" }, WPCM450_CLK_SMB4, 0 },
+	{ "smb5", { .name = "apb" }, WPCM450_CLK_SMB5, 0 },
+	{ "huart", { .name = "huartsel" }, WPCM450_CLK_HUART, 0 },
+	{ "pwm", { .name = "apb" }, WPCM450_CLK_PWM, 0 },
+	{ "timer0", { .name = "refdiv2" }, WPCM450_CLK_TIMER0, 0 },
+	{ "timer1", { .name = "refdiv2" }, WPCM450_CLK_TIMER1, 0 },
+	{ "timer2", { .name = "refdiv2" }, WPCM450_CLK_TIMER2, 0 },
+	{ "timer3", { .name = "refdiv2" }, WPCM450_CLK_TIMER3, 0 },
+	{ "timer4", { .name = "refdiv2" }, WPCM450_CLK_TIMER4, 0 },
+	{ "mft0", { .name = "apb" }, WPCM450_CLK_MFT0, 0 },
+	{ "mft1", { .name = "apb" }, WPCM450_CLK_MFT1, 0 },
+	{ "wdt", { .name = "refdiv2" }, WPCM450_CLK_WDT, 0 },
+	{ "adc", { .name = "adcdiv" }, WPCM450_CLK_ADC, 0 },
+	{ "sdio", { .name = "ahb" }, WPCM450_CLK_SDIO, 0 },
+	{ "sspi", { .name = "apb" }, WPCM450_CLK_SSPI, 0 },
+	{ "smb0", { .name = "apb" }, WPCM450_CLK_SMB0, 0 },
+	{ "smb1", { .name = "apb" }, WPCM450_CLK_SMB1, 0 },
+};
+
+static DEFINE_SPINLOCK(wpcm450_clk_lock);
+
+static void __init wpcm450_clk_init(struct device_node *clk_np)
+{
+	struct clk_hw_onecell_data *clk_data;
+	static struct clk_hw **hws;
+	static struct clk_hw *hw;
+	void __iomem *clk_base;
+	int i, ret;
+	struct reset_simple_data *reset;
+
+	clk_base = of_iomap(clk_np, 0);
+	if (!clk_base) {
+		pr_err("%pOFP: failed to map registers\n", clk_np);
+		of_node_put(clk_np);
+		return;
+	}
+	of_node_put(clk_np);
+
+	clk_data = kzalloc(struct_size(clk_data, hws, WPCM450_NUM_CLKS), GFP_KERNEL);
+	if (!clk_data)
+		goto err_unmap;
+
+	clk_data->num = WPCM450_NUM_CLKS;
+	hws = clk_data->hws;
+
+	for (i = 0; i < WPCM450_NUM_CLKS; i++)
+		hws[i] = ERR_PTR(-ENOENT);
+
+	// PLLs
+	for (i = 0; i < ARRAY_SIZE(pll_data); i++) {
+		const struct wpcm450_pll_data *data = &pll_data[i];
+
+		hw = wpcm450_clk_register_pll(clk_base + data->reg, data->name,
+					      &data->parent, data->flags);
+		if (IS_ERR(hw)) {
+			pr_info("Failed to register PLL: %pe", hw);
+			goto err_free;
+		}
+	}
+
+	// Early divisors (REF/2)
+	for (i = 0; i < ARRAY_SIZE(clkdiv_data_early); i++) {
+		const struct wpcm450_clkdiv_data *data = &clkdiv_data_early[i];
+
+		hw = clk_hw_register_divider_table_parent_data(NULL, data->name, &data->parent,
+							       data->flags, clk_base + REG_CLKDIV,
+							       data->shift, data->width,
+							       data->div_flags, data->table,
+							       &wpcm450_clk_lock);
+		if (IS_ERR(hw)) {
+			pr_err("Failed to register div table: %pe\n", hw);
+			goto err_free;
+		}
+	}
+
+	// Selects/muxes
+	for (i = 0; i < ARRAY_SIZE(clksel_data); i++) {
+		const struct wpcm450_clksel_data *data = &clksel_data[i];
+
+		hw = clk_hw_register_mux_parent_data(NULL, data->name, data->parents,
+						     data->num_parents, data->flags,
+						     clk_base + REG_CLKSEL, data->shift,
+						     data->width, 0,
+						     &wpcm450_clk_lock);
+		if (IS_ERR(hw)) {
+			pr_err("Failed to register mux: %pe\n", hw);
+			goto err_free;
+		}
+		if (data->index >= 0)
+			clk_data->hws[data->index] = hw;
+	}
+
+	// Divisors
+	for (i = 0; i < ARRAY_SIZE(clkdiv_data); i++) {
+		const struct wpcm450_clkdiv_data *data = &clkdiv_data[i];
+
+		hw = clk_hw_register_divider_table_parent_data(NULL, data->name, &data->parent,
+							       data->flags, clk_base + REG_CLKDIV,
+							       data->shift, data->width,
+							       data->div_flags, data->table,
+							       &wpcm450_clk_lock);
+		if (IS_ERR(hw)) {
+			pr_err("Failed to register divider: %pe\n", hw);
+			goto err_free;
+		}
+	}
+
+	// Enables/gates
+	for (i = 0; i < ARRAY_SIZE(clken_data); i++) {
+		const struct wpcm450_clken_data *data = &clken_data[i];
+
+		hw = clk_hw_register_gate_parent_data(NULL, data->name, &data->parent, data->flags,
+						      clk_base + REG_CLKEN, data->bitnum,
+						      data->flags, &wpcm450_clk_lock);
+		if (IS_ERR(hw)) {
+			pr_err("Failed to register gate: %pe\n", hw);
+			goto err_free;
+		}
+		clk_data->hws[data->bitnum] = hw;
+	}
+
+	ret = of_clk_add_hw_provider(clk_np, of_clk_hw_onecell_get, clk_data);
+	if (ret)
+		pr_err("Failed to add DT provider: %d\n", ret);
+
+	// Reset controller
+	reset = kzalloc(sizeof(*reset), GFP_KERNEL);
+	if (!reset)
+		goto err_free;
+	reset->rcdev.owner = THIS_MODULE;
+	reset->rcdev.nr_resets = WPCM450_NUM_RESETS;
+	reset->rcdev.ops = &reset_simple_ops;
+	reset->rcdev.of_node = clk_np;
+	reset->membase = clk_base + REG_IPSRST;
+	ret = reset_controller_register(&reset->rcdev);
+	if (ret)
+		pr_err("Failed to register reset controller: %d\n", ret);
+
+	of_node_put(clk_np);
+	return;
+
+err_free:
+	kfree(clk_data->hws);
+err_unmap:
+	iounmap(clk_base);
+	of_node_put(clk_np);
+}
+
+CLK_OF_DECLARE(wpcm450_clk_init, "nuvoton,wpcm450-clk", wpcm450_clk_init);
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index de176c2fbad96..de5662830fce8 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -208,7 +208,7 @@ config RESET_SCMI

 config RESET_SIMPLE
 	bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
-	default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
+	default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC || ARCH_NPCM
 	depends on HAS_IOMEM
 	help
 	  This enables a simple reset controller driver for reset lines that
--
2.35.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 6/6] [NOT FOR MERGE] ARM: dts: wpcm450: Switch clocks to clock controller
  2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
                   ` (4 preceding siblings ...)
  2022-11-04 16:18 ` [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
@ 2022-11-04 16:18 ` Jonathan Neuschäfer
  2022-11-22  1:40 ` [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Joel Stanley
  6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-11-04 16:18 UTC (permalink / raw)
  To: linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tomer Maimon,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair,
	Daniel Lezcano, Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck,
	Guenter Roeck, Krzysztof Kozlowski

This change is incompatible with older kernels because it requires the
clock controller driver, but I think that's acceptable because WPCM450
support is generally still in an early phase.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

This patch is currently only for demonstration purposes, as it will
break the build if applied in parallel (going through different
maintainer trees) with the other patches in this series.
I will resend it once the other patches have been merged.

v2-v5:
- no changes
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index 332cc222c7dc5..439f9047ad651 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -2,6 +2,7 @@
 // Copyright 2021 Jonathan Neuschäfer

 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/clock/nuvoton,wpcm450-clk.h>

 / {
 	compatible = "nuvoton,wpcm450";
@@ -30,13 +31,6 @@ cpu@0 {
 		};
 	};

-	clk24m: clock-24mhz {
-		/* 24 MHz dummy clock */
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		#clock-cells = <0>;
-	};
-
 	refclk: clock-48mhz {
 		/* 48 MHz reference oscillator */
 		compatible = "fixed-clock";
@@ -71,7 +65,7 @@ serial0: serial@b8000000 {
 			reg = <0xb8000000 0x20>;
 			reg-shift = <2>;
 			interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clk24m>;
+			clocks = <&clk WPCM450_CLK_UART0>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&bsp_pins>;
 			status = "disabled";
@@ -82,7 +76,7 @@ serial1: serial@b8000100 {
 			reg = <0xb8000100 0x20>;
 			reg-shift = <2>;
 			interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clk24m>;
+			clocks = <&clk WPCM450_CLK_UART1>;
 			status = "disabled";
 		};

@@ -90,14 +84,18 @@ timer0: timer@b8001000 {
 			compatible = "nuvoton,wpcm450-timer";
 			interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
 			reg = <0xb8001000 0x1c>;
-			clocks = <&clk24m>;
+			clocks = <&clk WPCM450_CLK_TIMER0>,
+				 <&clk WPCM450_CLK_TIMER1>,
+				 <&clk WPCM450_CLK_TIMER2>,
+				 <&clk WPCM450_CLK_TIMER3>,
+				 <&clk WPCM450_CLK_TIMER4>;
 		};

 		watchdog0: watchdog@b800101c {
 			compatible = "nuvoton,wpcm450-wdt";
 			interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
 			reg = <0xb800101c 0x4>;
-			clocks = <&clk24m>;
+			clocks = <&clk WPCM450_CLK_WDT>;
 		};

 		aic: interrupt-controller@b8002000 {
--
2.35.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver
  2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
                   ` (5 preceding siblings ...)
  2022-11-04 16:18 ` [PATCH v5 6/6] [NOT FOR MERGE] ARM: dts: wpcm450: Switch clocks to clock controller Jonathan Neuschäfer
@ 2022-11-22  1:40 ` Joel Stanley
  2022-11-22  8:09   ` Daniel Lezcano
  6 siblings, 1 reply; 16+ messages in thread
From: Joel Stanley @ 2022-11-22  1:40 UTC (permalink / raw)
  To: Jonathan Neuschäfer, Stephen Boyd, Arnd Bergmann
  Cc: linux-clk, openbmc, devicetree, Wim Van Sebroeck, linux-watchdog,
	Patrick Venture, Michael Turquette, Daniel Lezcano, linux-kernel,
	Avi Fishman, Rob Herring, Benjamin Fair, Philipp Zabel,
	Krzysztof Kozlowski, Tali Perry, Thomas Gleixner, Guenter Roeck,
	Tomer Maimon

On Fri, 4 Nov 2022 at 16:21, Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
>
> This series adds support for the clock and reset controller in the Nuvoton
> WPCM450 SoC. This means that the clock rates for peripherals will be calculated
> automatically based on the clock tree as it was preconfigured by the bootloader.
> The 24 MHz dummy clock, that is currently in the devicetree, is no longer needed.
> Somewhat unfortunately, this also means that there is a breaking change once
> the devicetree starts relying on the clock driver, but I find it acceptable in
> this case, because WPCM450 is still at a somewhat early stage.

Reviewed-by: Joel Stanley <joel@jms.id.au>

>
>
> Upstreaming plan (although other suggestions are welcome):
>
> Once reviewed,
>
> - The ARM/dts changes should go through Joel Stanley's bmc tree

I've picked up the standalone patch ("Add clock controller node").

> - The clocksource/timer changes should probably go via Daniel Lezcano and TIP
> - The clock controller bindings and driver should go through the clk tree

Stephen, do you plan on merging this driver for v6.2?

Alternatively, could we get an ack from you and merge this entire
series through Arnd, where we have precedent for merging these initial
support cross-tree patch sets?



> - It probably makes sense to delay the final ARM/dts patch ("ARM: dts:
>   wpcm450: Switch clocks to clock controller") until next cycle to make
>   sure it is merged after the clock driver.
>
>
> v5:
> - Dropped patch 2 (watchdog: npcm: Enable clock if provided), which
>   was since merged upstream
> - Added patch 2 (clocksource: timer-npcm7xx: Enable timer 1 clock before use) again,
>   because I wasn't able to find it in linux-next
> - Switched the driver to using struct clk_parent_data
> - Rebased on 6.1-rc3
>
> v4:
> - https://lore.kernel.org/lkml/20220610072141.347795-1-j.neuschaefer@gmx.net/
> - Leave WDT clock running during after restart handler
> - Fix reset controller initialization
> - Dropped patch 2/7 (clocksource: timer-npcm7xx: Enable timer 1 clock before use),
>   as it was applied by Daniel Lezcano
>
> v3:
> - https://lore.kernel.org/lkml/20220508194333.2170161-1-j.neuschaefer@gmx.net/
> - Changed "refclk" string to "ref"
> - Fixed some dead code in the driver
> - Added clk_prepare_enable call to the watchdog restart handler
> - Added a few review tags
>
> v2:
> - https://lore.kernel.org/lkml/20220429172030.398011-1-j.neuschaefer@gmx.net/
> - various small improvements
>
> v1:
> - https://lore.kernel.org/lkml/20220422183012.444674-1-j.neuschaefer@gmx.net/
>
> Jonathan Neuschäfer (6):
>   dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks
>   clocksource: timer-npcm7xx: Enable timer 1 clock before use
>   dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
>   ARM: dts: wpcm450: Add clock controller node
>   clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
>   [NOT FOR MERGE] ARM: dts: wpcm450: Switch clocks to clock controller
>
>  .../bindings/clock/nuvoton,wpcm450-clk.yaml   |  66 +++
>  .../bindings/timer/nuvoton,npcm7xx-timer.yaml |   8 +-
>  arch/arm/boot/dts/nuvoton-wpcm450.dtsi        |  29 +-
>  drivers/clk/Makefile                          |   1 +
>  drivers/clk/clk-wpcm450.c                     | 375 ++++++++++++++++++
>  drivers/clocksource/timer-npcm7xx.c           |  10 +
>  drivers/reset/Kconfig                         |   2 +-
>  .../dt-bindings/clock/nuvoton,wpcm450-clk.h   |  67 ++++
>  8 files changed, 549 insertions(+), 9 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/clock/nuvoton,wpcm450-clk.yaml
>  create mode 100644 drivers/clk/clk-wpcm450.c
>  create mode 100644 include/dt-bindings/clock/nuvoton,wpcm450-clk.h
>
> --
> 2.35.1
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver
  2022-11-22  1:40 ` [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Joel Stanley
@ 2022-11-22  8:09   ` Daniel Lezcano
  0 siblings, 0 replies; 16+ messages in thread
From: Daniel Lezcano @ 2022-11-22  8:09 UTC (permalink / raw)
  To: Joel Stanley, Jonathan Neuschäfer, Stephen Boyd, Arnd Bergmann
  Cc: linux-clk, openbmc, devicetree, Wim Van Sebroeck, linux-watchdog,
	Patrick Venture, Michael Turquette, linux-kernel, Avi Fishman,
	Rob Herring, Benjamin Fair, Philipp Zabel, Krzysztof Kozlowski,
	Tali Perry, Thomas Gleixner, Guenter Roeck, Tomer Maimon

On 22/11/2022 02:40, Joel Stanley wrote:
> On Fri, 4 Nov 2022 at 16:21, Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
>>
>> This series adds support for the clock and reset controller in the Nuvoton
>> WPCM450 SoC. This means that the clock rates for peripherals will be calculated
>> automatically based on the clock tree as it was preconfigured by the bootloader.
>> The 24 MHz dummy clock, that is currently in the devicetree, is no longer needed.
>> Somewhat unfortunately, this also means that there is a breaking change once
>> the devicetree starts relying on the clock driver, but I find it acceptable in
>> this case, because WPCM450 is still at a somewhat early stage.
> 
> Reviewed-by: Joel Stanley <joel@jms.id.au>
> 
>>
>>
>> Upstreaming plan (although other suggestions are welcome):
>>
>> Once reviewed,
>>
>> - The ARM/dts changes should go through Joel Stanley's bmc tree
> 
> I've picked up the standalone patch ("Add clock controller node").
> 
>> - The clocksource/timer changes should probably go via Daniel Lezcano and TIP

I picked the timer change along with the binding

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
  2022-11-04 16:18 ` [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
@ 2022-12-09 20:21   ` Stephen Boyd
  2023-04-12 19:13     ` Jonathan Neuschäfer
  0 siblings, 1 reply; 16+ messages in thread
From: Stephen Boyd @ 2022-12-09 20:21 UTC (permalink / raw)
  To: Jonathan Neuschäfer, linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Rob Herring,
	Krzysztof Kozlowski, Avi Fishman, Tomer Maimon, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair, Daniel Lezcano,
	Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck, Guenter Roeck,
	Krzysztof Kozlowski, Krzysztof Kozlowski

Quoting Jonathan Neuschäfer (2022-11-04 09:18:47)
> The Nuvoton WPCM450 SoC has a combined clock and reset controller.
> Add a devicetree binding for it, as well as definitions for the bit
> numbers used by it.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---

Applied to clk-next

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
  2022-11-04 16:18 ` [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
@ 2022-12-09 20:21   ` Stephen Boyd
  2022-12-12  7:30   ` Tomer Maimon
  1 sibling, 0 replies; 16+ messages in thread
From: Stephen Boyd @ 2022-12-09 20:21 UTC (permalink / raw)
  To: Jonathan Neuschäfer, linux-clk, openbmc
  Cc: linux-kernel, linux-watchdog, devicetree,
	Jonathan Neuschäfer, Michael Turquette, Rob Herring,
	Krzysztof Kozlowski, Avi Fishman, Tomer Maimon, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair, Daniel Lezcano,
	Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck, Guenter Roeck

Quoting Jonathan Neuschäfer (2022-11-04 09:18:49)
> This driver implements the following features w.r.t. the clock and reset
> controller in the WPCM450 SoC:
> 
> - It calculates the rates for all clocks managed by the clock controller
> - It leaves the clock tree mostly unchanged, except that it enables/
>   disables clock gates based on usage.
> - It exposes the reset lines managed by the controller using the
>   Generic Reset Controller subsystem
> 
> NOTE: If the driver and the corresponding devicetree node are present,
>       the driver will disable "unused" clocks. This is problem until
>       the clock relations are properly declared in the devicetree (in a
>       later patch). Until then, the clk_ignore_unused kernel parameter
>       can be used as a workaround.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---

Applied to clk-next

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
  2022-11-04 16:18 ` [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
  2022-12-09 20:21   ` Stephen Boyd
@ 2022-12-12  7:30   ` Tomer Maimon
  2022-12-13 14:53     ` Jonathan Neuschäfer
  1 sibling, 1 reply; 16+ messages in thread
From: Tomer Maimon @ 2022-12-12  7:30 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: linux-clk, openbmc, linux-kernel, linux-watchdog, devicetree,
	Michael Turquette, Stephen Boyd, Rob Herring,
	Krzysztof Kozlowski, Avi Fishman, Tali Perry, Patrick Venture,
	Nancy Yuen, Benjamin Fair, Daniel Lezcano, Thomas Gleixner,
	Philipp Zabel, Wim Van Sebroeck, Guenter Roeck

Hi Jonathan,

Thanks for your patch, and sorry for the late reply.

On Fri, 4 Nov 2022 at 18:19, Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
>
> This driver implements the following features w.r.t. the clock and reset
> controller in the WPCM450 SoC:
>
> - It calculates the rates for all clocks managed by the clock controller
> - It leaves the clock tree mostly unchanged, except that it enables/
>   disables clock gates based on usage.
> - It exposes the reset lines managed by the controller using the
>   Generic Reset Controller subsystem
>
> NOTE: If the driver and the corresponding devicetree node are present,
>       the driver will disable "unused" clocks. This is problem until
>       the clock relations are properly declared in the devicetree (in a
>       later patch). Until then, the clk_ignore_unused kernel parameter
>       can be used as a workaround.
>
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
>
> v5:
> - Switch to using clk_parent_data
>
> v4:
> - https://lore.kernel.org/lkml/20220610072141.347795-6-j.neuschaefer@gmx.net/
> - Fix reset controller initialization
>
> v3:
> - https://lore.kernel.org/lkml/20220508194333.2170161-7-j.neuschaefer@gmx.net/
> - Change reference clock name from "refclk" to "ref"
> - Remove unused variable in return path of wpcm450_clk_register_pll
> - Remove unused divisor tables
>
> v2:
> - https://lore.kernel.org/lkml/20220429172030.398011-7-j.neuschaefer@gmx.net/
> - no changes
> ---
>  drivers/clk/Makefile      |   1 +
>  drivers/clk/clk-wpcm450.c | 375 ++++++++++++++++++++++++++++++++++++++
>  drivers/reset/Kconfig     |   2 +-
>  3 files changed, 377 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/clk-wpcm450.c
>
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index e3ca0d058a256..b58352d4d615d 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -75,6 +75,7 @@ obj-$(CONFIG_COMMON_CLK_RS9_PCIE)     += clk-renesas-pcie.o
>  obj-$(CONFIG_COMMON_CLK_VC5)           += clk-versaclock5.o
>  obj-$(CONFIG_COMMON_CLK_VC7)           += clk-versaclock7.o
>  obj-$(CONFIG_COMMON_CLK_WM831X)                += clk-wm831x.o
> +obj-$(CONFIG_ARCH_WPCM450)             += clk-wpcm450.o
>  obj-$(CONFIG_COMMON_CLK_XGENE)         += clk-xgene.o
>
>  # please keep this section sorted lexicographically by directory path name
> diff --git a/drivers/clk/clk-wpcm450.c b/drivers/clk/clk-wpcm450.c
> new file mode 100644
> index 0000000000000..b5e81b3b6b982
> --- /dev/null
> +++ b/drivers/clk/clk-wpcm450.c
> @@ -0,0 +1,375 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Nuvoton WPCM450 clock and reset controller driver.
> + *
> + * Copyright (C) 2022 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/bitfield.h>
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/reset-controller.h>
> +#include <linux/reset/reset-simple.h>
> +#include <linux/slab.h>
> +
> +#include <dt-bindings/clock/nuvoton,wpcm450-clk.h>
> +
> +struct wpcm450_clk_pll {
> +       struct clk_hw hw;
> +       void __iomem *pllcon;
> +       u8 flags;
> +};
> +
> +#define to_wpcm450_clk_pll(_hw) container_of(_hw, struct wpcm450_clk_pll, hw)
> +
> +#define PLLCON_FBDV    GENMASK(24, 16)
> +#define PLLCON_PRST    BIT(13)
> +#define PLLCON_PWDEN   BIT(12)
> +#define PLLCON_OTDV    GENMASK(10, 8)
> +#define PLLCON_INDV    GENMASK(5, 0)
> +
> +static unsigned long wpcm450_clk_pll_recalc_rate(struct clk_hw *hw,
> +                                                unsigned long parent_rate)
> +{
> +       struct wpcm450_clk_pll *pll = to_wpcm450_clk_pll(hw);
> +       unsigned long fbdv, indv, otdv;
> +       u64 rate;
> +       u32 pllcon;
> +
> +       if (parent_rate == 0) {
> +               pr_err("%s: parent rate is zero", __func__);
> +               return 0;
> +       }
> +
> +       pllcon = readl_relaxed(pll->pllcon);
> +
> +       indv = FIELD_GET(PLLCON_INDV, pllcon) + 1;
> +       fbdv = FIELD_GET(PLLCON_FBDV, pllcon) + 1;
> +       otdv = FIELD_GET(PLLCON_OTDV, pllcon) + 1;
> +
> +       rate = (u64)parent_rate * fbdv;
> +       do_div(rate, indv * otdv);
> +
> +       return rate;
> +}
> +
> +static int wpcm450_clk_pll_is_enabled(struct clk_hw *hw)
> +{
> +       struct wpcm450_clk_pll *pll = to_wpcm450_clk_pll(hw);
> +       u32 pllcon;
> +
> +       pllcon = readl_relaxed(pll->pllcon);
> +
> +       return !(pllcon & PLLCON_PRST);
> +}
> +
> +static void wpcm450_clk_pll_disable(struct clk_hw *hw)
> +{
> +       struct wpcm450_clk_pll *pll = to_wpcm450_clk_pll(hw);
> +       u32 pllcon;
> +
> +       pllcon = readl_relaxed(pll->pllcon);
> +       pllcon |= PLLCON_PRST | PLLCON_PWDEN;
> +       writel(pllcon, pll->pllcon);
> +}
> +
> +static const struct clk_ops wpcm450_clk_pll_ops = {
> +       .recalc_rate = wpcm450_clk_pll_recalc_rate,
> +       .is_enabled = wpcm450_clk_pll_is_enabled,
> +       .disable = wpcm450_clk_pll_disable
> +};
> +
> +static struct clk_hw *
> +wpcm450_clk_register_pll(void __iomem *pllcon, const char *name,
> +                        const struct clk_parent_data *parent, unsigned long flags)
> +{
> +       struct wpcm450_clk_pll *pll;
> +       struct clk_init_data init = {};
> +       int ret;
> +
> +       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> +       if (!pll)
> +               return ERR_PTR(-ENOMEM);
> +
> +       init.name = name;
> +       init.ops = &wpcm450_clk_pll_ops;
> +       init.parent_data = parent;
> +       init.num_parents = 1;
> +       init.flags = flags;
> +
> +       pll->pllcon = pllcon;
> +       pll->hw.init = &init;
> +
> +       ret = clk_hw_register(NULL, &pll->hw);
> +       if (ret) {
> +               kfree(pll);
> +               return ERR_PTR(ret);
> +       }
> +
> +       return &pll->hw;
> +}
> +
> +#define REG_CLKEN      0x00
> +#define REG_CLKSEL     0x04
> +#define REG_CLKDIV     0x08
> +#define REG_PLLCON0    0x0c
> +#define REG_PLLCON1    0x10
> +#define REG_PMCON      0x14
> +#define REG_IRQWAKECON 0x18
> +#define REG_IRQWAKEFLAG        0x1c
> +#define REG_IPSRST     0x20
> +
> +struct wpcm450_pll_data {
> +       const char *name;
> +       struct clk_parent_data parent;
> +       unsigned int reg;
> +       unsigned long flags;
> +};
> +
> +static const struct wpcm450_pll_data pll_data[] = {
> +       { "pll0", { .name = "ref" }, REG_PLLCON0, 0 },
> +       { "pll1", { .name = "ref" }, REG_PLLCON1, 0 },
> +};
> +
> +struct wpcm450_clksel_data {
> +       const char *name;
> +       const struct clk_parent_data *parents;
> +       unsigned int num_parents;
> +       const u32 *table;
> +       int shift;
> +       int width;
> +       int index;
> +       unsigned long flags;
> +};
> +
> +static const u32 parent_table[] = { 0, 1, 2 };
> +
> +static const struct clk_parent_data default_parents[] = {
> +       { .name = "pll0" },
> +       { .name = "pll1" },
> +       { .name = "ref" },
> +};
> +
> +static const struct clk_parent_data huart_parents[] = {
> +       { .name = "ref" },
> +       { .name = "refdiv2" },
> +};
> +
> +static const struct wpcm450_clksel_data clksel_data[] = {
> +       { "cpusel", default_parents, ARRAY_SIZE(default_parents),
> +               parent_table, 0, 2, -1, CLK_IS_CRITICAL },
> +       { "clkout", default_parents, ARRAY_SIZE(default_parents),
> +               parent_table, 2, 2, -1, 0 },
> +       { "usbphy", default_parents, ARRAY_SIZE(default_parents),
> +               parent_table, 6, 2, -1, 0 },
> +       { "uartsel", default_parents, ARRAY_SIZE(default_parents),
> +               parent_table, 8, 2, WPCM450_CLK_USBPHY, 0 },
> +       { "huartsel", huart_parents, ARRAY_SIZE(huart_parents),
> +               parent_table, 10, 1, -1, 0 },
> +};
> +
> +static const struct clk_div_table div_fixed2[] = {
> +       { .val = 0, .div = 2 },
> +       { }
> +};
> +
> +struct wpcm450_clkdiv_data {
> +       const char *name;
> +       struct clk_parent_data parent;
> +       int div_flags;
> +       const struct clk_div_table *table;
> +       int shift;
> +       int width;
> +       unsigned long flags;
> +};
> +
> +static struct wpcm450_clkdiv_data clkdiv_data_early[] = {
> +       { "refdiv2", { .name = "ref" }, 0, div_fixed2, 0, 0 },
> +};
> +
> +static const struct wpcm450_clkdiv_data clkdiv_data[] = {
> +       { "cpu", { .name = "cpusel" }, 0, div_fixed2, 0, 0, CLK_IS_CRITICAL },
> +       { "adcdiv", { .name = "ref" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 28, 2, 0 },
> +       { "apb", { .name = "ahb" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 26, 2, 0 },
> +       { "ahb", { .name = "cpu" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 24, 2, 0 },
> +       { "uart", { .name = "uartsel" }, 0, NULL, 16, 4, 0 },
> +       { "ahb3", { .name = "ahb" }, CLK_DIVIDER_POWER_OF_TWO, NULL, 8, 2, 0 },
> +};
> +
> +struct wpcm450_clken_data {
> +       const char *name;
> +       struct clk_parent_data parent;
> +       int bitnum;
> +       unsigned long flags;
> +};
> +
> +static const struct wpcm450_clken_data clken_data[] = {
> +       { "fiu", { .name = "ahb3" }, WPCM450_CLK_FIU, 0 },
> +       { "xbus", { .name = "ahb3" }, WPCM450_CLK_XBUS, 0 },
> +       { "kcs", { .name = "apb" }, WPCM450_CLK_KCS, 0 },
> +       { "shm", { .name = "ahb3" }, WPCM450_CLK_SHM, 0 },
> +       { "usb1", { .name = "ahb" }, WPCM450_CLK_USB1, 0 },
> +       { "emc0", { .name = "ahb" }, WPCM450_CLK_EMC0, 0 },
> +       { "emc1", { .name = "ahb" }, WPCM450_CLK_EMC1, 0 },
> +       { "usb0", { .name = "ahb" }, WPCM450_CLK_USB0, 0 },
> +       { "peci", { .name = "apb" }, WPCM450_CLK_PECI, 0 },
> +       { "aes", { .name = "apb" }, WPCM450_CLK_AES, 0 },
> +       { "uart0", { .name = "uart" }, WPCM450_CLK_UART0, 0 },
> +       { "uart1", { .name = "uart" }, WPCM450_CLK_UART1, 0 },
> +       { "smb2", { .name = "apb" }, WPCM450_CLK_SMB2, 0 },
> +       { "smb3", { .name = "apb" }, WPCM450_CLK_SMB3, 0 },
> +       { "smb4", { .name = "apb" }, WPCM450_CLK_SMB4, 0 },
> +       { "smb5", { .name = "apb" }, WPCM450_CLK_SMB5, 0 },
> +       { "huart", { .name = "huartsel" }, WPCM450_CLK_HUART, 0 },
> +       { "pwm", { .name = "apb" }, WPCM450_CLK_PWM, 0 },
> +       { "timer0", { .name = "refdiv2" }, WPCM450_CLK_TIMER0, 0 },
> +       { "timer1", { .name = "refdiv2" }, WPCM450_CLK_TIMER1, 0 },
> +       { "timer2", { .name = "refdiv2" }, WPCM450_CLK_TIMER2, 0 },
> +       { "timer3", { .name = "refdiv2" }, WPCM450_CLK_TIMER3, 0 },
> +       { "timer4", { .name = "refdiv2" }, WPCM450_CLK_TIMER4, 0 },
> +       { "mft0", { .name = "apb" }, WPCM450_CLK_MFT0, 0 },
> +       { "mft1", { .name = "apb" }, WPCM450_CLK_MFT1, 0 },
> +       { "wdt", { .name = "refdiv2" }, WPCM450_CLK_WDT, 0 },
> +       { "adc", { .name = "adcdiv" }, WPCM450_CLK_ADC, 0 },
> +       { "sdio", { .name = "ahb" }, WPCM450_CLK_SDIO, 0 },
> +       { "sspi", { .name = "apb" }, WPCM450_CLK_SSPI, 0 },
> +       { "smb0", { .name = "apb" }, WPCM450_CLK_SMB0, 0 },
> +       { "smb1", { .name = "apb" }, WPCM450_CLK_SMB1, 0 },
> +};
> +
> +static DEFINE_SPINLOCK(wpcm450_clk_lock);
> +
> +static void __init wpcm450_clk_init(struct device_node *clk_np)
> +{
> +       struct clk_hw_onecell_data *clk_data;
> +       static struct clk_hw **hws;
> +       static struct clk_hw *hw;
> +       void __iomem *clk_base;
> +       int i, ret;
> +       struct reset_simple_data *reset;
> +
> +       clk_base = of_iomap(clk_np, 0);
> +       if (!clk_base) {
> +               pr_err("%pOFP: failed to map registers\n", clk_np);
> +               of_node_put(clk_np);
> +               return;
> +       }
> +       of_node_put(clk_np);
> +
> +       clk_data = kzalloc(struct_size(clk_data, hws, WPCM450_NUM_CLKS), GFP_KERNEL);
> +       if (!clk_data)
> +               goto err_unmap;
> +
> +       clk_data->num = WPCM450_NUM_CLKS;
> +       hws = clk_data->hws;
> +
> +       for (i = 0; i < WPCM450_NUM_CLKS; i++)
> +               hws[i] = ERR_PTR(-ENOENT);
> +
> +       // PLLs
> +       for (i = 0; i < ARRAY_SIZE(pll_data); i++) {
> +               const struct wpcm450_pll_data *data = &pll_data[i];
> +
> +               hw = wpcm450_clk_register_pll(clk_base + data->reg, data->name,
> +                                             &data->parent, data->flags);
> +               if (IS_ERR(hw)) {
> +                       pr_info("Failed to register PLL: %pe", hw);
> +                       goto err_free;
> +               }
> +       }
> +
> +       // Early divisors (REF/2)
> +       for (i = 0; i < ARRAY_SIZE(clkdiv_data_early); i++) {
> +               const struct wpcm450_clkdiv_data *data = &clkdiv_data_early[i];
> +
> +               hw = clk_hw_register_divider_table_parent_data(NULL, data->name, &data->parent,
> +                                                              data->flags, clk_base + REG_CLKDIV,
> +                                                              data->shift, data->width,
> +                                                              data->div_flags, data->table,
> +                                                              &wpcm450_clk_lock);
> +               if (IS_ERR(hw)) {
> +                       pr_err("Failed to register div table: %pe\n", hw);
> +                       goto err_free;
> +               }
> +       }
> +
> +       // Selects/muxes
> +       for (i = 0; i < ARRAY_SIZE(clksel_data); i++) {
> +               const struct wpcm450_clksel_data *data = &clksel_data[i];
> +
> +               hw = clk_hw_register_mux_parent_data(NULL, data->name, data->parents,
> +                                                    data->num_parents, data->flags,
> +                                                    clk_base + REG_CLKSEL, data->shift,
> +                                                    data->width, 0,
> +                                                    &wpcm450_clk_lock);
> +               if (IS_ERR(hw)) {
> +                       pr_err("Failed to register mux: %pe\n", hw);
> +                       goto err_free;
> +               }
> +               if (data->index >= 0)
> +                       clk_data->hws[data->index] = hw;
> +       }
> +
> +       // Divisors
> +       for (i = 0; i < ARRAY_SIZE(clkdiv_data); i++) {
> +               const struct wpcm450_clkdiv_data *data = &clkdiv_data[i];
> +
> +               hw = clk_hw_register_divider_table_parent_data(NULL, data->name, &data->parent,
> +                                                              data->flags, clk_base + REG_CLKDIV,
> +                                                              data->shift, data->width,
> +                                                              data->div_flags, data->table,
> +                                                              &wpcm450_clk_lock);
> +               if (IS_ERR(hw)) {
> +                       pr_err("Failed to register divider: %pe\n", hw);
> +                       goto err_free;
> +               }
> +       }
> +
> +       // Enables/gates
> +       for (i = 0; i < ARRAY_SIZE(clken_data); i++) {
> +               const struct wpcm450_clken_data *data = &clken_data[i];
> +
> +               hw = clk_hw_register_gate_parent_data(NULL, data->name, &data->parent, data->flags,
> +                                                     clk_base + REG_CLKEN, data->bitnum,
> +                                                     data->flags, &wpcm450_clk_lock);
> +               if (IS_ERR(hw)) {
> +                       pr_err("Failed to register gate: %pe\n", hw);
> +                       goto err_free;
> +               }
> +               clk_data->hws[data->bitnum] = hw;
> +       }
> +
> +       ret = of_clk_add_hw_provider(clk_np, of_clk_hw_onecell_get, clk_data);
> +       if (ret)
> +               pr_err("Failed to add DT provider: %d\n", ret);
> +
> +       // Reset controller
> +       reset = kzalloc(sizeof(*reset), GFP_KERNEL);
> +       if (!reset)
> +               goto err_free;
> +       reset->rcdev.owner = THIS_MODULE;
> +       reset->rcdev.nr_resets = WPCM450_NUM_RESETS;
> +       reset->rcdev.ops = &reset_simple_ops;
> +       reset->rcdev.of_node = clk_np;
> +       reset->membase = clk_base + REG_IPSRST;
> +       ret = reset_controller_register(&reset->rcdev);
> +       if (ret)
> +               pr_err("Failed to register reset controller: %d\n", ret);
> +
> +       of_node_put(clk_np);
> +       return;
> +
> +err_free:
> +       kfree(clk_data->hws);
> +err_unmap:
> +       iounmap(clk_base);
> +       of_node_put(clk_np);
> +}
> +
> +CLK_OF_DECLARE(wpcm450_clk_init, "nuvoton,wpcm450-clk", wpcm450_clk_init);
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index de176c2fbad96..de5662830fce8 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -208,7 +208,7 @@ config RESET_SCMI
>
>  config RESET_SIMPLE
>         bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
> -       default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
> +       default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC || ARCH_NPCM
Please modify the default ARCH_NPCM to the specific Hermon use,
ARCH_WPCM450, since NPCM7XX and NPCM8XX use a specific NPCM reset
driver.
https://elixir.bootlin.com/linux/v6.1-rc8/source/drivers/reset/reset-npcm.c
we prefer not to have two reset drivers when compiling ARCH_NPCM.
>         depends on HAS_IOMEM
>         help
>           This enables a simple reset controller driver for reset lines that
> --
> 2.35.1
>

Best regards,

Tomer

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
  2022-12-12  7:30   ` Tomer Maimon
@ 2022-12-13 14:53     ` Jonathan Neuschäfer
  0 siblings, 0 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2022-12-13 14:53 UTC (permalink / raw)
  To: Tomer Maimon
  Cc: Jonathan Neuschäfer, linux-clk, openbmc, linux-kernel,
	linux-watchdog, devicetree, Michael Turquette, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Avi Fishman, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair, Daniel Lezcano,
	Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck, Guenter Roeck

[-- Attachment #1: Type: text/plain, Size: 1213 bytes --]

On Mon, Dec 12, 2022 at 09:30:46AM +0200, Tomer Maimon wrote:
> Hi Jonathan,
> 
> Thanks for your patch, and sorry for the late reply.
> 
> On Fri, 4 Nov 2022 at 18:19, Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
[...]
> > diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> > index de176c2fbad96..de5662830fce8 100644
> > --- a/drivers/reset/Kconfig
> > +++ b/drivers/reset/Kconfig
> > @@ -208,7 +208,7 @@ config RESET_SCMI
> >
> >  config RESET_SIMPLE
> >         bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
> > -       default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
> > +       default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC || ARCH_NPCM
> Please modify the default ARCH_NPCM to the specific Hermon use,
> ARCH_WPCM450, since NPCM7XX and NPCM8XX use a specific NPCM reset
> driver.
> https://elixir.bootlin.com/linux/v6.1-rc8/source/drivers/reset/reset-npcm.c
> we prefer not to have two reset drivers when compiling ARCH_NPCM.

Good point. I'll fix that.


Thanks,
J.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
  2022-12-09 20:21   ` Stephen Boyd
@ 2023-04-12 19:13     ` Jonathan Neuschäfer
  2023-04-12 20:34       ` Stephen Boyd
  0 siblings, 1 reply; 16+ messages in thread
From: Jonathan Neuschäfer @ 2023-04-12 19:13 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Jonathan Neuschäfer, linux-clk, openbmc, linux-kernel,
	linux-watchdog, devicetree, Michael Turquette, Rob Herring,
	Krzysztof Kozlowski, Avi Fishman, Tomer Maimon, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair, Daniel Lezcano,
	Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck, Guenter Roeck,
	Krzysztof Kozlowski, Krzysztof Kozlowski

[-- Attachment #1: Type: text/plain, Size: 589 bytes --]

Hi,

On Fri, Dec 09, 2022 at 12:21:17PM -0800, Stephen Boyd wrote:
> Quoting Jonathan Neuschäfer (2022-11-04 09:18:47)
> > The Nuvoton WPCM450 SoC has a combined clock and reset controller.
> > Add a devicetree binding for it, as well as definitions for the bit
> > numbers used by it.
> > 
> > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> > ---
> 
> Applied to clk-next

I don't see this patch in clk/linux.git's clk-next branch. Did it get
lost somehow?


Best regards,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
  2023-04-12 19:13     ` Jonathan Neuschäfer
@ 2023-04-12 20:34       ` Stephen Boyd
  2023-04-12 21:24         ` Jonathan Neuschäfer
  0 siblings, 1 reply; 16+ messages in thread
From: Stephen Boyd @ 2023-04-12 20:34 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: Jonathan Neuschäfer, linux-clk, openbmc, linux-kernel,
	linux-watchdog, devicetree, Michael Turquette, Rob Herring,
	Krzysztof Kozlowski, Avi Fishman, Tomer Maimon, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair, Daniel Lezcano,
	Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck, Guenter Roeck,
	Krzysztof Kozlowski, Krzysztof Kozlowski

Quoting Jonathan Neuschäfer (2023-04-12 12:13:56)
> Hi,
> 
> On Fri, Dec 09, 2022 at 12:21:17PM -0800, Stephen Boyd wrote:
> > Quoting Jonathan Neuschäfer (2022-11-04 09:18:47)
> > > The Nuvoton WPCM450 SoC has a combined clock and reset controller.
> > > Add a devicetree binding for it, as well as definitions for the bit
> > > numbers used by it.
> > > 
> > > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > > Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> > > ---
> > 
> > Applied to clk-next
> 
> I don't see this patch in clk/linux.git's clk-next branch. Did it get
> lost somehow?
> 

Must have gotten lost. I don't see it in my branch history locally.
Resend?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
  2023-04-12 20:34       ` Stephen Boyd
@ 2023-04-12 21:24         ` Jonathan Neuschäfer
  0 siblings, 0 replies; 16+ messages in thread
From: Jonathan Neuschäfer @ 2023-04-12 21:24 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Jonathan Neuschäfer, linux-clk, openbmc, linux-kernel,
	linux-watchdog, devicetree, Michael Turquette, Rob Herring,
	Krzysztof Kozlowski, Avi Fishman, Tomer Maimon, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair, Daniel Lezcano,
	Thomas Gleixner, Philipp Zabel, Wim Van Sebroeck, Guenter Roeck,
	Krzysztof Kozlowski, Krzysztof Kozlowski

[-- Attachment #1: Type: text/plain, Size: 866 bytes --]

On Wed, Apr 12, 2023 at 01:34:20PM -0700, Stephen Boyd wrote:
> Quoting Jonathan Neuschäfer (2023-04-12 12:13:56)
> > Hi,
> > 
> > On Fri, Dec 09, 2022 at 12:21:17PM -0800, Stephen Boyd wrote:
> > > Quoting Jonathan Neuschäfer (2022-11-04 09:18:47)
> > > > The Nuvoton WPCM450 SoC has a combined clock and reset controller.
> > > > Add a devicetree binding for it, as well as definitions for the bit
> > > > numbers used by it.
> > > > 
> > > > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > > > Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> > > > ---
> > > 
> > > Applied to clk-next
> > 
> > I don't see this patch in clk/linux.git's clk-next branch. Did it get
> > lost somehow?
> > 
> 
> Must have gotten lost. I don't see it in my branch history locally.
> Resend?

Will do.

Thanks,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2023-04-12 21:25 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-04 16:18 [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
2022-11-04 16:18 ` [PATCH v5 1/6] dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks Jonathan Neuschäfer
2022-11-04 16:18 ` [PATCH v5 2/6] clocksource: timer-npcm7xx: Enable timer 1 clock before use Jonathan Neuschäfer
2022-11-04 16:18 ` [PATCH v5 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
2022-12-09 20:21   ` Stephen Boyd
2023-04-12 19:13     ` Jonathan Neuschäfer
2023-04-12 20:34       ` Stephen Boyd
2023-04-12 21:24         ` Jonathan Neuschäfer
2022-11-04 16:18 ` [PATCH v5 4/6] ARM: dts: wpcm450: Add clock controller node Jonathan Neuschäfer
2022-11-04 16:18 ` [PATCH v5 5/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
2022-12-09 20:21   ` Stephen Boyd
2022-12-12  7:30   ` Tomer Maimon
2022-12-13 14:53     ` Jonathan Neuschäfer
2022-11-04 16:18 ` [PATCH v5 6/6] [NOT FOR MERGE] ARM: dts: wpcm450: Switch clocks to clock controller Jonathan Neuschäfer
2022-11-22  1:40 ` [PATCH v5 0/6] Nuvoton WPCM450 clock and reset driver Joel Stanley
2022-11-22  8:09   ` Daniel Lezcano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).