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