2022-06-10 07:46:24

by Jonathan Neuschäfer

[permalink] [raw]
Subject: [PATCH v4 0/6] Nuvoton WPCM450 clock and reset driver

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 watchdog patch should go via the watchdog tree
- The clock controller bindings and driver should go through the clk tree
- It might make 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.


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/[email protected]/
- 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/[email protected]/
- various small improvements

v1:
- https://lore.kernel.org/lkml/[email protected]/

Jonathan Neuschäfer (6):
dt-bindings: timer: nuvoton,npcm7xx-timer: Allow specifying all clocks
watchdog: npcm: Enable clock if provided
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
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 | 364 ++++++++++++++++++
drivers/reset/Kconfig | 2 +-
drivers/watchdog/npcm_wdt.c | 16 +
.../dt-bindings/clock/nuvoton,wpcm450-clk.h | 67 ++++
8 files changed, 544 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


2022-06-10 07:59:08

by Jonathan Neuschäfer

[permalink] [raw]
Subject: [PATCH v4 3/6] dt-bindings: clock: Add Nuvoton WPCM450 clock/reset controller

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 <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
---

v4:
- 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/[email protected]/
- Various improvements, suggested by Krzysztof Kozlowski

v1:
- https://lore.kernel.org/lkml/[email protected]/
---
.../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 <[email protected]>
+
+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

2022-06-10 08:00:33

by Jonathan Neuschäfer

[permalink] [raw]
Subject: [PATCH v4 4/6] ARM: dts: wpcm450: Add clock controller node

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 <[email protected]>
---

v4:
- no changes

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

v2:
- https://lore.kernel.org/lkml/[email protected]/
- 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

2022-06-10 08:00:41

by Jonathan Neuschäfer

[permalink] [raw]
Subject: [PATCH v4 2/6] watchdog: npcm: Enable clock if provided

On the Nuvoton WPCM450 SoC, with its upcoming clock driver, peripheral
clocks are individually gated and ungated. Therefore, the watchdog
driver must be able to ungate the watchdog clock.

Signed-off-by: Jonathan Neuschäfer <[email protected]>
---

v4:
- Don't disable clock in npcm_wdt_restart function

v3:
- https://lore.kernel.org/lkml/[email protected]/
- Add enable/disable calls to npcm_wdt_restart handler
- Not applied due to the above change: Acked-by: Guenter Roeck <[email protected]>

v2:
- https://lore.kernel.org/lkml/[email protected]/
- Add clk_disable_unprepare call, suggested by Guenter Roeck

v1:
- https://lore.kernel.org/lkml/[email protected]/
---
drivers/watchdog/npcm_wdt.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)

diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
index 28a24caa2627c..a5dd1c2301374 100644
--- a/drivers/watchdog/npcm_wdt.c
+++ b/drivers/watchdog/npcm_wdt.c
@@ -3,6 +3,7 @@
// Copyright (c) 2018 IBM Corp.

#include <linux/bitops.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -43,6 +44,7 @@
struct npcm_wdt {
struct watchdog_device wdd;
void __iomem *reg;
+ struct clk *clk;
};

static inline struct npcm_wdt *to_npcm_wdt(struct watchdog_device *wdd)
@@ -66,6 +68,9 @@ static int npcm_wdt_start(struct watchdog_device *wdd)
struct npcm_wdt *wdt = to_npcm_wdt(wdd);
u32 val;

+ if (wdt->clk)
+ clk_prepare_enable(wdt->clk);
+
if (wdd->timeout < 2)
val = 0x800;
else if (wdd->timeout < 3)
@@ -100,6 +105,9 @@ static int npcm_wdt_stop(struct watchdog_device *wdd)

writel(0, wdt->reg);

+ if (wdt->clk)
+ clk_disable_unprepare(wdt->clk);
+
return 0;
}

