All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Simek <michal.simek@xilinx.com>
To: u-boot@lists.denx.de
Subject: [PATCH] versal: watchdog: Add support for Xilinx window watchdog
Date: Wed, 11 Mar 2020 11:48:23 +0100	[thread overview]
Message-ID: <2204261a8e80503d41bec1b0eb68e00080be5c4c.1583923701.git.michal.simek@xilinx.com> (raw)

From: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>

Add support for Xilinx window watchdog, which can be found on
Versal platforms.

Signed-off-by: Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
---

 MAINTAINERS                    |   1 +
 drivers/watchdog/Kconfig       |   8 ++
 drivers/watchdog/Makefile      |   1 +
 drivers/watchdog/xilinx_wwdt.c | 185 +++++++++++++++++++++++++++++++++
 4 files changed, 195 insertions(+)
 create mode 100644 drivers/watchdog/xilinx_wwdt.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 37ff21a037b4..7cb1bc0957a3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -433,6 +433,7 @@ M:	Michal Simek <michal.simek@xilinx.com>
 S:	Maintained
 T:	git https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze.git
 F:	arch/arm/mach-versal/
+F:	drivers/watchdog/xilinx_wwdt.c
 N:	(?<!uni)versal
 
 ARM VERSATILE EXPRESS DRIVERS
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d24c1e48353f..b3911cf346ed 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -185,6 +185,14 @@ config XILINX_TB_WATCHDOG
 	   Select this to enable Xilinx Axi watchdog timer, which can be found on some
 	   Xilinx Microblaze Platforms.
 
+config WWDT_XILINX
+	bool "Xilinx window watchdog timer support"
+	depends on WDT && ARCH_VERSAL
+	imply WATCHDOG
+	help
+	  Select this to enable Xilinx window watchdog timer, which can be found on
+	  Xilinx Versal Platforms.
+
 config WDT_TANGIER
 	bool "Intel Tangier watchdog timer support"
 	depends on WDT && INTEL_MID
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 87f92a43b14e..dc25560dbadf 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o
 obj-$(CONFIG_WDT_SP805) += sp805_wdt.o
 obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o
 obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o
