linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Add watchdog driver for Sunplus SP7021 SoC
@ 2021-11-12 10:59 Xiantao Hu
  2021-11-12 10:59 ` [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Xiantao Hu @ 2021-11-12 10:59 UTC (permalink / raw)
  To: wim, p.zabel, linux-kernel, linux-watchdog, linux, robh+dt, devicetree
  Cc: wells.lu, qinjian, Xiantao Hu

This is a patch series for watchdog driver for Sunplus SP7021 SoC.

Sunplus SP7021 is an ARM Cortex A7 (4 cores) based SoC. It integrates
many peripherals (ex: UART, I2C, SPI, SDIO, eMMC, USB, SD card and
etc.) into a single chip. It is designed for industrial control.

Refer to:
https://sunplus-tibbo.atlassian.net/wiki/spaces/doc/overview
https://tibbo.com/store/plus1.html

Xiantao Hu (2):
  watchdog: Add watchdog driver for Sunplus SP7021
  dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings
    documentation

 .../bindings/watchdog/sunplus,sp7021-wdt.yaml |  47 +++
 MAINTAINERS                                   |   7 +
 drivers/watchdog/Kconfig                      |  11 +
 drivers/watchdog/Makefile                     |   1 +
 drivers/watchdog/sunplus_wdt.c                | 297 ++++++++++++++++++
 5 files changed, 363 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
 create mode 100644 drivers/watchdog/sunplus_wdt.c

-- 
2.33.1


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

* [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-12 10:59 [PATCH 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
@ 2021-11-12 10:59 ` Xiantao Hu
  2021-11-12 14:45   ` Guenter Roeck
  2021-11-21  0:33   ` kernel test robot
  2021-11-12 10:59 ` [PATCH 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation Xiantao Hu
  2021-11-24 10:41 ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
  2 siblings, 2 replies; 17+ messages in thread
From: Xiantao Hu @ 2021-11-12 10:59 UTC (permalink / raw)
  To: wim, p.zabel, linux-kernel, linux-watchdog, linux, robh+dt, devicetree
  Cc: wells.lu, qinjian, Xiantao Hu

Sunplus SP7021 requires watchdog timer support.
Add watchdog driver to enable this.

Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
---
 MAINTAINERS                    |   6 +
 drivers/watchdog/Kconfig       |  11 ++
 drivers/watchdog/Makefile      |   1 +
 drivers/watchdog/sunplus_wdt.c | 297 +++++++++++++++++++++++++++++++++
 4 files changed, 315 insertions(+)
 create mode 100644 drivers/watchdog/sunplus_wdt.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e0bca0de0..f6a328772 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17933,6 +17933,12 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/ethernet/dlink/sundance.c
 
+SUNPLUS WATCHDOG DRIVER
+M:	Xiantao Hu <xt.hu@cqplus1.com>
+L:	linux-watchdog@vger.kernel.org
+S:	Maintained
+F:	drivers/watchdog/sunplus_wdt.c
+
 SUPERH
 M:	Yoshinori Sato <ysato@users.sourceforge.jp>
 M:	Rich Felker <dalias@libc.org>
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index bf59faeb3..1a95df8ed 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -990,6 +990,17 @@ config MSC313E_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called msc313e_wdt.
 
+config SUNPLUS_WATCHDOG
+	tristate "Sunplus watchdog support"
+	depends on ARCH_SUNPLUS || COMPILE_TEST
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include support for the watchdog timer
+	  in Sunplus SoCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sunplus_wdt.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 1bd2d6f37..d6a9e4d0e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -94,6 +94,7 @@ obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o
 obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o
 obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o
 obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o
+obj-$(CONFIG_SUNPLUS_WATCHDOG) += sunplus_wdt.o
 
 # X86 (i386 + ia64 + x86_64) Architecture
 obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
diff --git a/drivers/watchdog/sunplus_wdt.c b/drivers/watchdog/sunplus_wdt.c
new file mode 100644
index 000000000..27f22c518
--- /dev/null
+++ b/drivers/watchdog/sunplus_wdt.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * sunplus Watchdog Driver
+ *
+ * Copyright (C) 2021 Sunplus Technology Co., Ltd.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/watchdog.h>
+
+#define WDT_CTRL                0x00
+#define WDT_CNT                 0x04
+
+#define WDT_STOP				0x3877
+#define WDT_RESUME				0x4A4B
+#define WDT_CLRIRQ				0x7482
+#define WDT_UNLOCK				0xAB00
+#define WDT_LOCK				0xAB01
+#define WDT_CONMAX				0xDEAF
+
+#define RBUS_WDT_RST        BIT(1)
+#define STC_WDT_RST         BIT(4)
+
+#define MASK_SET(mask)		((mask) | (mask << 16))
+
+#define SP_WDT_MAX_TIMEOUT		11
+#define SP_WDT_MIN_TIMEOUT		1
+
+#define STC_CLK				90000
+
+#define DEVICE_NAME		"sunplus-wdt"
+
+static unsigned int timeout;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+			__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+struct sp_wdt_priv {
+	struct watchdog_device wdev;
+	void __iomem *base;
+	void __iomem *miscellaneous;
+	struct clk *clk;
+	struct reset_control *rstc;
+};
+
+static int sp_wdt_restart(struct watchdog_device *wdev,
+			       unsigned long action, void *data)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base;
+
+	base = priv->base;
+	writel(WDT_STOP, base + WDT_CTRL);
+	writel(WDT_UNLOCK, base + WDT_CTRL);
+	writel(0x0001, base + WDT_CNT);
+	writel(WDT_RESUME, base + WDT_CTRL);
+
+	return 0;
+}
+
+/* TIMEOUT_MAX = ffff0/90kHz =11.65,so longer than 11 seconds will time out */
+static int sp_wdt_ping(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+	u32 count;
+
+	writel(WDT_STOP, base + WDT_CTRL);
+	writel(WDT_UNLOCK, base + WDT_CTRL);
+	/* tiemrw_cnt[3:0]cant be write,only [19:4] can be write. */
+	count = (wdev->timeout * STC_CLK) >> 4;
+	writel(count, base + WDT_CNT);
+	writel(WDT_RESUME, base + WDT_CTRL);
+
+	return 0;
+}
+
+static int sp_wdt_set_timeout(struct watchdog_device *wdev,
+				   unsigned int timeout)
+{
+	wdev->timeout = timeout;
+
+	return 0;
+}
+
+static int sp_wdt_stop(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+
+	writel(WDT_STOP, base + WDT_CTRL);
+
+	return 0;
+}
+
+static int sp_wdt_start(struct watchdog_device *wdev)
+{
+	int ret;
+
+	ret = sp_wdt_set_timeout(wdev, wdev->timeout);
+	if (ret < 0)
+		return ret;
+
+	sp_wdt_ping(wdev);
+
+	return 0;
+}
+
+static unsigned int sp_wdt_get_timeleft(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+	u32 val;
+
+	val = readl(base + WDT_CNT);
+	val &= 0xffff;
+	val = val << 4;
+
+	return val;
+}
+
+/*
+ * 1.We need to reset watchdog flag(clear watchdog interrupt) here
+ * because watchdog timer driver does not have an interrupt handler,
+ * and before enalbe STC and RBUS watchdog timeout. Otherwise,
+ * the intr is always in the triggered state.
+ * 2.enable STC and RBUS watchdog timeout trigger.
+ * 3.watchdog conuter is running, need to be stopped.
+ */
+static int sp_wdt_hw_init(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+	void __iomem *miscellaneous = priv->miscellaneous;
+	u32 val;
+
+	writel(WDT_CLRIRQ, base + WDT_CTRL);
+	val = readl(miscellaneous);
+	val |= MASK_SET(STC_WDT_RST);
+	val |= MASK_SET(RBUS_WDT_RST);
+	writel(val, miscellaneous);
+
+	sp_wdt_stop(wdev);
+
+	return 0;
+}
+
+static const struct watchdog_info sp_wdt_info = {
+	.identity = DEVICE_NAME,
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+};
+
+static const struct watchdog_ops sp_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = sp_wdt_start,
+	.stop = sp_wdt_stop,
+	.ping = sp_wdt_ping,
+	.set_timeout = sp_wdt_set_timeout,
+	.get_timeleft = sp_wdt_get_timeleft,
+	.restart = sp_wdt_restart,
+};
+
+static int sp_wdt_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sp_wdt_priv *priv;
+	struct resource *wdt_res;
+	struct clk *clk;
+	int err;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "Can't find clock source\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	err = clk_prepare_enable(clk);
+	if (err) {
+		dev_err(dev, "Clock can't be enabled correctly\n");
+		return err;
+	}
+
+	priv->rstc = devm_reset_control_get_exclusive(dev, NULL);
+	if (!IS_ERR(priv->rstc))
+		reset_control_deassert(priv->rstc);
+
+	platform_set_drvdata(pdev, priv);
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	priv->miscellaneous =
+	    devm_ioremap(dev, wdt_res->start, resource_size(wdt_res));
+	if (IS_ERR(priv->miscellaneous))
+		return PTR_ERR(priv->miscellaneous);
+
+	priv->wdev.info = &sp_wdt_info;
+	priv->wdev.ops = &sp_wdt_ops;
+	priv->wdev.timeout = SP_WDT_MAX_TIMEOUT;
+	priv->wdev.max_timeout = SP_WDT_MAX_TIMEOUT;
+	priv->wdev.min_timeout = SP_WDT_MIN_TIMEOUT;
+	priv->wdev.parent = dev;
+
+	watchdog_set_drvdata(&priv->wdev, priv);
+	sp_wdt_hw_init(&priv->wdev);
+
+	watchdog_init_timeout(&priv->wdev, timeout, dev);
+	watchdog_set_nowayout(&priv->wdev, nowayout);
+	watchdog_stop_on_reboot(&priv->wdev);
+
+	err = devm_watchdog_register_device(dev, &priv->wdev);
+	if (unlikely(err))
+		return err;
+
+	dev_info(dev, "Watchdog enabled (timeout=%d sec%s.)\n",
+		 priv->wdev.timeout, nowayout ? ", nowayout" : "");
+
+	return 0;
+}
+
+static int sp_wdt_remove(struct platform_device *pdev)
+{
+	struct sp_wdt_priv *priv = platform_get_drvdata(pdev);
+
+	watchdog_unregister_device(&priv->wdev);
+
+	reset_control_assert(priv->rstc);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static const struct of_device_id sp_wdt_of_match[] = {
+	{.compatible = "sunplus,sp7021-wdt", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sp_wdt_of_match);
+
+static int __maybe_unused sp_wdt_suspend(struct device *dev)
+{
+	struct sp_wdt_priv *priv = dev_get_drvdata(dev);
+
+	if (watchdog_active(&priv->wdev))
+		sp_wdt_stop(&priv->wdev);
+
+	reset_control_assert(priv->rstc);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static int __maybe_unused sp_wdt_resume(struct device *dev)
+{
+	struct sp_wdt_priv *priv = dev_get_drvdata(dev);
+
+	if (watchdog_active(&priv->wdev))
+		sp_wdt_start(&priv->wdev);
+
+	reset_control_deassert(priv->rstc);
+	clk_prepare_enable(priv->clk);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(sp_wdt_pm_ops, sp_wdt_suspend, sp_wdt_resume);
+
+static struct platform_driver sp_wdt_driver = {
+	.probe = sp_wdt_probe,
+	.remove = sp_wdt_remove,
+	.driver = {
+		   .name = DEVICE_NAME,
+		   .of_match_table = sp_wdt_of_match,
+		   .pm = &sp_wdt_pm_ops,
+	},
+};
+
+module_platform_driver(sp_wdt_driver);
+
+MODULE_AUTHOR("Xiantao Hu <xt.hu@cqplus1.com>");
+MODULE_DESCRIPTION("Sunplus Watchdog Timer Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.33.1


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

* [PATCH 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation
  2021-11-12 10:59 [PATCH 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
  2021-11-12 10:59 ` [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
@ 2021-11-12 10:59 ` Xiantao Hu
  2021-11-24 10:41 ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
  2 siblings, 0 replies; 17+ messages in thread
From: Xiantao Hu @ 2021-11-12 10:59 UTC (permalink / raw)
  To: wim, p.zabel, linux-kernel, linux-watchdog, linux, robh+dt, devicetree
  Cc: wells.lu, qinjian, Xiantao Hu

This adds the documentation for the devicetree bindings of the Sunplus
SP7021 watchdog driver, found from SP7021 SoCs and newer.

Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
---
 .../bindings/watchdog/sunplus,sp7021-wdt.yaml | 47 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml

diff --git a/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml b/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
new file mode 100644
index 000000000..bb728f298
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) Sunplus Co., Ltd. 2021
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/sunplus,sp7021-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sunplus SoCs Watchdog Device Tree Bindings
+
+maintainers:
+  - XianTao Hu <xt.hu@cqplus1.com>
+
+allOf:
+  - $ref: watchdog.yaml#
+
+properties:
+  compatible:
+    const: sunplus,sp7021-wdt
+
+  reg:
+    items:
+      - description: Base address and length of the watchdog registers
+      - description: Base address and length of the miscellaneous control registers
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+
+additionalProperties: false
+
+examples:
+  - |
+    watchdog: watchdog@9c000630 {
+        compatible = "sunplus,sp7021-wdt";
+        reg = <0x9c000630 0x08>, <0x9C000274 0x04>;
+        clocks = <&clkc 0x24>;
+        resets = <&rstc 0x14>;
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index f6a328772..d51f0cb1a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17937,6 +17937,7 @@ SUNPLUS WATCHDOG DRIVER
 M:	Xiantao Hu <xt.hu@cqplus1.com>
 L:	linux-watchdog@vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
 F:	drivers/watchdog/sunplus_wdt.c
 
 SUPERH
-- 
2.33.1


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

* Re: [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-12 10:59 ` [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
@ 2021-11-12 14:45   ` Guenter Roeck
  2021-11-24 10:31     ` xt.hu[胡先韬]
  2021-11-21  0:33   ` kernel test robot
  1 sibling, 1 reply; 17+ messages in thread
From: Guenter Roeck @ 2021-11-12 14:45 UTC (permalink / raw)
  To: Xiantao Hu, wim, p.zabel, linux-kernel, linux-watchdog, robh+dt,
	devicetree
  Cc: wells.lu, qinjian

On 11/12/21 2:59 AM, Xiantao Hu wrote:
> Sunplus SP7021 requires watchdog timer support.
> Add watchdog driver to enable this.
> 
> Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
> ---
>   MAINTAINERS                    |   6 +
>   drivers/watchdog/Kconfig       |  11 ++
>   drivers/watchdog/Makefile      |   1 +
>   drivers/watchdog/sunplus_wdt.c | 297 +++++++++++++++++++++++++++++++++
>   4 files changed, 315 insertions(+)
>   create mode 100644 drivers/watchdog/sunplus_wdt.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e0bca0de0..f6a328772 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17933,6 +17933,12 @@ L:	netdev@vger.kernel.org
>   S:	Maintained
>   F:	drivers/net/ethernet/dlink/sundance.c
>   
> +SUNPLUS WATCHDOG DRIVER
> +M:	Xiantao Hu <xt.hu@cqplus1.com>
> +L:	linux-watchdog@vger.kernel.org
> +S:	Maintained
> +F:	drivers/watchdog/sunplus_wdt.c
> +
>   SUPERH
>   M:	Yoshinori Sato <ysato@users.sourceforge.jp>
>   M:	Rich Felker <dalias@libc.org>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index bf59faeb3..1a95df8ed 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -990,6 +990,17 @@ config MSC313E_WATCHDOG
>   	  To compile this driver as a module, choose M here: the
>   	  module will be called msc313e_wdt.
>   
> +config SUNPLUS_WATCHDOG
> +	tristate "Sunplus watchdog support"
> +	depends on ARCH_SUNPLUS || COMPILE_TEST
> +	select WATCHDOG_CORE
> +	help
> +	  Say Y here to include support for the watchdog timer
> +	  in Sunplus SoCs.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called sunplus_wdt.
> +
>   # X86 (i386 + ia64 + x86_64) Architecture
>   
>   config ACQUIRE_WDT
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 1bd2d6f37..d6a9e4d0e 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -94,6 +94,7 @@ obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o
>   obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o
>   obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o
>   obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o
> +obj-$(CONFIG_SUNPLUS_WATCHDOG) += sunplus_wdt.o
>   
>   # X86 (i386 + ia64 + x86_64) Architecture
>   obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
> diff --git a/drivers/watchdog/sunplus_wdt.c b/drivers/watchdog/sunplus_wdt.c
> new file mode 100644
> index 000000000..27f22c518
> --- /dev/null
> +++ b/drivers/watchdog/sunplus_wdt.c
> @@ -0,0 +1,297 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * sunplus Watchdog Driver
> + *
> + * Copyright (C) 2021 Sunplus Technology Co., Ltd.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/watchdog.h>
> +
> +#define WDT_CTRL                0x00
> +#define WDT_CNT                 0x04
> +
> +#define WDT_STOP				0x3877
> +#define WDT_RESUME				0x4A4B
> +#define WDT_CLRIRQ				0x7482
> +#define WDT_UNLOCK				0xAB00
> +#define WDT_LOCK				0xAB01
> +#define WDT_CONMAX				0xDEAF
> +
> +#define RBUS_WDT_RST        BIT(1)
> +#define STC_WDT_RST         BIT(4)
> +
> +#define MASK_SET(mask)		((mask) | (mask << 16))
> +
> +#define SP_WDT_MAX_TIMEOUT		11
> +#define SP_WDT_MIN_TIMEOUT		1
> +
> +#define STC_CLK				90000
> +
> +#define DEVICE_NAME		"sunplus-wdt"
> +
> +static unsigned int timeout;
> +module_param(timeout, int, 0);
> +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
> +
> +static bool nowayout = WATCHDOG_NOWAYOUT;
> +module_param(nowayout, bool, 0);
> +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
> +			__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
> +
> +struct sp_wdt_priv {
> +	struct watchdog_device wdev;
> +	void __iomem *base;
> +	void __iomem *miscellaneous;

Please find a better name for this variable. Also, unless I am
missing something, it is only used in the init function. That means
it can be passed to that function as parameter and doesn't need
to be stored in sp_wdt_priv.

> +	struct clk *clk;
> +	struct reset_control *rstc;
> +};
> +
> +static int sp_wdt_restart(struct watchdog_device *wdev,
> +			       unsigned long action, void *data)
> +{
> +	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	void __iomem *base;
> +
> +	base = priv->base;
> +	writel(WDT_STOP, base + WDT_CTRL);
> +	writel(WDT_UNLOCK, base + WDT_CTRL);
> +	writel(0x0001, base + WDT_CNT);
> +	writel(WDT_RESUME, base + WDT_CTRL);
> +
> +	return 0;
> +}
> +
> +/* TIMEOUT_MAX = ffff0/90kHz =11.65,so longer than 11 seconds will time out */
> +static int sp_wdt_ping(struct watchdog_device *wdev)
> +{
> +	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	void __iomem *base = priv->base;
> +	u32 count;
> +
> +	writel(WDT_STOP, base + WDT_CTRL);
> +	writel(WDT_UNLOCK, base + WDT_CTRL);
> +	/* tiemrw_cnt[3:0]cant be write,only [19:4] can be write. */
> +	count = (wdev->timeout * STC_CLK) >> 4;
> +	writel(count, base + WDT_CNT);
> +	writel(WDT_RESUME, base + WDT_CTRL);
> +
> +	return 0;
> +}
> +
> +static int sp_wdt_set_timeout(struct watchdog_device *wdev,
> +				   unsigned int timeout)
> +{
> +	wdev->timeout = timeout;
> +

I would assume this also needs to set the new timeout in HW if
the watchdog is running, or the watchdog could time out before
userspace sends another ping.

> +	return 0;
> +}
> +
> +static int sp_wdt_stop(struct watchdog_device *wdev)
> +{
> +	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	void __iomem *base = priv->base;
> +
> +	writel(WDT_STOP, base + WDT_CTRL);
> +
> +	return 0;
> +}
> +
> +static int sp_wdt_start(struct watchdog_device *wdev)
> +{
> +	int ret;
> +
> +	ret = sp_wdt_set_timeout(wdev, wdev->timeout);

That function never returns an error, so checking for it is
pointless here.

> +	if (ret < 0)
> +		return ret;
> +
> +	sp_wdt_ping(wdev);
> +
> +	return 0;
> +}
> +
> +static unsigned int sp_wdt_get_timeleft(struct watchdog_device *wdev)
> +{
> +	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	void __iomem *base = priv->base;
> +	u32 val;
> +
> +	val = readl(base + WDT_CNT);
> +	val &= 0xffff;
> +	val = val << 4;
> +
> +	return val;
> +}
> +
> +/*
> + * 1.We need to reset watchdog flag(clear watchdog interrupt) here
> + * because watchdog timer driver does not have an interrupt handler,
> + * and before enalbe STC and RBUS watchdog timeout. Otherwise,

enable

> + * the intr is always in the triggered state.
> + * 2.enable STC and RBUS watchdog timeout trigger.
> + * 3.watchdog conuter is running, need to be stopped.

counter

> + */
> +static int sp_wdt_hw_init(struct watchdog_device *wdev)
> +{
> +	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
> +	void __iomem *base = priv->base;
> +	void __iomem *miscellaneous = priv->miscellaneous;
> +	u32 val;
> +
> +	writel(WDT_CLRIRQ, base + WDT_CTRL);
> +	val = readl(miscellaneous);
> +	val |= MASK_SET(STC_WDT_RST);
> +	val |= MASK_SET(RBUS_WDT_RST);
> +	writel(val, miscellaneous);
> +
> +	sp_wdt_stop(wdev);
> +
> +	return 0;
> +}
> +
> +static const struct watchdog_info sp_wdt_info = {
> +	.identity = DEVICE_NAME,
> +	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
> +};
> +
> +static const struct watchdog_ops sp_wdt_ops = {
> +	.owner = THIS_MODULE,
> +	.start = sp_wdt_start,
> +	.stop = sp_wdt_stop,
> +	.ping = sp_wdt_ping,
> +	.set_timeout = sp_wdt_set_timeout,
> +	.get_timeleft = sp_wdt_get_timeleft,
> +	.restart = sp_wdt_restart,
> +};
> +
> +static int sp_wdt_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct sp_wdt_priv *priv;
> +	struct resource *wdt_res;
> +	struct clk *clk;
> +	int err;
> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(priv->clk)) {
> +		dev_err(dev, "Can't find clock source\n");
> +		return PTR_ERR(priv->clk);
> +	}
> +
> +	err = clk_prepare_enable(clk);
> +	if (err) {
> +		dev_err(dev, "Clock can't be enabled correctly\n");
> +		return err;
> +	}
> +
> +	priv->rstc = devm_reset_control_get_exclusive(dev, NULL);
> +	if (!IS_ERR(priv->rstc))
> +		reset_control_deassert(priv->rstc);
> +
> +	platform_set_drvdata(pdev, priv);
> +
> +	priv->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(priv->base))
> +		return PTR_ERR(priv->base);
> +
> +	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	priv->miscellaneous =
> +	    devm_ioremap(dev, wdt_res->start, resource_size(wdt_res));

Why not use devm_ioremap_resource() ? Or, for that matter,
devm_platform_ioremap_resource() like above ?

> +	if (IS_ERR(priv->miscellaneous))
> +		return PTR_ERR(priv->miscellaneous);
> +
> +	priv->wdev.info = &sp_wdt_info;
> +	priv->wdev.ops = &sp_wdt_ops;
> +	priv->wdev.timeout = SP_WDT_MAX_TIMEOUT;
> +	priv->wdev.max_timeout = SP_WDT_MAX_TIMEOUT;
> +	priv->wdev.min_timeout = SP_WDT_MIN_TIMEOUT;

THis should really use max_hw_heartbeat_ms to let the core
ping the watchdog if larger timeouts are desired.

> +	priv->wdev.parent = dev;
> +
> +	watchdog_set_drvdata(&priv->wdev, priv);
> +	sp_wdt_hw_init(&priv->wdev);
> +
> +	watchdog_init_timeout(&priv->wdev, timeout, dev);
> +	watchdog_set_nowayout(&priv->wdev, nowayout);
> +	watchdog_stop_on_reboot(&priv->wdev);
> +
> +	err = devm_watchdog_register_device(dev, &priv->wdev);

Since you call watchdog_unregister_device() below you can not use
the devm_ function here.

> +	if (unlikely(err))

This is not time critical. Drop the unlikely.

> +		return err;
> +
> +	dev_info(dev, "Watchdog enabled (timeout=%d sec%s.)\n",
> +		 priv->wdev.timeout, nowayout ? ", nowayout" : "");
> +
> +	return 0;
> +}
> +
> +static int sp_wdt_remove(struct platform_device *pdev)
> +{
> +	struct sp_wdt_priv *priv = platform_get_drvdata(pdev);
> +
> +	watchdog_unregister_device(&priv->wdev);
> +
> +	reset_control_assert(priv->rstc);
> +	clk_disable_unprepare(priv->clk);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id sp_wdt_of_match[] = {
> +	{.compatible = "sunplus,sp7021-wdt", },
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(of, sp_wdt_of_match);
> +
> +static int __maybe_unused sp_wdt_suspend(struct device *dev)
> +{
> +	struct sp_wdt_priv *priv = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&priv->wdev))
> +		sp_wdt_stop(&priv->wdev);
> +
> +	reset_control_assert(priv->rstc);
> +	clk_disable_unprepare(priv->clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused sp_wdt_resume(struct device *dev)
> +{
> +	struct sp_wdt_priv *priv = dev_get_drvdata(dev);
> +
> +	if (watchdog_active(&priv->wdev))
> +		sp_wdt_start(&priv->wdev);
> +
Shouldn't the order be the opposite of the order in the suspend function ?

> +	reset_control_deassert(priv->rstc);
> +	clk_prepare_enable(priv->clk);
> +
> +	return 0;
> +}
> +
> +static SIMPLE_DEV_PM_OPS(sp_wdt_pm_ops, sp_wdt_suspend, sp_wdt_resume);
> +
> +static struct platform_driver sp_wdt_driver = {
> +	.probe = sp_wdt_probe,
> +	.remove = sp_wdt_remove,
> +	.driver = {
> +		   .name = DEVICE_NAME,
> +		   .of_match_table = sp_wdt_of_match,
> +		   .pm = &sp_wdt_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(sp_wdt_driver);
> +
> +MODULE_AUTHOR("Xiantao Hu <xt.hu@cqplus1.com>");
> +MODULE_DESCRIPTION("Sunplus Watchdog Timer Driver");
> +MODULE_LICENSE("GPL v2");
> 


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

* Re: [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-12 10:59 ` [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
  2021-11-12 14:45   ` Guenter Roeck
@ 2021-11-21  0:33   ` kernel test robot
  1 sibling, 0 replies; 17+ messages in thread
From: kernel test robot @ 2021-11-21  0:33 UTC (permalink / raw)
  To: Xiantao Hu, wim, p.zabel, linux-kernel, linux-watchdog, linux,
	robh+dt, devicetree
  Cc: llvm, kbuild-all, wells.lu, qinjian, Xiantao Hu

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

Hi Xiantao,

I love your patch! Perhaps something to improve:

[auto build test WARNING on pza/reset/next]
[also build test WARNING on robh/for-next linux/master linus/master v5.16-rc1 next-20211118]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Xiantao-Hu/Add-watchdog-driver-for-Sunplus-SP7021-SoC/20211112-191201
base:   https://git.pengutronix.de/git/pza/linux reset/next
config: arm64-randconfig-r023-20211115 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project fbe72e41b99dc7994daac300d208a955be3e4a0a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/0day-ci/linux/commit/eac808eeed4a851ca5cfef12adefd6df199f62c2
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Xiantao-Hu/Add-watchdog-driver-for-Sunplus-SP7021-SoC/20211112-191201
        git checkout eac808eeed4a851ca5cfef12adefd6df199f62c2
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=arm64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/watchdog/sunplus_wdt.c:191:27: warning: variable 'clk' is uninitialized when used here [-Wuninitialized]
           err = clk_prepare_enable(clk);
                                    ^~~
   drivers/watchdog/sunplus_wdt.c:178:17: note: initialize the variable 'clk' to silence this warning
           struct clk *clk;
                          ^
                           = NULL
   1 warning generated.


vim +/clk +191 drivers/watchdog/sunplus_wdt.c

   172	
   173	static int sp_wdt_probe(struct platform_device *pdev)
   174	{
   175		struct device *dev = &pdev->dev;
   176		struct sp_wdt_priv *priv;
   177		struct resource *wdt_res;
   178		struct clk *clk;
   179		int err;
   180	
   181		priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
   182		if (!priv)
   183			return -ENOMEM;
   184	
   185		priv->clk = devm_clk_get(dev, NULL);
   186		if (IS_ERR(priv->clk)) {
   187			dev_err(dev, "Can't find clock source\n");
   188			return PTR_ERR(priv->clk);
   189		}
   190	
 > 191		err = clk_prepare_enable(clk);
   192		if (err) {
   193			dev_err(dev, "Clock can't be enabled correctly\n");
   194			return err;
   195		}
   196	
   197		priv->rstc = devm_reset_control_get_exclusive(dev, NULL);
   198		if (!IS_ERR(priv->rstc))
   199			reset_control_deassert(priv->rstc);
   200	
   201		platform_set_drvdata(pdev, priv);
   202	
   203		priv->base = devm_platform_ioremap_resource(pdev, 0);
   204		if (IS_ERR(priv->base))
   205			return PTR_ERR(priv->base);
   206	
   207		wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
   208		priv->miscellaneous =
   209		    devm_ioremap(dev, wdt_res->start, resource_size(wdt_res));
   210		if (IS_ERR(priv->miscellaneous))
   211			return PTR_ERR(priv->miscellaneous);
   212	
   213		priv->wdev.info = &sp_wdt_info;
   214		priv->wdev.ops = &sp_wdt_ops;
   215		priv->wdev.timeout = SP_WDT_MAX_TIMEOUT;
   216		priv->wdev.max_timeout = SP_WDT_MAX_TIMEOUT;
   217		priv->wdev.min_timeout = SP_WDT_MIN_TIMEOUT;
   218		priv->wdev.parent = dev;
   219	
   220		watchdog_set_drvdata(&priv->wdev, priv);
   221		sp_wdt_hw_init(&priv->wdev);
   222	
   223		watchdog_init_timeout(&priv->wdev, timeout, dev);
   224		watchdog_set_nowayout(&priv->wdev, nowayout);
   225		watchdog_stop_on_reboot(&priv->wdev);
   226	
   227		err = devm_watchdog_register_device(dev, &priv->wdev);
   228		if (unlikely(err))
   229			return err;
   230	
   231		dev_info(dev, "Watchdog enabled (timeout=%d sec%s.)\n",
   232			 priv->wdev.timeout, nowayout ? ", nowayout" : "");
   233	
   234		return 0;
   235	}
   236	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 39807 bytes --]

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

* RE: [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-12 14:45   ` Guenter Roeck
@ 2021-11-24 10:31     ` xt.hu[胡先韬]
  0 siblings, 0 replies; 17+ messages in thread
From: xt.hu[胡先韬] @ 2021-11-24 10:31 UTC (permalink / raw)
  To: Guenter Roeck, wim, p.zabel, linux-kernel, linux-watchdog,
	robh+dt, devicetree
  Cc: Wells Lu 呂芳騰, qinjian[覃健]

Hi, Guenter Roeck :

Thanks for your review. Sorry I was so focused on fixing code and 
I forgot to respond to the email. I modify the code as you comment
and answer the question.

Thanks
Best Regards,
Xiantao Hu

> -----Original Message-----
> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
> Sent: Friday, November 12, 2021 10:46 PM
> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>; wim@linux-watchdog.org; p.zabel@pengutronix.de;
> linux-kernel@vger.kernel.org; linux-watchdog@vger.kernel.org; robh+dt@kernel.org;
> devicetree@vger.kernel.org
> Cc: Wells Lu 呂芳騰 <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
> Subject: Re: [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021
> 
> On 11/12/21 2:59 AM, Xiantao Hu wrote:
> > Sunplus SP7021 requires watchdog timer support.
> > Add watchdog driver to enable this.
> >
> > Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
...
> > +struct sp_wdt_priv {
> > +	struct watchdog_device wdev;
> > +	void __iomem *base;
> > +	void __iomem *miscellaneous;
> 
> Please find a better name for this variable. Also, unless I am
> missing something, it is only used in the init function. That means
> it can be passed to that function as parameter and doesn't need
> to be stored in sp_wdt_priv.
> 

I will remove the miscellaneous from sp_wdt_priv and pass
to that function as parameter.

> > +	struct clk *clk;
> > +	struct reset_control *rstc;
> > +};
...
> > +static int sp_wdt_set_timeout(struct watchdog_device *wdev,
> > +				   unsigned int timeout)
> > +{
> > +	wdev->timeout = timeout;
> > +
> 
> I would assume this also needs to set the new timeout in HW if
> the watchdog is running, or the watchdog could time out before
> userspace sends another ping.
> 

I will call the ping() after assigning timeout.

> > +	return 0;
> > +}
> > +
...
> > +
> > +static int sp_wdt_start(struct watchdog_device *wdev)
> > +{
> > +	int ret;
> > +
> > +	ret = sp_wdt_set_timeout(wdev, wdev->timeout);
> 
> That function never returns an error, so checking for it is
> pointless here.
> 

I will remove the variable ret.

> > +	if (ret < 0)
> > +		return ret;
> > +
...
> > +/*
> > + * 1.We need to reset watchdog flag(clear watchdog interrupt) here
> > + * because watchdog timer driver does not have an interrupt handler,
> > + * and before enalbe STC and RBUS watchdog timeout. Otherwise,
> 
> enable
> 

I will fix it.

> > + * the intr is always in the triggered state.
> > + * 2.enable STC and RBUS watchdog timeout trigger.
> > + * 3.watchdog conuter is running, need to be stopped.
> 
> counter
> 

I will fix it.

> > + */
...
> > +
> > +	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> > +	priv->miscellaneous =
> > +	    devm_ioremap(dev, wdt_res->start, resource_size(wdt_res));
> 
> Why not use devm_ioremap_resource() ? Or, for that matter,
> devm_platform_ioremap_resource() like above ?
> 

The function of this register is miscellaneous. The register 
accessed here shared by multiple drivers. Use the function 
of devm_platform_ioremap_resource() which internally
call request_mem_region() causes an error. So I handle it 
in this way. Any better ways?

> > +	if (IS_ERR(priv->miscellaneous))
> > +		return PTR_ERR(priv->miscellaneous);
> > +
> > +	priv->wdev.info = &sp_wdt_info;
> > +	priv->wdev.ops = &sp_wdt_ops;
> > +	priv->wdev.timeout = SP_WDT_MAX_TIMEOUT;
> > +	priv->wdev.max_timeout = SP_WDT_MAX_TIMEOUT;
> > +	priv->wdev.min_timeout = SP_WDT_MIN_TIMEOUT;
> 
> THis should really use max_hw_heartbeat_ms to let the core
> ping the watchdog if larger timeouts are desired.
> 

I will add the max_hw_heartbeat_ms and modify the 
ping ().

> > +	priv->wdev.parent = dev;
> > +
> > +	watchdog_set_drvdata(&priv->wdev, priv);
> > +	sp_wdt_hw_init(&priv->wdev);
> > +
> > +	watchdog_init_timeout(&priv->wdev, timeout, dev);
> > +	watchdog_set_nowayout(&priv->wdev, nowayout);
> > +	watchdog_stop_on_reboot(&priv->wdev);
> > +
> > +	err = devm_watchdog_register_device(dev, &priv->wdev);
> 
> Since you call watchdog_unregister_device() below you can not use
> the devm_ function here.
> 

I will drop the function remove() and not call watchdog_unregister_device() .
Use the devm_add_action_or_reset() add reset_control_assert() and
clk_disable_unprepare().

> > +	if (unlikely(err))
> 
> This is not time critical. Drop the unlikely.
> 

I will fix it.

> > +		return err;
> > +
> > +	dev_info(dev, "Watchdog enabled (timeout=%d sec%s.)\n",
> > +		 priv->wdev.timeout, nowayout ? ", nowayout" : "");
> > +
> > +	return 0;
> > +}
> > +
> > +static int sp_wdt_remove(struct platform_device *pdev)
> > +{
> > +	struct sp_wdt_priv *priv = platform_get_drvdata(pdev);
> > +
> > +	watchdog_unregister_device(&priv->wdev);
> > +
> > +	reset_control_assert(priv->rstc);
> > +	clk_disable_unprepare(priv->clk);
> > +
> > +	return 0;
> > +}
> > +
...
> > +
> > +static int __maybe_unused sp_wdt_resume(struct device *dev)
> > +{
> > +	struct sp_wdt_priv *priv = dev_get_drvdata(dev);
> > +
> > +	if (watchdog_active(&priv->wdev))
> > +		sp_wdt_start(&priv->wdev);
> > +
> Shouldn't the order be the opposite of the order in the suspend function ?
>
 
I will fix it.

> > +	reset_control_deassert(priv->rstc);
> > +	clk_prepare_enable(priv->clk);
> > +
> > +	return 0;
> > +}
> >
...
> >


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

* [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC
  2021-11-12 10:59 [PATCH 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
  2021-11-12 10:59 ` [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
  2021-11-12 10:59 ` [PATCH 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation Xiantao Hu
@ 2021-11-24 10:41 ` Xiantao Hu
  2021-11-24 10:41   ` [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
                     ` (2 more replies)
  2 siblings, 3 replies; 17+ messages in thread
From: Xiantao Hu @ 2021-11-24 10:41 UTC (permalink / raw)
  To: wim, p.zabel, linux-kernel, linux-watchdog, linux, robh+dt, devicetree
  Cc: wells.lu, qinjian, Xiantao Hu

This is a patch series for watchdog driver for Sunplus SP7021 SoC.

Sunplus SP7021 is an ARM Cortex A7 (4 cores) based SoC. It integrates
many peripherals (ex: UART, I2C, SPI, SDIO, eMMC, USB, SD card and
etc.) into a single chip. It is designed for industrial control.

Refer to:
https://sunplus-tibbo.atlassian.net/wiki/spaces/doc/overview
https://tibbo.com/store/plus1.html

Xiantao Hu (2):
  watchdog: Add watchdog driver for Sunplus SP7021
  dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings
    documentation

 .../bindings/watchdog/sunplus,sp7021-wdt.yaml |  47 +++
 MAINTAINERS                                   |   7 +
 drivers/watchdog/Kconfig                      |  11 +
 drivers/watchdog/Makefile                     |   1 +
 drivers/watchdog/sunplus_wdt.c                | 322 ++++++++++++++++++
 5 files changed, 388 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
 create mode 100644 drivers/watchdog/sunplus_wdt.c

-- 
2.33.1


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

* [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-24 10:41 ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
@ 2021-11-24 10:41   ` Xiantao Hu
  2021-11-24 14:25     ` Guenter Roeck
  2021-11-24 10:41   ` [PATCH v2 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation Xiantao Hu
  2021-11-24 14:17   ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Guenter Roeck
  2 siblings, 1 reply; 17+ messages in thread
From: Xiantao Hu @ 2021-11-24 10:41 UTC (permalink / raw)
  To: wim, p.zabel, linux-kernel, linux-watchdog, linux, robh+dt, devicetree
  Cc: wells.lu, qinjian, Xiantao Hu

Sunplus SP7021 requires watchdog timer support.
Add watchdog driver to enable this.

Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
---
Changes in v2:
 - Addressed all comments from Mr. Guenter Roeck
 - Drop the remove()

 MAINTAINERS                    |   6 +
 drivers/watchdog/Kconfig       |  11 ++
 drivers/watchdog/Makefile      |   1 +
 drivers/watchdog/sunplus_wdt.c | 322 +++++++++++++++++++++++++++++++++
 4 files changed, 340 insertions(+)
 create mode 100644 drivers/watchdog/sunplus_wdt.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e0bca0de0..f6a328772 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17933,6 +17933,12 @@ L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/ethernet/dlink/sundance.c
 
+SUNPLUS WATCHDOG DRIVER
+M:	Xiantao Hu <xt.hu@cqplus1.com>
+L:	linux-watchdog@vger.kernel.org
+S:	Maintained
+F:	drivers/watchdog/sunplus_wdt.c
+
 SUPERH
 M:	Yoshinori Sato <ysato@users.sourceforge.jp>
 M:	Rich Felker <dalias@libc.org>
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index bf59faeb3..1a95df8ed 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -990,6 +990,17 @@ config MSC313E_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called msc313e_wdt.
 
+config SUNPLUS_WATCHDOG
+	tristate "Sunplus watchdog support"
+	depends on ARCH_SUNPLUS || COMPILE_TEST
+	select WATCHDOG_CORE
+	help
+	  Say Y here to include support for the watchdog timer
+	  in Sunplus SoCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sunplus_wdt.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 1bd2d6f37..d6a9e4d0e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -94,6 +94,7 @@ obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o
 obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o
 obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o
 obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o
+obj-$(CONFIG_SUNPLUS_WATCHDOG) += sunplus_wdt.o
 
 # X86 (i386 + ia64 + x86_64) Architecture
 obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
diff --git a/drivers/watchdog/sunplus_wdt.c b/drivers/watchdog/sunplus_wdt.c
new file mode 100644
index 000000000..44abc04df
--- /dev/null
+++ b/drivers/watchdog/sunplus_wdt.c
@@ -0,0 +1,322 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * sunplus Watchdog Driver
+ *
+ * Copyright (C) 2021 Sunplus Technology Co., Ltd.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/watchdog.h>
+
+#define WDT_CTRL                0x00
+#define WDT_CNT                 0x04
+
+#define WDT_STOP				0x3877
+#define WDT_RESUME				0x4A4B
+#define WDT_CLRIRQ				0x7482
+#define WDT_UNLOCK				0xAB00
+#define WDT_LOCK				0xAB01
+#define WDT_CONMAX				0xDEAF
+
+#define RBUS_WDT_RST        BIT(1)
+#define STC_WDT_RST         BIT(4)
+
+#define MASK_SET(mask)		((mask) | (mask << 16))
+
+#define SP_WDT_MAX_TIMEOUT		11U
+#define SP_WDT_DEFAULT_TIMEOUT	10
+
+#define STC_CLK				90000
+
+#define DEVICE_NAME		"sunplus-wdt"
+
+static unsigned int timeout;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+			__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+struct sp_wdt_priv {
+	struct watchdog_device wdev;
+	void __iomem *base;
+	struct clk *clk;
+	struct reset_control *rstc;
+};
+
+static int sp_wdt_restart(struct watchdog_device *wdev,
+			       unsigned long action, void *data)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+
+	writel(WDT_STOP, base + WDT_CTRL);
+	writel(WDT_UNLOCK, base + WDT_CTRL);
+	writel(0x0001, base + WDT_CNT);
+	writel(WDT_LOCK, base + WDT_CTRL);
+	writel(WDT_RESUME, base + WDT_CTRL);
+
+	return 0;
+}
+
+/* TIMEOUT_MAX = ffff0/90kHz =11.65,so longer than 11 seconds will time out */
+static int sp_wdt_ping(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+	u32 count;
+	u32 actual;
+
+	actual = min(wdev->timeout, SP_WDT_MAX_TIMEOUT);
+
+	if (actual > SP_WDT_MAX_TIMEOUT) {
+		writel(WDT_CONMAX, base + WDT_CTRL);
+	} else {
+		writel(WDT_UNLOCK, base + WDT_CTRL);
+		/* tiemrw_cnt[3:0]can't be write,only [19:4] can be write. */
+		count = (actual * STC_CLK) >> 4;
+		writel(count, base + WDT_CNT);
+		writel(WDT_LOCK, base + WDT_CTRL);
+	}
+
+	return 0;
+}
+
+static int sp_wdt_set_timeout(struct watchdog_device *wdev,
+				   unsigned int timeout)
+{
+
+	wdev->timeout = timeout;
+	sp_wdt_ping(wdev);
+
+	return 0;
+}
+
+static int sp_wdt_stop(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+
+	writel(WDT_STOP, base + WDT_CTRL);
+
+	return 0;
+}
+
+static int sp_wdt_start(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+
+	writel(WDT_RESUME, base + WDT_CTRL);
+
+	return 0;
+}
+
+static unsigned int sp_wdt_get_timeleft(struct watchdog_device *wdev)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+	u32 val;
+
+	val = readl(base + WDT_CNT);
+	val &= 0xffff;
+	val = val << 4;
+
+	return val;
+}
+
+/*
+ * 1.We need to reset watchdog flag(clear watchdog interrupt) here
+ * because watchdog timer driver does not have an interrupt handler,
+ * and before enable STC and RBUS watchdog timeout. Otherwise,
+ * the intr is always in the triggered state.
+ * 2.Enable STC and RBUS watchdog timeout trigger.
+ * 3.Watchdog counter is running, need to be stopped.
+ */
+static int sp_wdt_hw_init(struct watchdog_device *wdev, void __iomem *rst_en)
+{
+	struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
+	void __iomem *base = priv->base;
+	u32 val;
+
+	writel(WDT_CLRIRQ, base + WDT_CTRL);
+	val = readl(rst_en);
+	val |= MASK_SET(STC_WDT_RST);
+	val |= MASK_SET(RBUS_WDT_RST);
+	writel(val, rst_en);
+
+	sp_wdt_stop(wdev);
+	writel(WDT_LOCK, base + WDT_CTRL);
+	writel(WDT_CONMAX, base + WDT_CTRL);
+
+	return 0;
+}
+
+static const struct watchdog_info sp_wdt_info = {
+	.identity	= DEVICE_NAME,
+	.options	= WDIOF_SETTIMEOUT |
+			  WDIOF_MAGICCLOSE |
+			  WDIOF_KEEPALIVEPING,
+};
+
+static const struct watchdog_ops sp_wdt_ops = {
+	.owner		= THIS_MODULE,
+	.start		= sp_wdt_start,
+	.stop		= sp_wdt_stop,
+	.ping		= sp_wdt_ping,
+	.set_timeout	= sp_wdt_set_timeout,
+	.get_timeleft	= sp_wdt_get_timeleft,
+	.restart	= sp_wdt_restart,
+};
+
+static void sp_clk_disable_unprepare(void *data)
+{
+	clk_disable_unprepare(data);
+}
+
+static void sp_reset_control_assert(void *data)
+{
+	reset_control_assert(data);
+}
+
+static int sp_wdt_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sp_wdt_priv *priv;
+	struct resource *wdt_res;
+	int err;
+	void __iomem *rst_en;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "Can't find clock source\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	err = clk_prepare_enable(priv->clk);
+	if (err) {
+		dev_err(dev, "Clock can't be enabled correctly\n");
+		return err;
+	}
+
+	/* The timer and watchdog shared the STC reset */
+	priv->rstc = devm_reset_control_get_shared(dev, NULL);
+	if (!IS_ERR(priv->rstc))
+		reset_control_deassert(priv->rstc);
+
+	err = devm_add_action_or_reset(dev, sp_reset_control_assert,
+				       priv->rstc);
+	if (err)
+		return err;
+
+	err = devm_add_action_or_reset(dev, sp_clk_disable_unprepare,
+				       priv->clk);
+	if (err)
+		return err;
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	/* The registers accessed here shared by multiple drivers. */
+	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	rst_en =
+	    devm_ioremap(dev, wdt_res->start, resource_size(wdt_res));
+	if (IS_ERR(rst_en))
+		return PTR_ERR(rst_en);
+
+	priv->wdev.info = &sp_wdt_info;
+	priv->wdev.ops = &sp_wdt_ops;
+	priv->wdev.timeout = SP_WDT_DEFAULT_TIMEOUT;
+	priv->wdev.max_hw_heartbeat_ms = SP_WDT_MAX_TIMEOUT * 1000;
+	priv->wdev.min_timeout = 1;
+	priv->wdev.parent = dev;
+
+	watchdog_init_timeout(&priv->wdev, timeout, dev);
+	watchdog_set_nowayout(&priv->wdev, nowayout);
+	watchdog_set_restart_priority(&priv->wdev, 128);
+
+	watchdog_set_drvdata(&priv->wdev, priv);
+
+	sp_wdt_hw_init(&priv->wdev, rst_en);
+
+	watchdog_stop_on_reboot(&priv->wdev);
+	err = devm_watchdog_register_device(dev, &priv->wdev);
+	if (err)
+		return err;
+
+	platform_set_drvdata(pdev, priv);
+
+	dev_info(dev, "Watchdog enabled (timeout=%d sec%s.)\n",
+		 priv->wdev.timeout, nowayout ? ", nowayout" : "");
+
+	return 0;
+}
+
+static const struct of_device_id sp_wdt_of_match[] = {
+	{.compatible = "sunplus,sp7021-wdt", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sp_wdt_of_match);
+
+static int __maybe_unused sp_wdt_suspend(struct device *dev)
+{
+	struct sp_wdt_priv *priv = dev_get_drvdata(dev);
+
+	if (watchdog_active(&priv->wdev))
+		sp_wdt_stop(&priv->wdev);
+
+	reset_control_assert(priv->rstc);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static int __maybe_unused sp_wdt_resume(struct device *dev)
+{
+	int err;
+
+	struct sp_wdt_priv *priv = dev_get_drvdata(dev);
+
+	err = clk_prepare_enable(priv->clk);
+	if (err) {
+		dev_err(dev, "Clock can't be enabled correctly\n");
+		return err;
+	}
+
+	reset_control_deassert(priv->rstc);
+
+	if (watchdog_active(&priv->wdev))
+		sp_wdt_start(&priv->wdev);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(sp_wdt_pm_ops, sp_wdt_suspend, sp_wdt_resume);
+
+static struct platform_driver sp_wdt_driver = {
+	.probe = sp_wdt_probe,
+	.driver = {
+		   .name = DEVICE_NAME,
+		   .of_match_table = sp_wdt_of_match,
+		   .pm = &sp_wdt_pm_ops,
+	},
+};
+
+module_platform_driver(sp_wdt_driver);
+
+MODULE_AUTHOR("Xiantao Hu <xt.hu@cqplus1.com>");
+MODULE_DESCRIPTION("Sunplus Watchdog Timer Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.33.1


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

* [PATCH v2 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation
  2021-11-24 10:41 ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
  2021-11-24 10:41   ` [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
@ 2021-11-24 10:41   ` Xiantao Hu
  2021-11-30 22:38     ` Rob Herring
  2021-11-24 14:17   ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Guenter Roeck
  2 siblings, 1 reply; 17+ messages in thread
From: Xiantao Hu @ 2021-11-24 10:41 UTC (permalink / raw)
  To: wim, p.zabel, linux-kernel, linux-watchdog, linux, robh+dt, devicetree
  Cc: wells.lu, qinjian, Xiantao Hu

This adds the documentation for the devicetree bindings of the Sunplus
SP7021 watchdog driver, found from SP7021 SoCs and newer.

Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
---
 .../bindings/watchdog/sunplus,sp7021-wdt.yaml | 47 +++++++++++++++++++
 MAINTAINERS                                   |  1 +
 2 files changed, 48 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml

diff --git a/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml b/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
new file mode 100644
index 000000000..bb728f298
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) Sunplus Co., Ltd. 2021
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/sunplus,sp7021-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sunplus SoCs Watchdog Device Tree Bindings
+
+maintainers:
+  - XianTao Hu <xt.hu@cqplus1.com>
+
+allOf:
+  - $ref: watchdog.yaml#
+
+properties:
+  compatible:
+    const: sunplus,sp7021-wdt
+
+  reg:
+    items:
+      - description: Base address and length of the watchdog registers
+      - description: Base address and length of the miscellaneous control registers
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+
+additionalProperties: false
+
+examples:
+  - |
+    watchdog: watchdog@9c000630 {
+        compatible = "sunplus,sp7021-wdt";
+        reg = <0x9c000630 0x08>, <0x9C000274 0x04>;
+        clocks = <&clkc 0x24>;
+        resets = <&rstc 0x14>;
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index f6a328772..d51f0cb1a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17937,6 +17937,7 @@ SUNPLUS WATCHDOG DRIVER
 M:	Xiantao Hu <xt.hu@cqplus1.com>
 L:	linux-watchdog@vger.kernel.org
 S:	Maintained
+F:	Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
 F:	drivers/watchdog/sunplus_wdt.c
 
 SUPERH
-- 
2.33.1


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

* Re: [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC
  2021-11-24 10:41 ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
  2021-11-24 10:41   ` [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
  2021-11-24 10:41   ` [PATCH v2 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation Xiantao Hu
@ 2021-11-24 14:17   ` Guenter Roeck
  2021-11-25  2:52     ` xt.hu[胡先韬]
  2 siblings, 1 reply; 17+ messages in thread
From: Guenter Roeck @ 2021-11-24 14:17 UTC (permalink / raw)
  To: Xiantao Hu
  Cc: wim, p.zabel, linux-kernel, linux-watchdog, robh+dt, devicetree,
	wells.lu, qinjian

On Wed, Nov 24, 2021 at 06:41:47PM +0800, Xiantao Hu wrote:
> This is a patch series for watchdog driver for Sunplus SP7021 SoC.
> 
> Sunplus SP7021 is an ARM Cortex A7 (4 cores) based SoC. It integrates
> many peripherals (ex: UART, I2C, SPI, SDIO, eMMC, USB, SD card and
> etc.) into a single chip. It is designed for industrial control.
> 

Why are more and more people sending patches or patch series as reply to
previous patches ? This all by ensures that patches get lost.

Is that promoted somewhere ?

Thanks,
Guenter

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

* Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-24 10:41   ` [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
@ 2021-11-24 14:25     ` Guenter Roeck
  2021-11-25  2:42       ` xt.hu[胡先韬]
  0 siblings, 1 reply; 17+ messages in thread
From: Guenter Roeck @ 2021-11-24 14:25 UTC (permalink / raw)
  To: Xiantao Hu
  Cc: wim, p.zabel, linux-kernel, linux-watchdog, robh+dt, devicetree,
	wells.lu, qinjian

On Wed, Nov 24, 2021 at 06:41:48PM +0800, Xiantao Hu wrote:
> Sunplus SP7021 requires watchdog timer support.
> Add watchdog driver to enable this.
> 
> Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
> ---
> +
> +	priv->base = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(priv->base))
> +		return PTR_ERR(priv->base);
> +
> +	/* The registers accessed here shared by multiple drivers. */
> +	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);

This is unusual. Why would other drivers access WDT_CTRL and WDT_CNT
registers, and how is it ensured that the other drivers do not interfer
with the accesses by this driver ?

Normally such a resource would be shared through a parent driver with
appropriate access functions to ensure that accesses are synchronized.

Thanks,
Guenter

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

* RE: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-24 14:25     ` Guenter Roeck
@ 2021-11-25  2:42       ` xt.hu[胡先韬]
  2021-11-25  4:25         ` Guenter Roeck
  0 siblings, 1 reply; 17+ messages in thread
From: xt.hu[胡先韬] @ 2021-11-25  2:42 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: wim, p.zabel, linux-kernel, linux-watchdog, robh+dt, devicetree,
	Wells Lu 呂芳騰, qinjian[覃健]

Hi
	Thanks for your review. I explain this in detail below the comment.

Best Regards,
Xiantao
> -----Original Message-----
> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
> Sent: Wednesday, November 24, 2021 10:25 PM
> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>
> Cc: wim@linux-watchdog.org; p.zabel@pengutronix.de; linux-kernel@vger.kernel.org;
> linux-watchdog@vger.kernel.org; robh+dt@kernel.org; devicetree@vger.kernel.org; Wells Lu 呂芳騰
> <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
> Subject: Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
> 
> On Wed, Nov 24, 2021 at 06:41:48PM +0800, Xiantao Hu wrote:
> > Sunplus SP7021 requires watchdog timer support.
> > Add watchdog driver to enable this.
> >
> > Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
> > ---
> > +
> > +	priv->base = devm_platform_ioremap_resource(pdev, 0);
> > +	if (IS_ERR(priv->base))
> > +		return PTR_ERR(priv->base);
> > +
> > +	/* The registers accessed here shared by multiple drivers. */
> > +	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> 
> This is unusual. Why would other drivers access WDT_CTRL and WDT_CNT registers, and how is it
> ensured that the other drivers do not interfer with the accesses by this driver ?
> 
> Normally such a resource would be shared through a parent driver with appropriate access functions to
> ensure that accesses are synchronized.
> 

The register used by this driver consists of two parts. The first part which contains WDT_CTRL and WDT_CNT 
registers is exclusive by watchdog. 
In specially, the second part is belong to a multifunctional register group which control IP and bus. Refer to 
register manual below:
-------------------------------------------------------------------------------------------------------------------------------------------------
MO1_STC_WDG_RST_EN	4	RW		STC Watchdog Timeout Trigger System Reset Enable
									0: STC watchdog 2 timeout will not trigger system reset(default)
									1: STC watchdog 2 timeout will trigger system reset
MO1_RI_WDG_RST_EN		1	RW		RBUS Watchdog Timeout Trigger System Reset Enable
									0: RBUS watchdog timeout will not trigger system reset(default)
									1: RBUS watchdog timeout will trigger system reset
MO1_TIMER_STAND_BY_EN	0	RW		Timer Standby Mode Enable
									0: Disable (default)
									1: Enable Active high to enter timer standby mode, 
											default not in standby mode
-------------------------------------------------------------------------------------------------------------------------------------------------
You can see that in addition to the bits for watchdog there are bit fields for other modules.
I use this register bit4 and bit1. Default value is 0 that watchdog internal interrupt signal can't trigger system 
and RBUS reset. I need set 1 when watchdog probe. Early I implement the operation in 
arch/arm/mach-sunplus/sp7021.c and configure by macro. But in arch/arm64, directory mach-XXX is removed.
So I solve in this way. Any better way?

> Thanks,
> Guenter

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

* RE: [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC
  2021-11-24 14:17   ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Guenter Roeck
@ 2021-11-25  2:52     ` xt.hu[胡先韬]
  0 siblings, 0 replies; 17+ messages in thread
From: xt.hu[胡先韬] @ 2021-11-25  2:52 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: wim, p.zabel, linux-kernel, linux-watchdog, robh+dt, devicetree,
	Wells Lu 呂芳騰, qinjian[覃健]

Hi Guenter,
	This is my second submitting. I also refer to the format in others' emails.
	If the format is not correct, I will drop --in-reply-to when submit pathch next time.

Best Regards,
Xiantao
> -----Original Message-----
> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
> Sent: Wednesday, November 24, 2021 10:18 PM
> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>
> Cc: wim@linux-watchdog.org; p.zabel@pengutronix.de; linux-kernel@vger.kernel.org;
> linux-watchdog@vger.kernel.org; robh+dt@kernel.org; devicetree@vger.kernel.org; Wells Lu 呂芳騰
> <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
> Subject: Re: [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC
> 
> On Wed, Nov 24, 2021 at 06:41:47PM +0800, Xiantao Hu wrote:
> > This is a patch series for watchdog driver for Sunplus SP7021 SoC.
> >
> > Sunplus SP7021 is an ARM Cortex A7 (4 cores) based SoC. It integrates
> > many peripherals (ex: UART, I2C, SPI, SDIO, eMMC, USB, SD card and
> > etc.) into a single chip. It is designed for industrial control.
> >
> 
> Why are more and more people sending patches or patch series as reply to
> previous patches ? This all by ensures that patches get lost.
> 
> Is that promoted somewhere ?
> 
> Thanks,
> Guenter

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

* Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-25  2:42       ` xt.hu[胡先韬]
@ 2021-11-25  4:25         ` Guenter Roeck
  2021-11-29  7:57           ` xt.hu[胡先韬]
  0 siblings, 1 reply; 17+ messages in thread
From: Guenter Roeck @ 2021-11-25  4:25 UTC (permalink / raw)
  To: xt.hu[胡先韬]
  Cc: wim, p.zabel, linux-kernel, linux-watchdog, robh+dt, devicetree,
	Wells Lu 呂芳騰, qinjian[覃健]

On 11/24/21 6:42 PM, xt.hu[胡先韬] wrote:
> Hi
> 	Thanks for your review. I explain this in detail below the comment.
> 
> Best Regards,
> Xiantao
>> -----Original Message-----
>> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
>> Sent: Wednesday, November 24, 2021 10:25 PM
>> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>
>> Cc: wim@linux-watchdog.org; p.zabel@pengutronix.de; linux-kernel@vger.kernel.org;
>> linux-watchdog@vger.kernel.org; robh+dt@kernel.org; devicetree@vger.kernel.org; Wells Lu 呂芳騰
>> <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
>> Subject: Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
>>
>> On Wed, Nov 24, 2021 at 06:41:48PM +0800, Xiantao Hu wrote:
>>> Sunplus SP7021 requires watchdog timer support.
>>> Add watchdog driver to enable this.
>>>
>>> Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
>>> ---
>>> +
>>> +	priv->base = devm_platform_ioremap_resource(pdev, 0);
>>> +	if (IS_ERR(priv->base))
>>> +		return PTR_ERR(priv->base);
>>> +
>>> +	/* The registers accessed here shared by multiple drivers. */
>>> +	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>>
>> This is unusual. Why would other drivers access WDT_CTRL and WDT_CNT registers, and how is it
>> ensured that the other drivers do not interfer with the accesses by this driver ?
>>
>> Normally such a resource would be shared through a parent driver with appropriate access functions to
>> ensure that accesses are synchronized.
>>
> 
> The register used by this driver consists of two parts. The first part which contains WDT_CTRL and WDT_CNT
> registers is exclusive by watchdog.
> In specially, the second part is belong to a multifunctional register group which control IP and bus. Refer to
> register manual below:
> -------------------------------------------------------------------------------------------------------------------------------------------------
> MO1_STC_WDG_RST_EN	4	RW		STC Watchdog Timeout Trigger System Reset Enable
> 									0: STC watchdog 2 timeout will not trigger system reset(default)
> 									1: STC watchdog 2 timeout will trigger system reset
> MO1_RI_WDG_RST_EN		1	RW		RBUS Watchdog Timeout Trigger System Reset Enable
> 									0: RBUS watchdog timeout will not trigger system reset(default)
> 									1: RBUS watchdog timeout will trigger system reset
> MO1_TIMER_STAND_BY_EN	0	RW		Timer Standby Mode Enable
> 									0: Disable (default)
> 									1: Enable Active high to enter timer standby mode,
> 											default not in standby mode
> -------------------------------------------------------------------------------------------------------------------------------------------------
> You can see that in addition to the bits for watchdog there are bit fields for other modules.
> I use this register bit4 and bit1. Default value is 0 that watchdog internal interrupt signal can't trigger system
> and RBUS reset. I need set 1 when watchdog probe. Early I implement the operation in
> arch/arm/mach-sunplus/sp7021.c and configure by macro. But in arch/arm64, directory mach-XXX is removed.
> So I solve in this way. Any better way?
> 
If the register at 0x9C000274 is accessed by other drivers, accesses
to it must be protected against each other to avoid race conditions.
How to do that would be up to you.

Guenter

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

* RE: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-25  4:25         ` Guenter Roeck
@ 2021-11-29  7:57           ` xt.hu[胡先韬]
  2021-12-03 21:39             ` Guenter Roeck
  0 siblings, 1 reply; 17+ messages in thread
From: xt.hu[胡先韬] @ 2021-11-29  7:57 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: wim, p.zabel, linux-kernel, linux-watchdog, robh+dt, devicetree,
	Wells Lu 呂芳騰, qinjian[覃健]


> -----Original Message-----
> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
> Sent: Thursday, November 25, 2021 12:26 PM
> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>
> Cc: wim@linux-watchdog.org; p.zabel@pengutronix.de; linux-kernel@vger.kernel.org;
> linux-watchdog@vger.kernel.org; robh+dt@kernel.org; devicetree@vger.kernel.org; Wells Lu 呂芳騰
> <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
> Subject: Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
> 
> On 11/24/21 6:42 PM, xt.hu[胡先韬] wrote:
> > Hi
> > 	Thanks for your review. I explain this in detail below the comment.
> >
> > Best Regards,
> > Xiantao
> >> -----Original Message-----
> >> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
> >> Sent: Wednesday, November 24, 2021 10:25 PM
> >> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>
> >> Cc: wim@linux-watchdog.org; p.zabel@pengutronix.de; linux-kernel@vger.kernel.org;
> >> linux-watchdog@vger.kernel.org; robh+dt@kernel.org; devicetree@vger.kernel.org; Wells Lu 呂芳
> 騰
> >> <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
> >> Subject: Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
> >>
> >> On Wed, Nov 24, 2021 at 06:41:48PM +0800, Xiantao Hu wrote:
> >>> Sunplus SP7021 requires watchdog timer support.
> >>> Add watchdog driver to enable this.
> >>>
> >>> Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
> >>> ---
> >>> +
> >>> +	priv->base = devm_platform_ioremap_resource(pdev, 0);
> >>> +	if (IS_ERR(priv->base))
> >>> +		return PTR_ERR(priv->base);
> >>> +
> >>> +	/* The registers accessed here shared by multiple drivers. */
> >>> +	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> >>
> >> This is unusual. Why would other drivers access WDT_CTRL and WDT_CNT registers, and how is it
> >> ensured that the other drivers do not interfer with the accesses by this driver ?
> >>
> >> Normally such a resource would be shared through a parent driver with appropriate access functions
> to
> >> ensure that accesses are synchronized.
> >>
> >
> > The register used by this driver consists of two parts. The first part which contains WDT_CTRL and
> WDT_CNT
> > registers is exclusive by watchdog.
> > In specially, the second part is belong to a multifunctional register group which control IP and bus.
> Refer to
> > register manual below:
> > -------------------------------------------------------------------------------------------------------------------------------------------------
> > MO1_STC_WDG_RST_EN	4	RW		STC Watchdog Timeout Trigger System Reset Enable
> > 									0: STC watchdog 2 timeout will not trigger system
> reset(default)
> > 									1: STC watchdog 2 timeout will trigger system reset
> > MO1_RI_WDG_RST_EN		1	RW		RBUS Watchdog Timeout Trigger System Reset Enable
> > 									0: RBUS watchdog timeout will not trigger system
> reset(default)
> > 									1: RBUS watchdog timeout will trigger system reset
> > MO1_TIMER_STAND_BY_EN	0	RW		Timer Standby Mode Enable
> > 									0: Disable (default)
> > 									1: Enable Active high to enter timer standby mode,
> > 											default not in standby mode
> > -------------------------------------------------------------------------------------------------------------------------------------------------
> > You can see that in addition to the bits for watchdog there are bit fields for other modules.
> > I use this register bit4 and bit1. Default value is 0 that watchdog internal interrupt signal can't trigger
> system
> > and RBUS reset. I need set 1 when watchdog probe. Early I implement the operation in
> > arch/arm/mach-sunplus/sp7021.c and configure by macro. But in arch/arm64, directory mach-XXX is
> removed.
> > So I solve in this way. Any better way?
> >
> If the register at 0x9C000274 is accessed by other drivers, accesses
> to it must be protected against each other to avoid race conditions.
> How to do that would be up to you.
> 
Hi Guenter,

From the perspective of software, 0x9C000274 is only accessed during
driver probe. If the driver is build-in and only one core is running at kernel 
startup. There is no competition.
The only possibility of an error is to compile the driver into a module. In this 
case, the register at 0x9C000274 offer MASK_BITS[31:16] which write valid 
bit for each LSB 16 bits. Refer to the define in driver:
#define MASK_SET(mask)		((mask) | (mask << 16))
Even if both drivers access the register at the same time, the instructions are 
executed in order on the RBUS. So as long as the same bit in the same register 
is not accessed at the same time, no error will occur.

Best Regards,
Xiantao

> Guenter

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

* Re: [PATCH v2 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation
  2021-11-24 10:41   ` [PATCH v2 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation Xiantao Hu
@ 2021-11-30 22:38     ` Rob Herring
  0 siblings, 0 replies; 17+ messages in thread
From: Rob Herring @ 2021-11-30 22:38 UTC (permalink / raw)
  To: Xiantao Hu
  Cc: wells.lu, linux-watchdog, linux, linux-kernel, robh+dt, qinjian,
	devicetree, p.zabel, wim

On Wed, 24 Nov 2021 18:41:49 +0800, Xiantao Hu wrote:
> This adds the documentation for the devicetree bindings of the Sunplus
> SP7021 watchdog driver, found from SP7021 SoCs and newer.
> 
> Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
> ---
>  .../bindings/watchdog/sunplus,sp7021-wdt.yaml | 47 +++++++++++++++++++
>  MAINTAINERS                                   |  1 +
>  2 files changed, 48 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
  2021-11-29  7:57           ` xt.hu[胡先韬]
@ 2021-12-03 21:39             ` Guenter Roeck
  0 siblings, 0 replies; 17+ messages in thread
From: Guenter Roeck @ 2021-12-03 21:39 UTC (permalink / raw)
  To: xt.hu[胡先韬]
  Cc: wim, p.zabel, linux-kernel, linux-watchdog, robh+dt, devicetree,
	Wells Lu 呂芳騰, qinjian[覃健]

On 11/28/21 11:57 PM, xt.hu[胡先韬] wrote:
> 
>> -----Original Message-----
>> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
>> Sent: Thursday, November 25, 2021 12:26 PM
>> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>
>> Cc: wim@linux-watchdog.org; p.zabel@pengutronix.de; linux-kernel@vger.kernel.org;
>> linux-watchdog@vger.kernel.org; robh+dt@kernel.org; devicetree@vger.kernel.org; Wells Lu 呂芳騰
>> <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
>> Subject: Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
>>
>> On 11/24/21 6:42 PM, xt.hu[胡先韬] wrote:
>>> Hi
>>> 	Thanks for your review. I explain this in detail below the comment.
>>>
>>> Best Regards,
>>> Xiantao
>>>> -----Original Message-----
>>>> From: Guenter Roeck [mailto:groeck7@gmail.com] On Behalf Of Guenter Roeck
>>>> Sent: Wednesday, November 24, 2021 10:25 PM
>>>> To: xt.hu[胡先韬] <xt.hu@cqplus1.com>
>>>> Cc: wim@linux-watchdog.org; p.zabel@pengutronix.de; linux-kernel@vger.kernel.org;
>>>> linux-watchdog@vger.kernel.org; robh+dt@kernel.org; devicetree@vger.kernel.org; Wells Lu 呂芳
>> 騰
>>>> <wells.lu@sunplus.com>; qinjian[覃健] <qinjian@cqplus1.com>
>>>> Subject: Re: [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021
>>>>
>>>> On Wed, Nov 24, 2021 at 06:41:48PM +0800, Xiantao Hu wrote:
>>>>> Sunplus SP7021 requires watchdog timer support.
>>>>> Add watchdog driver to enable this.
>>>>>
>>>>> Signed-off-by: Xiantao Hu <xt.hu@cqplus1.com>
>>>>> ---
>>>>> +
>>>>> +	priv->base = devm_platform_ioremap_resource(pdev, 0);
>>>>> +	if (IS_ERR(priv->base))
>>>>> +		return PTR_ERR(priv->base);
>>>>> +
>>>>> +	/* The registers accessed here shared by multiple drivers. */
>>>>> +	wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>>>>
>>>> This is unusual. Why would other drivers access WDT_CTRL and WDT_CNT registers, and how is it
>>>> ensured that the other drivers do not interfer with the accesses by this driver ?
>>>>
>>>> Normally such a resource would be shared through a parent driver with appropriate access functions
>> to
>>>> ensure that accesses are synchronized.
>>>>
>>>
>>> The register used by this driver consists of two parts. The first part which contains WDT_CTRL and
>> WDT_CNT
>>> registers is exclusive by watchdog.
>>> In specially, the second part is belong to a multifunctional register group which control IP and bus.
>> Refer to
>>> register manual below:
>>> -------------------------------------------------------------------------------------------------------------------------------------------------
>>> MO1_STC_WDG_RST_EN	4	RW		STC Watchdog Timeout Trigger System Reset Enable
>>> 									0: STC watchdog 2 timeout will not trigger system
>> reset(default)
>>> 									1: STC watchdog 2 timeout will trigger system reset
>>> MO1_RI_WDG_RST_EN		1	RW		RBUS Watchdog Timeout Trigger System Reset Enable
>>> 									0: RBUS watchdog timeout will not trigger system
>> reset(default)
>>> 									1: RBUS watchdog timeout will trigger system reset
>>> MO1_TIMER_STAND_BY_EN	0	RW		Timer Standby Mode Enable
>>> 									0: Disable (default)
>>> 									1: Enable Active high to enter timer standby mode,
>>> 											default not in standby mode
>>> -------------------------------------------------------------------------------------------------------------------------------------------------
>>> You can see that in addition to the bits for watchdog there are bit fields for other modules.
>>> I use this register bit4 and bit1. Default value is 0 that watchdog internal interrupt signal can't trigger
>> system
>>> and RBUS reset. I need set 1 when watchdog probe. Early I implement the operation in
>>> arch/arm/mach-sunplus/sp7021.c and configure by macro. But in arch/arm64, directory mach-XXX is
>> removed.
>>> So I solve in this way. Any better way?
>>>
>> If the register at 0x9C000274 is accessed by other drivers, accesses
>> to it must be protected against each other to avoid race conditions.
>> How to do that would be up to you.
>>
> Hi Guenter,
> 
>  From the perspective of software, 0x9C000274 is only accessed during
> driver probe. If the driver is build-in and only one core is running at kernel
> startup. There is no competition.
> The only possibility of an error is to compile the driver into a module. In this
> case, the register at 0x9C000274 offer MASK_BITS[31:16] which write valid
> bit for each LSB 16 bits. Refer to the define in driver:
> #define MASK_SET(mask)		((mask) | (mask << 16))
> Even if both drivers access the register at the same time, the instructions are
> executed in order on the RBUS. So as long as the same bit in the same register
> is not accessed at the same time, no error will occur.
> 

This is inherently risky and racy. I am sure there is a better way to solve this
without risking race conditions, but I don't have time to analyze it further.
The above rationale needs to be added in detail to the driver as comments,
including references to all other drivers accessing the same register or
memory space.

Guenter

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

end of thread, other threads:[~2021-12-03 21:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-12 10:59 [PATCH 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
2021-11-12 10:59 ` [PATCH 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
2021-11-12 14:45   ` Guenter Roeck
2021-11-24 10:31     ` xt.hu[胡先韬]
2021-11-21  0:33   ` kernel test robot
2021-11-12 10:59 ` [PATCH 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation Xiantao Hu
2021-11-24 10:41 ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Xiantao Hu
2021-11-24 10:41   ` [PATCH v2 1/2] watchdog: Add watchdog driver for Sunplus SP7021 Xiantao Hu
2021-11-24 14:25     ` Guenter Roeck
2021-11-25  2:42       ` xt.hu[胡先韬]
2021-11-25  4:25         ` Guenter Roeck
2021-11-29  7:57           ` xt.hu[胡先韬]
2021-12-03 21:39             ` Guenter Roeck
2021-11-24 10:41   ` [PATCH v2 2/2] dt-bindings: watchdog: Add Sunplus SP7021 WDT devicetree bindings documentation Xiantao Hu
2021-11-30 22:38     ` Rob Herring
2021-11-24 14:17   ` [PATCH v2 0/2] Add watchdog driver for Sunplus SP7021 SoC Guenter Roeck
2021-11-25  2:52     ` xt.hu[胡先韬]

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