All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Komal Shah" <komal_shah802003@yahoo.com>
To: wim@iguana.be, gdavis@mvista.com
Cc: tony@atomide.com, linux-kernel@vger.kernel.org, akpm@osdl.org,
	dbrownell@users.sourceforge.net, r-woddruff2@ti.com
Subject: [PATCH] OMAP: Add Watchdog driver support
Date: Sat, 22 Jul 2006 04:23:55 -0700	[thread overview]
Message-ID: <1153567435.16250.266622064@webmail.messagingengine.com> (raw)

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

Wim/George/David,

Attached patch addes Texas Instruments (TI) OMAP1/2 (http://www.ti.com/omap)
based processors, like OMAP1610/1710/242x.

Please give your Signed-off-by: line if driver looks ok ;)

---Komal Shah
http://komalshah.blogspot.com

-- 
http://www.fastmail.fm - Send your email first class


[-- Attachment #2: 0001-OMAP-watchdog-driver-support.patch --]
[-- Type: application/octet-stream, Size: 14616 bytes --]

From nobody Mon Sep 17 00:00:00 2001
From: Komal Shah <komal_shah802003@yahoo.com>
Date: Sat, 22 Jul 2006 22:14:46 +0530
Subject: [PATCH] OMAP: Add Watchdog driver support.

Add watchdog driver support for Texas Instruments(TI)
OMAP1/2 (http://www.ti.com/omap) based processors, like
OMAP1610/1710/242x.

Signed-off-by: Komal Shah <komal_shah802003@yahoo.com>

---

 drivers/char/watchdog/Kconfig    |    7 +
 drivers/char/watchdog/Makefile   |    1 
 drivers/char/watchdog/omap_wdt.c |  385 ++++++++++++++++++++++++++++++++++++++
 drivers/char/watchdog/omap_wdt.h |   64 ++++++
 4 files changed, 457 insertions(+), 0 deletions(-)
 create mode 100644 drivers/char/watchdog/omap_wdt.c
 create mode 100644 drivers/char/watchdog/omap_wdt.h

e912e84428e62eb15c75975066391a61447f6e53
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index d53f664..2d627cc 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -165,6 +165,13 @@ config EP93XX_WATCHDOG
 	  To compile this driver as a module, choose M here: the
 	  module will be called ep93xx_wdt.
 
+config OMAP_WATCHDOG
+	tristate "OMAP Watchdog"
+	depends on WATCHDOG && (ARCH_OMAP16XX || ARCH_OMAP24XX)
+	help
+	  Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog. Say 'Y' here to enable the
+	  OMAP1610/OMAP1710 watchdog timer.
+
 # X86 (i386 + ia64 + x86_64) Architecture
 
 config ACQUIRE_WDT
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 6ab77b6..ecfba5b 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_S3C2410_WATCHDOG) += s3c241
 obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
 obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
 obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
+obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o
 
 # X86 (i386 + ia64 + x86_64) Architecture
 obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c
new file mode 100644
index 0000000..e5e7f1f
--- /dev/null
+++ b/drivers/char/watchdog/omap_wdt.c
@@ -0,0 +1,385 @@
+/*
+ * linux/drivers/char/watchdog/omap_wdt.c
+ *
+ * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog
+ *
+ * Author: MontaVista Software, Inc.
+ *	 <gdavis@mvista.com> or <source@mvista.com>
+ *
+ * 2003 (c) MontaVista Software, Inc. This file is licensed under the
+ * terms of the GNU General Public License version 2. This program is
+ * licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ *
+ * History:
+ *
+ * 20030527: George G. Davis <gdavis@mvista.com>
+ *	Initially based on linux-2.4.19-rmk7-pxa1/drivers/char/sa1100_wdt.c
+ *	(c) Copyright 2000 Oleg Drokin <green@crimea.edu>
+ *	Based on SoftDog driver by Alan Cox <alan@redhat.com>
+ *
+ * Copyright (c) 2004 Texas Instruments.
+ *	1. Modified to support OMAP1610 32-KHz watchdog timer
+ *	2. Ported to 2.6 kernel
+ *
+ * Copyright (c) 2005 David Brownell
+ *	Use the driver model and standard identifiers; handle bigger timeouts.
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/moduleparam.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/bitops.h>
+
+#include <asm/arch/prcm.h>
+
+#include "omap_wdt.h"
+
+static unsigned timer_margin;
+module_param(timer_margin, uint, 0);
+MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
+
+static int omap_wdt_users;
+static struct clk *armwdt_ck = NULL;
+static struct clk *mpu_wdt_ick = NULL;
+static struct clk *mpu_wdt_fck = NULL;
+
+static unsigned int wdt_trgr_pattern = 0x1234;
+
+static void omap_wdt_ping(void)
+{
+	/* wait for posted write to complete */
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08);
+	wdt_trgr_pattern = ~wdt_trgr_pattern;
+	omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR));
+	/* wait for posted write to complete */
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08);	
+	/* reloaded WCRR from WLDR */
+}
+
+static void omap_wdt_enable(void)
+{
+	/* Sequence to enable the watchdog */
+	omap_writel(0xBBBB, OMAP_WATCHDOG_SPR);
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) ;
+	omap_writel(0x4444, OMAP_WATCHDOG_SPR);
+	while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) ;
+}
+
+static void omap_wdt_disable(void)
+{
+	/* sequence required to disable watchdog */
+	omap_writel(0xAAAA, OMAP_WATCHDOG_SPR);	/* TIMER_MODE */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) ;
+	omap_writel(0x5555, OMAP_WATCHDOG_SPR);	/* TIMER_MODE */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) ;
+}
+
+static void omap_wdt_adjust_timeout(unsigned new_timeout)
+{
+	if (new_timeout < TIMER_MARGIN_MIN)
+		new_timeout = TIMER_MARGIN_DEFAULT;
+	if (new_timeout > TIMER_MARGIN_MAX)
+		new_timeout = TIMER_MARGIN_MAX;
+	timer_margin = new_timeout;
+}
+
+static void omap_wdt_set_timeout(void)
+{
+	u32 pre_margin = GET_WLDR_VAL(timer_margin);
+
+	/* just count up at 32 KHz */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+		continue;
+	omap_writel(pre_margin, OMAP_WATCHDOG_LDR);
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04)
+		continue;
+}
+
+/*
+ *	Allow only one task to hold it open
+ */
+
+static int omap_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users))
+		return -EBUSY;
+
+	if (cpu_is_omap16xx())
+		clk_enable(armwdt_ck);	/* Enable the clock */
+
+	if (cpu_is_omap24xx()) {
+		clk_enable(mpu_wdt_ick);	/* Enable the interface clock */
+		clk_enable(mpu_wdt_fck);	/* Enable the functional clock */
+	}
+
+	/* initialize prescaler */
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+		continue;
+	omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL);
+	while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01)
+		continue;
+
+	omap_wdt_set_timeout();
+	omap_wdt_enable();
+	return 0;
+}
+
+static int omap_wdt_release(struct inode *inode, struct file *file)
+{
+	/*
+	 *      Shut off the timer unless NOWAYOUT is defined.
+	 */
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
+	omap_wdt_disable();
+
+	if (cpu_is_omap16xx()) {
+		clk_disable(armwdt_ck);	/* Disable the clock */
+		clk_put(armwdt_ck);
+		armwdt_ck = NULL;
+	}
+
+	if (cpu_is_omap24xx()) {
+		clk_disable(mpu_wdt_ick);	/* Disable the clock */
+		clk_disable(mpu_wdt_fck);	/* Disable the clock */
+		clk_put(mpu_wdt_ick);
+		clk_put(mpu_wdt_fck);
+		mpu_wdt_ick = NULL;
+		mpu_wdt_fck = NULL;
+	}
+#else
+	printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
+#endif
+	omap_wdt_users = 0;
+	return 0;
+}
+
+static ssize_t
+omap_wdt_write(struct file *file, const char __user * data,
+	size_t len, loff_t * ppos)
+{
+	/* Refresh LOAD_TIME. */
+	if (len)
+		omap_wdt_ping();
+	return len;
+}
+
+static int
+omap_wdt_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg)
+{
+	int new_margin;
+	static struct watchdog_info ident = {
+		.identity = "OMAP Watchdog",
+		.options = WDIOF_SETTIMEOUT,
+		.firmware_version = 0,
+	};
+
+	switch (cmd) {
+	default:
+		return -ENOIOCTLCMD;
+	case WDIOC_GETSUPPORT:
+		return copy_to_user((struct watchdog_info __user *)arg, &ident,
+				sizeof(ident));
+	case WDIOC_GETSTATUS:
+		return put_user(0, (int __user *)arg);
+	case WDIOC_GETBOOTSTATUS:
+		if (cpu_is_omap16xx())
+			return put_user(omap_readw(ARM_SYSST),
+					(int __user *)arg);
+		if (cpu_is_omap24xx())
+			return put_user(omap_prcm_get_reset_sources(),
+					(int __user *)arg);
+	case WDIOC_KEEPALIVE:
+		omap_wdt_ping();
+		return 0;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int __user *)arg))
+			return -EFAULT;
+		omap_wdt_adjust_timeout(new_margin);
+
+		omap_wdt_disable();
+		omap_wdt_set_timeout();
+		omap_wdt_enable();
+
+		omap_wdt_ping();
+		/* Fall */
+	case WDIOC_GETTIMEOUT:
+		return put_user(timer_margin, (int __user *)arg);
+	}
+}
+
+static struct file_operations omap_wdt_fops = {
+	.owner = THIS_MODULE,
+	.write = omap_wdt_write,
+	.ioctl = omap_wdt_ioctl,
+	.open = omap_wdt_open,
+	.release = omap_wdt_release,
+};
+
+static struct miscdevice omap_wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &omap_wdt_fops
+};
+
+static int __init omap_wdt_probe(struct platform_device *pdev)
+{
+	struct resource *res, *mem;
+	int ret;
+
+	/* reserve static register mappings */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOENT;
+
+	mem = request_mem_region(res->start, res->end - res->start + 1,
+				 pdev->name);
+	if (mem == NULL)
+		return -EBUSY;
+
+	platform_set_drvdata(pdev, mem);
+
+	omap_wdt_users = 0;
+
+	if (cpu_is_omap16xx()) {
+		armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
+		if (IS_ERR(armwdt_ck)) {
+			ret = PTR_ERR(armwdt_ck);
+			armwdt_ck = NULL;
+			goto fail;
+		}
+	}
+
+	if (cpu_is_omap24xx()) {
+		mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
+		if (IS_ERR(mpu_wdt_ick)) {
+			ret = PTR_ERR(mpu_wdt_ick);
+			mpu_wdt_ick = NULL;
+			goto fail;
+		}
+		mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
+		if (IS_ERR(mpu_wdt_fck)) {
+			ret = PTR_ERR(mpu_wdt_fck);
+			mpu_wdt_fck = NULL;
+			goto fail;
+		}
+	}
+
+	omap_wdt_disable();
+	omap_wdt_adjust_timeout(timer_margin);
+
+	omap_wdt_miscdev.dev = &pdev->dev;
+	ret = misc_register(&omap_wdt_miscdev);
+	if (ret)
+		goto fail;
+
+	pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);
+
+	/* autogate OCP interface clock */
+	omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
+	return 0;
+
+fail:
+	if (armwdt_ck)
+		clk_put(armwdt_ck);
+	if (mpu_wdt_ick)
+		clk_put(mpu_wdt_ick);
+	if (mpu_wdt_fck)
+		clk_put(mpu_wdt_fck);
+	release_resource(mem);
+	return ret;
+}
+
+static void omap_wdt_shutdown(struct platform_device *pdev)
+{
+	omap_wdt_disable();
+}
+
+static int omap_wdt_remove(struct platform_device *pdev)
+{
+	struct resource *mem = platform_get_drvdata(pdev);
+	misc_deregister(&omap_wdt_miscdev);
+	release_resource(mem);
+	if (armwdt_ck)
+		clk_put(armwdt_ck);
+	if (mpu_wdt_ick)
+		clk_put(mpu_wdt_ick);
+	if (mpu_wdt_fck)
+		clk_put(mpu_wdt_fck);
+	return 0;
+}
+
+#ifdef	CONFIG_PM
+
+/* REVISIT ... not clear this is the best way to handle system suspend; and
+ * it's very inappropriate for selective device suspend (e.g. suspending this
+ * through sysfs rather than by stopping the watchdog daemon).  Also, this
+ * may not play well enough with NOWAYOUT...
+ */
+
+static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	if (omap_wdt_users)
+		omap_wdt_disable();
+	return 0;
+}
+
+static int omap_wdt_resume(struct platform_device *pdev)
+{
+	if (omap_wdt_users) {
+		omap_wdt_enable();
+		omap_wdt_ping();
+	}
+	return 0;
+}
+
+#else
+#define	omap_wdt_suspend	NULL
+#define	omap_wdt_resume		NULL
+#endif
+
+static struct platform_driver omap_wdt_driver = {
+	.probe		= omap_wdt_probe,
+	.remove		= omap_wdt_remove,
+	.shutdown	= omap_wdt_shutdown,
+	.suspend	= omap_wdt_suspend,
+	.resume		= omap_wdt_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "omap_wdt",
+	},
+};
+
+static int __init omap_wdt_init(void)
+{
+	return platform_driver_register(&omap_wdt_driver);
+}
+
+static void __exit omap_wdt_exit(void)
+{
+	platform_driver_unregister(&omap_wdt_driver);
+}
+
+module_init(omap_wdt_init);
+module_exit(omap_wdt_exit);
+
+MODULE_AUTHOR("George G. Davis");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/omap_wdt.h b/drivers/char/watchdog/omap_wdt.h
new file mode 100644
index 0000000..52a532a
--- /dev/null
+++ b/drivers/char/watchdog/omap_wdt.h
@@ -0,0 +1,64 @@
+/*
+ *  linux/drivers/char/watchdog/omap_wdt.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      OMAP Watchdog timer register definitions
+ *
+ *  Copyright (C) 2004 Texas Instruments.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _OMAP_WATCHDOG_H
+#define _OMAP_WATCHDOG_H
+
+#define OMAP1610_WATCHDOG_BASE		0xfffeb000
+#define OMAP2420_WATCHDOG_BASE		0x48022000	/*WDT Timer 2 */
+
+#ifdef CONFIG_ARCH_OMAP24XX
+#define OMAP_WATCHDOG_BASE 		OMAP2420_WATCHDOG_BASE
+#else
+#define OMAP_WATCHDOG_BASE 		OMAP1610_WATCHDOG_BASE
+#define RM_RSTST_WKUP			0
+#endif
+
+#define OMAP_WATCHDOG_REV		(OMAP_WATCHDOG_BASE + 0x00)
+#define OMAP_WATCHDOG_SYS_CONFIG	(OMAP_WATCHDOG_BASE + 0x10)
+#define OMAP_WATCHDOG_STATUS		(OMAP_WATCHDOG_BASE + 0x14)
+#define OMAP_WATCHDOG_CNTRL		(OMAP_WATCHDOG_BASE + 0x24)
+#define OMAP_WATCHDOG_CRR		(OMAP_WATCHDOG_BASE + 0x28)
+#define OMAP_WATCHDOG_LDR		(OMAP_WATCHDOG_BASE + 0x2c)
+#define OMAP_WATCHDOG_TGR		(OMAP_WATCHDOG_BASE + 0x30)
+#define OMAP_WATCHDOG_WPS		(OMAP_WATCHDOG_BASE + 0x34)
+#define OMAP_WATCHDOG_SPR		(OMAP_WATCHDOG_BASE + 0x48)
+
+/* Using the prescaler, the OMAP watchdog could go for many
+ * months before firing.  These limits work without scaling,
+ * with the 60 second default assumed by most tools and docs.
+ */
+#define TIMER_MARGIN_MAX    	(24 * 60 * 60)	/* 1 day */
+#define TIMER_MARGIN_DEFAULT	60	/* 60 secs */
+#define TIMER_MARGIN_MIN	1
+
+#define PTV			0	/* prescale */
+#define GET_WLDR_VAL(secs)	(0xffffffff - ((secs) * (32768/(1<<PTV))) + 1)
+
+#endif				/* _OMAP_WATCHDOG_H */
-- 
1.3.3


             reply	other threads:[~2006-07-22 11:23 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-22 11:23 Komal Shah [this message]
2006-08-01 20:14 ` [PATCH] OMAP: Add Watchdog driver support Wim Van Sebroeck
2006-08-07 12:04   ` Tony Lindgren

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=1153567435.16250.266622064@webmail.messagingengine.com \
    --to=komal_shah802003@yahoo.com \
    --cc=akpm@osdl.org \
    --cc=dbrownell@users.sourceforge.net \
    --cc=gdavis@mvista.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=r-woddruff2@ti.com \
    --cc=tony@atomide.com \
    --cc=wim@iguana.be \
    /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.