mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Juergen Borleis <jbe@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH 18/19] MPC5125/WDG: add a watchdog driver
Date: Tue,  7 Oct 2014 16:22:17 +0200	[thread overview]
Message-ID: <1412691738-11145-19-git-send-email-jbe@pengutronix.de> (raw)
In-Reply-To: <1412691738-11145-1-git-send-email-jbe@pengutronix.de>

This watchdog is always enabled after reset and can be configured only once.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 drivers/watchdog/Kconfig   |   6 ++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/mpc5125.c | 148 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 drivers/watchdog/mpc5125.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7f7b02e..4c57111 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -28,4 +28,10 @@ config WATCHDOG_JZ4740
 	help
 	  Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
 
+config WATCHDOG_MPC5125
+	bool "MPC5125 SoC hardware watchdog"
+	depends on SOC_MPC5125
+	help
+	  Hardware driver for the built-in watchdog timer on MPC5125 SoCs.
+
 endif
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 865fc47..b7aa549 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_WATCHDOG) += wd_core.o
 obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o
 obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o
 obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o
+obj-$(CONFIG_WATCHDOG_MPC5125) += mpc5125.o
diff --git a/drivers/watchdog/mpc5125.c b/drivers/watchdog/mpc5125.c
new file mode 100644
index 0000000..7fefa21
--- /dev/null
+++ b/drivers/watchdog/mpc5125.c
@@ -0,0 +1,148 @@
+/*
+ * (c) 2014 Juergen Borleis <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Note: this driver works for the MPC5125. It might work for the
+ * MPC512X SoCs as well, but is not tested yet.
+ */
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <errno.h>
+#include <malloc.h>
+#include <watchdog.h>
+#include <mach/clocks.h>
+
+/* WD register description */
+struct wdt {
+	u32 res0;
+	u32 swcrr; /* note: read often, write once */
+	u32 swcnr;
+	u16 res1;
+	u16 swsrr;
+};
+
+struct mpc5125_wd {
+	struct watchdog wd;
+	struct wdt *regs;
+	bool re_configured;
+};
+
+#define WDT_SWCRR_GET_SWTC(x) ((x) >> 16)
+#define WDT_SWCRR_SET_SWTC(x) ((x) << 16)
+#define WDT_SWCRR_SWEN (1 << 2)
+#define WDT_SWCRR_SWRI (1 << 1)
+#define WDT_SWCRR_SWPR (1 << 0)
+
+#define MPC5125_WDT_RESET1_MAGIC 0x556c
+#define MPC5125_WDT_RESET2_MAGIC 0xaa39
+
+#define MPC5125_WDT_PRESCALE 0x10000
+
+#define to_mpc5125_wd(h) container_of(h, struct mpc5125_wd, wd)
+
+static void mpc5125_wd_retrigger(struct mpc5125_wd *wd)
+{
+	out_be16(&wd->regs->swsrr, 0x556c);
+	out_be16(&wd->regs->swsrr, 0xaa39);
+}
+
+/* note: setting a new timeout is an irreversible step! */
+static int mpc5125_watchdog_set_timeout(struct watchdog *wd, unsigned timeout)
+{
+	struct mpc5125_wd *pwd = (struct mpc5125_wd *)to_mpc5125_wd(wd);
+	unsigned cnt_val, time;
+	uint64_t new_cnt_val;
+	u32 swcrr;
+
+	/*
+	 * what does the user wants us to do?
+	 * - just retrigger?
+	 * - or re-programming to a different timout value?
+	 *
+	 * Due to the fact we can program the SWCRR register only once we
+	 * must detect a difference between the given timeout and the time
+	 * which is currently in use to have the latter case.
+	 * If the given timeout is "nealy" the same then currently used, just
+	 * a re-trigger should occure (first case).
+	 */
+	swcrr = in_be32(&pwd->regs->swcrr);
+	cnt_val = WDT_SWCRR_GET_SWTC(swcrr);
+
+	if (swcrr & WDT_SWCRR_SWPR)
+		time = (cnt_val * MPC5125_WDT_PRESCALE) / get_timebase_clock();
+	else
+		time = cnt_val / get_timebase_clock();
+
+	if (time != timeout) {
+		/* it seems the user wants a new timout value */
+		if (pwd->re_configured) {
+			pr_err("Cannot configure the watchdog twice. "
+					"Still sticked to %u seconds.\n", time);
+			return -EINVAL;
+		}
+		/*
+		 * we always need the prescaler enabled, because without it
+		 * the timeout is far below a second...
+		 */
+		new_cnt_val = timeout * get_timebase_clock();
+		if (new_cnt_val >= 0xffff0000) {
+			time = 0xffff0000 / get_timebase_clock();
+			pr_err("Invalid timout value. Max value is "
+							"%u seconds.\n", time);
+			return -EINVAL;
+		}
+		new_cnt_val /= MPC5125_WDT_PRESCALE;
+		out_be32(&pwd->regs->swcrr, WDT_SWCRR_SET_SWTC(new_cnt_val) |
+			WDT_SWCRR_SWPR | WDT_SWCRR_SWEN | WDT_SWCRR_SWRI);
+		pwd->re_configured = true;
+	}
+
+	mpc5125_wd_retrigger(pwd);
+
+	return 0;
+}
+
+static int mpc5125_wd_probe(struct device_d *dev)
+{
+	struct mpc5125_wd *priv;
+	int rc;
+
+	priv = xzalloc(sizeof(struct mpc5125_wd));
+	priv->regs = dev_request_mem_region(dev, 0);
+	priv->wd.set_timeout = mpc5125_watchdog_set_timeout;
+
+	rc = watchdog_register(&priv->wd);
+	if (rc != 0)
+		goto on_error;
+
+	dev->priv = priv;
+	return 0;
+
+on_error:
+	free(priv);
+	return rc;
+}
+
+static void mpc5125_wd_remove(struct device_d *dev)
+{
+	struct mpc5125_wd *priv= dev->priv;
+	watchdog_deregister(&priv->wd);
+	free(priv);
+}
+
+static struct driver_d mpc5125_wd_driver = {
+	.name   = "mpc5125wd",
+	.probe  = mpc5125_wd_probe,
+	.remove = mpc5125_wd_remove,
+};
+device_platform_driver(mpc5125_wd_driver);
-- 
2.1.0


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

  parent reply	other threads:[~2014-10-07 14:22 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-07 14:21 [RFC] Add PowerPC MPC5125 support Juergen Borleis
2014-10-07 14:22 ` [PATCH 01/19] arch/MPC5xxx: fix linker script for MPC5200 Juergen Borleis
2014-10-07 14:22 ` [PATCH 02/19] arch/MPC5xxx: use a mach specific linker script instead of a board specific one Juergen Borleis
2014-10-07 14:22 ` [PATCH 03/19] arch/MPC5xxx: replace 'depends on' by 'select' Juergen Borleis
2014-10-07 14:22 ` [PATCH 04/19] arch/MPC5xxx: Simplify the calculation Juergen Borleis
2014-10-07 14:22 ` [PATCH 05/19] arch/MPC5xxx: just a format clean up Juergen Borleis
2014-10-07 14:22 ` [PATCH 06/19] arch/MPC5xxx: move away existing files to be able to add a new SoC type Juergen Borleis
2014-10-07 14:22 ` [PATCH 07/19] arch/MPC5xxx: separate architecture's main SoC header file Juergen Borleis
2014-10-07 14:22 ` [PATCH 08/19] arch/MPC5xxx: separate clock functions Juergen Borleis
2014-10-07 14:22 ` [PATCH 09/19] arch/MPC5xxx: just use macros instead of anonymous digits Juergen Borleis
2014-10-07 14:22 ` [PATCH 10/19] MPC5xxx/serial: use dedicated I/O functions instead of memory access Juergen Borleis
2014-10-07 14:22 ` [PATCH 11/19] MPC5xxx/serial: provide an easier way to share register description Juergen Borleis
2014-10-07 14:22 ` [PATCH 12/19] MPC5xxx/serial: use new shared " Juergen Borleis
2014-10-07 14:22 ` [PATCH 13/19] MPC5xxx/serial: re-factor the code to share it between MPC5200/MPC5125 Juergen Borleis
2014-10-07 14:22 ` [PATCH 14/19] arch/MPC5xxx: add MPC5125 SoC support Juergen Borleis
2014-10-07 14:22 ` [PATCH 15/19] arch/MPC5xxx: add MPC5125 to the build-system Juergen Borleis
2014-10-07 14:22 ` [PATCH 16/19] MPC5xxx/serial: add support for the MPC5125 SoC Juergen Borleis
2014-10-07 14:22 ` [PATCH 17/19] MPC5125/FEC: add another FEC driver " Juergen Borleis
2014-10-07 14:22 ` Juergen Borleis [this message]
2014-10-07 14:22 ` [PATCH 19/19] MPC5125/GPIO: add a generic GPIO driver Juergen Borleis

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=1412691738-11145-19-git-send-email-jbe@pengutronix.de \
    --to=jbe@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox