openbmc.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver
@ 2024-05-02 10:39 Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 1/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Jonathan Neuschäfer @ 2024-05-02 10:39 UTC (permalink / raw)
  To: openbmc, linux-clk, devicetree
  Cc: Rob Herring, Conor Dooley, Stephen Boyd, Michael Turquette,
	linux-kernel, Jonathan Neuschäfer, Krzysztof Kozlowski,
	Joel Stanley, Philipp Zabel

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.

v12:
- Convert to platform driver, but use fixed-factor-clock for timer
  (a necessary workaround because npcm7xx-timer needs its clock earlier
  than a platform driver can provide it)
- Various driver improvements suggested or inspired by Stephen Boyd
- New patches:
  - clk: Introduce devm_clk_hw_register_divider_table_parent_data()
  - clk: provider: Address documentation pitfall in struct clk_parent_data

v11:
- Link: https://lore.kernel.org/r/20240401-wpcm-clk-v11-0-379472961244@gmx.net
- Improved description in "ARM: dts: wpcm450: Remove clock-output-names
  from reference clock node"
- some minor format differences due to switching to B4

v10:
- A small tweak (using selected instead of extending an already-long
  default line) in Kconfig, for better robustness

v9:
- Various improvements to the driver
- No longer use global clock names (and the clock-output-names property)
  to refer to the reference clock, but instead rely on a phandle reference

v8:
- https://lore.kernel.org/lkml/20230428190226.1304326-1-j.neuschaefer@gmx.net/
- Use %pe throughout the driver

v7:
- Simplified the error handling, by largely removing resource
  deallocation, which:
  - was already incomplete
  - would only happen in a case when the system is in pretty bad state
    because the clock driver didn't initialize correctly (in other
    words, the clock driver isn't optional enough that complex error
    handling really pays off)

v6:
- Dropped all patches except the clock binding and the clock driver, because
  they have mostly been merged
- Minor correction to how RESET_SIMPLE is selected

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:
- 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/

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---
---
Jonathan Neuschäfer (6):
      dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
      clk: Introduce devm_clk_hw_register_divider_table_parent_data()
      clk: provider: Address documentation pitfall in struct clk_parent_data
      clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
      ARM: dts: wpcm450: Remove clock-output-names from reference clock node
      ARM: dts: wpcm450: Switch clocks to clock controller

 .../bindings/clock/nuvoton,wpcm450-clk.yaml        |  65 +++
 arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi     |  33 +-
 drivers/clk/Makefile                               |   2 +-
 drivers/clk/nuvoton/Kconfig                        |  10 +-
 drivers/clk/nuvoton/Makefile                       |   1 +
 drivers/clk/nuvoton/clk-wpcm450.c                  | 455 +++++++++++++++++++++
 include/dt-bindings/clock/nuvoton,wpcm450-clk.h    |  67 +++
 include/linux/clk-provider.h                       |  26 +-
 8 files changed, 643 insertions(+), 16 deletions(-)
---
base-commit: 4cece764965020c22cff7665b18a012006359095
change-id: 20240330-wpcm-clk-222a37f59cfb

Best regards,
--
Jonathan Neuschäfer <j.neuschaefer@gmx.net>


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

* [PATCH v12 1/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller
  2024-05-02 10:39 [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
@ 2024-05-02 10:40 ` Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 2/6] clk: Introduce devm_clk_hw_register_divider_table_parent_data() Jonathan Neuschäfer
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jonathan Neuschäfer @ 2024-05-02 10:40 UTC (permalink / raw)
  To: openbmc, linux-clk, devicetree
  Cc: Rob Herring, Conor Dooley, Stephen Boyd, Michael Turquette,
	linux-kernel, Jonathan Neuschäfer, Krzysztof Kozlowski,
	Joel Stanley, Philipp Zabel

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>
---
v10-v11:
- no changes

v9:
- Remove clock-output-names in example, because it's now unnecessary due
  to driver improvements

v5-v8:
- 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        | 65 +++++++++++++++++++++
 include/dt-bindings/clock/nuvoton,wpcm450-clk.h    | 67 ++++++++++++++++++++++
 2 files changed, 132 insertions(+)

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 00000000000000..93521cf68a040f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nuvoton,wpcm450-clk.yaml
@@ -0,0 +1,65 @@
+# 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-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 00000000000000..86e1c895921b71
--- /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.43.0


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

* [PATCH v12 2/6] clk: Introduce devm_clk_hw_register_divider_table_parent_data()
  2024-05-02 10:39 [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 1/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
@ 2024-05-02 10:40 ` Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 3/6] clk: provider: Address documentation pitfall in struct clk_parent_data Jonathan Neuschäfer
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jonathan Neuschäfer @ 2024-05-02 10:40 UTC (permalink / raw)
  To: openbmc, linux-clk, devicetree
  Cc: Rob Herring, Conor Dooley, Stephen Boyd, Michael Turquette,
	linux-kernel, Jonathan Neuschäfer, Krzysztof Kozlowski,
	Joel Stanley, Philipp Zabel

Introduce the devm pendant to clk_hw_register_divider_table_parent_data.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---
 include/linux/clk-provider.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 4a537260f6557d..5d537d0776a11f 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -932,6 +932,28 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 				       (width), (clk_divider_flags), (table), \
 				       (lock))

