From 038432485c6af25bdc4ebec62ace7fe4dc0731c5 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 26 Jul 2005 03:36:59 -0700 Subject: [PATCH] [PATCH] ARM: OMAP: Watchdog 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 Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/devices.c | 34 ++++++++++++ drivers/char/watchdog/omap1610_wdt.c | 83 ++++++++++++++++++++++++++-- 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index c3d04994be9..bc2406a83c9 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -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; } diff --git a/drivers/char/watchdog/omap1610_wdt.c b/drivers/char/watchdog/omap1610_wdt.c index deae24fa5d8..431a3e62777 100644 --- a/drivers/char/watchdog/omap1610_wdt.c +++ b/drivers/char/watchdog/omap1610_wdt.c @@ -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 @@ -35,6 +38,7 @@ #include #include #include +#include #include #include @@ -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); -- 2.41.1