Atheros AR531X (Generic) watchdog support code (based on ar7_wdt.c). This
watchdog should work on most AR5315 / AR5312 devices. I've personally tested it
on La Fonera and D-Link DWL-2100AP. Please note that the DWL-2100AP uses a
slightly faster clock for its watchdog, see the source files.

Signed-off-by: Axel Gembe <[EMAIL PROTECTED]>
---
 target/linux/atheros/config-2.6.23                 |    1 +
 target/linux/atheros/config-2.6.24                 |    1 +
 target/linux/atheros/config-2.6.25                 |    1 +
 .../files/drivers/char/watchdog/ar531x_wdt.c       |  326 ++++++++++++++++++++
 .../atheros/files/drivers/watchdog/ar531x_wdt.c    |  326 ++++++++++++++++++++
 .../include/asm-mips/mach-atheros/ar5315/ar5315.h  |    1 +
 .../atheros/patches-2.6.23/160-watchdog.patch      |   35 ++
 .../atheros/patches-2.6.24/160-watchdog.patch      |   35 ++
 .../atheros/patches-2.6.25/160-watchdog.patch      |   35 ++
 9 files changed, 761 insertions(+), 0 deletions(-)
 create mode 100644 
target/linux/atheros/files/drivers/char/watchdog/ar531x_wdt.c
 create mode 100644 target/linux/atheros/files/drivers/watchdog/ar531x_wdt.c
 create mode 100644 target/linux/atheros/patches-2.6.23/160-watchdog.patch
 create mode 100644 target/linux/atheros/patches-2.6.24/160-watchdog.patch
 create mode 100644 target/linux/atheros/patches-2.6.25/160-watchdog.patch

diff --git a/target/linux/atheros/config-2.6.23 
b/target/linux/atheros/config-2.6.23
index e1694ba..4876047 100644
--- a/target/linux/atheros/config-2.6.23
+++ b/target/linux/atheros/config-2.6.23
@@ -8,6 +8,7 @@ CONFIG_AR2313=y
 CONFIG_ATHEROS=y
 CONFIG_ATHEROS_AR5312=y
 CONFIG_ATHEROS_AR5315=y
+CONFIG_ATHEROS_WDT=y
 # CONFIG_ATM is not set
 CONFIG_BASE_SMALL=0
 CONFIG_BITREVERSE=y
diff --git a/target/linux/atheros/config-2.6.24 
b/target/linux/atheros/config-2.6.24
index 848f459..ef34de9 100644
--- a/target/linux/atheros/config-2.6.24
+++ b/target/linux/atheros/config-2.6.24
@@ -9,6 +9,7 @@ CONFIG_ARCH_SUPPORTS_OPROFILE=y
 CONFIG_ATHEROS=y
 CONFIG_ATHEROS_AR5312=y
 CONFIG_ATHEROS_AR5315=y
+CONFIG_ATHEROS_WDT=y
 # CONFIG_ATM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_BCM47XX is not set
diff --git a/target/linux/atheros/config-2.6.25 
b/target/linux/atheros/config-2.6.25
index fc1cda4..39e31b2 100644
--- a/target/linux/atheros/config-2.6.25
+++ b/target/linux/atheros/config-2.6.25
@@ -10,6 +10,7 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_ATHEROS=y
 CONFIG_ATHEROS_AR5312=y
 CONFIG_ATHEROS_AR5315=y
+CONFIG_ATHEROS_WDT=y
 # CONFIG_ATM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_BCM47XX is not set
