[WATCHDOG] orion5x_wdt: fix compile issue by providing tclk as platform data
authorThomas Reitmayr <treitmayr@devbase.at>
Tue, 24 Feb 2009 22:59:22 +0000 (14:59 -0800)
committerWim Van Sebroeck <wim@iguana.be>
Wed, 25 Mar 2009 09:02:50 +0000 (09:02 +0000)
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>
arch/arm/mach-orion5x/common.c
arch/arm/plat-orion/include/plat/orion5x_wdt.h [new file with mode: 0644]
drivers/watchdog/orion5x_wdt.c

index 8a0e49d..1a1df24 100644 (file)
@@ -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 @@ void __init orion5x_xor_init(void)
 
 
 /*****************************************************************************
+ * 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 @@ void __init orion5x_init(void)
                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 (file)
index 0000000..3c9cf6a
--- /dev/null
@@ -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
+
index b64ae1a..e81441f 100644 (file)
 #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.
 #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 @@ static void wdt_enable(void)
        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 void wdt_disable(void)
 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 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd,
                if (ret)
                        break;
 
-               if (time <= 0 || time > WDT_MAX_DURATION) {
+               if (time <= 0 || time > wdt_max_duration) {
                        ret = -EINVAL;
                        break;
                }
@@ -210,23 +213,69 @@ static struct miscdevice orion5x_wdt_miscdev = {
        .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;
 
-       spin_lock_init(&wdt_lock);
+       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 == 0)
-               printk("Orion5x Watchdog Timer: heartbeat %d sec\n",
-                                                               heartbeat);
+       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;
+
+       if (test_bit(WDT_IN_USE, &wdt_status)) {
+               wdt_disable();
+               clear_bit(WDT_IN_USE, &wdt_status);
+       }
+
+       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_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>");
 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");