riowatchdog: Move under drivers/watchdog

The config stuff was already in drivers/watchdog/Kconfig

Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
new file mode 100644
index 0000000..98bb60f
--- /dev/null
+++ b/drivers/watchdog/riowd.c
@@ -0,0 +1,259 @@
+/* riowd.c - driver for hw watchdog inside Super I/O of RIO
+ *
+ * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/smp_lock.h>
+#include <linux/watchdog.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+/* RIO uses the NatSemi Super I/O power management logical device
+ * as its' watchdog.
+ *
+ * When the watchdog triggers, it asserts a line to the BBC (Boot Bus
+ * Controller) of the machine.  The BBC can only be configured to
+ * trigger a power-on reset when the signal is asserted.  The BBC
+ * can be configured to ignore the signal entirely as well.
+ *
+ * The only Super I/O device register we care about is at index
+ * 0x05 (WDTO_INDEX) which is the watchdog time-out in minutes (1-255).
+ * If set to zero, this disables the watchdog.  When set, the system
+ * must periodically (before watchdog expires) clear (set to zero) and
+ * re-set the watchdog else it will trigger.
+ *
+ * There are two other indexed watchdog registers inside this Super I/O
+ * logical device, but they are unused.  The first, at index 0x06 is
+ * the watchdog control and can be used to make the watchdog timer re-set
+ * when the PS/2 mouse or serial lines show activity.  The second, at
+ * index 0x07 is merely a sampling of the line from the watchdog to the
+ * BBC.
+ *
+ * The watchdog device generates no interrupts.
+ */
+
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
+MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO");
+MODULE_SUPPORTED_DEVICE("watchdog");
+MODULE_LICENSE("GPL");
+
+#define RIOWD_NAME	"pmc"
+#define PFX		RIOWD_NAME ": "
+
+struct riowd {
+	void __iomem		*regs;
+	spinlock_t		lock;
+};
+
+static struct riowd *riowd_device;
+
+#define WDTO_INDEX	0x05
+
+static int riowd_timeout = 1;		/* in minutes */
+module_param(riowd_timeout, int, 0);
+MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes");
+
+static void riowd_writereg(struct riowd *p, u8 val, int index)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&p->lock, flags);
+	writeb(index, p->regs + 0);
+	writeb(val, p->regs + 1);
+	spin_unlock_irqrestore(&p->lock, flags);
+}
+
+static int riowd_open(struct inode *inode, struct file *filp)
+{
+	cycle_kernel_lock();
+	nonseekable_open(inode, filp);
+	return 0;
+}
+
+static int riowd_release(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+static int riowd_ioctl(struct inode *inode, struct file *filp,
+		       unsigned int cmd, unsigned long arg)
+{
+	static struct watchdog_info info = {
+		.options		= WDIOF_SETTIMEOUT,
+		.firmware_version	= 1,
+		.identity		= "riowd",
+	};
+	void __user *argp = (void __user *)arg;
+	struct riowd *p = riowd_device;
+	unsigned int options;
+	int new_margin;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		if (copy_to_user(argp, &info, sizeof(info)))
+			return -EFAULT;
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		if (put_user(0, (int __user *)argp))
+			return -EFAULT;
+		break;
+
+	case WDIOC_KEEPALIVE:
+		riowd_writereg(p, riowd_timeout, WDTO_INDEX);
+		break;
+
+	case WDIOC_SETOPTIONS:
+		if (copy_from_user(&options, argp, sizeof(options)))
+			return -EFAULT;
+
+		if (options & WDIOS_DISABLECARD)
+			riowd_writereg(p, 0, WDTO_INDEX);
+		else if (options & WDIOS_ENABLECARD)
+			riowd_writereg(p, riowd_timeout, WDTO_INDEX);
+		else
+			return -EINVAL;
+
+		break;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, (int __user *)argp))
+			return -EFAULT;
+		if ((new_margin < 60) || (new_margin > (255 * 60)))
+			return -EINVAL;
+		riowd_timeout = (new_margin + 59) / 60;
+		riowd_writereg(p, riowd_timeout, WDTO_INDEX);
+		/* Fall */
+
+	case WDIOC_GETTIMEOUT:
+		return put_user(riowd_timeout * 60, (int __user *)argp);
+
+	default:
+		return -EINVAL;
+	};
+
+	return 0;
+}
+
+static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct riowd *p = riowd_device;
+
+	if (count) {
+		riowd_writereg(p, riowd_timeout, WDTO_INDEX);
+		return 1;
+	}
+
+	return 0;
+}
+
+static const struct file_operations riowd_fops = {
+	.owner =	THIS_MODULE,
+	.llseek =	no_llseek,
+	.ioctl =	riowd_ioctl,
+	.open =		riowd_open,
+	.write =	riowd_write,
+	.release =	riowd_release,
+};
+
+static struct miscdevice riowd_miscdev = {
+	.minor	= WATCHDOG_MINOR,
+	.name	= "watchdog",
+	.fops	= &riowd_fops
+};
+
+static int __devinit riowd_probe(struct of_device *op,
+				 const struct of_device_id *match)
+{
+	struct riowd *p;
+	int err = -EINVAL;
+
+	if (riowd_device)
+		goto out;
+
+	err = -ENOMEM;
+	p = kzalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		goto out;
+
+	spin_lock_init(&p->lock);
+
+	p->regs = of_ioremap(&op->resource[0], 0, 2, "riowd");
+	if (!p->regs) {
+		printk(KERN_ERR PFX "Cannot map registers.\n");
+		goto out_free;
+	}
+
+	err = misc_register(&riowd_miscdev);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot register watchdog misc device.\n");
+		goto out_iounmap;
+	}
+
+	printk(KERN_INFO PFX "Hardware watchdog [%i minutes], "
+	       "regs at %p\n", riowd_timeout, p->regs);
+
+	dev_set_drvdata(&op->dev, p);
+	riowd_device = p;
+	err = 0;
+
+out_iounmap:
+	of_iounmap(&op->resource[0], p->regs, 2);
+
+out_free:
+	kfree(p);
+
+out:
+	return err;
+}
+
+static int __devexit riowd_remove(struct of_device *op)
+{
+	struct riowd *p = dev_get_drvdata(&op->dev);
+
+	misc_deregister(&riowd_miscdev);
+	of_iounmap(&op->resource[0], p->regs, 2);
+	kfree(p);
+
+	return 0;
+}
+
+static struct of_device_id riowd_match[] = {
+	{
+		.name = "pmc",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, riowd_match);
+
+static struct of_platform_driver riowd_driver = {
+	.name		= "riowd",
+	.match_table	= riowd_match,
+	.probe		= riowd_probe,
+	.remove		= __devexit_p(riowd_remove),
+};
+
+static int __init riowd_init(void)
+{
+	return of_register_driver(&riowd_driver, &of_bus_type);
+}
+
+static void __exit riowd_exit(void)
+{
+	of_unregister_driver(&riowd_driver);
+}
+
+module_init(riowd_init);
+module_exit(riowd_exit);