diff --git a/target/linux/atheros/files/drivers/char/watchdog/ar531x_wdt.c 
b/target/linux/atheros/files/drivers/char/watchdog/ar531x_wdt.c
new file mode 100644
index 0000000..16c0eea
--- /dev/null
+++ b/target/linux/atheros/files/drivers/char/watchdog/ar531x_wdt.c
@@ -0,0 +1,326 @@
+/*
+ * drivers/watchdog/ar531x_wdt.c
+ *
+ * Atheros 531x Watchdog Timer support
+ *
+ * Copyright (C) 2008 Axel Gembe <[EMAIL PROTECTED]>
+ *
+ * Some base code taken from:
+ * OpenWRT AR7 watchdog driver
+ * Copyright (C) 2007 Nicolas Thill <[EMAIL PROTECTED]>
+ * Copyright (C) 2005 Enrik Berkhan <[EMAIL PROTECTED]>
+ * Copyright (C) 2001, 2002 Christer Weinigel <[EMAIL PROTECTED]>
+ *
+ * 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-atheros/ar531x.h>
+
+#define DRVNAME "ar531x_wdt"
+#define LONGNAME "Atheros 531x Watchdog Timer"
+
+MODULE_AUTHOR("Axel Gembe <[EMAIL PROTECTED]>");
+MODULE_DESCRIPTION(LONGNAME);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+static int margin = 60;
+module_param(margin, int, 0);
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
+
+/*
+       I found these clock rates so far:
+       48MHz   -       DLink DWL-2100AP
+       40MHz   -       Meraki
+*/
+
+static int wdtclock = 40000000; /* 40MHz */
+module_param(wdtclock, int, 0);
+MODULE_PARM_DESC(wdtclock, "Watchdog clock in hertz");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+/*
+       WDC_IGNORE_EXPIRATION   0 Just interrupt gets triggered
+       WDC_NMI                 1 Make the interrupt a NMI
+       WDC_RESET               2 Board gets reset
+       WDC_AHB                 4 AHB interrupt gets triggered
+*/
+static int wdflags = WDC_IGNORE_EXPIRATION;
+module_param(wdflags, int, 0);
+MODULE_PARM_DESC(wdflags, "Watchdog flags (0-Int., 1-NMI, 2-Reset, 4-AHB)");
+
+#define WDT_FLAGS_MASK 0x7     /* Mask out all flags except the lowest 3 */
+
+static u32 ar531x_wd;
+static u32 ar531x_wdc;
+static u32 ar531x_isr;
+static u32 ar531x_isr_wd;
+
+static struct semaphore open_semaphore;
+static int expect_close = -1;
+
+static void ar531x_wdt_get_regs(void)
+{
+       DO_AR5312(
+               ar531x_wd       = AR531X_WD_TIMER;
+               ar531x_wdc      = AR531X_WD_CTRL;
+               ar531x_isr      = AR531X_ISR;
+               ar531x_isr_wd   = AR531X_ISR_WD;
+       )
+
+       DO_AR5315(
+               ar531x_wd       = AR5315_WD;
+               ar531x_wdc      = AR5315_WDC;
+               ar531x_isr      = AR5315_ISR;
+               ar531x_isr_wd   = AR5315_ISR_WD;
+       )
+}
+
+static void ar531x_wdt_kick(void)
+{
+       sysRegWrite(ar531x_wd, margin * wdtclock);
+       sysRegWrite(ar531x_isr, sysRegRead(ar531x_isr) | ar531x_isr_wd);
+}
+
+static void ar531x_wdt_enable_wdt(void)
+{
+       printk(KERN_DEBUG DRVNAME ": enabling watchdog timer\n");
+
+       ar531x_wdt_kick();
+       sysRegWrite(ar531x_wdc, wdflags & WDT_FLAGS_MASK);
+}
+
+static void ar531x_wdt_disable_wdt(void)
+{
+       printk(KERN_DEBUG DRVNAME ": disabling watchdog timer\n");
+
+       expect_close = -1;
+       sysRegWrite(ar531x_wdc, 0);
+       sysRegWrite(ar531x_wd, 0);
+}
+
+static int ar531x_wdt_open(struct inode *inode, struct file *file)
+{
+       /* only allow one at a time */
+       if (down_trylock(&open_semaphore))
+               return -EBUSY;
+
+       ar531x_wdt_enable_wdt();
+       expect_close = 0;
+
+       return nonseekable_open(inode, file);
+}
+
+static int ar531x_wdt_release(struct inode *inode, struct file *file)
+{
+       if (!expect_close)
+               printk(KERN_WARNING DRVNAME
+               ": watchdog device closed unexpectedly, "
+               "will not disable the watchdog timer\n");
+       else if (!nowayout)
+               ar531x_wdt_disable_wdt();
+
+       up(&open_semaphore);
+
+       return 0;
+}
+
+static int ar531x_wdt_notify_sys(struct notifier_block *this,
+                               unsigned long code, void *unused)
+{
+       if (code == SYS_HALT || code == SYS_POWER_OFF)
+               if (!nowayout)
+                       ar531x_wdt_disable_wdt();
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block ar531x_wdt_notifier = {
+       .notifier_call = ar531x_wdt_notify_sys
+};
+
+static ssize_t ar531x_wdt_write(struct file *file, const char *data,
+                               size_t len, loff_t *ppos)
+{
+       /* check for a magic close character */
+       if (len) {
+               size_t i;
+
+               ar531x_wdt_kick();
+
+               expect_close = 0;
+               for (i = 0; i < len; ++i) {
+                       char c;
+                       if (get_user(c, data + i))
+                               return -EFAULT;
+                       if (c == 'V')
+                               expect_close = 1;
+               }
+
+       }
+       return len;
+}
+
+static int ar531x_wdt_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               .identity               =       LONGNAME,
+               .firmware_version       =       1,
+               .options                =       WDIOF_SETTIMEOUT |
+                                               WDIOF_MAGICCLOSE |
+                                               WDIOF_KEEPALIVEPING
+       };
+       int new_margin;
+
+       switch (cmd) {
+       default:
+               return -ENOTTY;
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user((struct watchdog_info *)arg, &ident,
+                       sizeof(ident)))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(0, (int *)arg))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_KEEPALIVE:
+               ar531x_wdt_kick();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_margin, (int *)arg))
+                       return -EFAULT;
+               if (new_margin < 1 || new_margin > 90)
+                       return -EINVAL;
+               margin = new_margin;
+               /* omit break */
+       case WDIOC_GETTIMEOUT:
+               if (put_user(margin, (int *)arg))
+                       return -EFAULT;
+               return 0;
+       }
+}
+
+static irqreturn_t ar531x_wdt_interrupt(int irq, void *devid)
+{
+       if (expect_close == 0) {
+               printk(KERN_CRIT DRVNAME ": expired, restarting system\n");
+               machine_restart("Watchdog expired!");
+       }
+
+       sysRegWrite(ar531x_wd, 0);
+       sysRegWrite(ar531x_wdc, 0);
+       sysRegWrite(ar531x_isr, sysRegRead(ar531x_isr) | ar531x_isr_wd);
+
+       return IRQ_HANDLED;
+}
+
+static struct file_operations ar531x_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .write          = ar531x_wdt_write,
+       .ioctl          = ar531x_wdt_ioctl,
+       .open           = ar531x_wdt_open,
+       .release        = ar531x_wdt_release,
+};
+
+static struct miscdevice ar531x_wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &ar531x_wdt_fops,
+};
+
+static int __init ar531x_wdt_init(void)
+{
+       int rc;
+
+       sema_init(&open_semaphore, 1);
+
+       ar531x_wdt_get_regs();
+
+       if (!request_mem_region(ar531x_wd, sizeof(u32), LONGNAME)) {
+               printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+               return -EBUSY;
+       }
+
+       if (!request_mem_region(ar531x_wdc, sizeof(u32), LONGNAME)) {
+               printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+               rc = -EBUSY;
+               goto out_alloc;
+       }
+
+       rc = register_reboot_notifier(&ar531x_wdt_notifier);
+       if (rc) {
+               printk(KERN_ERR DRVNAME
+                       ": unable to register reboot notifier\n");
+               goto out_alloc_wdc;
+       }
+
+       rc = request_irq(AR531X_MISC_IRQ_WATCHDOG, ar531x_wdt_interrupt,
+                       IRQF_DISABLED, "ar531x_wdt", NULL);
+       if (rc) {
+               printk(KERN_ERR DRVNAME ": IRQ is already in use\n");
+               goto out_register;
+       }
+
+       rc = misc_register(&ar531x_wdt_miscdev);
+       if (rc) {
+               printk(KERN_ERR DRVNAME ": unable to register misc device\n");
+               goto out_reqirq;
+       }
+       goto out;
+
+out_reqirq:
+       free_irq(AR531X_MISC_IRQ_WATCHDOG, NULL);
+out_register:
+       unregister_reboot_notifier(&ar531x_wdt_notifier);
+out_alloc_wdc:
+       release_mem_region(ar531x_wdc, sizeof(u32));
+out_alloc:
+       release_mem_region(ar531x_wd, sizeof(u32));
+out:
+       return rc;
+}
+
+static void __exit ar531x_wdt_cleanup(void)
+{
+       misc_deregister(&ar531x_wdt_miscdev);
+       free_irq(AR531X_MISC_IRQ_WATCHDOG, NULL);
+       unregister_reboot_notifier(&ar531x_wdt_notifier);
+       release_mem_region(ar531x_wdc, sizeof(u32));
+       release_mem_region(ar531x_wd, sizeof(u32));
+}
+
+module_init(ar531x_wdt_init);
+module_exit(ar531x_wdt_cleanup);
diff --git a/target/linux/atheros/files/drivers/watchdog/ar531x_wdt.c 
b/target/linux/atheros/files/drivers/watchdog/ar531x_wdt.c
new file mode 100644
index 0000000..16c0eea
--- /dev/null
+++ b/target/linux/atheros/files/drivers/watchdog/ar531x_wdt.c
@@ -0,0 +1,326 @@
+/*
+ * drivers/watchdog/ar531x_wdt.c
+ *
+ * Atheros 531x Watchdog Timer support
+ *
+ * Copyright (C) 2008 Axel Gembe <[EMAIL PROTECTED]>
+ *
+ * Some base code taken from:
+ * OpenWRT AR7 watchdog driver
+ * Copyright (C) 2007 Nicolas Thill <[EMAIL PROTECTED]>
+ * Copyright (C) 2005 Enrik Berkhan <[EMAIL PROTECTED]>
+ * Copyright (C) 2001, 2002 Christer Weinigel <[EMAIL PROTECTED]>
+ *
+ * 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/interrupt.h>
+
+#include <asm/addrspace.h>
+#include <asm/mach-atheros/ar531x.h>
+
+#define DRVNAME "ar531x_wdt"
+#define LONGNAME "Atheros 531x Watchdog Timer"
+
+MODULE_AUTHOR("Axel Gembe <[EMAIL PROTECTED]>");
+MODULE_DESCRIPTION(LONGNAME);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+static int margin = 60;
+module_param(margin, int, 0);
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
+
+/*
+       I found these clock rates so far:
+       48MHz   -       DLink DWL-2100AP
+       40MHz   -       Meraki
+*/
+
+static int wdtclock = 40000000; /* 40MHz */
+module_param(wdtclock, int, 0);
+MODULE_PARM_DESC(wdtclock, "Watchdog clock in hertz");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+/*
+       WDC_IGNORE_EXPIRATION   0 Just interrupt gets triggered
+       WDC_NMI                 1 Make the interrupt a NMI
+       WDC_RESET               2 Board gets reset
+       WDC_AHB                 4 AHB interrupt gets triggered
+*/
+static int wdflags = WDC_IGNORE_EXPIRATION;
+module_param(wdflags, int, 0);
+MODULE_PARM_DESC(wdflags, "Watchdog flags (0-Int., 1-NMI, 2-Reset, 4-AHB)");
+
+#define WDT_FLAGS_MASK 0x7     /* Mask out all flags except the lowest 3 */
+
+static u32 ar531x_wd;
+static u32 ar531x_wdc;
+static u32 ar531x_isr;
+static u32 ar531x_isr_wd;
+
+static struct semaphore open_semaphore;
+static int expect_close = -1;
+
+static void ar531x_wdt_get_regs(void)
+{
+       DO_AR5312(
+               ar531x_wd       = AR531X_WD_TIMER;
+               ar531x_wdc      = AR531X_WD_CTRL;
+               ar531x_isr      = AR531X_ISR;
+               ar531x_isr_wd   = AR531X_ISR_WD;
+       )
+
+       DO_AR5315(
+               ar531x_wd       = AR5315_WD;
+               ar531x_wdc      = AR5315_WDC;
+               ar531x_isr      = AR5315_ISR;
+               ar531x_isr_wd   = AR5315_ISR_WD;
+       )
+}
+
+static void ar531x_wdt_kick(void)
+{
+       sysRegWrite(ar531x_wd, margin * wdtclock);
+       sysRegWrite(ar531x_isr, sysRegRead(ar531x_isr) | ar531x_isr_wd);
+}
+
+static void ar531x_wdt_enable_wdt(void)
+{
+       printk(KERN_DEBUG DRVNAME ": enabling watchdog timer\n");
+
+       ar531x_wdt_kick();
+       sysRegWrite(ar531x_wdc, wdflags & WDT_FLAGS_MASK);
+}
+
+static void ar531x_wdt_disable_wdt(void)
+{
+       printk(KERN_DEBUG DRVNAME ": disabling watchdog timer\n");
+
+       expect_close = -1;
+       sysRegWrite(ar531x_wdc, 0);
+       sysRegWrite(ar531x_wd, 0);
+}
+
+static int ar531x_wdt_open(struct inode *inode, struct file *file)
+{
+       /* only allow one at a time */
+       if (down_trylock(&open_semaphore))
+               return -EBUSY;
+
+       ar531x_wdt_enable_wdt();
+       expect_close = 0;
+
+       return nonseekable_open(inode, file);
+}
+
+static int ar531x_wdt_release(struct inode *inode, struct file *file)
+{
+       if (!expect_close)
+               printk(KERN_WARNING DRVNAME
+               ": watchdog device closed unexpectedly, "
+               "will not disable the watchdog timer\n");
+       else if (!nowayout)
+               ar531x_wdt_disable_wdt();
+
+       up(&open_semaphore);
+
+       return 0;
+}
+
+static int ar531x_wdt_notify_sys(struct notifier_block *this,
+                               unsigned long code, void *unused)
+{
+       if (code == SYS_HALT || code == SYS_POWER_OFF)
+               if (!nowayout)
+                       ar531x_wdt_disable_wdt();
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block ar531x_wdt_notifier = {
+       .notifier_call = ar531x_wdt_notify_sys
+};
+
+static ssize_t ar531x_wdt_write(struct file *file, const char *data,
+                               size_t len, loff_t *ppos)
+{
+       /* check for a magic close character */
+       if (len) {
+               size_t i;
+
+               ar531x_wdt_kick();
+
+               expect_close = 0;
+               for (i = 0; i < len; ++i) {
+                       char c;
+                       if (get_user(c, data + i))
+                               return -EFAULT;
+                       if (c == 'V')
+                               expect_close = 1;
+               }
+
+       }
+       return len;
+}
+
+static int ar531x_wdt_ioctl(struct inode *inode, struct file *file,
+                               unsigned int cmd, unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               .identity               =       LONGNAME,
+               .firmware_version       =       1,
+               .options                =       WDIOF_SETTIMEOUT |
+                                               WDIOF_MAGICCLOSE |
+                                               WDIOF_KEEPALIVEPING
+       };
+       int new_margin;
+
+       switch (cmd) {
+       default:
+               return -ENOTTY;
+       case WDIOC_GETSUPPORT:
+               if (copy_to_user((struct watchdog_info *)arg, &ident,
+                       sizeof(ident)))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(0, (int *)arg))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_KEEPALIVE:
+               ar531x_wdt_kick();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_margin, (int *)arg))
+                       return -EFAULT;
+               if (new_margin < 1 || new_margin > 90)
+                       return -EINVAL;
+               margin = new_margin;
+               /* omit break */
+       case WDIOC_GETTIMEOUT:
+               if (put_user(margin, (int *)arg))
+                       return -EFAULT;
+               return 0;
+       }
+}
+
+static irqreturn_t ar531x_wdt_interrupt(int irq, void *devid)
+{
+       if (expect_close == 0) {
+               printk(KERN_CRIT DRVNAME ": expired, restarting system\n");
+               machine_restart("Watchdog expired!");
+       }
+
+       sysRegWrite(ar531x_wd, 0);
+       sysRegWrite(ar531x_wdc, 0);
+       sysRegWrite(ar531x_isr, sysRegRead(ar531x_isr) | ar531x_isr_wd);
+
+       return IRQ_HANDLED;
+}
+
+static struct file_operations ar531x_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .write          = ar531x_wdt_write,
+       .ioctl          = ar531x_wdt_ioctl,
+       .open           = ar531x_wdt_open,
+       .release        = ar531x_wdt_release,
+};
+
+static struct miscdevice ar531x_wdt_miscdev = {
+       .minor          = WATCHDOG_MINOR,
+       .name           = "watchdog",
+       .fops           = &ar531x_wdt_fops,
+};
+
+static int __init ar531x_wdt_init(void)
+{
+       int rc;
+
+       sema_init(&open_semaphore, 1);
+
+       ar531x_wdt_get_regs();
+
+       if (!request_mem_region(ar531x_wd, sizeof(u32), LONGNAME)) {
+               printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+               return -EBUSY;
+       }
+
+       if (!request_mem_region(ar531x_wdc, sizeof(u32), LONGNAME)) {
+               printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
+               rc = -EBUSY;
+               goto out_alloc;
+       }
+
+       rc = register_reboot_notifier(&ar531x_wdt_notifier);
+       if (rc) {
+               printk(KERN_ERR DRVNAME
+                       ": unable to register reboot notifier\n");
+               goto out_alloc_wdc;
+       }
+
+       rc = request_irq(AR531X_MISC_IRQ_WATCHDOG, ar531x_wdt_interrupt,
+                       IRQF_DISABLED, "ar531x_wdt", NULL);
+       if (rc) {
+               printk(KERN_ERR DRVNAME ": IRQ is already in use\n");
+               goto out_register;
+       }
+
+       rc = misc_register(&ar531x_wdt_miscdev);
+       if (rc) {
+               printk(KERN_ERR DRVNAME ": unable to register misc device\n");
+               goto out_reqirq;
+       }
+       goto out;
+
+out_reqirq:
+       free_irq(AR531X_MISC_IRQ_WATCHDOG, NULL);
+out_register:
+       unregister_reboot_notifier(&ar531x_wdt_notifier);
+out_alloc_wdc:
+       release_mem_region(ar531x_wdc, sizeof(u32));
+out_alloc:
+       release_mem_region(ar531x_wd, sizeof(u32));
+out:
+       return rc;
+}
+
+static void __exit ar531x_wdt_cleanup(void)
+{
+       misc_deregister(&ar531x_wdt_miscdev);
+       free_irq(AR531X_MISC_IRQ_WATCHDOG, NULL);
+       unregister_reboot_notifier(&ar531x_wdt_notifier);
+       release_mem_region(ar531x_wdc, sizeof(u32));
+       release_mem_region(ar531x_wd, sizeof(u32));
+}
+
+module_init(ar531x_wdt_init);
+module_exit(ar531x_wdt_cleanup);
diff --git 
a/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5315/ar5315.h 
b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5315/ar5315.h
index 8ad8810..ff67ec5 100644
--- a/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5315/ar5315.h
+++ b/target/linux/atheros/files/include/asm-mips/mach-atheros/ar5315/ar5315.h
@@ -198,6 +198,7 @@
 #define AR5315_WD               (AR5315_DSLBASE + 0x0038)
 #define AR5315_WDC              (AR5315_DSLBASE + 0x003c)
 