+/**
+ * devm_clk_hw_register_divider_table_parent_data - register a table based divider clock
+ * with the clock framework (devres variant)
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_data: parent clk data
+ * @flags: framework-specific flags
+ * @reg: register address to adjust divider
+ * @shift: number of bits to shift the bitfield
+ * @width: width of the bitfield
+ * @clk_divider_flags: divider-specific flags for this clock
+ * @table: array of divider/value pairs ending with a div set to 0
+ * @lock: shared register lock for this clock
+ */
+#define devm_clk_hw_register_divider_table_parent_data(dev, name, parent_data, flags,   \
+						       reg, shift, width,               \
+						       clk_divider_flags, table, lock)  \
+	__devm_clk_hw_register_divider((dev), NULL, (name), NULL,                       \
+				       NULL, (parent_data), (flags), (reg), (shift),    \
+				       (width), (clk_divider_flags), (table),           \
+				       (lock))
+
 void clk_unregister_divider(struct clk *clk);
 void clk_hw_unregister_divider(struct clk_hw *hw);


--
2.43.0


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

* [PATCH v12 3/6] clk: provider: Address documentation pitfall in struct clk_parent_data
  2024-05-02 10:39 [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 1/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 2/6] clk: Introduce devm_clk_hw_register_divider_table_parent_data() Jonathan Neuschäfer
@ 2024-05-02 10:40 ` Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 4/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jonathan Neuschäfer @ 2024-05-02 10:40 UTC (permalink / raw)
  To: openbmc, linux-clk, devicetree
  Cc: Rob Herring, Conor Dooley, Stephen Boyd, Michael Turquette,
	linux-kernel, Jonathan Neuschäfer, Krzysztof Kozlowski,
	Joel Stanley, Philipp Zabel

For some reason, I understood the description of .index to mean an index
into the list of clocks defined by the provider itself. This is not the
case, and it caused me much confusion.

Let's be a bit more explicit for those who read the documentation after me.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---
 include/linux/clk-provider.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 5d537d0776a11f..88bdada390c772 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -273,7 +273,9 @@ struct clk_ops {
  * @hw: parent clk_hw pointer (used for clk providers with internal clks)
  * @fw_name: parent name local to provider registering clk
  * @name: globally unique parent name (used as a fallback)
- * @index: parent index local to provider registering clk (if @fw_name absent)
+ * @index: parent index local to provider registering clk (if @fw_name absent).
+ *         Note that this is not an index into the provider's own clocks but
+ *         into its list of parents!
  */
 struct clk_parent_data {
 	const struct clk_hw	*hw;

--
2.43.0


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

* [PATCH v12 4/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver
  2024-05-02 10:39 [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
                   ` (2 preceding siblings ...)
  2024-05-02 10:40 ` [PATCH v12 3/6] clk: provider: Address documentation pitfall in struct clk_parent_data Jonathan Neuschäfer
@ 2024-05-02 10:40 ` Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 5/6] ARM: dts: wpcm450: Remove clock-output-names from reference clock node Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 6/6] ARM: dts: wpcm450: Switch clocks to clock controller Jonathan Neuschäfer
  5 siblings, 0 replies; 7+ messages in thread
