Linux-Watchdog Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver
@ 2021-03-15 10:46 Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 1/9] watchdog: of_xilinx_wdt: Add comment to spinlock Srinivas Neeli
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Neeli

This patch series does the following:
- Add comment to spinlock
- Used BIT macro
- Used dev_dbg()
- Initialize watchdog via data structure
- Introduce wdttype enum for identification
- Add binding for Versal watchdog
- Add Versal Window watchdog support
- Remove passing null pointer
- Skip printing pointer value
---
Note:
- Converting DT bindings to yaml pending, Will update on top of this series.
---
Srinivas Goud (3):
  watchdog: of_xilinx_wdt: Add comment to spinlock
  watchdog: of_xilinx_wdt: Used BIT macro
  watchdog: of_xilinx_wdt: Used dev_dbg()

Srinivas Neeli (6):
  watchdog: of_xilinx_wdt: Initialize watchdog via data structure
  watchdog: of_xilinx_wdt: Introduce wdttype enum for identification
  dt-bindings: watchdog: xilinx: Add binding for Versal watchdog
  watchdog: of_xilinx_wdt: Add Versal Window watchdog support
  watchdog: of_xilinx_wdt: Remove passing null pointer
  watchdog: of_xilinx_wdt: Skip printing pointer value

 .../devicetree/bindings/watchdog/of-xilinx-wdt.txt |  33 +-
 drivers/watchdog/of_xilinx_wdt.c                   | 439 ++++++++++++++++++---
 2 files changed, 414 insertions(+), 58 deletions(-)

-- 
2.7.4


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

* [PATCH 1/9] watchdog: of_xilinx_wdt: Add comment to spinlock
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-16  2:21   ` Guenter Roeck
  2021-03-15 10:46 ` [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro Srinivas Neeli
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git,
	Srinivas Goud, Srinivas Neeli

From: Srinivas Goud <srinivas.goud@xilinx.com>

Based on checkpatch every spinlock should be documented.
The patch is fixing this issue:
./scripts/checkpatch.pl --strict -f drivers/watchdog/of_xilinx_wdt.c
CHECK: spinlock_t definition without comment
+	spinlock_t spinlock;

Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 7fe4f7c3f7ce..00549164b3d7 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -40,7 +40,7 @@
 struct xwdt_device {
 	void __iomem *base;
 	u32 wdt_interval;
-	spinlock_t spinlock;
+	spinlock_t spinlock; /* spinlock for register handling */
 	struct watchdog_device xilinx_wdt_wdd;
 	struct clk		*clk;
 };
-- 
2.7.4


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

* [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 1/9] watchdog: of_xilinx_wdt: Add comment to spinlock Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-16  2:23   ` Guenter Roeck
  2021-03-15 10:46 ` [PATCH 3/9] watchdog: of_xilinx_wdt: Used dev_dbg() Srinivas Neeli
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git,
	Srinivas Goud, Srinivas Neeli

From: Srinivas Goud <srinivas.goud@xilinx.com>

Used BIT macro instead of mask value.

Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 00549164b3d7..0d7df2370db7 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -24,12 +24,12 @@
 #define XWT_TBR_OFFSET      0x8 /* Timebase Register Offset */
 
 /* Control/Status Register Masks  */
-#define XWT_CSR0_WRS_MASK   0x00000008 /* Reset status */
-#define XWT_CSR0_WDS_MASK   0x00000004 /* Timer state  */
-#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */
+#define XWT_CSR0_WRS_MASK	BIT(3) /* Reset status */
+#define XWT_CSR0_WDS_MASK	BIT(2) /* Timer state  */
+#define XWT_CSR0_EWDT1_MASK	BIT(1) /* Enable bit 1 */
 
 /* Control/Status Register 0/1 bits  */
-#define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 */
+#define XWT_CSRX_EWDT2_MASK	BIT(0) /* Enable bit 2 */
 
 /* SelfTest constants */
 #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000
-- 
2.7.4


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

* [PATCH 3/9] watchdog: of_xilinx_wdt: Used dev_dbg()
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 1/9] watchdog: of_xilinx_wdt: Add comment to spinlock Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-16  2:27   ` Guenter Roeck
  2021-03-15 10:46 ` [PATCH 4/9] watchdog: of_xilinx_wdt: Initialize watchdog via data structure Srinivas Neeli
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git,
	Srinivas Goud, Srinivas Neeli

From: Srinivas Goud <srinivas.goud@xilinx.com>

This patch removes pr_info in stop function and adds dev_dbg()
in start/stop function to display device specific debug info.

Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 0d7df2370db7..9e67b598907e 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -50,6 +50,7 @@ static int xilinx_wdt_start(struct watchdog_device *wdd)
 	int ret;
 	u32 control_status_reg;
 	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
 
 	ret = clk_enable(xdev->clk);
 	if (ret) {
@@ -70,6 +71,8 @@ static int xilinx_wdt_start(struct watchdog_device *wdd)
 
 	spin_unlock(&xdev->spinlock);
 
+	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Started!\n");
+
 	return 0;
 }
 
@@ -77,6 +80,7 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd)
 {
 	u32 control_status_reg;
 	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
 
 	spin_lock(&xdev->spinlock);
 
@@ -91,7 +95,7 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd)
 
 	clk_disable(xdev->clk);
 
-	pr_info("Stopped!\n");
+	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Stopped!\n");
 
 	return 0;
 }
-- 
2.7.4


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

* [PATCH 4/9] watchdog: of_xilinx_wdt: Initialize watchdog via data structure
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
                   ` (2 preceding siblings ...)
  2021-03-15 10:46 ` [PATCH 3/9] watchdog: of_xilinx_wdt: Used dev_dbg() Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 5/9] watchdog: of_xilinx_wdt: Introduce wdttype enum for identification Srinivas Neeli
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git,
	Srinivas Neeli, Srinivas Goud

This patch is preparation for adding new watchdog based on this driver.
of_id->data is storing link xwdt_devtype_data which stores watchdog
info and ops pointers to structures.

Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 50 +++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 14 deletions(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 9e67b598907e..b2ce1b90237e 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -37,6 +37,11 @@
 
 #define WATCHDOG_NAME     "Xilinx Watchdog"
 
+struct xwdt_devtype_data {
+	const struct watchdog_ops *xwdt_ops;
+	const struct watchdog_info *xwdt_info;
+};
+
 struct xwdt_device {
 	void __iomem *base;
 	u32 wdt_interval;
@@ -160,6 +165,20 @@ static void xwdt_clk_disable_unprepare(void *data)
 	clk_disable_unprepare(data);
 }
 
+static const struct xwdt_devtype_data xwdt_wdt_data = {
+	.xwdt_info = &xilinx_wdt_ident,
+	.xwdt_ops = &xilinx_wdt_ops,
+};
+
+static const struct of_device_id xwdt_of_match[] = {
+	{ .compatible = "xlnx,xps-timebase-wdt-1.00.a",
+		.data = &xwdt_wdt_data },
+	{ .compatible = "xlnx,xps-timebase-wdt-1.01.a",
+		.data = &xwdt_wdt_data },
+	{},
+};
+MODULE_DEVICE_TABLE(of, xwdt_of_match);
+
 static int xwdt_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -167,14 +186,23 @@ static int xwdt_probe(struct platform_device *pdev)
 	u32 pfreq = 0, enable_once = 0;
 	struct xwdt_device *xdev;
 	struct watchdog_device *xilinx_wdt_wdd;
+	const struct of_device_id *of_id;
+	const struct xwdt_devtype_data *devtype;
 
 	xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL);
 	if (!xdev)
 		return -ENOMEM;
 
 	xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
-	xilinx_wdt_wdd->info = &xilinx_wdt_ident;
-	xilinx_wdt_wdd->ops = &xilinx_wdt_ops;
+
+	of_id = of_match_device(xwdt_of_match, &pdev->dev);
+	if (!of_id)
+		return -EINVAL;
+
+	devtype = of_id->data;
+
+	xilinx_wdt_wdd->info = devtype->xwdt_info;
+	xilinx_wdt_wdd->ops = devtype->xwdt_ops;
 	xilinx_wdt_wdd->parent = dev;
 
 	xdev->base = devm_platform_ioremap_resource(pdev, 0);
@@ -264,9 +292,10 @@ static int xwdt_probe(struct platform_device *pdev)
 static int __maybe_unused xwdt_suspend(struct device *dev)
 {
 	struct xwdt_device *xdev = dev_get_drvdata(dev);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
 
-	if (watchdog_active(&xdev->xilinx_wdt_wdd))
-		xilinx_wdt_stop(&xdev->xilinx_wdt_wdd);
+	if (watchdog_active(xilinx_wdt_wdd))
+		xilinx_wdt_wdd->ops->stop(xilinx_wdt_wdd);
 
 	return 0;
 }
@@ -280,24 +309,17 @@ static int __maybe_unused xwdt_suspend(struct device *dev)
 static int __maybe_unused xwdt_resume(struct device *dev)
 {
 	struct xwdt_device *xdev = dev_get_drvdata(dev);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
 	int ret = 0;
 
-	if (watchdog_active(&xdev->xilinx_wdt_wdd))
-		ret = xilinx_wdt_start(&xdev->xilinx_wdt_wdd);
+	if (watchdog_active(xilinx_wdt_wdd))
+		ret = xilinx_wdt_wdd->ops->start(xilinx_wdt_wdd);
 
 	return ret;
 }
 
 static SIMPLE_DEV_PM_OPS(xwdt_pm_ops, xwdt_suspend, xwdt_resume);
 
-/* Match table for of_platform binding */
-static const struct of_device_id xwdt_of_match[] = {
-	{ .compatible = "xlnx,xps-timebase-wdt-1.00.a", },
-	{ .compatible = "xlnx,xps-timebase-wdt-1.01.a", },
-	{},
-};
-MODULE_DEVICE_TABLE(of, xwdt_of_match);
-
 static struct platform_driver xwdt_driver = {
 	.probe       = xwdt_probe,
 	.driver = {
-- 
2.7.4


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

* [PATCH 5/9] watchdog: of_xilinx_wdt: Introduce wdttype enum for identification
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
                   ` (3 preceding siblings ...)
  2021-03-15 10:46 ` [PATCH 4/9] watchdog: of_xilinx_wdt: Initialize watchdog via data structure Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 6/9] dt-bindings: watchdog: xilinx: Add binding for Versal watchdog Srinivas Neeli
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git,
	Srinivas Neeli, Srinivas Goud

There is a need to identify watchdog type that's why new enum was
was introduced to cover it. Move functionality valid only for this
watchdog type if statement.

Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 64 +++++++++++++++++++++++++++-------------
 1 file changed, 43 insertions(+), 21 deletions(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index b2ce1b90237e..3b93b60f1a00 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -37,7 +37,17 @@
 
 #define WATCHDOG_NAME     "Xilinx Watchdog"
 
+/**
+ * enum xwdt_ip_type - WDT IP type.
+ *
+ * @XWDT_WDT: Soft wdt ip.
+ */
+enum xwdt_ip_type {
+	XWDT_WDT = 0,
+};
+
 struct xwdt_devtype_data {
+	enum xwdt_ip_type wdttype;
 	const struct watchdog_ops *xwdt_ops;
 	const struct watchdog_info *xwdt_info;
 };
@@ -166,6 +176,7 @@ static void xwdt_clk_disable_unprepare(void *data)
 }
 
 static const struct xwdt_devtype_data xwdt_wdt_data = {
+	.wdttype = XWDT_WDT,
 	.xwdt_info = &xilinx_wdt_ident,
 	.xwdt_ops = &xilinx_wdt_ops,
 };
@@ -188,6 +199,7 @@ static int xwdt_probe(struct platform_device *pdev)
 	struct watchdog_device *xilinx_wdt_wdd;
 	const struct of_device_id *of_id;
 	const struct xwdt_devtype_data *devtype;
+	enum xwdt_ip_type wdttype;
 
 	xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL);
 	if (!xdev)
