[WATCHDOG] orion5x_wdt: fix compile issue by providing tclk as platform data

The orion5x-wdt driver is now registered as a platform device and
receives the tclk value as platform data. This fixes a compile issue
cause by a previously removed define "ORION5X_TCLK".

Signed-off-by: Thomas Reitmayr <treitmayr@devbase.at>
Acked-by: Nicolas Pitre <nico@marvell.com>
Signed-off-by: Kristof Provost <kristof@sigsegv.be>
Cc: Lennert Buytenhek <buytenh@wantstofly.org>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Martin Michlmayr <tbm@cyrius.com>
Cc: Sylver Bruneau <sylver.bruneau@googlemail.com>
Cc: Kunihiko IMAI <bak@d2.dion.ne.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 8a0e49d..1a1df24 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -31,6 +31,7 @@
 #include <plat/ehci-orion.h>
 #include <plat/mv_xor.h>
 #include <plat/orion_nand.h>
+#include <plat/orion5x_wdt.h>
 #include <plat/time.h>
 #include "common.h"
 
@@ -533,6 +534,29 @@
 
 
 /*****************************************************************************
+ * Watchdog
+ ****************************************************************************/
+static struct orion5x_wdt_platform_data orion5x_wdt_data = {
+	.tclk			= 0,
+};
+
+static struct platform_device orion5x_wdt_device = {
+	.name		= "orion5x_wdt",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &orion5x_wdt_data,
+	},
+	.num_resources	= 0,
+};
+
+void __init orion5x_wdt_init(void)
+{
+	orion5x_wdt_data.tclk = orion5x_tclk;
+	platform_device_register(&orion5x_wdt_device);
+}
+
+
+/*****************************************************************************
  * Time handling
  ****************************************************************************/
 int orion5x_tclk;
@@ -631,6 +655,11 @@
 		printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n");
 		disable_hlt();
 	}
+
+	/*
+	 * Register watchdog driver
+	 */
+	orion5x_wdt_init();
 }
 
 /*
diff --git a/arch/arm/plat-orion/include/plat/orion5x_wdt.h b/arch/arm/plat-orion/include/plat/orion5x_wdt.h
new file mode 100644
index 0000000..3c9cf6a3
--- /dev/null
+++ b/arch/arm/plat-orion/include/plat/orion5x_wdt.h
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/plat-orion/include/plat/orion5x_wdt.h
+ *
+ * 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.
+ */
+
+#ifndef __PLAT_ORION5X_WDT_H
+#define __PLAT_ORION5X_WDT_H
+
+struct orion5x_wdt_platform_data {
+	u32	tclk;		/* no <linux/clk.h> support yet */
+};
+
+
+#endif
+
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c
index b64ae1a..e81441f 100644
--- a/drivers/watchdog/orion5x_wdt.c
+++ b/drivers/watchdog/orion5x_wdt.c
@@ -16,11 +16,13 @@
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/platform_device.h>
 #include <linux/watchdog.h>
 #include <linux/init.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <plat/orion5x_wdt.h>
 
 /*
  * Watchdog timer block registers.
@@ -29,13 +31,14 @@
 #define  WDT_EN			0x0010
 #define WDT_VAL			(TIMER_VIRT_BASE + 0x0024)
 
-#define ORION5X_TCLK		166666667
-#define WDT_MAX_DURATION	(0xffffffff / ORION5X_TCLK)
+#define WDT_MAX_CYCLE_COUNT	0xffffffff
 #define WDT_IN_USE		0
 #define WDT_OK_TO_CLOSE		1
 
 static int nowayout = WATCHDOG_NOWAYOUT;
-static int heartbeat =  WDT_MAX_DURATION;	/* (seconds) */
+static int heartbeat = -1;		/* module parameter (seconds) */
+static unsigned int wdt_max_duration;	/* (seconds) */
+static unsigned int wdt_tclk;
 static unsigned long wdt_status;
 static spinlock_t wdt_lock;
 
@@ -46,7 +49,7 @@
 	spin_lock(&wdt_lock);
 
 	/* Set watchdog duration */
-	writel(ORION5X_TCLK * heartbeat, WDT_VAL);
+	writel(wdt_tclk * heartbeat, WDT_VAL);
 
 	/* Clear watchdog timer interrupt */
 	reg = readl(BRIDGE_CAUSE);
@@ -88,7 +91,7 @@
 static int orion5x_wdt_get_timeleft(int *time_left)
 {
 	spin_lock(&wdt_lock);
-	*time_left = readl(WDT_VAL) / ORION5X_TCLK;
+	*time_left = readl(WDT_VAL) / wdt_tclk;
 	spin_unlock(&wdt_lock);
 	return 0;
 }
@@ -158,7 +161,7 @@
 		if (ret)
 			break;
 
-		if (time <= 0 || time > WDT_MAX_DURATION) {
+		if (time <= 0 || time > wdt_max_duration) {
 			ret = -EINVAL;
 			break;
 		}
@@ -210,23 +213,69 @@
 	.fops		= &orion5x_wdt_fops,
 };
 
-static int __init orion5x_wdt_init(void)
+static int __devinit orion5x_wdt_probe(struct platform_device *pdev)
+{
+	struct orion5x_wdt_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+
+	if (pdata) {
+		wdt_tclk = pdata->tclk;
+	} else {
+		printk(KERN_ERR "Orion5x Watchdog misses platform data\n");
+		return -ENODEV;
+	}
+
+	if (orion5x_wdt_miscdev.parent)
+		return -EBUSY;
+	orion5x_wdt_miscdev.parent = &pdev->dev;
+
+	wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
+	if (heartbeat <= 0 || heartbeat > wdt_max_duration)
+		heartbeat = wdt_max_duration;
+
+	ret = misc_register(&orion5x_wdt_miscdev);
+	if (ret)
+		return ret;
+
+	printk(KERN_INFO "Orion5x Watchdog Timer: Initial timeout %d sec%s\n",
+				heartbeat, nowayout ? ", nowayout" : "");
+	return 0;
+}
+
+static int __devexit orion5x_wdt_remove(struct platform_device *pdev)
 {
 	int ret;
 
-	spin_lock_init(&wdt_lock);
+	if (test_bit(WDT_IN_USE, &wdt_status)) {
+		wdt_disable();
+		clear_bit(WDT_IN_USE, &wdt_status);
+	}
 
-	ret = misc_register(&orion5x_wdt_miscdev);
-	if (ret == 0)
-		printk("Orion5x Watchdog Timer: heartbeat %d sec\n",
-								heartbeat);
+	ret = misc_deregister(&orion5x_wdt_miscdev);
+	if (!ret)
+		orion5x_wdt_miscdev.parent = NULL;
 
 	return ret;
 }
 
+static struct platform_driver orion5x_wdt_driver = {
+	.probe		= orion5x_wdt_probe,
+	.remove		= __devexit_p(orion5x_wdt_remove),
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "orion5x_wdt",
+	},
+};
+
+static int __init orion5x_wdt_init(void)
+{
+	spin_lock_init(&wdt_lock);
+	return platform_driver_register(&orion5x_wdt_driver);
+}
+
 static void __exit orion5x_wdt_exit(void)
 {
-	misc_deregister(&orion5x_wdt_miscdev);
+	platform_driver_unregister(&orion5x_wdt_driver);
 }
 
 module_init(orion5x_wdt_init);
@@ -236,8 +285,7 @@
 MODULE_DESCRIPTION("Orion5x Processor Watchdog");
 
 module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default is "
-					__MODULE_STRING(WDT_MAX_DURATION) ")");
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds");
 
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");