From: Jonathan Neuschäfer @ 2024-05-02 10:40 UTC (permalink / raw)
  To: openbmc, linux-clk, devicetree
  Cc: Rob Herring, Conor Dooley, Stephen Boyd, Michael Turquette,
	linux-kernel, Jonathan Neuschäfer, Krzysztof Kozlowski,
	Joel Stanley, Philipp Zabel

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
- A few clocks are marked as critical because they don't have consumers
  in the common clock framework:
  - CPU clock
  - timer clocks, because the timer-npcm7xx driver (in its current shape)
    can't depend on a platform driver (clk-wpcm450), but the timer clocks
    must not be disabled

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>
Reviewed-by: Joel Stanley <joel@jms.id.au>
---

v12:
- Switch ref clock inputs to .fw_name = "ref"
- Use .hw to refer to internal clocks
- Remove unnecessary pr_fmt definition
- Convert to a platform driver, to avoid use of .name; use devm_ API
- Mark timer0/1 clocks as critical
- Update copyright year to 2024
- Split reset controller initialization into a separate function
- Change MODULE_LICENSE to "GPL" according to commit bf7fbeeae6db
  ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity")

v11:
- no changes

v10:
- select RESET_{CONTROLLER,SIMPLE} from CLK_WPCM450 instead of messing with the 'default' statement

v9:
- Apply comments made by Stephen Boyd
- Move to drivers/clk/nuvoton/ directory
- Update SPDX license identifier from GPL-2.0 to GPL-2.0-only
- Rename clk_np variable to np
- Use of_clk_hw_register
- Refer to clock parents by .fw_name

v8:
- https://lore.kernel.org/lkml/20230428190226.1304326-3-j.neuschaefer@gmx.net/
- Use %pe format specifier throughout the driver, as suggested by Philipp Zabel
- Add Joel's R-b

v7:
- https://lore.kernel.org/lkml/20230422220240.322572-3-j.neuschaefer@gmx.net/
- Simplify error handling by not deallocating resources

v6:
- Enable RESET_SIMPLE based on ARCH_WPCM450, not ARCH_NPCM, as suggested by Tomer Maimon

v5:
- https://lore.kernel.org/lkml/20221104161850.2889894-6-j.neuschaefer@gmx.net/
- Switch to using clk_parent_data

v4:
- Fix reset controller initialization

v3:
- Change reference clock name from "refclk" to "ref"
- Remove unused variable in return path of wpcm450_clk_register_pll
- Remove unused divisor tables

v2:
- no changes
---
 drivers/clk/Makefile              |   2 +-
 drivers/clk/nuvoton/Kconfig       |  10 +-
 drivers/clk/nuvoton/Makefile      |   1 +
 drivers/clk/nuvoton/clk-wpcm450.c | 455 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 466 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 14fa8d4ecc1fbe..cdeb2ecf3a8e99 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -107,7 +107,7 @@ endif
 obj-y					+= mstar/
 obj-y					+= mvebu/
 obj-$(CONFIG_ARCH_MXS)			+= mxs/
-obj-$(CONFIG_ARCH_MA35)			+= nuvoton/
+obj-y					+= nuvoton/
 obj-$(CONFIG_COMMON_CLK_NXP)		+= nxp/
 obj-$(CONFIG_COMMON_CLK_PISTACHIO)	+= pistachio/
 obj-$(CONFIG_COMMON_CLK_PXA)		+= pxa/
diff --git a/drivers/clk/nuvoton/Kconfig b/drivers/clk/nuvoton/Kconfig
index fe4b7f62f46704..908881654b2e91 100644
--- a/drivers/clk/nuvoton/Kconfig
+++ b/drivers/clk/nuvoton/Kconfig
@@ -3,7 +3,7 @@

 config COMMON_CLK_NUVOTON
 	bool "Nuvoton clock controller common support"
-	depends on ARCH_MA35 || COMPILE_TEST
+	depends on ARCH_MA35 || ARCH_NPCM || COMPILE_TEST
 	default y
 	help
 	  Say y here to enable common clock controller for Nuvoton platforms.
@@ -16,4 +16,12 @@ config CLK_MA35D1
 	help
 	  Build the clock controller driver for MA35D1 SoC.

+config CLK_WPCM450
+	bool "Nuvoton WPCM450 clock/reset controller support"
+	default y
+	select RESET_CONTROLLER
+	select RESET_SIMPLE
+	help
+	  Build the clock and reset controller driver for the WPCM450 SoC.
+
 endif