@@ -201,6 +213,8 @@ static int xwdt_probe(struct platform_device *pdev)
 
 	devtype = of_id->data;
 
+	wdttype = devtype->wdttype;
+
 	xilinx_wdt_wdd->info = devtype->xwdt_info;
 	xilinx_wdt_wdd->ops = devtype->xwdt_ops;
 	xilinx_wdt_wdd->parent = dev;
@@ -209,18 +223,20 @@ static int xwdt_probe(struct platform_device *pdev)
 	if (IS_ERR(xdev->base))
 		return PTR_ERR(xdev->base);
 
-	rc = of_property_read_u32(dev->of_node, "xlnx,wdt-interval",
-				  &xdev->wdt_interval);
-	if (rc)
-		dev_warn(dev, "Parameter \"xlnx,wdt-interval\" not found\n");
+	if (wdttype == XWDT_WDT) {
+		rc = of_property_read_u32(dev->of_node, "xlnx,wdt-interval",
+					  &xdev->wdt_interval);
+		if (rc)
+			dev_warn(dev, "Parameter \"xlnx,wdt-interval\" not found\n");
 
-	rc = of_property_read_u32(dev->of_node, "xlnx,wdt-enable-once",
-				  &enable_once);
-	if (rc)
-		dev_warn(dev,
-			 "Parameter \"xlnx,wdt-enable-once\" not found\n");
+		rc = of_property_read_u32(dev->of_node, "xlnx,wdt-enable-once",
+					  &enable_once);
+		if (rc)
+			dev_warn(dev,
+				 "Parameter \"xlnx,wdt-enable-once\" not found\n");
 
-	watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
+		watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
+	}
 
 	xdev->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(xdev->clk)) {
@@ -242,13 +258,17 @@ static int xwdt_probe(struct platform_device *pdev)
 		pfreq = clk_get_rate(xdev->clk);
 	}
 
-	/*
-	 * Twice of the 2^wdt_interval / freq  because the first wdt overflow is
-	 * ignored (interrupt), reset is only generated at second wdt overflow
-	 */
-	if (pfreq && xdev->wdt_interval)
-		xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) /
-					  pfreq);
+	if (wdttype == XWDT_WDT) {
+		/*
+		 * Twice of the 2^wdt_interval / freq  because
+		 * the first wdt overflow is ignored (interrupt),
+		 * reset is only generated at second wdt overflow
+		 */
+		if (pfreq && xdev->wdt_interval)
+			xilinx_wdt_wdd->timeout =
+				2 * ((1 << xdev->wdt_interval) /
+					pfreq);
+	}
 
 	spin_lock_init(&xdev->spinlock);
 	watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
@@ -263,10 +283,12 @@ static int xwdt_probe(struct platform_device *pdev)
 	if (rc)
 		return rc;
 
