]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
[PATCH] ARM: OMAP: Watchdog
authorDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 26 Jul 2005 10:36:59 +0000 (03:36 -0700)
committerTony Lindgren <tony@atomide.com>
Tue, 26 Jul 2005 10:36:59 +0000 (03:36 -0700)
Teach the OMAP watchdog driver about the driver model, including
defining a shutdown method (to stop the timer before kexec etc)
and suspend/resume methods (for system sleep states).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Tony Lindgren <tony@atomide.com>
arch/arm/mach-omap1/devices.c
drivers/char/watchdog/omap1610_wdt.c

index c3d04994be9f6dfa9eb19769eebc9e8a118a10be..bc2406a83c9a4703c75b01a4cef34db34c64e0e2 100644 (file)
@@ -194,6 +194,39 @@ static void __init omap_init_mmc(void)
 static inline void omap_init_mmc(void) {}
 #endif
 
+#if    defined(CONFIG_OMAP16XX_WATCHDOG) || defined(CONFIG_OMAP16XX_WATCHDOG_MODULE)
+
+#define        OMAP_WDT_BASE           0xfffeb000
+
+static struct resource wdt_resources[] = {
+       {
+               .start          = OMAP_WDT_BASE,
+               .end            = OMAP_WDT_BASE + 0x4f,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap_wdt_device = {
+       .name      = "omap1610_wdt",
+       .id          = -1,
+       .dev = {
+               .release        = omap_nop_release,
+       },
+       .num_resources  = ARRAY_SIZE(wdt_resources),
+       .resource       = wdt_resources,
+};
+
+static void omap_init_wdt(void)
+{
+       (void) platform_device_register(&omap_wdt_device);
+}
+#else
+static inline void omap_init_wdt(void) {}
+#endif
+
+
+/*-------------------------------------------------------------------------*/
+
 /*
  * This gets called after board-specific INIT_MACHINE, and initializes most
  * on-chip peripherals accessible on this board (except for few like USB):
@@ -219,6 +252,7 @@ static int __init omap_init_devices(void)
        omap_init_i2c();
        omap_init_irda();
        omap_init_mmc();
+       omap_init_wdt();
 
        return 0;
 }
index deae24fa5d8d1f3ffa6d2f93745c7a0d2dcf2a5f..431a3e6277743576bf137abad92c116faf973372 100644 (file)
@@ -21,6 +21,9 @@
  * Copyright (c) 2004 Texas Instruments.
  *     1. Modified to support OMAP1610 32-KHz watchdog timer
  *     2. Ported to 2.6 kernel
+ *
+ * Copyright (c) 2005 David Brownell
+ *     Use the driver model and standard identifiers; handle bigger timeouts.
  */
 
 #include <linux/module.h>
@@ -35,6 +38,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/device.h>
 #include <linux/moduleparam.h>
 
 #include <asm/io.h>
@@ -212,12 +216,24 @@ static struct miscdevice omap_wdt_miscdev = {
 };
 
 static int __init
-omap_wdt_init(void)
+omap1610_wdt_probe(struct device *dev)
 {
-       int ret;
+       struct platform_device  *pdev = to_platform_device(dev);
+       struct resource         *res, *mem;
+       int                     ret;
+
+       /* reserve static register mappings */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -ENOENT;
+       mem = request_mem_region(res->start, res->end - res->start + 1,
+                               pdev->name);
+       if (mem == NULL)
+               return -EBUSY;
+       dev_set_drvdata(dev, mem);
 
        omap_wdt_users = 0;
-       armwdt_ck = clk_get(NULL, "armwdt_ck");
+       armwdt_ck = clk_get(dev, "armwdt_ck");
        if (IS_ERR(armwdt_ck)) {
                ret = PTR_ERR(armwdt_ck);
                armwdt_ck = NULL;
@@ -227,6 +243,7 @@ omap_wdt_init(void)
        omap_wdt_disable();
        omap_wdt_adjust_timeout(timer_margin);
 
+       omap_wdt_miscdev.dev = dev;
        ret = misc_register(&omap_wdt_miscdev);
        if (ret)
                goto fail;
@@ -240,16 +257,74 @@ omap_wdt_init(void)
 fail:
        if (armwdt_ck)
                clk_put(armwdt_ck);
+       release_resource(mem);
        return ret;
 }
 
+static void
+omap1610_wdt_shutdown(struct device *dev)
+{
+       omap_wdt_disable();
+}
+
 static void __exit
-omap_wdt_exit(void)
+omap1610_wdt_remove(struct device *dev)
 {
+       struct resource *mem = dev_get_drvdata(dev);
        misc_deregister(&omap_wdt_miscdev);
+       release_resource(mem);
        clk_put(armwdt_ck);
 }
 
+#ifdef CONFIG_PM
+
+/* REVISIT ... not clear this is the best way to handle system suspend; and
+ * it's very inappropriate for selective device suspend (e.g. suspending this
+ * through sysfs rather than by stopping the watchdog daemon).  Also, this
+ * may not play well enough with NOWAYOUT...
+ */
+
+static int omap1610_wdt_suspend(struct device *dev, pm_message_t mesg, u32 level)
+{
+       if (level == SUSPEND_POWER_DOWN && omap_wdt_users)
+               omap_wdt_disable();
+       return 0;
+}
+
+static int omap1610_wdt_resume(struct device *dev, u32 level)
+{
+       if (level == RESUME_POWER_ON && omap_wdt_users) {
+               omap_wdt_enable();
+               omap_wdt_ping();
+       }
+       return 0;
+}
+
+#else
+#define        omap1610_wdt_suspend    NULL
+#define        omap1610_wdt_resume     NULL
+#endif
+
+static struct device_driver omap1610_wdt_driver = {
+       .name           = "omap1610_wdt",
+       .bus            = &platform_bus_type,
+       .probe          = omap1610_wdt_probe,
+       .shutdown       = omap1610_wdt_shutdown,
+       .remove         = __exit_p(omap1610_wdt_remove),
+       .suspend        = omap1610_wdt_suspend,
+       .resume         = omap1610_wdt_resume,
+};
+
+static int __init omap_wdt_init(void)
+{
+       return driver_register(&omap1610_wdt_driver);
+}
+
+static void __exit omap_wdt_exit(void)
+{
+       driver_unregister(&omap1610_wdt_driver);
+}
+
 module_init(omap_wdt_init);
 module_exit(omap_wdt_exit);