diff --git a/drivers/clk/nuvoton/Makefile b/drivers/clk/nuvoton/Makefile
index c3c59dd9f2aaab..b130f0d3889ca0 100644
--- a/drivers/clk/nuvoton/Makefile
+++ b/drivers/clk/nuvoton/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1.o
 obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1-divider.o
 obj-$(CONFIG_CLK_MA35D1) += clk-ma35d1-pll.o
+obj-$(CONFIG_CLK_WPCM450) += clk-wpcm450.o
diff --git a/drivers/clk/nuvoton/clk-wpcm450.c b/drivers/clk/nuvoton/clk-wpcm450.c
new file mode 100644
index 00000000000000..9a0f9c0bd8e6c8
--- /dev/null
+++ b/drivers/clk/nuvoton/clk-wpcm450.c
@@ -0,0 +1,455 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Nuvoton WPCM450 clock and reset controller driver.
+ *
+ * Copyright (C) 2024 Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/device.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 <linux/platform_device.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)
+		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(struct device *dev, 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 = devm_kzalloc(dev, 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 = devm_clk_hw_register(dev, &pll->hw);
+	if (ret) {
+		devm_kfree(dev, pll);
+		return ERR_PTR(ret);
+	}
+
+	return &pll->hw;
+}
+
+// Additional clock indexes for internal use.
+enum {
+	WPCM450_CLK_REF = -1,
+	WPCM450_CLK_REFDIV2 = WPCM450_NUM_CLKS,
+	WPCM450_CLK_PLL0,
+	WPCM450_CLK_PLL1,
+	WPCM450_CLK_CPUSEL,
+	WPCM450_CLK_CLKOUT,
+	WPCM450_CLK_UARTSEL,
+	WPCM450_CLK_HUARTSEL,
+	WPCM450_CLK_CPU,
+	WPCM450_CLK_ADCDIV,
+	WPCM450_CLK_APB,
+	WPCM450_CLK_AHB,
+	WPCM450_CLK_AHB3,
+	WPCM450_CLK_UART,
+	WPCM450_NUM_CLKS_TOTAL
+};
+
+static struct clk_parent_data index_to_parent_data(struct clk_hw **hws, int index)
+{
+	struct clk_parent_data parent_data = {};
+
+	if (index == WPCM450_CLK_REF)
+		parent_data.fw_name = "ref";
+	else
+		parent_data.hw = hws[index];
+
+	return parent_data;
+}
+
+static size_t index_to_parent_data_array(struct clk_hw **hws,
+					 const int *indexes, size_t num_indexes,
+					 struct clk_parent_data *parent_data,
+					 size_t num_parent_data)
+{
+	size_t i;
+
+	for (i = 0; i < min(num_parent_data, num_indexes); i++)
+		parent_data[i] = index_to_parent_data(hws, indexes[i]);
+
+	return i;
+}
+
+#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;
+	int index;
+	int parent;
+	unsigned int reg;
+	unsigned long flags;
+};
+
+static const struct wpcm450_pll_data pll_data[] = {
+	{ "pll0", WPCM450_CLK_PLL0, WPCM450_CLK_REF, REG_PLLCON0, 0 },
+	{ "pll1", WPCM450_CLK_PLL1, WPCM450_CLK_REF, REG_PLLCON1, 0 },
+};
+
+struct wpcm450_clksel_data {
+	const char *name;
+	int index;
+	const int *parents;
+	unsigned int num_parents;
+	const u32 *table;
+	int shift;
+	int width;
+	unsigned long flags;
+};
+
+static const u32 parent_table[] = { 0, 1, 2 };
+
+static const int default_parents[] = {
+	WPCM450_CLK_PLL0,
+	WPCM450_CLK_PLL1,
+	WPCM450_CLK_REF,
+};
+
+static const int huart_parents[] = {
+	WPCM450_CLK_REF,
+	WPCM450_CLK_REFDIV2,
+};
+
+static const struct wpcm450_clksel_data clksel_data[] = {
+	{ "cpusel", WPCM450_CLK_CPUSEL, default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 0, 2, CLK_IS_CRITICAL },
+	{ "clkout", WPCM450_CLK_CLKOUT, default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 2, 2, 0 },
+	{ "usbphy", WPCM450_CLK_USBPHY, default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 6, 2, 0 },
+	{ "uartsel", WPCM450_CLK_UARTSEL, default_parents, ARRAY_SIZE(default_parents),
+		parent_table, 8, 2, 0 },
+	{ "huartsel", WPCM450_CLK_HUARTSEL, huart_parents, ARRAY_SIZE(huart_parents),
+		parent_table, 10, 1, 0 },
+};
+
+static const struct clk_div_table div_fixed2[] = {
+	{ .val = 0, .div = 2 },
+	{ }
+};
+
+struct wpcm450_clkdiv_data {
+	const char *name;
+	int index;
+	int 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[] = {
+	{ "ref/2", WPCM450_CLK_REFDIV2, WPCM450_CLK_REF, 0, div_fixed2, 0, 0 },
+};
+
+static const struct wpcm450_clkdiv_data clkdiv_data[] = {
+	{ "cpu", WPCM450_CLK_CPU, WPCM450_CLK_CPUSEL, 0, div_fixed2, 0, 0, CLK_IS_CRITICAL },
+	{ "adcdiv", WPCM450_CLK_ADCDIV, WPCM450_CLK_REF, CLK_DIVIDER_POWER_OF_TWO, NULL, 28, 2, 0 },
+	{ "ahb", WPCM450_CLK_AHB, WPCM450_CLK_CPU, CLK_DIVIDER_POWER_OF_TWO, NULL, 24, 2, 0 },
+	{ "apb", WPCM450_CLK_APB, WPCM450_CLK_AHB, CLK_DIVIDER_POWER_OF_TWO, NULL, 26, 2, 0 },
+	{ "uart", WPCM450_CLK_UART, WPCM450_CLK_UARTSEL, 0, NULL, 16, 4, 0 },
+	{ "ahb3", WPCM450_CLK_AHB3, WPCM450_CLK_AHB, CLK_DIVIDER_POWER_OF_TWO, NULL, 8, 2, 0 },
+};
+
+struct wpcm450_clken_data {
+	const char *name;
+	int index;
+	int parent;
+	unsigned long flags;
+};
+
+static const struct wpcm450_clken_data clken_data[] = {
+	{ "fiu", WPCM450_CLK_FIU, WPCM450_CLK_AHB3, 0 },
+	{ "xbus", WPCM450_CLK_XBUS, WPCM450_CLK_AHB3, 0 },
+	{ "kcs", WPCM450_CLK_KCS, WPCM450_CLK_APB, 0 },
+	{ "shm", WPCM450_CLK_SHM, WPCM450_CLK_AHB3, 0 },
+	{ "usb1", WPCM450_CLK_USB1, WPCM450_CLK_AHB, 0 },
+	{ "emc0", WPCM450_CLK_EMC0, WPCM450_CLK_AHB, 0 },
+	{ "emc1", WPCM450_CLK_EMC1, WPCM450_CLK_AHB, 0 },
+	{ "usb0", WPCM450_CLK_USB0, WPCM450_CLK_AHB, 0 },
+	{ "peci", WPCM450_CLK_PECI, WPCM450_CLK_APB, 0 },
+	{ "aes", WPCM450_CLK_AES, WPCM450_CLK_APB, 0 },
+	{ "uart0", WPCM450_CLK_UART0, WPCM450_CLK_UART, 0 },
+	{ "uart1", WPCM450_CLK_UART1, WPCM450_CLK_UART, 0 },
+	{ "smb2", WPCM450_CLK_SMB2, WPCM450_CLK_APB, 0 },
+	{ "smb3", WPCM450_CLK_SMB3, WPCM450_CLK_APB, 0 },
+	{ "smb4", WPCM450_CLK_SMB4, WPCM450_CLK_APB, 0 },
+	{ "smb5", WPCM450_CLK_SMB5, WPCM450_CLK_APB, 0 },
+	{ "huart", WPCM450_CLK_HUART, WPCM450_CLK_HUARTSEL, 0 },
+	{ "pwm", WPCM450_CLK_PWM, WPCM450_CLK_APB, 0 },
+	{ "timer0", WPCM450_CLK_TIMER0, WPCM450_CLK_REFDIV2, CLK_IS_CRITICAL },
+	{ "timer1", WPCM450_CLK_TIMER1, WPCM450_CLK_REFDIV2, CLK_IS_CRITICAL },
+	{ "timer2", WPCM450_CLK_TIMER2, WPCM450_CLK_REFDIV2, 0 },
+	{ "timer3", WPCM450_CLK_TIMER3, WPCM450_CLK_REFDIV2, 0 },
+	{ "timer4", WPCM450_CLK_TIMER4, WPCM450_CLK_REFDIV2, 0 },
+	{ "mft0", WPCM450_CLK_MFT0, WPCM450_CLK_APB, 0 },
+	{ "mft1", WPCM450_CLK_MFT1, WPCM450_CLK_APB, 0 },
+	{ "wdt", WPCM450_CLK_WDT, WPCM450_CLK_REFDIV2, 0 },
+	{ "adc", WPCM450_CLK_ADC, WPCM450_CLK_ADCDIV, 0 },
+	{ "sdio", WPCM450_CLK_SDIO, WPCM450_CLK_AHB, 0 },
+	{ "sspi", WPCM450_CLK_SSPI, WPCM450_CLK_APB, 0 },
+	{ "smb0", WPCM450_CLK_SMB0, WPCM450_CLK_APB, 0 },
+	{ "smb1", WPCM450_CLK_SMB1, WPCM450_CLK_APB, 0 },
+};
+
+static DEFINE_SPINLOCK(wpcm450_clk_lock);
+
+static int wpcm450_reset_probe(struct platform_device *pdev, void __iomem *clk_base)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct reset_simple_data *reset;
+
+	reset = devm_kzalloc(dev, sizeof(*reset), GFP_KERNEL);
+	if (!reset)
+		return -ENOMEM;
+
+	reset->rcdev.owner = THIS_MODULE;
+	reset->rcdev.nr_resets = WPCM450_NUM_RESETS;
+	reset->rcdev.ops = &reset_simple_ops;
+	reset->rcdev.of_node = np;
+	reset->membase = clk_base + REG_IPSRST;
+	return devm_reset_controller_register(dev, &reset->rcdev);
+}
+
+static int wpcm450_clk_probe(struct platform_device *pdev)
+{
+	struct clk_hw_onecell_data *clk_data;
+	struct clk_hw **hws;
+	struct clk_hw *hw;
+	void __iomem *clk_base;
+	int i, ret;
+
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	resource_size_t map_size;
+
+	clk_base = devm_of_iomap(dev, np, 0, &map_size);
+	if (IS_ERR(clk_base)) {
+		dev_err(dev, "failed to map registers\n");
+		return PTR_ERR(clk_base);
+	}
+
+	clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, WPCM450_NUM_CLKS_TOTAL),
+				GFP_KERNEL);
+	if (!clk_data)
+		return -ENOMEM;
+
+	clk_data->num = WPCM450_NUM_CLKS;
+	hws = clk_data->hws;
+
+	for (i = 0; i < WPCM450_NUM_CLKS_TOTAL; 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];
+		struct clk_parent_data parent = index_to_parent_data(hws, data->parent);
+
+		hw = wpcm450_clk_register_pll(dev, clk_base + data->reg, data->name,
+					      &parent, data->flags);
+		if (IS_ERR(hw)) {
+			dev_err(dev, "Failed to register PLL: %pe\n", hw);
+			return PTR_ERR(hw);
+		}
+		clk_data->hws[data->index] = hw;
+	}
+
+	/* Early divisors (REF/2) */
+	for (i = 0; i < ARRAY_SIZE(clkdiv_data_early); i++) {
+		const struct wpcm450_clkdiv_data *data = &clkdiv_data_early[i];
+		struct clk_parent_data parent = index_to_parent_data(hws, data->parent);
+
+		hw = devm_clk_hw_register_divider_table_parent_data(dev, data->name, &parent,
+								    data->flags,
+								    clk_base + REG_CLKDIV,
+								    data->shift, data->width,
+								    data->div_flags, data->table,
+								    &wpcm450_clk_lock);
+
+		if (IS_ERR(hw)) {
+			dev_err(dev, "Failed to register div table: %pe\n", hw);
+			return PTR_ERR(hw);
+		}
+		clk_data->hws[data->index] = hw;
+	}
+
+	/* Selects/muxes */
+	for (i = 0; i < ARRAY_SIZE(clksel_data); i++) {
+		const struct wpcm450_clksel_data *data = &clksel_data[i];
+		struct clk_parent_data parents[4];
+		size_t num_parents = index_to_parent_data_array(hws,
+				data->parents, data->num_parents, parents,
+				ARRAY_SIZE(parents));
+
+		hw = devm_clk_hw_register_mux_parent_data_table(dev, data->name, parents,
+								num_parents, data->flags,
+								clk_base + REG_CLKSEL, data->shift,
+								data->width, 0, NULL,
+								&wpcm450_clk_lock);
+
+		if (IS_ERR(hw)) {
+			dev_err(dev, "Failed to register mux: %pe\n", hw);
+			return PTR_ERR(hw);
+		}
+		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];
+		struct clk_parent_data parent = index_to_parent_data(hws, data->parent);
+
+		hw = devm_clk_hw_register_divider_table_parent_data(dev, data->name, &parent,
+								    data->flags,
+								    clk_base + REG_CLKDIV,
+								    data->shift, data->width,
+								    data->div_flags, data->table,
+								    &wpcm450_clk_lock);
+
+		if (IS_ERR(hw)) {
+			dev_err(dev, "Failed to register divider: %pe\n", hw);
+			return PTR_ERR(hw);
+		}
+		clk_data->hws[data->index] = hw;
+	}
+
+	/* Enables/gates */
+	for (i = 0; i < ARRAY_SIZE(clken_data); i++) {
+		const struct wpcm450_clken_data *data = &clken_data[i];
+		struct clk_parent_data parent = index_to_parent_data(hws, data->parent);
+
+		hw = devm_clk_hw_register_gate_parent_data(dev, data->name, &parent, data->flags,
+							   clk_base + REG_CLKEN, data->index,
+							   data->flags, &wpcm450_clk_lock);
+		if (IS_ERR(hw)) {
+			dev_err(dev, "Failed to register gate: %pe\n", hw);
+			return PTR_ERR(hw);
+		}
+		clk_data->hws[data->index] = hw;
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+	if (ret)
+		dev_err(dev, "Failed to add DT provider: %pe\n", ERR_PTR(ret));
+
+	ret = wpcm450_reset_probe(pdev, clk_base);
+	if (ret)
+		dev_err(dev, "Failed to register reset controller: %pe\n", ERR_PTR(ret));
+
+	return 0;
+}
+
+static const struct of_device_id wpcm450_of_match[] = {
+	{ .compatible = "nuvoton,wpcm450-clk" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, wpcm450_of_match);
+
+static struct platform_driver wpcm450_clk_driver = {
+	.driver = {
+		.name = "wpcm450-clk",
+		.of_match_table = wpcm450_of_match,
+	},
+	.probe = wpcm450_clk_probe,
+};
+module_platform_driver(wpcm450_clk_driver);
+
+MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
+MODULE_DESCRIPTION("Nuvoton WPCM450 clock and reset controller driver");
+MODULE_LICENSE("GPL");

--
2.43.0


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

* [PATCH v12 5/6] ARM: dts: wpcm450: Remove clock-output-names from reference clock node
  2024-05-02 10:39 [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
                   ` (3 preceding siblings ...)
  2024-05-02 10:40 ` [PATCH v12 4/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
@ 2024-05-02 10:40 ` Jonathan Neuschäfer
  2024-05-02 10:40 ` [PATCH v12 6/6] ARM: dts: wpcm450: Switch clocks to clock controller Jonathan Neuschäfer
  5 siblings, 0 replies; 7+ messages in thread
From: Jonathan Neuschäfer @ 2024-05-02 10:40 UTC (permalink / raw)
  To: openbmc, linux-clk, devicetree
  Cc: Rob Herring, Conor Dooley, Stephen Boyd, Michael Turquette,
	linux-kernel, Jonathan Neuschäfer, Krzysztof Kozlowski,
	Joel Stanley, Philipp Zabel

A previous version of the as-yet unmerged clk-wpcm450 driver[1] used the
output name, but in the current iteration it doesn't rely on it anymore.
Thus it can be removed from the devicetree.

Preserve the "reference" naming aspect in the node name instead.

[1]: Added in "clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver"

Fixes: 362e8be2ec04a6 ("ARM: dts: wpcm450: Add clock controller node")
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

v12:
- rename node to clock-ref, because it isn't necessarily 48MHz, just by
  board design recommendation

v11:
- Specify since when clock-output-names is unnecessary

v10:
- no changes

v9:
- New patch
---
 arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

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

-	refclk: clock-48mhz {
+	refclk: clock-ref {
 		/* 48 MHz reference oscillator */
 		compatible = "fixed-clock";
-		clock-output-names = "ref";
 		clock-frequency = <48000000>;
 		#clock-cells = <0>;
 	};

--
2.43.0


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

* [PATCH v12 6/6] ARM: dts: wpcm450: Switch clocks to clock controller
  2024-05-02 10:39 [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
                   ` (4 preceding siblings ...)
  2024-05-02 10:40 ` [PATCH v12 5/6] ARM: dts: wpcm450: Remove clock-output-names from reference clock node Jonathan Neuschäfer
@ 2024-05-02 10:40 ` Jonathan Neuschäfer
  5 siblings, 0 replies; 7+ messages in thread
From: Jonathan Neuschäfer @ 2024-05-02 10:40 UTC (permalink / raw)
  To: openbmc, linux-clk, devicetree
  Cc: Rob Herring, Conor Dooley, Stephen Boyd, Michael Turquette,
	linux-kernel, Jonathan Neuschäfer, Krzysztof Kozlowski,
	Joel Stanley, Philipp Zabel

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>
---

It's probably best to delay merging of this patch until after the driver
is merged; I'm including it here for review, and in case someone wants
to set up a shared branch between the clock and devicetree parts.

v12:
- work around timer-npcm7xx driver issue by providing timer clock separately

v11:
- no changes

v10:
- Reintroducing this patch as part of the clock/reset controller series
---
 arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi | 32 ++++++++++++++++----------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi
index ff153858801ccf..daf4d399ecab4c 100644
--- a/arch/arm/boot/dts/nuvoton/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton/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-ref {
 		/* 48 MHz reference oscillator */
 		compatible = "fixed-clock";
@@ -44,6 +38,19 @@ refclk: clock-ref {
 		#clock-cells = <0>;
 	};

+	refclk_div2: clock-refdiv2 {
+		/*
+		 * reference oscillator divided by 2, as a workaround because
+		 * the npcm7xx-timer driver needs its clock earlier than the
+		 * clk-wpcm450 driver (as a platform driver) can provide it.
+		 */
+		compatible = "fixed-factor-clock";
+		clocks = <&refclk>;
+		#clock-cells = <0>;
+		clock-mult = <1>;
+		clock-div = <2>;
+	};
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -70,7 +77,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";
@@ -81,7 +88,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";
 		};

@@ -89,14 +96,15 @@ timer0: timer@b8001000 {
 			compatible = "nuvoton,wpcm450-timer";
 			interrupts = <12 IRQ_TYPE_LEVEL_HIGH>;
 			reg = <0xb8001000 0x1c>;
-			clocks = <&clk24m>;
+			clocks = <&refclk_div2>,
+				 <&refclk_div2>;
 		};

 		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 {
@@ -480,7 +488,7 @@ fiu: spi-controller@c8000000 {
 			#size-cells = <0>;
 			reg = <0xc8000000 0x1000>, <0xc0000000 0x4000000>;
 			reg-names = "control", "memory";
-			clocks = <&clk 0>;
+			clocks = <&clk WPCM450_CLK_FIU>;
 			nuvoton,shm = <&shm>;
 			status = "disabled";
 		};

--
2.43.0


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

end of thread, other threads:[~2024-05-02 10:46 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-02 10:39 [PATCH v12 0/6] Nuvoton WPCM450 clock and reset driver Jonathan Neuschäfer
2024-05-02 10:40 ` [PATCH v12 1/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller Jonathan Neuschäfer
2024-05-02 10:40 ` [PATCH v12 2/6] clk: Introduce devm_clk_hw_register_divider_table_parent_data() Jonathan Neuschäfer
2024-05-02 10:40 ` [PATCH v12 3/6] clk: provider: Address documentation pitfall in struct clk_parent_data Jonathan Neuschäfer
2024-05-02 10:40 ` [PATCH v12 4/6] clk: wpcm450: Add Nuvoton WPCM450 clock/reset controller driver Jonathan Neuschäfer
2024-05-02 10:40 ` [PATCH v12 5/6] ARM: dts: wpcm450: Remove clock-output-names from reference clock node Jonathan Neuschäfer
2024-05-02 10:40 ` [PATCH v12 6/6] ARM: dts: wpcm450: Switch clocks to clock controller Jonathan Neuschäfer

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).