-	rc = xwdt_selftest(xdev);
-	if (rc == XWT_TIMER_FAILED) {
-		dev_err(dev, "SelfTest routine error\n");
-		return rc;
+	if (wdttype == XWDT_WDT) {
+		rc = xwdt_selftest(xdev);
+		if (rc == XWT_TIMER_FAILED) {
+			dev_err(dev, "SelfTest routine error\n");
+			return rc;
+		}
 	}
 
 	rc = devm_watchdog_register_device(dev, xilinx_wdt_wdd);
-- 
2.7.4


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

* [PATCH 6/9] dt-bindings: watchdog: xilinx: Add binding for Versal watchdog
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
                   ` (4 preceding siblings ...)
  2021-03-15 10:46 ` [PATCH 5/9] watchdog: of_xilinx_wdt: Introduce wdttype enum for identification Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support Srinivas Neeli
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Neeli

Updated watchdog binding for Versal window watchdog.

Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 .../devicetree/bindings/watchdog/of-xilinx-wdt.txt | 33 ++++++++++++++++++++--
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt b/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
index c6ae9c9d5e3e..57903645d685 100644
--- a/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
@@ -1,21 +1,37 @@
-Xilinx AXI/PLB soft-core watchdog Device Tree Bindings
----------------------------------------------------------
+Xilinx AXI/PLB soft-core watchdog and window watchdog Device Tree Bindings
+--------------------------------------------------------------------------
 
 Required properties:
 - compatible		: Should be "xlnx,xps-timebase-wdt-1.00.a" or
-			  "xlnx,xps-timebase-wdt-1.01.a".
+			  "xlnx,xps-timebase-wdt-1.01.a" or
+			  "xlnx,versal-wwdt-1.0".
 - reg			: Physical base address and size
 
 Optional properties:
 - clocks		: Input clock specifier. Refer to common clock
 			  bindings.
 - clock-frequency	: Frequency of clock in Hz
+
+Optional properties for AXI/PLB soft-core watchdog:
 - xlnx,wdt-enable-once	: 0 - Watchdog can be restarted
 			  1 - Watchdog can be enabled just once
 - xlnx,wdt-interval	: Watchdog timeout interval in 2^<val> clock cycles,
 			  <val> is integer from 8 to 31.
 
+Optional properties for window watchdog:
+- timeout-sec          : Watchdog timeout value (in seconds).
+			 if unset, the default timeout is 10 seconds.
+- pretimeout-sec	: Watchdog pretimeout value in seconds.
+- interrupts		: IRQ line for the WWDT.
+- interrupt-names	: Interrupt line names "wdt" or "wwdt_reset_pending".
+			  wdt - will assert high after first (closed) window
+			  timer expires. wwdt_reset_pending - will assert high
+			  after second (open) window timer expires if WRP
+			  (Watchdog Reset pending) is configured with third
+			  (SST) timer.
+
 Example:
+Xilinx AXI/PLB soft-core watchdog:
 axi-timebase-wdt@40100000 {
 	clock-frequency = <50000000>;
 	compatible = "xlnx,xps-timebase-wdt-1.00.a";
@@ -24,3 +40,14 @@ axi-timebase-wdt@40100000 {
 	xlnx,wdt-enable-once = <0x0>;
 	xlnx,wdt-interval = <0x1b>;
 } ;
+
+Xilinx Versal window watchdog:
+watchdog@fd4d0000 {
+	compatible = "xlnx,versal-wwdt-1.0";
+	reg = <0x0 0xfd4d0000 0x0 0x10000>;
+	clocks = <&clk25>;
+	timeout-sec = <10>;
+	interrupt-names = "wdt", "wwdt_reset_pending";
+	interrupts = <0x0 0x64 0x1>, <0x0 0x6D 0x1>;
+	pretimeout-sec = <5>;
+} ;
-- 
2.7.4


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

* [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
                   ` (5 preceding siblings ...)
  2021-03-15 10:46 ` [PATCH 6/9] dt-bindings: watchdog: xilinx: Add binding for Versal watchdog Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-16  2:31   ` Guenter Roeck
  2021-03-15 10:46 ` [PATCH 8/9] watchdog: of_xilinx_wdt: Remove passing null pointer Srinivas Neeli
  2021-03-15 10:46 ` [PATCH 9/9] watchdog: of_xilinx_wdt: Skip printing pointer value Srinivas Neeli
  8 siblings, 1 reply; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Neeli

Versal watchdog driver uses Window watchdog mode. Window watchdog
timer(WWDT) contains closed(first) and open(second) window with
32 bit width. WWDT will generate an interrupt after the first window
timeout and reset signal after the second window timeout. Timeout
and Pre-timeout configuration, Stop and Refresh trigger only
in open window.

Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 285 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 283 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 3b93b60f1a00..3656e716b4f7 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -2,10 +2,11 @@
 /*
  * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt
  *
- * (C) Copyright 2013 - 2014 Xilinx, Inc.
+ * (C) Copyright 2013 - 2021 Xilinx, Inc.
  * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>)
  */
 
+#include <linux/bits.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -17,6 +18,11 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_address.h>
+#include <linux/interrupt.h>
+
+#define XWT_WWDT_DEFAULT_TIMEOUT	10
+#define XWT_WWDT_MIN_TIMEOUT		1
+#define XWT_WWDT_MAX_TIMEOUT		42
 
 /* Register offsets for the Wdt device */
 #define XWT_TWCSR0_OFFSET   0x0 /* Control/Status Register0 */
@@ -35,15 +41,44 @@
 #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000
 #define XWT_TIMER_FAILED            0xFFFFFFFF
 
+/* Register offsets for the WWdt device */
+#define XWT_WWDT_MWR_OFFSET	0x00
+#define XWT_WWDT_ESR_OFFSET	0x04
+#define XWT_WWDT_FCR_OFFSET	0x08
+#define XWT_WWDT_FWR_OFFSET	0x0c
+#define XWT_WWDT_SWR_OFFSET	0x10
+
+/* Master Write Control Register Masks */
+#define XWT_WWDT_MWR_MASK	BIT(0)
+
+/* Enable and Status Register Masks */
+#define XWT_WWDT_ESR_WINT_MASK	BIT(16)
+#define XWT_WWDT_ESR_WSW_MASK	BIT(8)
+#define XWT_WWDT_ESR_WEN_MASK	BIT(0)
+
+/* Function control Register Masks */
+#define XWT_WWDT_SBC_MASK	0xFF00
+#define XWT_WWDT_SBC_SHIFT	16
+#define XWT_WWDT_BSS_MASK	0xC0
+
 #define WATCHDOG_NAME     "Xilinx Watchdog"
 
+static int wdt_timeout;
+
+module_param(wdt_timeout, int, 0644);
+MODULE_PARM_DESC(wdt_timeout,
+		 "Watchdog time in seconds. (default="
+		 __MODULE_STRING(XWT_WWDT_DEFAULT_TIMEOUT) ")");
+
 /**
  * enum xwdt_ip_type - WDT IP type.
  *
  * @XWDT_WDT: Soft wdt ip.
+ * @XWDT_WWDT: Window wdt ip.
  */
 enum xwdt_ip_type {
 	XWDT_WDT = 0,
+	XWDT_WWDT = 1,
 };
 
 struct xwdt_devtype_data {
@@ -58,6 +93,7 @@ struct xwdt_device {
 	spinlock_t spinlock; /* spinlock for register handling */
 	struct watchdog_device xilinx_wdt_wdd;
 	struct clk		*clk;
+	int irq;
 };
 
 static int xilinx_wdt_start(struct watchdog_device *wdd)
@@ -145,6 +181,220 @@ static const struct watchdog_ops xilinx_wdt_ops = {
 	.ping = xilinx_wdt_keepalive,
 };
 
+static int is_wwdt_in_closed_window(struct watchdog_device *wdd)
+{
+	u32 control_status_reg;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+
+	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
+	if (control_status_reg & XWT_WWDT_ESR_WEN_MASK)
+		if (!(control_status_reg & XWT_WWDT_ESR_WSW_MASK))
+			return 0;
+
+	return 1;
+}
+
+static int xilinx_wwdt_start(struct watchdog_device *wdd)
+{
+	int ret;
+	u32 control_status_reg, fcr;
+	u64 time_out, pre_timeout, count;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
+
+	count = clk_get_rate(xdev->clk);
+	if (!count)
+		return -EINVAL;
+
+	/* Calculate timeout count */
+	pre_timeout = count * wdd->pretimeout;
+	time_out = count * wdd->timeout;
+	if (!watchdog_active(xilinx_wdt_wdd)) {
+		ret  = clk_enable(xdev->clk);
+		if (ret) {
+			dev_err(wdd->parent, "Failed to enable clock\n");
+			return ret;
+		}
+	}
+
+	spin_lock(&xdev->spinlock);
+	iowrite32(XWT_WWDT_MWR_MASK, xdev->base + XWT_WWDT_MWR_OFFSET);
+	iowrite32(~(u32)XWT_WWDT_ESR_WEN_MASK,
+		  xdev->base + XWT_WWDT_ESR_OFFSET);
+
+	if (pre_timeout) {
+		iowrite32((u32)(time_out - pre_timeout),
+			  xdev->base + XWT_WWDT_FWR_OFFSET);
+		iowrite32((u32)pre_timeout, xdev->base + XWT_WWDT_SWR_OFFSET);
+		fcr = ioread32(xdev->base + XWT_WWDT_SWR_OFFSET);
+		fcr = (fcr >> XWT_WWDT_SBC_SHIFT) & XWT_WWDT_SBC_MASK;
+		fcr = fcr | XWT_WWDT_BSS_MASK;
+		iowrite32(fcr, xdev->base + XWT_WWDT_FCR_OFFSET);
+	} else {
+		iowrite32((u32)pre_timeout,
+			  xdev->base + XWT_WWDT_FWR_OFFSET);
+		iowrite32((u32)time_out, xdev->base + XWT_WWDT_SWR_OFFSET);
+		iowrite32(0x0, xdev->base + XWT_WWDT_FCR_OFFSET);
+	}
+
+	/* Enable the window watchdog timer */
+	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
+	control_status_reg |= XWT_WWDT_ESR_WEN_MASK;
+	iowrite32(control_status_reg, xdev->base + XWT_WWDT_ESR_OFFSET);
+
+	spin_unlock(&xdev->spinlock);
+
+	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Started!\n");
+
+	return 0;
+}
+
+static int xilinx_wwdt_stop(struct watchdog_device *wdd)
+{
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
+
+	if (!is_wwdt_in_closed_window(wdd)) {
+		dev_warn(xilinx_wdt_wdd->parent, "timer in closed window");
+		return -EINVAL;
+	}
+
+	spin_lock(&xdev->spinlock);
+
+	iowrite32(XWT_WWDT_MWR_MASK, xdev->base + XWT_WWDT_MWR_OFFSET);
+	/* Disable the Window watchdog timer */
+	iowrite32(~(u32)XWT_WWDT_ESR_WEN_MASK,
+		  xdev->base + XWT_WWDT_ESR_OFFSET);
+
+	spin_unlock(&xdev->spinlock);
+
+	if (watchdog_active(xilinx_wdt_wdd))
+		clk_disable(xdev->clk);
+
+	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Stopped!\n");
+
+	return 0;
+}
+
+static int xilinx_wwdt_keepalive(struct watchdog_device *wdd)
+{
+	u32 control_status_reg;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+
+	/* Refresh in open window is ignored */
+	if (!is_wwdt_in_closed_window(wdd))
+		return 0;
+
+	spin_lock(&xdev->spinlock);
+
+	iowrite32(XWT_WWDT_MWR_MASK, xdev->base + XWT_WWDT_MWR_OFFSET);
+	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
+	control_status_reg |= XWT_WWDT_ESR_WINT_MASK;
+	control_status_reg &= ~XWT_WWDT_ESR_WSW_MASK;
+	iowrite32(control_status_reg, xdev->base + XWT_WWDT_ESR_OFFSET);
+	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
+	control_status_reg |= XWT_WWDT_ESR_WSW_MASK;
+	iowrite32(control_status_reg, xdev->base + XWT_WWDT_ESR_OFFSET);
+
+	spin_unlock(&xdev->spinlock);
+
+	return 0;
+}
+
+static int xilinx_wwdt_set_timeout(struct watchdog_device *wdd,
+				   unsigned int new_time)
+{
+	u32 ret = 0;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
+
+	if (!is_wwdt_in_closed_window(wdd)) {
+		dev_warn(xilinx_wdt_wdd->parent, "timer in closed window");
+		return -EINVAL;
+	}
+
+	if (new_time < XWT_WWDT_MIN_TIMEOUT ||
+	    new_time > XWT_WWDT_MAX_TIMEOUT) {
+		dev_warn(xilinx_wdt_wdd->parent,
+			 "timeout value must be %d<=x<=%d, using %d\n",
+				XWT_WWDT_MIN_TIMEOUT,
+				XWT_WWDT_MAX_TIMEOUT, new_time);
+		return -EINVAL;
+	}
+
+	wdd->timeout = new_time;
+	wdd->pretimeout = 0;
+
+	if (watchdog_active(xilinx_wdt_wdd)) {
+		ret = xilinx_wwdt_start(wdd);
+		if (ret)
+			dev_dbg(xilinx_wdt_wdd->parent, "timer start failed");
+	}
+
+	return 0;
+}
+
+static int xilinx_wwdt_set_pretimeout(struct watchdog_device *wdd,
+				      u32 new_pretimeout)
+{
+	u32 ret = 0;
+	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
+	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
+
+	if (!is_wwdt_in_closed_window(wdd)) {
+		dev_warn(xilinx_wdt_wdd->parent, "timer in closed window");
+		return -EINVAL;
+	}
+
+	if (new_pretimeout < wdd->min_timeout ||
+	    new_pretimeout >= wdd->timeout)
+		return -EINVAL;
+
+	wdd->pretimeout = new_pretimeout;
+
+	if (watchdog_active(xilinx_wdt_wdd)) {
+		ret = xilinx_wwdt_start(wdd);
+		if (ret)
+			dev_dbg(xilinx_wdt_wdd->parent, "timer start failed");
+	}
+
+	return 0;
+}
+
+static irqreturn_t xilinx_wwdt_isr(int irq, void *wdog_arg)
+{
+	struct xwdt_device *xdev = wdog_arg;
+
+	watchdog_notify_pretimeout(&xdev->xilinx_wdt_wdd);
+	return IRQ_HANDLED;
+}
+
+static const struct watchdog_info xilinx_wwdt_ident = {
+	.options =  WDIOF_MAGICCLOSE |
+		WDIOF_KEEPALIVEPING |
+		WDIOF_SETTIMEOUT,
+	.firmware_version = 1,
+	.identity = "xlnx_wwdt watchdog",
+};
+
+static const struct watchdog_info xilinx_wwdt_pretimeout_ident = {
+	.options = WDIOF_MAGICCLOSE |
+		   WDIOF_KEEPALIVEPING |
+		   WDIOF_PRETIMEOUT |
+		   WDIOF_SETTIMEOUT,
+	.firmware_version = 1,
+	.identity = "xlnx_wwdt watchdog",
+};
+
+static const struct watchdog_ops xilinx_wwdt_ops = {
+	.owner = THIS_MODULE,
+	.start = xilinx_wwdt_start,
+	.stop = xilinx_wwdt_stop,
+	.ping = xilinx_wwdt_keepalive,
+	.set_timeout = xilinx_wwdt_set_timeout,
+	.set_pretimeout = xilinx_wwdt_set_pretimeout,
+};
+
 static u32 xwdt_selftest(struct xwdt_device *xdev)
 {
 	int i;
@@ -181,11 +431,19 @@ static const struct xwdt_devtype_data xwdt_wdt_data = {
 	.xwdt_ops = &xilinx_wdt_ops,
 };
 
+static const struct xwdt_devtype_data xwdt_wwdt_data = {
+	.wdttype = XWDT_WWDT,
+	.xwdt_info = &xilinx_wwdt_ident,
+	.xwdt_ops = &xilinx_wwdt_ops,
+};
+
 static const struct of_device_id xwdt_of_match[] = {
 	{ .compatible = "xlnx,xps-timebase-wdt-1.00.a",
 		.data = &xwdt_wdt_data },
 	{ .compatible = "xlnx,xps-timebase-wdt-1.01.a",
 		.data = &xwdt_wdt_data },
+	{ .compatible = "xlnx,versal-wwdt-1.0",
+		.data = &xwdt_wwdt_data },
 	{},
 };
 MODULE_DEVICE_TABLE(of, xwdt_of_match);
@@ -194,7 +452,7 @@ static int xwdt_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	int rc;
-	u32 pfreq = 0, enable_once = 0;
+	u32 pfreq = 0, enable_once = 0, pre_timeout = 0;
 	struct xwdt_device *xdev;
 	struct watchdog_device *xilinx_wdt_wdd;
 	const struct of_device_id *of_id;
@@ -236,6 +494,12 @@ static int xwdt_probe(struct platform_device *pdev)
 				 "Parameter \"xlnx,wdt-enable-once\" not found\n");
 
 		watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
+	} else {
+		rc = of_property_read_u32(dev->of_node, "pretimeout-sec",
+					  &pre_timeout);
+		if (rc)
+			dev_dbg(dev,
+				"Parameter \"pretimeout-sec\" not found\n");
 	}
 
 	xdev->clk = devm_clk_get(dev, NULL);
@@ -268,6 +532,23 @@ static int xwdt_probe(struct platform_device *pdev)
 			xilinx_wdt_wdd->timeout =
 				2 * ((1 << xdev->wdt_interval) /
 					pfreq);
+	} else {
+		xilinx_wdt_wdd->pretimeout = pre_timeout;
+		xilinx_wdt_wdd->timeout = XWT_WWDT_DEFAULT_TIMEOUT;
+		xilinx_wdt_wdd->min_timeout = XWT_WWDT_MIN_TIMEOUT;
+		xilinx_wdt_wdd->max_timeout = XWT_WWDT_MAX_TIMEOUT;
+		xdev->irq = platform_get_irq_byname(pdev, "wdt");
+		if (xdev->irq > 0) {
+			if (!devm_request_irq(dev, xdev->irq, xilinx_wwdt_isr,
+					      0, dev_name(dev), xdev)) {
+				xilinx_wdt_wdd->info =
+				&xilinx_wwdt_pretimeout_ident;
+			}
+		}
+		rc = watchdog_init_timeout(xilinx_wdt_wdd,
+					   wdt_timeout, &pdev->dev);
+		if (rc)
+			dev_warn(&pdev->dev, "unable to set timeout value\n");
 	}
 
 	spin_lock_init(&xdev->spinlock);
-- 
2.7.4


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

* [PATCH 8/9] watchdog: of_xilinx_wdt: Remove passing null pointer
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
                   ` (6 preceding siblings ...)
  2021-03-15 10:46 ` [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-16  2:33   ` Guenter Roeck
  2021-03-15 10:46 ` [PATCH 9/9] watchdog: of_xilinx_wdt: Skip printing pointer value Srinivas Neeli
  8 siblings, 1 reply; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Neeli

clk is an optional property, if clock not defined,
calling clk_prepare_enable() and devm_add_action_or_reset()
are not useful.
so calling these two apis only when clock is present.

Addresses-Coverity:"FORWARD_NULL"

Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 3656e716b4f7..ad35c93b7684 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -520,6 +520,16 @@ static int xwdt_probe(struct platform_device *pdev)
 				 "The watchdog clock freq cannot be obtained\n");
 	} else {
 		pfreq = clk_get_rate(xdev->clk);
+		rc = clk_prepare_enable(xdev->clk);
+
+		if (rc) {
+			dev_err(dev, "unable to enable clock\n");
+			return rc;
+		}
+		rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare,
+					      xdev->clk);
+		if (rc)
+			return rc;
 	}
 
 	if (wdttype == XWDT_WDT) {
@@ -554,16 +564,6 @@ static int xwdt_probe(struct platform_device *pdev)
 	spin_lock_init(&xdev->spinlock);
 	watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
 
-	rc = clk_prepare_enable(xdev->clk);
-	if (rc) {
-		dev_err(dev, "unable to enable clock\n");
-		return rc;
-	}
-	rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare,
-				      xdev->clk);
-	if (rc)
-		return rc;
-
 	if (wdttype == XWDT_WDT) {
 		rc = xwdt_selftest(xdev);
 		if (rc == XWT_TIMER_FAILED) {
-- 
2.7.4


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

* [PATCH 9/9] watchdog: of_xilinx_wdt: Skip printing pointer value
  2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
                   ` (7 preceding siblings ...)
  2021-03-15 10:46 ` [PATCH 8/9] watchdog: of_xilinx_wdt: Remove passing null pointer Srinivas Neeli
@ 2021-03-15 10:46 ` Srinivas Neeli
  2021-03-16  2:34   ` Guenter Roeck
  8 siblings, 1 reply; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-15 10:46 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Neeli

"%p" is not printing the pointer value.
In driver, printing pointer value is not useful so avoiding print.

Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index ad35c93b7684..df84734eba68 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -578,8 +578,8 @@ static int xwdt_probe(struct platform_device *pdev)
 
 	clk_disable(xdev->clk);
 
-	dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds\n",
-		 xdev->base, xilinx_wdt_wdd->timeout);
+	dev_info(dev, "Xilinx Watchdog Timer with timeout %ds\n",
+		 xilinx_wdt_wdd->timeout);
 
 	platform_set_drvdata(pdev, xdev);
 
-- 
2.7.4


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

* Re: [PATCH 1/9] watchdog: of_xilinx_wdt: Add comment to spinlock
  2021-03-15 10:46 ` [PATCH 1/9] watchdog: of_xilinx_wdt: Add comment to spinlock Srinivas Neeli
@ 2021-03-16  2:21   ` Guenter Roeck
  0 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2021-03-16  2:21 UTC (permalink / raw)
  To: Srinivas Neeli, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Goud

On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> From: Srinivas Goud <srinivas.goud@xilinx.com>
> 
> Based on checkpatch every spinlock should be documented.
> The patch is fixing this issue:
> ./scripts/checkpatch.pl --strict -f drivers/watchdog/of_xilinx_wdt.c
> CHECK: spinlock_t definition without comment
> +	spinlock_t spinlock;
> 
> Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/watchdog/of_xilinx_wdt.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
> index 7fe4f7c3f7ce..00549164b3d7 100644
> --- a/drivers/watchdog/of_xilinx_wdt.c
> +++ b/drivers/watchdog/of_xilinx_wdt.c
> @@ -40,7 +40,7 @@
>  struct xwdt_device {
>  	void __iomem *base;
>  	u32 wdt_interval;
> -	spinlock_t spinlock;
> +	spinlock_t spinlock; /* spinlock for register handling */
>  	struct watchdog_device xilinx_wdt_wdd;
>  	struct clk		*clk;
>  };
> 


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

* Re: [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro
  2021-03-15 10:46 ` [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro Srinivas Neeli
@ 2021-03-16  2:23   ` Guenter Roeck
  2021-03-24  6:06     ` Srinivas Neeli
  0 siblings, 1 reply; 20+ messages in thread
From: Guenter Roeck @ 2021-03-16  2:23 UTC (permalink / raw)
  To: Srinivas Neeli, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Goud

On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> From: Srinivas Goud <srinivas.goud@xilinx.com>
> 
> Used BIT macro instead of mask value.
> 
> Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
> ---
>  drivers/watchdog/of_xilinx_wdt.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
> index 00549164b3d7..0d7df2370db7 100644
> --- a/drivers/watchdog/of_xilinx_wdt.c
> +++ b/drivers/watchdog/of_xilinx_wdt.c
> @@ -24,12 +24,12 @@
>  #define XWT_TBR_OFFSET      0x8 /* Timebase Register Offset */
>  
>  /* Control/Status Register Masks  */
> -#define XWT_CSR0_WRS_MASK   0x00000008 /* Reset status */
> -#define XWT_CSR0_WDS_MASK   0x00000004 /* Timer state  */
> -#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */
> +#define XWT_CSR0_WRS_MASK	BIT(3) /* Reset status */
> +#define XWT_CSR0_WDS_MASK	BIT(2) /* Timer state  */
> +#define XWT_CSR0_EWDT1_MASK	BIT(1) /* Enable bit 1 */
>  
>  /* Control/Status Register 0/1 bits  */
> -#define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 */
> +#define XWT_CSRX_EWDT2_MASK	BIT(0) /* Enable bit 2 */
>  

Requires #include <linux/bits.h>

>  /* SelfTest constants */
>  #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000
> 


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

* Re: [PATCH 3/9] watchdog: of_xilinx_wdt: Used dev_dbg()
  2021-03-15 10:46 ` [PATCH 3/9] watchdog: of_xilinx_wdt: Used dev_dbg() Srinivas Neeli
@ 2021-03-16  2:27   ` Guenter Roeck
  0 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2021-03-16  2:27 UTC (permalink / raw)
  To: Srinivas Neeli, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Goud

On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> From: Srinivas Goud <srinivas.goud@xilinx.com>
> 
> This patch removes pr_info in stop function and adds dev_dbg()
> in start/stop function to display device specific debug info.
> 
> Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
> Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
> ---
>  drivers/watchdog/of_xilinx_wdt.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
> index 0d7df2370db7..9e67b598907e 100644
> --- a/drivers/watchdog/of_xilinx_wdt.c
> +++ b/drivers/watchdog/of_xilinx_wdt.c
> @@ -50,6 +50,7 @@ static int xilinx_wdt_start(struct watchdog_device *wdd)
>  	int ret;
>  	u32 control_status_reg;
>  	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
>  
This is the same as wdd and thus pointless.

>  	ret = clk_enable(xdev->clk);
>  	if (ret) {
> @@ -70,6 +71,8 @@ static int xilinx_wdt_start(struct watchdog_device *wdd)
>  
>  	spin_unlock(&xdev->spinlock);
>  
> +	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Started!\n");
> +
>  	return 0;
>  }
>  
> @@ -77,6 +80,7 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd)
>  {
>  	u32 control_status_reg;
>  	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
>  
Same as above: This is the same as wdd and thus pointless.

>  	spin_lock(&xdev->spinlock);
>  
> @@ -91,7 +95,7 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd)
>  
>  	clk_disable(xdev->clk);
>  
> -	pr_info("Stopped!\n");
> +	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Stopped!\n");
>  
>  	return 0;
>  }
> 


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

* Re: [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support
  2021-03-15 10:46 ` [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support Srinivas Neeli
@ 2021-03-16  2:31   ` Guenter Roeck
  2021-03-24  6:04     ` Srinivas Neeli
  0 siblings, 1 reply; 20+ messages in thread
From: Guenter Roeck @ 2021-03-16  2:31 UTC (permalink / raw)
  To: Srinivas Neeli, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git

On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> Versal watchdog driver uses Window watchdog mode. Window watchdog
> timer(WWDT) contains closed(first) and open(second) window with
> 32 bit width. WWDT will generate an interrupt after the first window
> timeout and reset signal after the second window timeout. Timeout
> and Pre-timeout configuration, Stop and Refresh trigger only
> in open window.
> 
> Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>

I think this should be a separate watchdog driver. There is pretty much no overlap
with the existing driver.

Guenter

> ---
>  drivers/watchdog/of_xilinx_wdt.c | 285 ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 283 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
> index 3b93b60f1a00..3656e716b4f7 100644
> --- a/drivers/watchdog/of_xilinx_wdt.c
> +++ b/drivers/watchdog/of_xilinx_wdt.c
> @@ -2,10 +2,11 @@
>  /*
>   * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt
>   *
> - * (C) Copyright 2013 - 2014 Xilinx, Inc.
> + * (C) Copyright 2013 - 2021 Xilinx, Inc.
>   * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>)
>   */
>  
> +#include <linux/bits.h>
>  #include <linux/clk.h>
>  #include <linux/err.h>
>  #include <linux/module.h>
> @@ -17,6 +18,11 @@
>  #include <linux/of.h>
>  #include <linux/of_device.h>
>  #include <linux/of_address.h>
> +#include <linux/interrupt.h>
> +
> +#define XWT_WWDT_DEFAULT_TIMEOUT	10
> +#define XWT_WWDT_MIN_TIMEOUT		1
> +#define XWT_WWDT_MAX_TIMEOUT		42
>  
>  /* Register offsets for the Wdt device */
>  #define XWT_TWCSR0_OFFSET   0x0 /* Control/Status Register0 */
> @@ -35,15 +41,44 @@
>  #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000
>  #define XWT_TIMER_FAILED            0xFFFFFFFF
>  
> +/* Register offsets for the WWdt device */
> +#define XWT_WWDT_MWR_OFFSET	0x00
> +#define XWT_WWDT_ESR_OFFSET	0x04
> +#define XWT_WWDT_FCR_OFFSET	0x08
> +#define XWT_WWDT_FWR_OFFSET	0x0c
> +#define XWT_WWDT_SWR_OFFSET	0x10
> +
> +/* Master Write Control Register Masks */
> +#define XWT_WWDT_MWR_MASK	BIT(0)
> +
> +/* Enable and Status Register Masks */
> +#define XWT_WWDT_ESR_WINT_MASK	BIT(16)
> +#define XWT_WWDT_ESR_WSW_MASK	BIT(8)
> +#define XWT_WWDT_ESR_WEN_MASK	BIT(0)
> +
> +/* Function control Register Masks */
> +#define XWT_WWDT_SBC_MASK	0xFF00
> +#define XWT_WWDT_SBC_SHIFT	16
> +#define XWT_WWDT_BSS_MASK	0xC0
> +
>  #define WATCHDOG_NAME     "Xilinx Watchdog"
>  
> +static int wdt_timeout;
> +
> +module_param(wdt_timeout, int, 0644);
> +MODULE_PARM_DESC(wdt_timeout,
> +		 "Watchdog time in seconds. (default="
> +		 __MODULE_STRING(XWT_WWDT_DEFAULT_TIMEOUT) ")");
> +
>  /**
>   * enum xwdt_ip_type - WDT IP type.
>   *
>   * @XWDT_WDT: Soft wdt ip.
> + * @XWDT_WWDT: Window wdt ip.
>   */
>  enum xwdt_ip_type {
>  	XWDT_WDT = 0,
> +	XWDT_WWDT = 1,
>  };
>  
>  struct xwdt_devtype_data {
> @@ -58,6 +93,7 @@ struct xwdt_device {
>  	spinlock_t spinlock; /* spinlock for register handling */
>  	struct watchdog_device xilinx_wdt_wdd;
>  	struct clk		*clk;
> +	int irq;
>  };
>  
>  static int xilinx_wdt_start(struct watchdog_device *wdd)
> @@ -145,6 +181,220 @@ static const struct watchdog_ops xilinx_wdt_ops = {
>  	.ping = xilinx_wdt_keepalive,
>  };
>  
> +static int is_wwdt_in_closed_window(struct watchdog_device *wdd)
> +{
> +	u32 control_status_reg;
> +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +
> +	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
> +	if (control_status_reg & XWT_WWDT_ESR_WEN_MASK)
> +		if (!(control_status_reg & XWT_WWDT_ESR_WSW_MASK))
> +			return 0;
> +
> +	return 1;
> +}
> +
> +static int xilinx_wwdt_start(struct watchdog_device *wdd)
> +{
> +	int ret;
> +	u32 control_status_reg, fcr;
> +	u64 time_out, pre_timeout, count;
> +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
> +
> +	count = clk_get_rate(xdev->clk);
> +	if (!count)
> +		return -EINVAL;
> +
> +	/* Calculate timeout count */
> +	pre_timeout = count * wdd->pretimeout;
> +	time_out = count * wdd->timeout;
> +	if (!watchdog_active(xilinx_wdt_wdd)) {
> +		ret  = clk_enable(xdev->clk);
> +		if (ret) {
> +			dev_err(wdd->parent, "Failed to enable clock\n");
> +			return ret;
> +		}
> +	}
> +
> +	spin_lock(&xdev->spinlock);
> +	iowrite32(XWT_WWDT_MWR_MASK, xdev->base + XWT_WWDT_MWR_OFFSET);
> +	iowrite32(~(u32)XWT_WWDT_ESR_WEN_MASK,
> +		  xdev->base + XWT_WWDT_ESR_OFFSET);
> +
> +	if (pre_timeout) {
> +		iowrite32((u32)(time_out - pre_timeout),
> +			  xdev->base + XWT_WWDT_FWR_OFFSET);
> +		iowrite32((u32)pre_timeout, xdev->base + XWT_WWDT_SWR_OFFSET);
> +		fcr = ioread32(xdev->base + XWT_WWDT_SWR_OFFSET);
> +		fcr = (fcr >> XWT_WWDT_SBC_SHIFT) & XWT_WWDT_SBC_MASK;
> +		fcr = fcr | XWT_WWDT_BSS_MASK;
> +		iowrite32(fcr, xdev->base + XWT_WWDT_FCR_OFFSET);
> +	} else {
> +		iowrite32((u32)pre_timeout,
> +			  xdev->base + XWT_WWDT_FWR_OFFSET);
> +		iowrite32((u32)time_out, xdev->base + XWT_WWDT_SWR_OFFSET);
> +		iowrite32(0x0, xdev->base + XWT_WWDT_FCR_OFFSET);
> +	}
> +
> +	/* Enable the window watchdog timer */
> +	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
> +	control_status_reg |= XWT_WWDT_ESR_WEN_MASK;
> +	iowrite32(control_status_reg, xdev->base + XWT_WWDT_ESR_OFFSET);
> +
> +	spin_unlock(&xdev->spinlock);
> +
> +	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Started!\n");
> +
> +	return 0;
> +}
> +
> +static int xilinx_wwdt_stop(struct watchdog_device *wdd)
> +{
> +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
> +
> +	if (!is_wwdt_in_closed_window(wdd)) {
> +		dev_warn(xilinx_wdt_wdd->parent, "timer in closed window");
> +		return -EINVAL;
> +	}
> +
> +	spin_lock(&xdev->spinlock);
> +
> +	iowrite32(XWT_WWDT_MWR_MASK, xdev->base + XWT_WWDT_MWR_OFFSET);
> +	/* Disable the Window watchdog timer */
> +	iowrite32(~(u32)XWT_WWDT_ESR_WEN_MASK,
> +		  xdev->base + XWT_WWDT_ESR_OFFSET);
> +
> +	spin_unlock(&xdev->spinlock);
> +
> +	if (watchdog_active(xilinx_wdt_wdd))
> +		clk_disable(xdev->clk);
> +
> +	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Stopped!\n");
> +
> +	return 0;
> +}
> +
> +static int xilinx_wwdt_keepalive(struct watchdog_device *wdd)
> +{
> +	u32 control_status_reg;
> +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +
> +	/* Refresh in open window is ignored */
> +	if (!is_wwdt_in_closed_window(wdd))
> +		return 0;
> +
> +	spin_lock(&xdev->spinlock);
> +
> +	iowrite32(XWT_WWDT_MWR_MASK, xdev->base + XWT_WWDT_MWR_OFFSET);
> +	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
> +	control_status_reg |= XWT_WWDT_ESR_WINT_MASK;
> +	control_status_reg &= ~XWT_WWDT_ESR_WSW_MASK;
> +	iowrite32(control_status_reg, xdev->base + XWT_WWDT_ESR_OFFSET);
> +	control_status_reg = ioread32(xdev->base + XWT_WWDT_ESR_OFFSET);
> +	control_status_reg |= XWT_WWDT_ESR_WSW_MASK;
> +	iowrite32(control_status_reg, xdev->base + XWT_WWDT_ESR_OFFSET);
> +
> +	spin_unlock(&xdev->spinlock);
> +
> +	return 0;
> +}
> +
> +static int xilinx_wwdt_set_timeout(struct watchdog_device *wdd,
> +				   unsigned int new_time)
> +{
> +	u32 ret = 0;
> +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
> +
> +	if (!is_wwdt_in_closed_window(wdd)) {
> +		dev_warn(xilinx_wdt_wdd->parent, "timer in closed window");
> +		return -EINVAL;
> +	}
> +
> +	if (new_time < XWT_WWDT_MIN_TIMEOUT ||
> +	    new_time > XWT_WWDT_MAX_TIMEOUT) {
> +		dev_warn(xilinx_wdt_wdd->parent,
> +			 "timeout value must be %d<=x<=%d, using %d\n",
> +				XWT_WWDT_MIN_TIMEOUT,
> +				XWT_WWDT_MAX_TIMEOUT, new_time);
> +		return -EINVAL;
> +	}
> +
> +	wdd->timeout = new_time;
> +	wdd->pretimeout = 0;
> +
> +	if (watchdog_active(xilinx_wdt_wdd)) {
> +		ret = xilinx_wwdt_start(wdd);
> +		if (ret)
> +			dev_dbg(xilinx_wdt_wdd->parent, "timer start failed");
> +	}
> +
> +	return 0;
> +}
> +
> +static int xilinx_wwdt_set_pretimeout(struct watchdog_device *wdd,
> +				      u32 new_pretimeout)
> +{
> +	u32 ret = 0;
> +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> +	struct watchdog_device *xilinx_wdt_wdd = &xdev->xilinx_wdt_wdd;
> +
> +	if (!is_wwdt_in_closed_window(wdd)) {
> +		dev_warn(xilinx_wdt_wdd->parent, "timer in closed window");
> +		return -EINVAL;
> +	}
> +
> +	if (new_pretimeout < wdd->min_timeout ||
> +	    new_pretimeout >= wdd->timeout)
> +		return -EINVAL;
> +
> +	wdd->pretimeout = new_pretimeout;
> +
> +	if (watchdog_active(xilinx_wdt_wdd)) {
> +		ret = xilinx_wwdt_start(wdd);
> +		if (ret)
> +			dev_dbg(xilinx_wdt_wdd->parent, "timer start failed");
> +	}
> +
> +	return 0;
> +}
> +
> +static irqreturn_t xilinx_wwdt_isr(int irq, void *wdog_arg)
> +{
> +	struct xwdt_device *xdev = wdog_arg;
> +
> +	watchdog_notify_pretimeout(&xdev->xilinx_wdt_wdd);
> +	return IRQ_HANDLED;
> +}
> +
> +static const struct watchdog_info xilinx_wwdt_ident = {
> +	.options =  WDIOF_MAGICCLOSE |
> +		WDIOF_KEEPALIVEPING |
> +		WDIOF_SETTIMEOUT,
> +	.firmware_version = 1,
> +	.identity = "xlnx_wwdt watchdog",
> +};
> +
> +static const struct watchdog_info xilinx_wwdt_pretimeout_ident = {
> +	.options = WDIOF_MAGICCLOSE |
> +		   WDIOF_KEEPALIVEPING |
> +		   WDIOF_PRETIMEOUT |
> +		   WDIOF_SETTIMEOUT,
> +	.firmware_version = 1,
> +	.identity = "xlnx_wwdt watchdog",
> +};
> +
> +static const struct watchdog_ops xilinx_wwdt_ops = {
> +	.owner = THIS_MODULE,
> +	.start = xilinx_wwdt_start,
> +	.stop = xilinx_wwdt_stop,
> +	.ping = xilinx_wwdt_keepalive,
> +	.set_timeout = xilinx_wwdt_set_timeout,
> +	.set_pretimeout = xilinx_wwdt_set_pretimeout,
> +};
> +
>  static u32 xwdt_selftest(struct xwdt_device *xdev)
>  {
>  	int i;
> @@ -181,11 +431,19 @@ static const struct xwdt_devtype_data xwdt_wdt_data = {
>  	.xwdt_ops = &xilinx_wdt_ops,
>  };
>  
> +static const struct xwdt_devtype_data xwdt_wwdt_data = {
> +	.wdttype = XWDT_WWDT,
> +	.xwdt_info = &xilinx_wwdt_ident,
> +	.xwdt_ops = &xilinx_wwdt_ops,
> +};
> +
>  static const struct of_device_id xwdt_of_match[] = {
>  	{ .compatible = "xlnx,xps-timebase-wdt-1.00.a",
>  		.data = &xwdt_wdt_data },
>  	{ .compatible = "xlnx,xps-timebase-wdt-1.01.a",
>  		.data = &xwdt_wdt_data },
> +	{ .compatible = "xlnx,versal-wwdt-1.0",
> +		.data = &xwdt_wwdt_data },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, xwdt_of_match);
> @@ -194,7 +452,7 @@ static int xwdt_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
>  	int rc;
> -	u32 pfreq = 0, enable_once = 0;
> +	u32 pfreq = 0, enable_once = 0, pre_timeout = 0;
>  	struct xwdt_device *xdev;
>  	struct watchdog_device *xilinx_wdt_wdd;
>  	const struct of_device_id *of_id;
> @@ -236,6 +494,12 @@ static int xwdt_probe(struct platform_device *pdev)
>  				 "Parameter \"xlnx,wdt-enable-once\" not found\n");
>  
>  		watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
> +	} else {
> +		rc = of_property_read_u32(dev->of_node, "pretimeout-sec",
> +					  &pre_timeout);
> +		if (rc)
> +			dev_dbg(dev,
> +				"Parameter \"pretimeout-sec\" not found\n");
>  	}
>  
>  	xdev->clk = devm_clk_get(dev, NULL);
> @@ -268,6 +532,23 @@ static int xwdt_probe(struct platform_device *pdev)
>  			xilinx_wdt_wdd->timeout =
>  				2 * ((1 << xdev->wdt_interval) /
>  					pfreq);
> +	} else {
> +		xilinx_wdt_wdd->pretimeout = pre_timeout;
> +		xilinx_wdt_wdd->timeout = XWT_WWDT_DEFAULT_TIMEOUT;
> +		xilinx_wdt_wdd->min_timeout = XWT_WWDT_MIN_TIMEOUT;
> +		xilinx_wdt_wdd->max_timeout = XWT_WWDT_MAX_TIMEOUT;
> +		xdev->irq = platform_get_irq_byname(pdev, "wdt");
> +		if (xdev->irq > 0) {
> +			if (!devm_request_irq(dev, xdev->irq, xilinx_wwdt_isr,
> +					      0, dev_name(dev), xdev)) {
> +				xilinx_wdt_wdd->info =
> +				&xilinx_wwdt_pretimeout_ident;
> +			}
> +		}
> +		rc = watchdog_init_timeout(xilinx_wdt_wdd,
> +					   wdt_timeout, &pdev->dev);
> +		if (rc)
> +			dev_warn(&pdev->dev, "unable to set timeout value\n");
>  	}
>  
>  	spin_lock_init(&xdev->spinlock);
> 


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

* Re: [PATCH 8/9] watchdog: of_xilinx_wdt: Remove passing null pointer
  2021-03-15 10:46 ` [PATCH 8/9] watchdog: of_xilinx_wdt: Remove passing null pointer Srinivas Neeli
@ 2021-03-16  2:33   ` Guenter Roeck
  0 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2021-03-16  2:33 UTC (permalink / raw)
  To: Srinivas Neeli, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git

On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> clk is an optional property, if clock not defined,
> calling clk_prepare_enable() and devm_add_action_or_reset()
> are not useful.
> so calling these two apis only when clock is present.
> 
> Addresses-Coverity:"FORWARD_NULL"
> 
> Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/watchdog/of_xilinx_wdt.c | 20 ++++++++++----------
>  1 file changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
> index 3656e716b4f7..ad35c93b7684 100644
> --- a/drivers/watchdog/of_xilinx_wdt.c
> +++ b/drivers/watchdog/of_xilinx_wdt.c
> @@ -520,6 +520,16 @@ static int xwdt_probe(struct platform_device *pdev)
>  				 "The watchdog clock freq cannot be obtained\n");
>  	} else {
>  		pfreq = clk_get_rate(xdev->clk);
> +		rc = clk_prepare_enable(xdev->clk);
> +
> +		if (rc) {
> +			dev_err(dev, "unable to enable clock\n");
> +			return rc;
> +		}
> +		rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare,
> +					      xdev->clk);
> +		if (rc)
> +			return rc;
>  	}
>  
>  	if (wdttype == XWDT_WDT) {
> @@ -554,16 +564,6 @@ static int xwdt_probe(struct platform_device *pdev)
>  	spin_lock_init(&xdev->spinlock);
>  	watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
>  
> -	rc = clk_prepare_enable(xdev->clk);
> -	if (rc) {
> -		dev_err(dev, "unable to enable clock\n");
> -		return rc;
> -	}
> -	rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare,
> -				      xdev->clk);
> -	if (rc)
> -		return rc;
> -
>  	if (wdttype == XWDT_WDT) {
>  		rc = xwdt_selftest(xdev);
>  		if (rc == XWT_TIMER_FAILED) {
> 


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

* Re: [PATCH 9/9] watchdog: of_xilinx_wdt: Skip printing pointer value
  2021-03-15 10:46 ` [PATCH 9/9] watchdog: of_xilinx_wdt: Skip printing pointer value Srinivas Neeli
@ 2021-03-16  2:34   ` Guenter Roeck
  0 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2021-03-16  2:34 UTC (permalink / raw)
  To: Srinivas Neeli, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git

On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> "%p" is not printing the pointer value.
> In driver, printing pointer value is not useful so avoiding print.
> 
> Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>  drivers/watchdog/of_xilinx_wdt.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
> index ad35c93b7684..df84734eba68 100644
> --- a/drivers/watchdog/of_xilinx_wdt.c
> +++ b/drivers/watchdog/of_xilinx_wdt.c
> @@ -578,8 +578,8 @@ static int xwdt_probe(struct platform_device *pdev)
>  
>  	clk_disable(xdev->clk);
>  
> -	dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds\n",
> -		 xdev->base, xilinx_wdt_wdd->timeout);
> +	dev_info(dev, "Xilinx Watchdog Timer with timeout %ds\n",
> +		 xilinx_wdt_wdd->timeout);
>  
>  	platform_set_drvdata(pdev, xdev);
>  
> 


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

* RE: [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support
  2021-03-16  2:31   ` Guenter Roeck
@ 2021-03-24  6:04     ` Srinivas Neeli
  2021-03-24 14:01       ` Guenter Roeck
  0 siblings, 1 reply; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-24  6:04 UTC (permalink / raw)
  To: Guenter Roeck, Michal Simek, Shubhrajyoti Datta, Srinivas Goud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git

Hi Guenter,

Thanks for review

> -----Original Message-----
> From: Guenter Roeck <groeck7@gmail.com> On Behalf Of Guenter Roeck
> Sent: Tuesday, March 16, 2021 8:01 AM
> To: Srinivas Neeli <sneeli@xilinx.com>; Michal Simek <michals@xilinx.com>;
> Shubhrajyoti Datta <shubhraj@xilinx.com>; Srinivas Goud
> <sgoud@xilinx.com>
> Cc: wim@linux-watchdog.org; linux-watchdog@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; linux-kernel@vger.kernel.org; git
> <git@xilinx.com>
> Subject: Re: [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window
> watchdog support
> 
> On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> > Versal watchdog driver uses Window watchdog mode. Window watchdog
> > timer(WWDT) contains closed(first) and open(second) window with
> > 32 bit width. WWDT will generate an interrupt after the first window
> > timeout and reset signal after the second window timeout. Timeout and
> > Pre-timeout configuration, Stop and Refresh trigger only in open
> > window.
> >
> > Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
> 
> I think this should be a separate watchdog driver. There is pretty much no
> overlap with the existing driver.

Xilinx AXI Timebase Watchdog Timer supports two independent modes
1)Timebase Watchdog Mode
2)Window Watchdog Timer Mode.
Current of_xilinx_wdt.c driver already have support for Timebase Watchdog Mode, but Window watchdog timer Mode feature is missing.
Versal platform contains customized AXI Timebase Watchdog Timer, which supports Window Watchdog Timer Mode.
For that reason we are creating common driver for both the modes.

Thanks
Srinivas Neeli
> 
> Guenter
> 
> > ---
> >  drivers/watchdog/of_xilinx_wdt.c | 285
> > ++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 283 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/watchdog/of_xilinx_wdt.c
> > b/drivers/watchdog/of_xilinx_wdt.c
> > index 3b93b60f1a00..3656e716b4f7 100644
> > --- a/drivers/watchdog/of_xilinx_wdt.c
> > +++ b/drivers/watchdog/of_xilinx_wdt.c
> > @@ -2,10 +2,11 @@
> >  /*
> >   * Watchdog Device Driver for Xilinx axi/xps_timebase_wdt
> >   *
> > - * (C) Copyright 2013 - 2014 Xilinx, Inc.
> > + * (C) Copyright 2013 - 2021 Xilinx, Inc.
> >   * (C) Copyright 2011 (Alejandro Cabrera <aldaya@gmail.com>)
> >   */
> >
> > +#include <linux/bits.h>
> >  #include <linux/clk.h>
> >  #include <linux/err.h>
> >  #include <linux/module.h>
> > @@ -17,6 +18,11 @@
> >  #include <linux/of.h>
> >  #include <linux/of_device.h>
> >  #include <linux/of_address.h>
> > +#include <linux/interrupt.h>
> > +
> > +#define XWT_WWDT_DEFAULT_TIMEOUT	10
> > +#define XWT_WWDT_MIN_TIMEOUT		1
> > +#define XWT_WWDT_MAX_TIMEOUT		42
> >
> >  /* Register offsets for the Wdt device */
> >  #define XWT_TWCSR0_OFFSET   0x0 /* Control/Status Register0 */
> > @@ -35,15 +41,44 @@
> >  #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000
> >  #define XWT_TIMER_FAILED            0xFFFFFFFF
> >
> > +/* Register offsets for the WWdt device */
> > +#define XWT_WWDT_MWR_OFFSET	0x00
> > +#define XWT_WWDT_ESR_OFFSET	0x04
> > +#define XWT_WWDT_FCR_OFFSET	0x08
> > +#define XWT_WWDT_FWR_OFFSET	0x0c
> > +#define XWT_WWDT_SWR_OFFSET	0x10
> > +
> > +/* Master Write Control Register Masks */
> > +#define XWT_WWDT_MWR_MASK	BIT(0)
> > +
> > +/* Enable and Status Register Masks */
> > +#define XWT_WWDT_ESR_WINT_MASK	BIT(16)
> > +#define XWT_WWDT_ESR_WSW_MASK	BIT(8)
> > +#define XWT_WWDT_ESR_WEN_MASK	BIT(0)
> > +
> > +/* Function control Register Masks */
> > +#define XWT_WWDT_SBC_MASK	0xFF00
> > +#define XWT_WWDT_SBC_SHIFT	16
> > +#define XWT_WWDT_BSS_MASK	0xC0
> > +
> >  #define WATCHDOG_NAME     "Xilinx Watchdog"
> >
> > +static int wdt_timeout;
> > +
> > +module_param(wdt_timeout, int, 0644);
> MODULE_PARM_DESC(wdt_timeout,
> > +		 "Watchdog time in seconds. (default="
> > +		 __MODULE_STRING(XWT_WWDT_DEFAULT_TIMEOUT) ")");
> > +
> >  /**
> >   * enum xwdt_ip_type - WDT IP type.
> >   *
> >   * @XWDT_WDT: Soft wdt ip.
> > + * @XWDT_WWDT: Window wdt ip.
> >   */
> >  enum xwdt_ip_type {
> >  	XWDT_WDT = 0,
> > +	XWDT_WWDT = 1,
> >  };
> >
> >  struct xwdt_devtype_data {
> > @@ -58,6 +93,7 @@ struct xwdt_device {
> >  	spinlock_t spinlock; /* spinlock for register handling */
> >  	struct watchdog_device xilinx_wdt_wdd;
> >  	struct clk		*clk;
> > +	int irq;
> >  };
> >
> >  static int xilinx_wdt_start(struct watchdog_device *wdd) @@ -145,6
> > +181,220 @@ static const struct watchdog_ops xilinx_wdt_ops = {
> >  	.ping = xilinx_wdt_keepalive,
> >  };
> >
> > +static int is_wwdt_in_closed_window(struct watchdog_device *wdd) {
> > +	u32 control_status_reg;
> > +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> > +
> > +	control_status_reg = ioread32(xdev->base +
> XWT_WWDT_ESR_OFFSET);
> > +	if (control_status_reg & XWT_WWDT_ESR_WEN_MASK)
> > +		if (!(control_status_reg & XWT_WWDT_ESR_WSW_MASK))
> > +			return 0;
> > +
> > +	return 1;
> > +}
> > +
> > +static int xilinx_wwdt_start(struct watchdog_device *wdd) {
> > +	int ret;
> > +	u32 control_status_reg, fcr;
> > +	u64 time_out, pre_timeout, count;
> > +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> > +	struct watchdog_device *xilinx_wdt_wdd = &xdev-
> >xilinx_wdt_wdd;
> > +
> > +	count = clk_get_rate(xdev->clk);
> > +	if (!count)
> > +		return -EINVAL;
> > +
> > +	/* Calculate timeout count */
> > +	pre_timeout = count * wdd->pretimeout;
> > +	time_out = count * wdd->timeout;
> > +	if (!watchdog_active(xilinx_wdt_wdd)) {
> > +		ret  = clk_enable(xdev->clk);
> > +		if (ret) {
> > +			dev_err(wdd->parent, "Failed to enable clock\n");
> > +			return ret;
> > +		}
> > +	}
> > +
> > +	spin_lock(&xdev->spinlock);
> > +	iowrite32(XWT_WWDT_MWR_MASK, xdev->base +
> XWT_WWDT_MWR_OFFSET);
> > +	iowrite32(~(u32)XWT_WWDT_ESR_WEN_MASK,
> > +		  xdev->base + XWT_WWDT_ESR_OFFSET);
> > +
> > +	if (pre_timeout) {
> > +		iowrite32((u32)(time_out - pre_timeout),
> > +			  xdev->base + XWT_WWDT_FWR_OFFSET);
> > +		iowrite32((u32)pre_timeout, xdev->base +
> XWT_WWDT_SWR_OFFSET);
> > +		fcr = ioread32(xdev->base + XWT_WWDT_SWR_OFFSET);
> > +		fcr = (fcr >> XWT_WWDT_SBC_SHIFT) &
> XWT_WWDT_SBC_MASK;
> > +		fcr = fcr | XWT_WWDT_BSS_MASK;
> > +		iowrite32(fcr, xdev->base + XWT_WWDT_FCR_OFFSET);
> > +	} else {
> > +		iowrite32((u32)pre_timeout,
> > +			  xdev->base + XWT_WWDT_FWR_OFFSET);
> > +		iowrite32((u32)time_out, xdev->base +
> XWT_WWDT_SWR_OFFSET);
> > +		iowrite32(0x0, xdev->base + XWT_WWDT_FCR_OFFSET);
> > +	}
> > +
> > +	/* Enable the window watchdog timer */
> > +	control_status_reg = ioread32(xdev->base +
> XWT_WWDT_ESR_OFFSET);
> > +	control_status_reg |= XWT_WWDT_ESR_WEN_MASK;
> > +	iowrite32(control_status_reg, xdev->base +
> XWT_WWDT_ESR_OFFSET);
> > +
> > +	spin_unlock(&xdev->spinlock);
> > +
> > +	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Started!\n");
> > +
> > +	return 0;
> > +}
> > +
> > +static int xilinx_wwdt_stop(struct watchdog_device *wdd) {
> > +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> > +	struct watchdog_device *xilinx_wdt_wdd = &xdev-
> >xilinx_wdt_wdd;
> > +
> > +	if (!is_wwdt_in_closed_window(wdd)) {
> > +		dev_warn(xilinx_wdt_wdd->parent, "timer in closed
> window");
> > +		return -EINVAL;
> > +	}
> > +
> > +	spin_lock(&xdev->spinlock);
> > +
> > +	iowrite32(XWT_WWDT_MWR_MASK, xdev->base +
> XWT_WWDT_MWR_OFFSET);
> > +	/* Disable the Window watchdog timer */
> > +	iowrite32(~(u32)XWT_WWDT_ESR_WEN_MASK,
> > +		  xdev->base + XWT_WWDT_ESR_OFFSET);
> > +
> > +	spin_unlock(&xdev->spinlock);
> > +
> > +	if (watchdog_active(xilinx_wdt_wdd))
> > +		clk_disable(xdev->clk);
> > +
> > +	dev_dbg(xilinx_wdt_wdd->parent, "Watchdog Stopped!\n");
> > +
> > +	return 0;
> > +}
> > +
> > +static int xilinx_wwdt_keepalive(struct watchdog_device *wdd) {
> > +	u32 control_status_reg;
> > +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> > +
> > +	/* Refresh in open window is ignored */
> > +	if (!is_wwdt_in_closed_window(wdd))
> > +		return 0;
> > +
> > +	spin_lock(&xdev->spinlock);
> > +
> > +	iowrite32(XWT_WWDT_MWR_MASK, xdev->base +
> XWT_WWDT_MWR_OFFSET);
> > +	control_status_reg = ioread32(xdev->base +
> XWT_WWDT_ESR_OFFSET);
> > +	control_status_reg |= XWT_WWDT_ESR_WINT_MASK;
> > +	control_status_reg &= ~XWT_WWDT_ESR_WSW_MASK;
> > +	iowrite32(control_status_reg, xdev->base +
> XWT_WWDT_ESR_OFFSET);
> > +	control_status_reg = ioread32(xdev->base +
> XWT_WWDT_ESR_OFFSET);
> > +	control_status_reg |= XWT_WWDT_ESR_WSW_MASK;
> > +	iowrite32(control_status_reg, xdev->base +
> XWT_WWDT_ESR_OFFSET);
> > +
> > +	spin_unlock(&xdev->spinlock);
> > +
> > +	return 0;
> > +}
> > +
> > +static int xilinx_wwdt_set_timeout(struct watchdog_device *wdd,
> > +				   unsigned int new_time)
> > +{
> > +	u32 ret = 0;
> > +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> > +	struct watchdog_device *xilinx_wdt_wdd = &xdev-
> >xilinx_wdt_wdd;
> > +
> > +	if (!is_wwdt_in_closed_window(wdd)) {
> > +		dev_warn(xilinx_wdt_wdd->parent, "timer in closed
> window");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (new_time < XWT_WWDT_MIN_TIMEOUT ||
> > +	    new_time > XWT_WWDT_MAX_TIMEOUT) {
> > +		dev_warn(xilinx_wdt_wdd->parent,
> > +			 "timeout value must be %d<=x<=%d, using %d\n",
> > +				XWT_WWDT_MIN_TIMEOUT,
> > +				XWT_WWDT_MAX_TIMEOUT, new_time);
> > +		return -EINVAL;
> > +	}
> > +
> > +	wdd->timeout = new_time;
> > +	wdd->pretimeout = 0;
> > +
> > +	if (watchdog_active(xilinx_wdt_wdd)) {
> > +		ret = xilinx_wwdt_start(wdd);
> > +		if (ret)
> > +			dev_dbg(xilinx_wdt_wdd->parent, "timer start
> failed");
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int xilinx_wwdt_set_pretimeout(struct watchdog_device *wdd,
> > +				      u32 new_pretimeout)
> > +{
> > +	u32 ret = 0;
> > +	struct xwdt_device *xdev = watchdog_get_drvdata(wdd);
> > +	struct watchdog_device *xilinx_wdt_wdd = &xdev-
> >xilinx_wdt_wdd;
> > +
> > +	if (!is_wwdt_in_closed_window(wdd)) {
> > +		dev_warn(xilinx_wdt_wdd->parent, "timer in closed
> window");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (new_pretimeout < wdd->min_timeout ||
> > +	    new_pretimeout >= wdd->timeout)
> > +		return -EINVAL;
> > +
> > +	wdd->pretimeout = new_pretimeout;
> > +
> > +	if (watchdog_active(xilinx_wdt_wdd)) {
> > +		ret = xilinx_wwdt_start(wdd);
> > +		if (ret)
> > +			dev_dbg(xilinx_wdt_wdd->parent, "timer start
> failed");
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static irqreturn_t xilinx_wwdt_isr(int irq, void *wdog_arg) {
> > +	struct xwdt_device *xdev = wdog_arg;
> > +
> > +	watchdog_notify_pretimeout(&xdev->xilinx_wdt_wdd);
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static const struct watchdog_info xilinx_wwdt_ident = {
> > +	.options =  WDIOF_MAGICCLOSE |
> > +		WDIOF_KEEPALIVEPING |
> > +		WDIOF_SETTIMEOUT,
> > +	.firmware_version = 1,
> > +	.identity = "xlnx_wwdt watchdog",
> > +};
> > +
> > +static const struct watchdog_info xilinx_wwdt_pretimeout_ident = {
> > +	.options = WDIOF_MAGICCLOSE |
> > +		   WDIOF_KEEPALIVEPING |
> > +		   WDIOF_PRETIMEOUT |
> > +		   WDIOF_SETTIMEOUT,
> > +	.firmware_version = 1,
> > +	.identity = "xlnx_wwdt watchdog",
> > +};
> > +
> > +static const struct watchdog_ops xilinx_wwdt_ops = {
> > +	.owner = THIS_MODULE,
> > +	.start = xilinx_wwdt_start,
> > +	.stop = xilinx_wwdt_stop,
> > +	.ping = xilinx_wwdt_keepalive,
> > +	.set_timeout = xilinx_wwdt_set_timeout,
> > +	.set_pretimeout = xilinx_wwdt_set_pretimeout, };
> > +
> >  static u32 xwdt_selftest(struct xwdt_device *xdev)  {
> >  	int i;
> > @@ -181,11 +431,19 @@ static const struct xwdt_devtype_data
> xwdt_wdt_data = {
> >  	.xwdt_ops = &xilinx_wdt_ops,
> >  };
> >
> > +static const struct xwdt_devtype_data xwdt_wwdt_data = {
> > +	.wdttype = XWDT_WWDT,
> > +	.xwdt_info = &xilinx_wwdt_ident,
> > +	.xwdt_ops = &xilinx_wwdt_ops,
> > +};
> > +
> >  static const struct of_device_id xwdt_of_match[] = {
> >  	{ .compatible = "xlnx,xps-timebase-wdt-1.00.a",
> >  		.data = &xwdt_wdt_data },
> >  	{ .compatible = "xlnx,xps-timebase-wdt-1.01.a",
> >  		.data = &xwdt_wdt_data },
> > +	{ .compatible = "xlnx,versal-wwdt-1.0",
> > +		.data = &xwdt_wwdt_data },
> >  	{},
> >  };
> >  MODULE_DEVICE_TABLE(of, xwdt_of_match); @@ -194,7 +452,7 @@
> static
> > int xwdt_probe(struct platform_device *pdev)  {
> >  	struct device *dev = &pdev->dev;
> >  	int rc;
> > -	u32 pfreq = 0, enable_once = 0;
> > +	u32 pfreq = 0, enable_once = 0, pre_timeout = 0;
> >  	struct xwdt_device *xdev;
> >  	struct watchdog_device *xilinx_wdt_wdd;
> >  	const struct of_device_id *of_id;
> > @@ -236,6 +494,12 @@ static int xwdt_probe(struct platform_device
> *pdev)
> >  				 "Parameter \"xlnx,wdt-enable-once\" not
> found\n");
> >
> >  		watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
> > +	} else {
> > +		rc = of_property_read_u32(dev->of_node, "pretimeout-
> sec",
> > +					  &pre_timeout);
> > +		if (rc)
> > +			dev_dbg(dev,
> > +				"Parameter \"pretimeout-sec\" not
> found\n");
> >  	}
> >
> >  	xdev->clk = devm_clk_get(dev, NULL); @@ -268,6 +532,23 @@ static
> int
> > xwdt_probe(struct platform_device *pdev)
> >  			xilinx_wdt_wdd->timeout =
> >  				2 * ((1 << xdev->wdt_interval) /
> >  					pfreq);
> > +	} else {
> > +		xilinx_wdt_wdd->pretimeout = pre_timeout;
> > +		xilinx_wdt_wdd->timeout =
> XWT_WWDT_DEFAULT_TIMEOUT;
> > +		xilinx_wdt_wdd->min_timeout =
> XWT_WWDT_MIN_TIMEOUT;
> > +		xilinx_wdt_wdd->max_timeout =
> XWT_WWDT_MAX_TIMEOUT;
> > +		xdev->irq = platform_get_irq_byname(pdev, "wdt");
> > +		if (xdev->irq > 0) {
> > +			if (!devm_request_irq(dev, xdev->irq,
> xilinx_wwdt_isr,
> > +					      0, dev_name(dev), xdev)) {
> > +				xilinx_wdt_wdd->info =
> > +				&xilinx_wwdt_pretimeout_ident;
> > +			}
> > +		}
> > +		rc = watchdog_init_timeout(xilinx_wdt_wdd,
> > +					   wdt_timeout, &pdev->dev);
> > +		if (rc)
> > +			dev_warn(&pdev->dev, "unable to set timeout
> value\n");
> >  	}
> >
> >  	spin_lock_init(&xdev->spinlock);
> >


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

* RE: [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro
  2021-03-16  2:23   ` Guenter Roeck
@ 2021-03-24  6:06     ` Srinivas Neeli
  0 siblings, 0 replies; 20+ messages in thread
From: Srinivas Neeli @ 2021-03-24  6:06 UTC (permalink / raw)
  To: Guenter Roeck, Michal Simek, Shubhrajyoti Datta, Srinivas Goud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git, Srinivas Goud

Hi,

> -----Original Message-----
> From: Guenter Roeck <groeck7@gmail.com> On Behalf Of Guenter Roeck
> Sent: Tuesday, March 16, 2021 7:53 AM
> To: Srinivas Neeli <sneeli@xilinx.com>; Michal Simek <michals@xilinx.com>;
> Shubhrajyoti Datta <shubhraj@xilinx.com>; Srinivas Goud
> <sgoud@xilinx.com>
> Cc: wim@linux-watchdog.org; linux-watchdog@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; linux-kernel@vger.kernel.org; git
> <git@xilinx.com>; Srinivas Goud <sgoud@xilinx.com>
> Subject: Re: [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro
> 
> On 3/15/21 3:46 AM, Srinivas Neeli wrote:
> > From: Srinivas Goud <srinivas.goud@xilinx.com>
> >
> > Used BIT macro instead of mask value.
> >
> > Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
> > Signed-off-by: Michal Simek <michal.simek@xilinx.com>
> > Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
> > ---
> >  drivers/watchdog/of_xilinx_wdt.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/watchdog/of_xilinx_wdt.c
> > b/drivers/watchdog/of_xilinx_wdt.c
> > index 00549164b3d7..0d7df2370db7 100644
> > --- a/drivers/watchdog/of_xilinx_wdt.c
> > +++ b/drivers/watchdog/of_xilinx_wdt.c
> > @@ -24,12 +24,12 @@
> >  #define XWT_TBR_OFFSET      0x8 /* Timebase Register Offset */
> >
> >  /* Control/Status Register Masks  */
> > -#define XWT_CSR0_WRS_MASK   0x00000008 /* Reset status */
> > -#define XWT_CSR0_WDS_MASK   0x00000004 /* Timer state  */
> > -#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */
> > +#define XWT_CSR0_WRS_MASK	BIT(3) /* Reset status */
> > +#define XWT_CSR0_WDS_MASK	BIT(2) /* Timer state  */
> > +#define XWT_CSR0_EWDT1_MASK	BIT(1) /* Enable bit 1 */
> >
> >  /* Control/Status Register 0/1 bits  */ -#define XWT_CSRX_EWDT2_MASK
> > 0x00000001 /* Enable bit 2 */
> > +#define XWT_CSRX_EWDT2_MASK	BIT(0) /* Enable bit 2 */
> >
> 
> Requires #include <linux/bits.h>

Will update in V2 series.

> 
> >  /* SelfTest constants */
> >  #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000
> >


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

* Re: [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support
  2021-03-24  6:04     ` Srinivas Neeli
@ 2021-03-24 14:01       ` Guenter Roeck
  0 siblings, 0 replies; 20+ messages in thread
From: Guenter Roeck @ 2021-03-24 14:01 UTC (permalink / raw)
  To: Srinivas Neeli, Michal Simek, Shubhrajyoti Datta, Srinivas Goud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git

On 3/23/21 11:04 PM, Srinivas Neeli wrote:
> Hi Guenter,
> 
> Thanks for review
> 
>> -----Original Message-----
>> From: Guenter Roeck <groeck7@gmail.com> On Behalf Of Guenter Roeck
>> Sent: Tuesday, March 16, 2021 8:01 AM
>> To: Srinivas Neeli <sneeli@xilinx.com>; Michal Simek <michals@xilinx.com>;
>> Shubhrajyoti Datta <shubhraj@xilinx.com>; Srinivas Goud
>> <sgoud@xilinx.com>
>> Cc: wim@linux-watchdog.org; linux-watchdog@vger.kernel.org; linux-arm-
>> kernel@lists.infradead.org; linux-kernel@vger.kernel.org; git
>> <git@xilinx.com>
>> Subject: Re: [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window
>> watchdog support
>>
>> On 3/15/21 3:46 AM, Srinivas Neeli wrote:
>>> Versal watchdog driver uses Window watchdog mode. Window watchdog
>>> timer(WWDT) contains closed(first) and open(second) window with
>>> 32 bit width. WWDT will generate an interrupt after the first window
>>> timeout and reset signal after the second window timeout. Timeout and
>>> Pre-timeout configuration, Stop and Refresh trigger only in open
>>> window.
>>>
>>> Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
>>
>> I think this should be a separate watchdog driver. There is pretty much no
>> overlap with the existing driver.
> 
> Xilinx AXI Timebase Watchdog Timer supports two independent modes
> 1)Timebase Watchdog Mode
> 2)Window Watchdog Timer Mode.
> Current of_xilinx_wdt.c driver already have support for Timebase Watchdog Mode, but Window watchdog timer Mode feature is missing.
> Versal platform contains customized AXI Timebase Watchdog Timer, which supports Window Watchdog Timer Mode.
> For that reason we are creating common driver for both the modes.
> 

That is not an argument. The two watchdogs are still completely different,
and there is no value having a single driver.

Guenter

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

* [PATCH 5/9] watchdog: of_xilinx_wdt: Introduce wdttype enum for identification
  2020-01-16 13:26 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on watchdog driver Srinivas Neeli
@ 2020-01-16 13:26 ` Srinivas Neeli
  0 siblings, 0 replies; 20+ messages in thread
From: Srinivas Neeli @ 2020-01-16 13:26 UTC (permalink / raw)
  To: linux, michal.simek, shubhrajyoti.datta, sgoud
  Cc: wim, linux-watchdog, linux-arm-kernel, linux-kernel, git

There is a need to identify watchdog type that's why new enum was
was introduced to cover it. Move functionality valid only for this
watchdog type if statement.

Signed-off-by: Srinivas Goud <srinivas.goud@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Srinivas Neeli <srinivas.neeli@xilinx.com>
---
 drivers/watchdog/of_xilinx_wdt.c | 64 +++++++++++++++++++++++++++-------------
 1 file changed, 43 insertions(+), 21 deletions(-)

diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index b2ce1b90237e..3b93b60f1a00 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -37,7 +37,17 @@
 
 #define WATCHDOG_NAME     "Xilinx Watchdog"
 
+/**
+ * enum xwdt_ip_type - WDT IP type.
+ *
+ * @XWDT_WDT: Soft wdt ip.
+ */
+enum xwdt_ip_type {
+	XWDT_WDT = 0,
+};
+
 struct xwdt_devtype_data {
+	enum xwdt_ip_type wdttype;
 	const struct watchdog_ops *xwdt_ops;
 	const struct watchdog_info *xwdt_info;
 };
@@ -166,6 +176,7 @@ static void xwdt_clk_disable_unprepare(void *data)
 }
 
 static const struct xwdt_devtype_data xwdt_wdt_data = {
+	.wdttype = XWDT_WDT,
 	.xwdt_info = &xilinx_wdt_ident,
 	.xwdt_ops = &xilinx_wdt_ops,
 };
@@ -188,6 +199,7 @@ static int xwdt_probe(struct platform_device *pdev)
 	struct watchdog_device *xilinx_wdt_wdd;
 	const struct of_device_id *of_id;
 	const struct xwdt_devtype_data *devtype;
+	enum xwdt_ip_type wdttype;
 
 	xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL);
 	if (!xdev)
@@ -201,6 +213,8 @@ static int xwdt_probe(struct platform_device *pdev)
 
 	devtype = of_id->data;
 
+	wdttype = devtype->wdttype;
+
 	xilinx_wdt_wdd->info = devtype->xwdt_info;
 	xilinx_wdt_wdd->ops = devtype->xwdt_ops;
 	xilinx_wdt_wdd->parent = dev;
@@ -209,18 +223,20 @@ static int xwdt_probe(struct platform_device *pdev)
 	if (IS_ERR(xdev->base))
 		return PTR_ERR(xdev->base);
 
-	rc = of_property_read_u32(dev->of_node, "xlnx,wdt-interval",
-				  &xdev->wdt_interval);
-	if (rc)
-		dev_warn(dev, "Parameter \"xlnx,wdt-interval\" not found\n");
+	if (wdttype == XWDT_WDT) {
+		rc = of_property_read_u32(dev->of_node, "xlnx,wdt-interval",
+					  &xdev->wdt_interval);
+		if (rc)
+			dev_warn(dev, "Parameter \"xlnx,wdt-interval\" not found\n");
 
-	rc = of_property_read_u32(dev->of_node, "xlnx,wdt-enable-once",
-				  &enable_once);
-	if (rc)
-		dev_warn(dev,
-			 "Parameter \"xlnx,wdt-enable-once\" not found\n");
+		rc = of_property_read_u32(dev->of_node, "xlnx,wdt-enable-once",
+					  &enable_once);
+		if (rc)
+			dev_warn(dev,
+				 "Parameter \"xlnx,wdt-enable-once\" not found\n");
 
-	watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
+		watchdog_set_nowayout(xilinx_wdt_wdd, enable_once);
+	}
 
 	xdev->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(xdev->clk)) {
@@ -242,13 +258,17 @@ static int xwdt_probe(struct platform_device *pdev)
 		pfreq = clk_get_rate(xdev->clk);
 	}
 
-	/*
-	 * Twice of the 2^wdt_interval / freq  because the first wdt overflow is
-	 * ignored (interrupt), reset is only generated at second wdt overflow
-	 */
-	if (pfreq && xdev->wdt_interval)
-		xilinx_wdt_wdd->timeout = 2 * ((1 << xdev->wdt_interval) /
-					  pfreq);
+	if (wdttype == XWDT_WDT) {
+		/*
+		 * Twice of the 2^wdt_interval / freq  because
+		 * the first wdt overflow is ignored (interrupt),
+		 * reset is only generated at second wdt overflow
+		 */
+		if (pfreq && xdev->wdt_interval)
+			xilinx_wdt_wdd->timeout =
+				2 * ((1 << xdev->wdt_interval) /
+					pfreq);
+	}
 
 	spin_lock_init(&xdev->spinlock);
 	watchdog_set_drvdata(xilinx_wdt_wdd, xdev);
@@ -263,10 +283,12 @@ static int xwdt_probe(struct platform_device *pdev)
 	if (rc)
 		return rc;
 
-	rc = xwdt_selftest(xdev);
-	if (rc == XWT_TIMER_FAILED) {
-		dev_err(dev, "SelfTest routine error\n");
-		return rc;
+	if (wdttype == XWDT_WDT) {
+		rc = xwdt_selftest(xdev);
+		if (rc == XWT_TIMER_FAILED) {
+			dev_err(dev, "SelfTest routine error\n");
+			return rc;
+		}
 	}
 
 	rc = devm_watchdog_register_device(dev, xilinx_wdt_wdd);
-- 
2.7.4


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

end of thread, back to index

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-15 10:46 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on xilinx watchdog driver Srinivas Neeli
2021-03-15 10:46 ` [PATCH 1/9] watchdog: of_xilinx_wdt: Add comment to spinlock Srinivas Neeli
2021-03-16  2:21   ` Guenter Roeck
2021-03-15 10:46 ` [PATCH 2/9] watchdog: of_xilinx_wdt: Used BIT macro Srinivas Neeli
2021-03-16  2:23   ` Guenter Roeck
2021-03-24  6:06     ` Srinivas Neeli
2021-03-15 10:46 ` [PATCH 3/9] watchdog: of_xilinx_wdt: Used dev_dbg() Srinivas Neeli
2021-03-16  2:27   ` Guenter Roeck
2021-03-15 10:46 ` [PATCH 4/9] watchdog: of_xilinx_wdt: Initialize watchdog via data structure Srinivas Neeli
2021-03-15 10:46 ` [PATCH 5/9] watchdog: of_xilinx_wdt: Introduce wdttype enum for identification Srinivas Neeli
2021-03-15 10:46 ` [PATCH 6/9] dt-bindings: watchdog: xilinx: Add binding for Versal watchdog Srinivas Neeli
2021-03-15 10:46 ` [PATCH 7/9] watchdog: of_xilinx_wdt: Add Versal Window watchdog support Srinivas Neeli
2021-03-16  2:31   ` Guenter Roeck
2021-03-24  6:04     ` Srinivas Neeli
2021-03-24 14:01       ` Guenter Roeck
2021-03-15 10:46 ` [PATCH 8/9] watchdog: of_xilinx_wdt: Remove passing null pointer Srinivas Neeli
2021-03-16  2:33   ` Guenter Roeck
2021-03-15 10:46 ` [PATCH 9/9] watchdog: of_xilinx_wdt: Skip printing pointer value Srinivas Neeli
2021-03-16  2:34   ` Guenter Roeck
  -- strict thread matches above, loose matches on Subject: below --
2020-01-16 13:26 [PATCH 0/9] watchdog: of_xilinx_wdt: Update on watchdog driver Srinivas Neeli
2020-01-16 13:26 ` [PATCH 5/9] watchdog: of_xilinx_wdt: Introduce wdttype enum for identification Srinivas Neeli

Linux-Watchdog Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-watchdog/0 linux-watchdog/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-watchdog linux-watchdog/ https://lore.kernel.org/linux-watchdog \
		linux-watchdog@vger.kernel.org
	public-inbox-index linux-watchdog

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-watchdog


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git