brcm2708: drop support for 3.3 kernel
[openwrt.git] / target / linux / brcm2708 / patches-3.3 / 0003-bcm2708-watchdog-driver.patch
diff --git a/target/linux/brcm2708/patches-3.3/0003-bcm2708-watchdog-driver.patch b/target/linux/brcm2708/patches-3.3/0003-bcm2708-watchdog-driver.patch
deleted file mode 100644 (file)
index cde3eef..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-From ed8c2d720954efc5a440912292ed11da2f50aaea Mon Sep 17 00:00:00 2001
-From: popcornmix <popcornmix@gmail.com>
-Date: Tue, 17 Jan 2012 19:20:57 +0000
-Subject: [PATCH 3/7] bcm2708 watchdog driver
-
-Signed-off-by: popcornmix <popcornmix@gmail.com>
----
- drivers/watchdog/Kconfig        |    6 +
- drivers/watchdog/Makefile       |    1 +
- drivers/watchdog/bcm2708_wdog.c |  385 +++++++++++++++++++++++++++++++++++++++
- 3 files changed, 392 insertions(+), 0 deletions(-)
- create mode 100644 drivers/watchdog/bcm2708_wdog.c
-
-diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
-index 86b0735..7675ebc 100644
---- a/drivers/watchdog/Kconfig
-+++ b/drivers/watchdog/Kconfig
-@@ -348,6 +348,12 @@ config IMX2_WDT
-         To compile this driver as a module, choose M here: the
-         module will be called imx2_wdt.
-+config BCM2708_WDT
-+      tristate "BCM2708 Watchdog"
-+      depends on ARCH_BCM2708
-+      help
-+        Enables BCM2708 watchdog support.
-+
- # AVR32 Architecture
- config AT32AP700X_WDT
-diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
-index 55bd574..803f0bc 100644
---- a/drivers/watchdog/Makefile
-+++ b/drivers/watchdog/Makefile
-@@ -54,6 +54,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
- obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
- obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
- obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
-+obj-$(CONFIG_BCM2708_WDT) += bcm2708_wdog.o
- # AVR32 Architecture
- obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
-diff --git a/drivers/watchdog/bcm2708_wdog.c b/drivers/watchdog/bcm2708_wdog.c
-new file mode 100644
-index 0000000..dd33c35
---- /dev/null
-+++ b/drivers/watchdog/bcm2708_wdog.c
-@@ -0,0 +1,385 @@
-+/*
-+ *    Broadcom BCM2708 watchdog driver.
-+ *
-+ *    (c) Copyright 2010 Broadcom Europe Ltd
-+ *
-+ *    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.
-+ *
-+ *      BCM2708 watchdog driver. Loosely based on wdt driver.
-+ */
-+
-+#include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/types.h>
-+#include <linux/miscdevice.h>
-+#include <linux/watchdog.h>
-+#include <linux/fs.h>
-+#include <linux/ioport.h>
-+#include <linux/notifier.h>
-+#include <linux/reboot.h>
-+#include <linux/init.h>
-+#include <linux/io.h>
-+#include <linux/uaccess.h>
-+#include <mach/platform.h>
-+
-+#include <asm/system.h>
-+
-+#define SECS_TO_WDOG_TICKS(x) ((x) << 16)
-+#define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
-+
-+static unsigned long wdog_is_open;
-+static uint32_t wdog_ticks;          /* Ticks to load into wdog timer */
-+static char expect_close;
-+
-+/*
-+ *    Module parameters
-+ */
-+
-+#define WD_TIMO 10                   /* Default heartbeat = 60 seconds */
-+static int heartbeat = WD_TIMO;              /* Heartbeat in seconds */
-+
-+module_param(heartbeat, int, 0);
-+MODULE_PARM_DESC(heartbeat,
-+      "Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default="
-+                              __MODULE_STRING(WD_TIMO) ")");
-+
-+static int nowayout = WATCHDOG_NOWAYOUT;
-+module_param(nowayout, int, 0);
-+MODULE_PARM_DESC(nowayout,
-+      "Watchdog cannot be stopped once started (default="
-+                              __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-+
-+static DEFINE_SPINLOCK(wdog_lock);
-+
-+/**
-+ *    Start the watchdog driver.
-+ */
-+
-+static int wdog_start(unsigned long timeout)
-+{
-+      uint32_t cur;
-+      unsigned long flags;
-+      spin_lock_irqsave(&wdog_lock, flags);
-+
-+      /* enable the watchdog */
-+      iowrite32(PM_PASSWORD | (timeout & PM_WDOG_TIME_SET), 
-+                __io_address(PM_WDOG));
-+      cur = ioread32(__io_address(PM_RSTC));
-+      iowrite32(PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) |
-+                PM_RSTC_WRCFG_FULL_RESET, __io_address(PM_RSTC));
-+
-+      spin_unlock_irqrestore(&wdog_lock, flags);
-+      return 0;
-+}
-+
-+/**
-+ *    Stop the watchdog driver.
-+ */
-+
-+static int wdog_stop(void)
-+{
-+      iowrite32(PM_PASSWORD | PM_RSTC_RESET, __io_address(PM_RSTC));
-+      printk(KERN_INFO "watchdog stopped\n");
-+      return 0;
-+}
-+
-+/**
-+ *    Reload counter one with the watchdog heartbeat. We don't bother
-+ *    reloading the cascade counter.
-+ */
-+
-+static void wdog_ping(void)
-+{
-+      wdog_start(wdog_ticks);
-+}
-+
-+/**
-+ *    @t:             the new heartbeat value that needs to be set.
-+ *
-+ *    Set a new heartbeat value for the watchdog device. If the heartbeat
-+ *    value is incorrect we keep the old value and return -EINVAL. If
-+ *    successful we return 0.
-+ */
-+
-+static int wdog_set_heartbeat(int t)
-+{
-+      if (t < 1 || t > WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET))
-+              return -EINVAL;
-+
-+      heartbeat = t;
-+      wdog_ticks = SECS_TO_WDOG_TICKS(t);
-+      return 0;
-+}
-+
-+/**
-+ *    @file: file handle to the watchdog
-+ *    @buf: buffer to write (unused as data does not matter here
-+ *    @count: count of bytes
-+ *    @ppos: pointer to the position to write. No seeks allowed
-+ *
-+ *    A write to a watchdog device is defined as a keepalive signal.
-+ *    
-+ *      if 'nowayout' is set then normally a close() is ignored. But
-+ *      if you write 'V' first then the close() will stop the timer.
-+ */
-+
-+static ssize_t wdog_write(struct file *file, const char __user *buf,
-+                                              size_t count, loff_t *ppos)
-+{
-+      if (count) {
-+              if (!nowayout) {
-+                      size_t i;
-+
-+                      /* In case it was set long ago */
-+                      expect_close = 0;
-+
-+                      for (i = 0; i != count; i++) {
-+                              char c;
-+                              if (get_user(c, buf + i))
-+                                      return -EFAULT;
-+                              if (c == 'V')
-+                                      expect_close = 42;
-+                      }
-+              }
-+              wdog_ping();
-+      }
-+      return count;
-+}
-+
-+static int wdog_get_status(void)
-+{
-+      unsigned long flags;
-+      int status = 0;
-+      spin_lock_irqsave(&wdog_lock, flags);
-+      /* FIXME: readback reset reason */
-+      spin_unlock_irqrestore(&wdog_lock, flags);
-+      return status;
-+}
-+
-+static uint32_t wdog_get_remaining(void)
-+{
-+      uint32_t ret = ioread32(__io_address(PM_WDOG));
-+      return ret & PM_WDOG_TIME_SET;
-+}
-+
-+/**
-+ *    @file: file handle to the device
-+ *    @cmd: watchdog command
-+ *    @arg: argument pointer
-+ *
-+ *    The watchdog API defines a common set of functions for all watchdogs
-+ *    according to their available features. We only actually usefully support
-+ *    querying capabilities and current status.
-+ */
-+
-+static long wdog_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-+{
-+      void __user *argp = (void __user *)arg;
-+      int __user *p = argp;
-+      int new_heartbeat;
-+      int status;
-+      int options;
-+      uint32_t remaining;
-+
-+      struct watchdog_info ident = {
-+              .options =              WDIOF_SETTIMEOUT|
-+                                      WDIOF_MAGICCLOSE|
-+                                      WDIOF_KEEPALIVEPING,
-+              .firmware_version =     1,
-+              .identity =             "BCM2708",
-+      };
-+
-+      switch (cmd) {
-+      case WDIOC_GETSUPPORT:
-+              return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
-+      case WDIOC_GETSTATUS:
-+              status = wdog_get_status();
-+              return put_user(status, p);
-+      case WDIOC_GETBOOTSTATUS:
-+              return put_user(0, p);
-+      case WDIOC_KEEPALIVE:
-+              wdog_ping();
-+              return 0;
-+      case WDIOC_SETTIMEOUT:
-+              if (get_user(new_heartbeat, p))
-+                      return -EFAULT;
-+              if (wdog_set_heartbeat(new_heartbeat))
-+                      return -EINVAL;
-+              wdog_ping();
-+              /* Fall */
-+      case WDIOC_GETTIMEOUT:
-+              return put_user(heartbeat, p);
-+      case WDIOC_GETTIMELEFT:
-+              remaining = WDOG_TICKS_TO_SECS(wdog_get_remaining());
-+              return put_user(remaining, p);
-+      case WDIOC_SETOPTIONS:
-+              if (get_user(options, p))
-+                      return -EFAULT;
-+              if (options & WDIOS_DISABLECARD)
-+                      wdog_stop();
-+              if (options & WDIOS_ENABLECARD)
-+                      wdog_start(wdog_ticks);
-+              return 0;
-+      default:
-+              return -ENOTTY;
-+      }
-+}
-+
-+/**
-+ *    @inode: inode of device
-+ *    @file: file handle to device
-+ *
-+ *    The watchdog device has been opened. The watchdog device is single
-+ *    open and on opening we load the counters.
-+ */
-+
-+static int wdog_open(struct inode *inode, struct file *file)
-+{
-+      if (test_and_set_bit(0, &wdog_is_open))
-+              return -EBUSY;
-+      /*
-+       *      Activate
-+       */
-+      wdog_start(wdog_ticks);
-+      return nonseekable_open(inode, file);
-+}
-+
-+/**
-+ *    @inode: inode to board
-+ *    @file: file handle to board
-+ *
-+ *    The watchdog has a configurable API. There is a religious dispute
-+ *    between people who want their watchdog to be able to shut down and
-+ *    those who want to be sure if the watchdog manager dies the machine
-+ *    reboots. In the former case we disable the counters, in the latter
-+ *    case you have to open it again very soon.
-+ */
-+
-+static int wdog_release(struct inode *inode, struct file *file)
-+{
-+      if (expect_close == 42) {
-+              wdog_stop();
-+      } else {
-+              printk(KERN_CRIT
-+               "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
-+              wdog_ping();
-+      }
-+      clear_bit(0, &wdog_is_open);
-+      expect_close = 0;
-+      return 0;
-+}
-+
-+/**
-+ *    @this: our notifier block
-+ *    @code: the event being reported
-+ *    @unused: unused
-+ *
-+ *    Our notifier is called on system shutdowns. Turn the watchdog
-+ *    off so that it does not fire during the next reboot.
-+ */
-+
-+static int wdog_notify_sys(struct notifier_block *this, unsigned long code,
-+      void *unused)
-+{
-+      if (code == SYS_DOWN || code == SYS_HALT)
-+              wdog_stop();
-+      return NOTIFY_DONE;
-+}
-+
-+/*
-+ *    Kernel Interfaces
-+ */
-+
-+
-+static const struct file_operations wdog_fops = {
-+      .owner          = THIS_MODULE,
-+      .llseek         = no_llseek,
-+      .write          = wdog_write,
-+      .unlocked_ioctl = wdog_ioctl,
-+      .open           = wdog_open,
-+      .release        = wdog_release,
-+};
-+
-+static struct miscdevice wdog_miscdev = {
-+      .minor  = WATCHDOG_MINOR,
-+      .name   = "watchdog",
-+      .fops   = &wdog_fops,
-+};
-+
-+/*
-+ *    The WDT card needs to learn about soft shutdowns in order to
-+ *    turn the timebomb registers off.
-+ */
-+
-+static struct notifier_block wdog_notifier = {
-+      .notifier_call = wdog_notify_sys,
-+};
-+
-+/**
-+ *    cleanup_module:
-+ *
-+ *    Unload the watchdog. You cannot do this with any file handles open.
-+ *    If your watchdog is set to continue ticking on close and you unload
-+ *    it, well it keeps ticking. We won't get the interrupt but the board
-+ *    will not touch PC memory so all is fine. You just have to load a new
-+ *    module in 60 seconds or reboot.
-+ */
-+
-+static void __exit wdog_exit(void)
-+{
-+      misc_deregister(&wdog_miscdev);
-+      unregister_reboot_notifier(&wdog_notifier);
-+}
-+
-+static int __init wdog_init(void)
-+{
-+      int ret;
-+
-+      /* Check that the heartbeat value is within it's range;
-+         if not reset to the default */
-+      if (wdog_set_heartbeat(heartbeat)) {
-+              wdog_set_heartbeat(WD_TIMO);
-+              printk(KERN_INFO "bcm2708_wdog: heartbeat value must be "
-+                      "0 < heartbeat < %d, using %d\n", 
-+                              WDOG_TICKS_TO_SECS(PM_WDOG_TIME_SET),
-+                              WD_TIMO);
-+      }
-+
-+      ret = register_reboot_notifier(&wdog_notifier);
-+      if (ret) {
-+              printk(KERN_ERR
-+                    "wdt: cannot register reboot notifier (err=%d)\n", ret);
-+              goto out_reboot;
-+      }
-+
-+      ret = misc_register(&wdog_miscdev);
-+      if (ret) {
-+              printk(KERN_ERR
-+                      "wdt: cannot register miscdev on minor=%d (err=%d)\n",
-+                                                      WATCHDOG_MINOR, ret);
-+              goto out_misc;
-+      }
-+
-+      printk(KERN_INFO "bcm2708 watchdog, heartbeat=%d sec (nowayout=%d)\n",
-+              heartbeat, nowayout);
-+      return 0;
-+
-+out_misc:
-+      unregister_reboot_notifier(&wdog_notifier);
-+out_reboot:
-+      return ret;
-+}
-+
-+module_init(wdog_init);
-+module_exit(wdog_exit);
-+
-+MODULE_AUTHOR("Luke Diamand");
-+MODULE_DESCRIPTION("Driver for BCM2708 watchdog");
-+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
-+MODULE_LICENSE("GPL");
-+
--- 
-1.7.5.4
-