+obj-$(CONFIG_WWDT_XILINX) += xilinx_wwdt.o
diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c
new file mode 100644
index 000000000000..34018e2b2b34
--- /dev/null
+++ b/drivers/watchdog/xilinx_wwdt.c
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx window watchdog timer driver.
+ *
+ * Author(s):	Michal Simek <michal.simek@xilinx.com>
+ *		Ashok Reddy Soma <ashokred@xilinx.com>
+ *
+ * Copyright (c) 2020, Xilinx Inc.
+ */
+
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <wdt.h>
+#include <linux/io.h>
+
+/* Refresh Register Masks */
+#define XWT_WWREF_GWRR_MASK	BIT(0) /* Refresh and start new period */
+
+/* Generic Control/Status Register Masks */
+#define XWT_WWCSR_GWEN_MASK	BIT(0) /* Enable Bit */
+
+struct wwdt_regs {
+	u32 reserved0[1024];
+	u32 refresh;		/* Refresh Register [0x1000] */
+	u32 reserved1[1023];
+	u32 csr;		/* Control/Status Register [0x2000] */
+	u32 reserved2;
+	u32 offset;		/* Offset Register [0x2008] */
+	u32 reserved3;
+	u32 cmp0;		/* Compare Value Register0 [0x2010] */
+	u32 cmp1;		/* Compare Value Register1 [0x2014] */
+	u32 reserved4[1006];
+	u32 warmrst;		/* Warm Reset Register [0x2FD0] */
+};
+
+struct xlnx_wwdt_priv {
+	bool enable_once;
+	struct wwdt_regs *regs;
+	struct clk clk;
+};
+
+struct xlnx_wwdt_platdata {
+	bool enable_once;
+	phys_addr_t iobase;
+};
+
+static int xlnx_wwdt_reset(struct udevice *dev)
+{
+	struct xlnx_wwdt_priv *wdt = dev_get_priv(dev);
+
+	dev_dbg(dev, "%s ", __func__);
+
+	writel(XWT_WWREF_GWRR_MASK, &wdt->regs->refresh);
+
+	return 0;
+}
+
+static int xlnx_wwdt_stop(struct udevice *dev)
+{
+	u32 csr;
+	struct xlnx_wwdt_priv *wdt = dev_get_priv(dev);
+
+	if (wdt->enable_once) {
+		dev_warn(dev, "Can't stop Xilinx watchdog.\n");
+		return -EBUSY;
+	}
+
+	/* Disable the generic watchdog timer */
+	csr = readl(&wdt->regs->csr);
+	csr &= ~(XWT_WWCSR_GWEN_MASK);
+	writel(csr, &wdt->regs->csr);
+
+	clk_disable(&wdt->clk);
+
+	dev_dbg(dev, "Watchdog disabled!\n");
+
+	return 0;
+}
+
+static int xlnx_wwdt_start(struct udevice *dev, u64 timeout, ulong flags)
+{
+	int ret;
+	u32 csr;
+	u64 count;
+	unsigned long clock_f;
+	struct xlnx_wwdt_priv *wdt = dev_get_priv(dev);
+
+	dev_dbg(dev, "%s:\n", __func__);
+
+	clock_f = clk_get_rate(&wdt->clk);
+	if (IS_ERR_VALUE(clock_f)) {
+		dev_err(dev, "failed to get rate\n");
+		return clock_f;
+	}
+
+	dev_dbg(dev, "%s: CLK %ld\n", __func__, clock_f);
+
+	/* Calculate timeout count */
+	count = timeout * clock_f;
+
+	/* clk_enable will return -ENOSYS when it is not implemented */
+	ret = clk_enable(&wdt->clk);
+	if (ret && ret != -ENOSYS) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	/*
+	 * Timeout count is half as there are two windows
+	 * first window overflow is ignored (interrupt),
+	 * reset is only generated at second window overflow
+	 */
+	count = count >> 1;
+
+	/* Disable the generic watchdog timer */
+	csr = readl(&wdt->regs->csr);
+	csr &= ~(XWT_WWCSR_GWEN_MASK);
+	writel(csr, &wdt->regs->csr);
+
+	/* Set compare and offset registers for generic watchdog timeout */
+	writel((u32)count, &wdt->regs->cmp0);
+	writel((u32)0, &wdt->regs->cmp1);
+	writel((u32)count, &wdt->regs->offset);
+
+	/* Enable the generic watchdog timer */
+	csr = readl(&wdt->regs->csr);
+	csr |= (XWT_WWCSR_GWEN_MASK);
+	writel(csr, &wdt->regs->csr);
+
+	return 0;
+}
+
+static int xlnx_wwdt_probe(struct udevice *dev)
+{
+	int ret;
+	struct xlnx_wwdt_platdata *platdata = dev_get_platdata(dev);
+	struct xlnx_wwdt_priv *wdt = dev_get_priv(dev);
+
+	dev_dbg(dev, "%s: Probing wdt%u\n", __func__, dev->seq);
+
+	wdt->regs = (struct wwdt_regs *)ioremap(platdata->iobase,
+						sizeof(struct wwdt_regs));
+	wdt->enable_once = platdata->enable_once;
+
+	ret = clk_get_by_index(dev, 0, &wdt->clk);
+	if (ret < 0)
+		dev_err(dev, "failed to get clock\n");
+
+	return ret;
+}
+
+static int xlnx_wwdt_ofdata_to_platdata(struct udevice *dev)
+{
+	struct xlnx_wwdt_platdata *platdata = dev_get_platdata(dev);
+
+	platdata->iobase = dev_read_addr(dev);
+	platdata->enable_once = dev_read_u32_default(dev,
+						     "xlnx,wdt-enable-once", 0);
+	dev_dbg(dev, "wdt-enable-once %d\n", platdata->enable_once);
+
+	return 0;
+}
+
+static const struct wdt_ops xlnx_wwdt_ops = {
+	.start = xlnx_wwdt_start,
+	.reset = xlnx_wwdt_reset,
+	.stop = xlnx_wwdt_stop,
+};
+
+static const struct udevice_id xlnx_wwdt_ids[] = {
+	{ .compatible = "xlnx,versal-wwdt-1.0", },
+	{},
+};
+
+U_BOOT_DRIVER(xlnx_wwdt) = {
+	.name = "xlnx_wwdt",
+	.id = UCLASS_WDT,
+	.of_match = xlnx_wwdt_ids,
+	.probe = xlnx_wwdt_probe,
+	.priv_auto_alloc_size = sizeof(struct xlnx_wwdt_priv),
+	.platdata_auto_alloc_size = sizeof(struct xlnx_wwdt_platdata),
+	.ofdata_to_platdata = xlnx_wwdt_ofdata_to_platdata,
+	.ops = &xlnx_wwdt_ops,
+};
-- 
2.25.1

             reply	other threads:[~2020-03-11 10:48 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-11 10:48 Michal Simek [this message]
2020-03-11 11:25 ` [PATCH] versal: watchdog: Add support for Xilinx window watchdog Stefan Roese
2020-03-11 11:34   ` Michal Simek
2020-03-11 11:54     ` Andy Shevchenko
2020-03-11 12:31       ` Michal Simek
2020-03-11 11:56     ` Stefan Roese
2020-03-11 12:11       ` Michal Simek
2020-03-11 14:28         ` Tom Rini
2020-03-11 14:30           ` Michal Simek
2020-03-11 11:52 ` Andy Shevchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2204261a8e80503d41bec1b0eb68e00080be5c4c.1583923701.git.michal.simek@xilinx.com \
    --to=michal.simek@xilinx.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.