+#define WDC_AHB                     0x00000004
 #define WDC_RESET                   0x00000002               /* reset on 
watchdog */
 #define WDC_NMI                     0x00000001               /* NMI on 
watchdog */
 #define WDC_IGNORE_EXPIRATION       0x00000000
diff --git a/target/linux/atheros/patches-2.6.23/160-watchdog.patch 
b/target/linux/atheros/patches-2.6.23/160-watchdog.patch
new file mode 100644
index 0000000..841c10d
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.23/160-watchdog.patch
@@ -0,0 +1,35 @@
+commit 57765d87f8b4f34c598e39a2f95b8c60359b7b3e
+Author: Axel Gembe <[EMAIL PROTECTED]>
+Date:   Wed May 7 10:17:56 2008 +0200
+
+    watchdog patch
+
+diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
+index 37bddc1..9b1b631 100644
+--- a/drivers/char/watchdog/Kconfig
++++ b/drivers/char/watchdog/Kconfig
+@@ -609,6 +609,12 @@ config WDT_RM9K_GPI
+         To compile this driver as a module, choose M here: the
+         module will be called rm9k_wdt.
+ 
++config ATHEROS_WDT
++      tristate "Atheros hardware watchdog"
++      depends on ATHEROS
++      help
++        Hardware driver for the Atheros Watchdog Timer.
++
+ # PARISC Architecture
+ 
+ # POWERPC Architecture
+diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
+index 389f8b1..0bafa42 100644
+--- a/drivers/char/watchdog/Makefile
++++ b/drivers/char/watchdog/Makefile
+@@ -90,6 +90,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
+ obj-$(CONFIG_INDYDOG) += indydog.o
+ obj-$(CONFIG_WDT_MTX1)        += mtx-1_wdt.o
+ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
++obj-$(CONFIG_ATHEROS_WDT) += ar531x_wdt.o
+ 
+ # PARISC Architecture
+ 
diff --git a/target/linux/atheros/patches-2.6.24/160-watchdog.patch 
b/target/linux/atheros/patches-2.6.24/160-watchdog.patch
new file mode 100644
index 0000000..dc9ad51
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.24/160-watchdog.patch
@@ -0,0 +1,35 @@
+commit a9d0bee7a0891667764e4c1c0c76af5abb7ab446
+Author: Axel Gembe <[EMAIL PROTECTED]>
+Date:   Wed May 7 10:30:26 2008 +0200
+
+    watchdog patch
+
+diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
+index 52dff40..89f4b0a 100644
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -639,6 +639,12 @@ config AR7_WDT
+       help
+         Hardware driver for the TI AR7 Watchdog Timer.
+ 
++config ATHEROS_WDT
++      tristate "Atheros hardware watchdog"
++      depends on ATHEROS
++      help
++        Hardware driver for the Atheros Watchdog Timer.
++
+ # PARISC Architecture
+ 
+ # POWERPC Architecture
+diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
+index 87483cc..9dee070 100644
+--- a/drivers/watchdog/Makefile
++++ b/drivers/watchdog/Makefile
+@@ -93,6 +93,7 @@ obj-$(CONFIG_INDYDOG) += indydog.o
+ obj-$(CONFIG_WDT_MTX1)        += mtx-1_wdt.o
+ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
+ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
++obj-$(CONFIG_ATHEROS_WDT) += ar531x_wdt.o
+ 
+ # PARISC Architecture
+ 
diff --git a/target/linux/atheros/patches-2.6.25/160-watchdog.patch 
b/target/linux/atheros/patches-2.6.25/160-watchdog.patch
new file mode 100644
index 0000000..1273d8b
--- /dev/null
+++ b/target/linux/atheros/patches-2.6.25/160-watchdog.patch
@@ -0,0 +1,35 @@
+commit acdf903800de2d3329c7036a43f61e9d9baf0a4b
+Author: Axel Gembe <[EMAIL PROTECTED]>
+Date:   Tue May 6 12:46:05 2008 +0200
+
+    watchdog patch
+
+diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
+index 254d115..0162147 100644
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -670,6 +670,12 @@ config TXX9_WDT
+       help
+         Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
+ 
++config ATHEROS_WDT
++      tristate "Atheros hardware watchdog"
++      depends on ATHEROS
++      help
++        Hardware driver for the Atheros Watchdog Timer.
++
+ # PARISC Architecture
+ 
+ # POWERPC Architecture
+diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
+index f3fb170..68b630e 100644
+--- a/drivers/watchdog/Makefile
++++ b/drivers/watchdog/Makefile
+@@ -96,6 +96,7 @@ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
+ obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
+ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
+ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
++obj-$(CONFIG_ATHEROS_WDT) += ar531x_wdt.o
+ 
+ # PARISC Architecture
+ 
-- 
1.5.5.1

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
http://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to