aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch')
-rw-r--r--target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch310
1 files changed, 0 insertions, 310 deletions
diff --git a/target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch b/target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch
deleted file mode 100644
index 903f674681..0000000000
--- a/target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch
+++ /dev/null
@@ -1,310 +0,0 @@
-From 3466449c8f455da0cb646231602e6af16190f592 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 5 May 2011 23:00:23 +0200
-Subject: [PATCH 13/13] MIPS: Lantiq: Add watchdog support
-
-This patch adds the driver for the watchdog found inside the Lantiq SoC family.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
-Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
-Cc: Wim Van Sebroeck <wim@iguana.be>
-Cc: linux-mips@linux-mips.org
-Cc: linux-watchdog@vger.kernel.org
-Patchwork: https://patchwork.linux-mips.org/patch/2327/
-Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
----
- drivers/watchdog/Kconfig | 6 +
- drivers/watchdog/Makefile | 1 +
- drivers/watchdog/lantiq_wdt.c | 261 +++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 268 insertions(+), 0 deletions(-)
- create mode 100644 drivers/watchdog/lantiq_wdt.c
-
---- a/drivers/watchdog/Kconfig
-+++ b/drivers/watchdog/Kconfig
-@@ -850,6 +850,12 @@
- help
- Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
-
-+config LANTIQ_WDT
-+ tristate "Lantiq SoC watchdog"
-+ depends on LANTIQ
-+ help
-+ Hardware driver for the Lantiq SoC Watchdog Timer.
-+
- # PARISC Architecture
-
- # POWERPC Architecture
---- a/drivers/watchdog/Makefile
-+++ b/drivers/watchdog/Makefile
-@@ -113,6 +113,7 @@
- obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
- obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
- obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
-+obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
-
- # PARISC Architecture
-
---- /dev/null
-+++ b/drivers/watchdog/lantiq_wdt.c
-@@ -0,0 +1,261 @@
-+/*
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ *
-+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
-+ * Based on EP93xx wdt driver
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/platform_device.h>
-+#include <linux/uaccess.h>
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+
-+#include <lantiq.h>
-+
-+/* Section 3.4 of the datasheet
-+ * The password sequence protects the WDT control register from unintended
-+ * write actions, which might cause malfunction of the WDT.
-+ *
-+ * essentially the following two magic passwords need to be written to allow
-+ * IO access to the WDT core
-+ */
-+#define LTQ_WDT_PW1 0x00BE0000
-+#define LTQ_WDT_PW2 0x00DC0000
-+
-+#define LTQ_WDT_CR 0x0 /* watchdog control register */
-+#define LTQ_WDT_SR 0x8 /* watchdog status register */
-+
-+#define LTQ_WDT_SR_EN (0x1 << 31) /* enable bit */
-+#define LTQ_WDT_SR_PWD (0x3 << 26) /* turn on power */
-+#define LTQ_WDT_SR_CLKDIV (0x3 << 24) /* turn on clock and set */
-+ /* divider to 0x40000 */
-+#define LTQ_WDT_DIVIDER 0x40000
-+#define LTQ_MAX_TIMEOUT ((1 << 16) - 1) /* the reload field is 16 bit */
-+
-+static int nowayout = WATCHDOG_NOWAYOUT;
-+
-+static void __iomem *ltq_wdt_membase;
-+static unsigned long ltq_io_region_clk_rate;
-+
-+static unsigned long ltq_wdt_bootstatus;
-+static unsigned long ltq_wdt_in_use;
-+static int ltq_wdt_timeout = 30;
-+static int ltq_wdt_ok_to_close;
-+
-+static void
-+ltq_wdt_enable(void)
-+{
-+ ltq_wdt_timeout = ltq_wdt_timeout *
-+ (ltq_io_region_clk_rate / LTQ_WDT_DIVIDER) + 0x1000;
-+ if (ltq_wdt_timeout > LTQ_MAX_TIMEOUT)
-+ ltq_wdt_timeout = LTQ_MAX_TIMEOUT;
-+
-+ /* write the first password magic */
-+ ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
-+ /* write the second magic plus the configuration and new timeout */
-+ ltq_w32(LTQ_WDT_SR_EN | LTQ_WDT_SR_PWD | LTQ_WDT_SR_CLKDIV |
-+ LTQ_WDT_PW2 | ltq_wdt_timeout, ltq_wdt_membase + LTQ_WDT_CR);
-+}
-+
-+static void
-+ltq_wdt_disable(void)
-+{
-+ /* write the first password magic */
-+ ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
-+ /* write the second password magic with no config
-+ * this turns the watchdog off
-+ */
-+ ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR);
-+}
-+
-+static ssize_t
-+ltq_wdt_write(struct file *file, const char __user *data,
-+ size_t len, loff_t *ppos)
-+{
-+ if (len) {
-+ if (!nowayout) {
-+ size_t i;
-+
-+ ltq_wdt_ok_to_close = 0;
-+ for (i = 0; i != len; i++) {
-+ char c;
-+
-+ if (get_user(c, data + i))
-+ return -EFAULT;
-+ if (c == 'V')
-+ ltq_wdt_ok_to_close = 1;
-+ else
-+ ltq_wdt_ok_to_close = 0;
-+ }
-+ }
-+ ltq_wdt_enable();
-+ }
-+
-+ return len;
-+}
-+
-+static struct watchdog_info ident = {
-+ .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
-+ WDIOF_CARDRESET,
-+ .identity = "ltq_wdt",
-+};
-+
-+static long
-+ltq_wdt_ioctl(struct file *file,
-+ unsigned int cmd, unsigned long arg)
-+{
-+ int ret = -ENOTTY;
-+
-+ switch (cmd) {
-+ case WDIOC_GETSUPPORT:
-+ ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
-+ sizeof(ident)) ? -EFAULT : 0;
-+ break;
-+
-+ case WDIOC_GETBOOTSTATUS:
-+ ret = put_user(ltq_wdt_bootstatus, (int __user *)arg);
-+ break;
-+
-+ case WDIOC_GETSTATUS:
-+ ret = put_user(0, (int __user *)arg);
-+ break;
-+
-+ case WDIOC_SETTIMEOUT:
-+ ret = get_user(ltq_wdt_timeout, (int __user *)arg);
-+ if (!ret)
-+ ltq_wdt_enable();
-+ /* intentional drop through */
-+ case WDIOC_GETTIMEOUT:
-+ ret = put_user(ltq_wdt_timeout, (int __user *)arg);
-+ break;
-+
-+ case WDIOC_KEEPALIVE:
-+ ltq_wdt_enable();
-+ ret = 0;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static int
-+ltq_wdt_open(struct inode *inode, struct file *file)
-+{
-+ if (test_and_set_bit(0, &ltq_wdt_in_use))
-+ return -EBUSY;
-+ ltq_wdt_in_use = 1;
-+ ltq_wdt_enable();
-+
-+ return nonseekable_open(inode, file);
-+}
-+
-+static int
-+ltq_wdt_release(struct inode *inode, struct file *file)
-+{
-+ if (ltq_wdt_ok_to_close)
-+ ltq_wdt_disable();
-+ else
-+ pr_err("ltq_wdt: watchdog closed without warning\n");
-+ ltq_wdt_ok_to_close = 0;
-+ clear_bit(0, &ltq_wdt_in_use);
-+
-+ return 0;
-+}
-+
-+static const struct file_operations ltq_wdt_fops = {
-+ .owner = THIS_MODULE,
-+ .write = ltq_wdt_write,
-+ .unlocked_ioctl = ltq_wdt_ioctl,
-+ .open = ltq_wdt_open,
-+ .release = ltq_wdt_release,
-+ .llseek = no_llseek,
-+};
-+
-+static struct miscdevice ltq_wdt_miscdev = {
-+ .minor = WATCHDOG_MINOR,
-+ .name = "watchdog",
-+ .fops = &ltq_wdt_fops,
-+};
-+
-+static int __init
-+ltq_wdt_probe(struct platform_device *pdev)
-+{
-+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ struct clk *clk;
-+
-+ if (!res) {
-+ dev_err(&pdev->dev, "cannot obtain I/O memory region");
-+ return -ENOENT;
-+ }
-+ res = devm_request_mem_region(&pdev->dev, res->start,
-+ resource_size(res), dev_name(&pdev->dev));
-+ if (!res) {
-+ dev_err(&pdev->dev, "cannot request I/O memory region");
-+ return -EBUSY;
-+ }
-+ ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start,
-+ resource_size(res));
-+ if (!ltq_wdt_membase) {
-+ dev_err(&pdev->dev, "cannot remap I/O memory region\n");
-+ return -ENOMEM;
-+ }
-+
-+ /* we do not need to enable the clock as it is always running */
-+ clk = clk_get(&pdev->dev, "io");
-+ WARN_ON(!clk);
-+ ltq_io_region_clk_rate = clk_get_rate(clk);
-+ clk_put(clk);
-+
-+ if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST)
-+ ltq_wdt_bootstatus = WDIOF_CARDRESET;
-+
-+ return misc_register(&ltq_wdt_miscdev);
-+}
-+
-+static int __devexit
-+ltq_wdt_remove(struct platform_device *pdev)
-+{
-+ misc_deregister(&ltq_wdt_miscdev);
-+
-+ if (ltq_wdt_membase)
-+ iounmap(ltq_wdt_membase);
-+
-+ return 0;
-+}
-+
-+
-+static struct platform_driver ltq_wdt_driver = {
-+ .remove = __devexit_p(ltq_wdt_remove),
-+ .driver = {
-+ .name = "ltq_wdt",
-+ .owner = THIS_MODULE,
-+ },
-+};
-+
-+static int __init
-+init_ltq_wdt(void)
-+{
-+ return platform_driver_probe(&ltq_wdt_driver, ltq_wdt_probe);
-+}
-+
-+static void __exit
-+exit_ltq_wdt(void)
-+{
-+ return platform_driver_unregister(&ltq_wdt_driver);
-+}
-+
-+module_init(init_ltq_wdt);
-+module_exit(exit_ltq_wdt);
-+
-+module_param(nowayout, int, 0);
-+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
-+
-+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
-+MODULE_DESCRIPTION("Lantiq SoC Watchdog");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);