@@ -147,6 +155,10 @@ static int npcm_wdt_restart(struct watchdog_device *wdd,
{
struct npcm_wdt *wdt = to_npcm_wdt(wdd);

+ /* For reset, we start the WDT clock and leave it running. */
+ if (wdt->clk)
+ clk_prepare_enable(wdt->clk);
+
writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, wdt->reg);
udelay(1000);

@@ -191,6 +203,10 @@ static int npcm_wdt_probe(struct platform_device *pdev)
if (IS_ERR(wdt->reg))
return PTR_ERR(wdt->reg);

+ wdt->clk = devm_clk_get_optional(&pdev->dev, NULL);
+ if (IS_ERR(wdt->clk))
+ return PTR_ERR(wdt->clk);
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
--
2.35.1

2022-09-25 17:13:42

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v4 2/6] watchdog: npcm: Enable clock if provided

On Fri, Jun 10, 2022 at 09:21:37AM +0200, Jonathan Neusch?fer wrote:
> On the Nuvoton WPCM450 SoC, with its upcoming clock driver, peripheral
> clocks are individually gated and ungated. Therefore, the watchdog
> driver must be able to ungate the watchdog clock.
>
> Signed-off-by: Jonathan Neusch?fer <[email protected]>

Reviewed-by: Guenter Roeck <[email protected]>

> ---
>
> v4:
> - Don't disable clock in npcm_wdt_restart function
>
> v3:
> - https://lore.kernel.org/lkml/[email protected]/
> - Add enable/disable calls to npcm_wdt_restart handler
> - Not applied due to the above change: Acked-by: Guenter Roeck <[email protected]>
>
> v2:
> - https://lore.kernel.org/lkml/[email protected]/
> - Add clk_disable_unprepare call, suggested by Guenter Roeck
>
> v1:
> - https://lore.kernel.org/lkml/[email protected]/
> ---
> drivers/watchdog/npcm_wdt.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
>
> --
> 2.35.1
>
> diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c
> index 28a24caa2627c..a5dd1c2301374 100644
> --- a/drivers/watchdog/npcm_wdt.c
> +++ b/drivers/watchdog/npcm_wdt.c
> @@ -3,6 +3,7 @@
> // Copyright (c) 2018 IBM Corp.
>
> #include <linux/bitops.h>
> +#include <linux/clk.h>
> #include <linux/delay.h>
> #include <linux/interrupt.h>
> #include <linux/kernel.h>
> @@ -43,6 +44,7 @@
> struct npcm_wdt {
> struct watchdog_device wdd;
> void __iomem *reg;
> + struct clk *clk;
> };
>
> static inline struct npcm_wdt *to_npcm_wdt(struct watchdog_device *wdd)
> @@ -66,6 +68,9 @@ static int npcm_wdt_start(struct watchdog_device *wdd)
> struct npcm_wdt *wdt = to_npcm_wdt(wdd);
> u32 val;
>
> + if (wdt->clk)
> + clk_prepare_enable(wdt->clk);
> +
> if (wdd->timeout < 2)
> val = 0x800;
> else if (wdd->timeout < 3)
> @@ -100,6 +105,9 @@ static int npcm_wdt_stop(struct watchdog_device *wdd)
>
> writel(0, wdt->reg);
>
> + if (wdt->clk)
> + clk_disable_unprepare(wdt->clk);
> +
> return 0;
> }
>
> @@ -147,6 +155,10 @@ static int npcm_wdt_restart(struct watchdog_device *wdd,
> {
> struct npcm_wdt *wdt = to_npcm_wdt(wdd);
>
> + /* For reset, we start the WDT clock and leave it running. */
> + if (wdt->clk)
> + clk_prepare_enable(wdt->clk);
> +
> writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, wdt->reg);
> udelay(1000);
>
> @@ -191,6 +203,10 @@ static int npcm_wdt_probe(struct platform_device *pdev)
> if (IS_ERR(wdt->reg))
> return PTR_ERR(wdt->reg);
>
> + wdt->clk = devm_clk_get_optional(&pdev->dev, NULL);
> + if (IS_ERR(wdt->clk))
> + return PTR_ERR(wdt->clk);
> +
> irq = platform_get_irq(pdev, 0);
> if (irq < 0)
> return irq;