Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:
"This includes some fixes and code improvements (like
clk_prepare_enable and clk_disable_unprepare), conversion from the
omap_wdt and twl4030_wdt drivers to the watchdog framework, addition
of the SB8x0 chipset support and the DA9055 Watchdog driver and some
OF support for the davinci_wdt driver."

* git://www.linux-watchdog.org/linux-watchdog: (22 commits)
watchdog: mei: avoid oops in watchdog unregister code path
watchdog: Orion: Fix possible null-deference in orion_wdt_probe
watchdog: sp5100_tco: Add SB8x0 chipset support
watchdog: davinci_wdt: add OF support
watchdog: da9052: Fix invalid free of devm_ allocated data
watchdog: twl4030_wdt: Change TWL4030_MODULE_PM_RECEIVER to TWL_MODULE_PM_RECEIVER
watchdog: remove depends on CONFIG_EXPERIMENTAL
watchdog: Convert dev_printk(KERN_<LEVEL> to dev_<level>(
watchdog: DA9055 Watchdog driver
watchdog: omap_wdt: eliminate goto
watchdog: omap_wdt: delete redundant platform_set_drvdata() calls
watchdog: omap_wdt: convert to devm_ functions
watchdog: omap_wdt: convert to new watchdog core
watchdog: WatchDog Timer Driver Core: fix comment
watchdog: s3c2410_wdt: use clk_prepare_enable and clk_disable_unprepare
watchdog: imx2_wdt: Select the driver via ARCH_MXC
watchdog: cpu5wdt.c: add missing del_timer call
watchdog: hpwdt.c: Increase version string
watchdog: Convert twl4030_wdt to watchdog core
davinci_wdt: preparation for switch to common clock framework
...

+742 -449
+12
Documentation/devicetree/bindings/watchdog/davinci-wdt.txt
··· 1 + DaVinci Watchdog Timer (WDT) Controller 2 + 3 + Required properties: 4 + - compatible : Should be "ti,davinci-wdt" 5 + - reg : Should contain WDT registers location and length 6 + 7 + Examples: 8 + 9 + wdt: wdt@2320000 { 10 + compatible = "ti,davinci-wdt"; 11 + reg = <0x02320000 0x80>; 12 + };
+1 -1
drivers/misc/mei/wd.c
··· 370 370 371 371 void mei_watchdog_unregister(struct mei_device *dev) 372 372 { 373 - if (test_bit(WDOG_UNREGISTERED, &amt_wd_dev.status)) 373 + if (watchdog_get_drvdata(&amt_wd_dev) == NULL) 374 374 return; 375 375 376 376 watchdog_set_drvdata(&amt_wd_dev, NULL);
+15 -3
drivers/watchdog/Kconfig
··· 76 76 Alternatively say M to compile the driver as a module, 77 77 which will be called da9052_wdt. 78 78 79 + config DA9055_WATCHDOG 80 + tristate "Dialog Semiconductor DA9055 Watchdog" 81 + depends on MFD_DA9055 82 + help 83 + If you say yes here you get support for watchdog on the Dialog 84 + Semiconductor DA9055 PMIC. 85 + 86 + This driver can also be built as a module. If so, the module 87 + will be called da9055_wdt. 88 + 79 89 config WM831X_WATCHDOG 80 90 tristate "WM831x watchdog" 81 91 depends on MFD_WM831X ··· 242 232 config OMAP_WATCHDOG 243 233 tristate "OMAP Watchdog" 244 234 depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS 235 + select WATCHDOG_CORE 245 236 help 246 237 Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog. Say 'Y' 247 238 here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. ··· 311 300 config TWL4030_WATCHDOG 312 301 tristate "TWL4030 Watchdog" 313 302 depends on TWL4030_CORE 303 + select WATCHDOG_CORE 314 304 help 315 305 Support for TI TWL4030 watchdog. Say 'Y' here to enable the 316 306 watchdog timer support for TWL4030 chips. ··· 354 342 355 343 config IMX2_WDT 356 344 tristate "IMX2+ Watchdog" 357 - depends on IMX_HAVE_PLATFORM_IMX2_WDT 345 + depends on ARCH_MXC 358 346 help 359 347 This is the driver for the hardware watchdog 360 348 on the Freescale IMX2 and later processors. ··· 443 431 444 432 config F71808E_WDT 445 433 tristate "Fintek F71808E, F71862FG, F71869, F71882FG and F71889FG Watchdog" 446 - depends on X86 && EXPERIMENTAL 434 + depends on X86 447 435 help 448 436 This is the driver for the hardware watchdog on the Fintek 449 437 F71808E, F71862FG, F71869, F71882FG and F71889FG Super I/O controllers. ··· 634 622 635 623 config IT87_WDT 636 624 tristate "IT87 Watchdog Timer" 637 - depends on X86 && EXPERIMENTAL 625 + depends on X86 638 626 ---help--- 639 627 This is the driver for the hardware watchdog on the ITE IT8702, 640 628 IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 and IT8728
+1
drivers/watchdog/Makefile
··· 164 164 165 165 # Architecture Independent 166 166 obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o 167 + obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o 167 168 obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o 168 169 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o 169 170 obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
+2 -11
drivers/watchdog/ath79_wdt.c
··· 284 284 } 285 285 286 286 static struct platform_driver ath79_wdt_driver = { 287 + .probe = ath79_wdt_probe, 287 288 .remove = ath79_wdt_remove, 288 289 .shutdown = ath97_wdt_shutdown, 289 290 .driver = { ··· 293 292 }, 294 293 }; 295 294 296 - static int __init ath79_wdt_init(void) 297 - { 298 - return platform_driver_probe(&ath79_wdt_driver, ath79_wdt_probe); 299 - } 300 - module_init(ath79_wdt_init); 301 - 302 - static void __exit ath79_wdt_exit(void) 303 - { 304 - platform_driver_unregister(&ath79_wdt_driver); 305 - } 306 - module_exit(ath79_wdt_exit); 295 + module_platform_driver(ath79_wdt_driver); 307 296 308 297 MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X hardware watchdog driver"); 309 298 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
+1
drivers/watchdog/cpu5wdt.c
··· 266 266 if (cpu5wdt_device.queue) { 267 267 cpu5wdt_device.queue = 0; 268 268 wait_for_completion(&cpu5wdt_device.stop); 269 + del_timer(&cpu5wdt_device.timer); 269 270 } 270 271 271 272 misc_deregister(&cpu5wdt_misc);
-4
drivers/watchdog/da9052_wdt.c
··· 53 53 54 54 static void da9052_wdt_release_resources(struct kref *r) 55 55 { 56 - struct da9052_wdt_data *driver_data = 57 - container_of(r, struct da9052_wdt_data, kref); 58 - 59 - kfree(driver_data); 60 56 } 61 57 62 58 static int da9052_wdt_set_timeout(struct watchdog_device *wdt_dev,
+216
drivers/watchdog/da9055_wdt.c
··· 1 + /* 2 + * System monitoring driver for DA9055 PMICs. 3 + * 4 + * Copyright(c) 2012 Dialog Semiconductor Ltd. 5 + * 6 + * Author: David Dajun Chen <dchen@diasemi.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + * 13 + */ 14 + 15 + #include <linux/module.h> 16 + #include <linux/types.h> 17 + #include <linux/kernel.h> 18 + #include <linux/slab.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/watchdog.h> 21 + #include <linux/delay.h> 22 + 23 + #include <linux/mfd/da9055/core.h> 24 + #include <linux/mfd/da9055/reg.h> 25 + 26 + static bool nowayout = WATCHDOG_NOWAYOUT; 27 + module_param(nowayout, bool, 0); 28 + MODULE_PARM_DESC(nowayout, 29 + "Watchdog cannot be stopped once started (default=" 30 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 31 + 32 + #define DA9055_DEF_TIMEOUT 4 33 + #define DA9055_TWDMIN 256 34 + 35 + struct da9055_wdt_data { 36 + struct watchdog_device wdt; 37 + struct da9055 *da9055; 38 + struct kref kref; 39 + }; 40 + 41 + static const struct { 42 + u8 reg_val; 43 + int user_time; /* In seconds */ 44 + } da9055_wdt_maps[] = { 45 + { 0, 0 }, 46 + { 1, 2 }, 47 + { 2, 4 }, 48 + { 3, 8 }, 49 + { 4, 16 }, 50 + { 5, 32 }, 51 + { 5, 33 }, /* Actual time 32.768s so included both 32s and 33s */ 52 + { 6, 65 }, 53 + { 6, 66 }, /* Actual time 65.536s so include both, 65s and 66s */ 54 + { 7, 131 }, 55 + }; 56 + 57 + static int da9055_wdt_set_timeout(struct watchdog_device *wdt_dev, 58 + unsigned int timeout) 59 + { 60 + struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 61 + struct da9055 *da9055 = driver_data->da9055; 62 + int ret, i; 63 + 64 + for (i = 0; i < ARRAY_SIZE(da9055_wdt_maps); i++) 65 + if (da9055_wdt_maps[i].user_time == timeout) 66 + break; 67 + 68 + if (i == ARRAY_SIZE(da9055_wdt_maps)) 69 + ret = -EINVAL; 70 + else 71 + ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, 72 + DA9055_TWDSCALE_MASK, 73 + da9055_wdt_maps[i].reg_val << 74 + DA9055_TWDSCALE_SHIFT); 75 + if (ret < 0) 76 + dev_err(da9055->dev, 77 + "Failed to update timescale bit, %d\n", ret); 78 + 79 + wdt_dev->timeout = timeout; 80 + 81 + return ret; 82 + } 83 + 84 + static int da9055_wdt_ping(struct watchdog_device *wdt_dev) 85 + { 86 + struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 87 + struct da9055 *da9055 = driver_data->da9055; 88 + int ret; 89 + 90 + /* 91 + * We have a minimum time for watchdog window called TWDMIN. A write 92 + * to the watchdog before this elapsed time will cause an error. 93 + */ 94 + mdelay(DA9055_TWDMIN); 95 + 96 + /* Reset the watchdog timer */ 97 + ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_E, 98 + DA9055_WATCHDOG_MASK, 1); 99 + 100 + return ret; 101 + } 102 + 103 + static void da9055_wdt_release_resources(struct kref *r) 104 + { 105 + struct da9055_wdt_data *driver_data = 106 + container_of(r, struct da9055_wdt_data, kref); 107 + 108 + kfree(driver_data); 109 + } 110 + 111 + static void da9055_wdt_ref(struct watchdog_device *wdt_dev) 112 + { 113 + struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 114 + 115 + kref_get(&driver_data->kref); 116 + } 117 + 118 + static void da9055_wdt_unref(struct watchdog_device *wdt_dev) 119 + { 120 + struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 121 + 122 + kref_put(&driver_data->kref, da9055_wdt_release_resources); 123 + } 124 + 125 + static int da9055_wdt_start(struct watchdog_device *wdt_dev) 126 + { 127 + return da9055_wdt_set_timeout(wdt_dev, wdt_dev->timeout); 128 + } 129 + 130 + static int da9055_wdt_stop(struct watchdog_device *wdt_dev) 131 + { 132 + return da9055_wdt_set_timeout(wdt_dev, 0); 133 + } 134 + 135 + static struct watchdog_info da9055_wdt_info = { 136 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 137 + .identity = "DA9055 Watchdog", 138 + }; 139 + 140 + static const struct watchdog_ops da9055_wdt_ops = { 141 + .owner = THIS_MODULE, 142 + .start = da9055_wdt_start, 143 + .stop = da9055_wdt_stop, 144 + .ping = da9055_wdt_ping, 145 + .set_timeout = da9055_wdt_set_timeout, 146 + .ref = da9055_wdt_ref, 147 + .unref = da9055_wdt_unref, 148 + }; 149 + 150 + static int da9055_wdt_probe(struct platform_device *pdev) 151 + { 152 + struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent); 153 + struct da9055_wdt_data *driver_data; 154 + struct watchdog_device *da9055_wdt; 155 + int ret; 156 + 157 + driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data), 158 + GFP_KERNEL); 159 + if (!driver_data) { 160 + dev_err(da9055->dev, "Failed to allocate watchdog device\n"); 161 + return -ENOMEM; 162 + } 163 + 164 + driver_data->da9055 = da9055; 165 + 166 + da9055_wdt = &driver_data->wdt; 167 + 168 + da9055_wdt->timeout = DA9055_DEF_TIMEOUT; 169 + da9055_wdt->info = &da9055_wdt_info; 170 + da9055_wdt->ops = &da9055_wdt_ops; 171 + watchdog_set_nowayout(da9055_wdt, nowayout); 172 + watchdog_set_drvdata(da9055_wdt, driver_data); 173 + 174 + kref_init(&driver_data->kref); 175 + 176 + ret = da9055_wdt_stop(da9055_wdt); 177 + if (ret < 0) { 178 + dev_err(&pdev->dev, "Failed to stop watchdog, %d\n", ret); 179 + goto err; 180 + } 181 + 182 + dev_set_drvdata(&pdev->dev, driver_data); 183 + 184 + ret = watchdog_register_device(&driver_data->wdt); 185 + if (ret != 0) 186 + dev_err(da9055->dev, "watchdog_register_device() failed: %d\n", 187 + ret); 188 + 189 + err: 190 + return ret; 191 + } 192 + 193 + static int da9055_wdt_remove(struct platform_device *pdev) 194 + { 195 + struct da9055_wdt_data *driver_data = dev_get_drvdata(&pdev->dev); 196 + 197 + watchdog_unregister_device(&driver_data->wdt); 198 + kref_put(&driver_data->kref, da9055_wdt_release_resources); 199 + 200 + return 0; 201 + } 202 + 203 + static struct platform_driver da9055_wdt_driver = { 204 + .probe = da9055_wdt_probe, 205 + .remove = da9055_wdt_remove, 206 + .driver = { 207 + .name = "da9055-watchdog", 208 + }, 209 + }; 210 + 211 + module_platform_driver(da9055_wdt_driver); 212 + 213 + MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); 214 + MODULE_DESCRIPTION("DA9055 watchdog"); 215 + MODULE_LICENSE("GPL"); 216 + MODULE_ALIAS("platform:da9055-watchdog");
+9 -2
drivers/watchdog/davinci_wdt.c
··· 208 208 if (WARN_ON(IS_ERR(wdt_clk))) 209 209 return PTR_ERR(wdt_clk); 210 210 211 - clk_enable(wdt_clk); 211 + clk_prepare_enable(wdt_clk); 212 212 213 213 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 214 214 heartbeat = DEFAULT_HEARTBEAT; ··· 256 256 wdt_mem = NULL; 257 257 } 258 258 259 - clk_disable(wdt_clk); 259 + clk_disable_unprepare(wdt_clk); 260 260 clk_put(wdt_clk); 261 261 262 262 return 0; 263 263 } 264 264 265 + static const struct of_device_id davinci_wdt_of_match[] = { 266 + { .compatible = "ti,davinci-wdt", }, 267 + {}, 268 + }; 269 + MODULE_DEVICE_TABLE(of, davinci_wdt_of_match); 270 + 265 271 static struct platform_driver platform_wdt_driver = { 266 272 .driver = { 267 273 .name = "watchdog", 268 274 .owner = THIS_MODULE, 275 + .of_match_table = davinci_wdt_of_match, 269 276 }, 270 277 .probe = davinci_wdt_probe, 271 278 .remove = davinci_wdt_remove,
+1 -1
drivers/watchdog/hpwdt.c
··· 39 39 #endif /* CONFIG_HPWDT_NMI_DECODING */ 40 40 #include <asm/nmi.h> 41 41 42 - #define HPWDT_VERSION "1.3.0" 42 + #define HPWDT_VERSION "1.3.1" 43 43 #define SECS_TO_TICKS(secs) ((secs) * 1000 / 128) 44 44 #define TICKS_TO_SECS(ticks) ((ticks) * 128 / 1000) 45 45 #define HPWDT_MAX_TIMER TICKS_TO_SECS(65535)
+9 -10
drivers/watchdog/mpcore_wdt.c
··· 80 80 81 81 /* Check it really was our interrupt */ 82 82 if (readl(wdt->base + TWD_WDOG_INTSTAT)) { 83 - dev_printk(KERN_CRIT, wdt->dev, 84 - "Triggered - Reboot ignored.\n"); 83 + dev_crit(wdt->dev, "Triggered - Reboot ignored\n"); 85 84 /* Clear the interrupt on the watchdog */ 86 85 writel(1, wdt->base + TWD_WDOG_INTSTAT); 87 86 return IRQ_HANDLED; ··· 122 123 123 124 static void mpcore_wdt_start(struct mpcore_wdt *wdt) 124 125 { 125 - dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); 126 + dev_info(wdt->dev, "enabling watchdog\n"); 126 127 127 128 /* This loads the count register but does NOT start the count yet */ 128 129 mpcore_wdt_keepalive(wdt); ··· 179 180 if (wdt->expect_close == 42) 180 181 mpcore_wdt_stop(wdt); 181 182 else { 182 - dev_printk(KERN_CRIT, wdt->dev, 183 - "unexpected close, not stopping watchdog!\n"); 183 + dev_crit(wdt->dev, 184 + "unexpected close, not stopping watchdog!\n"); 184 185 mpcore_wdt_keepalive(wdt); 185 186 } 186 187 clear_bit(0, &wdt->timer_alive); ··· 350 351 ret = devm_request_irq(wdt->dev, wdt->irq, mpcore_wdt_fire, 0, 351 352 "mpcore_wdt", wdt); 352 353 if (ret) { 353 - dev_printk(KERN_ERR, wdt->dev, 354 - "cannot register IRQ%d for watchdog\n", 355 - wdt->irq); 354 + dev_err(wdt->dev, 355 + "cannot register IRQ%d for watchdog\n", 356 + wdt->irq); 356 357 return ret; 357 358 } 358 359 } ··· 364 365 mpcore_wdt_miscdev.parent = &pdev->dev; 365 366 ret = misc_register(&mpcore_wdt_miscdev); 366 367 if (ret) { 367 - dev_printk(KERN_ERR, wdt->dev, 368 + dev_err(wdt->dev, 368 369 "cannot register miscdev on minor=%d (err=%d)\n", 369 - WATCHDOG_MINOR, ret); 370 + WATCHDOG_MINOR, ret); 370 371 return ret; 371 372 } 372 373
+126 -193
drivers/watchdog/omap_wdt.c
··· 31 31 #include <linux/module.h> 32 32 #include <linux/types.h> 33 33 #include <linux/kernel.h> 34 - #include <linux/fs.h> 35 34 #include <linux/mm.h> 36 - #include <linux/miscdevice.h> 37 35 #include <linux/watchdog.h> 38 36 #include <linux/reboot.h> 39 37 #include <linux/init.h> 40 38 #include <linux/err.h> 41 39 #include <linux/platform_device.h> 42 40 #include <linux/moduleparam.h> 43 - #include <linux/bitops.h> 44 41 #include <linux/io.h> 45 - #include <linux/uaccess.h> 46 42 #include <linux/slab.h> 47 43 #include <linux/pm_runtime.h> 48 44 #include <linux/platform_data/omap-wd-timer.h> 49 45 50 46 #include "omap_wdt.h" 51 47 52 - static struct platform_device *omap_wdt_dev; 53 - 54 48 static unsigned timer_margin; 55 49 module_param(timer_margin, uint, 0); 56 50 MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); 57 51 58 - static unsigned int wdt_trgr_pattern = 0x1234; 59 - static DEFINE_SPINLOCK(wdt_lock); 60 - 61 52 struct omap_wdt_dev { 62 53 void __iomem *base; /* physical */ 63 54 struct device *dev; 64 - int omap_wdt_users; 55 + bool omap_wdt_users; 65 56 struct resource *mem; 66 - struct miscdevice omap_wdt_miscdev; 57 + int wdt_trgr_pattern; 58 + struct mutex lock; /* to avoid races with PM */ 67 59 }; 68 60 69 - static void omap_wdt_ping(struct omap_wdt_dev *wdev) 61 + static void omap_wdt_reload(struct omap_wdt_dev *wdev) 70 62 { 71 63 void __iomem *base = wdev->base; 72 64 ··· 66 74 while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) 67 75 cpu_relax(); 68 76 69 - wdt_trgr_pattern = ~wdt_trgr_pattern; 70 - __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); 77 + wdev->wdt_trgr_pattern = ~wdev->wdt_trgr_pattern; 78 + __raw_writel(wdev->wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); 71 79 72 80 /* wait for posted write to complete */ 73 81 while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) ··· 103 111 cpu_relax(); 104 112 } 105 113 106 - static void omap_wdt_adjust_timeout(unsigned new_timeout) 114 + static void omap_wdt_set_timer(struct omap_wdt_dev *wdev, 115 + unsigned int timeout) 107 116 { 108 - if (new_timeout < TIMER_MARGIN_MIN) 109 - new_timeout = TIMER_MARGIN_DEFAULT; 110 - if (new_timeout > TIMER_MARGIN_MAX) 111 - new_timeout = TIMER_MARGIN_MAX; 112 - timer_margin = new_timeout; 113 - } 114 - 115 - static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) 116 - { 117 - u32 pre_margin = GET_WLDR_VAL(timer_margin); 117 + u32 pre_margin = GET_WLDR_VAL(timeout); 118 118 void __iomem *base = wdev->base; 119 119 120 120 /* just count up at 32 KHz */ ··· 118 134 cpu_relax(); 119 135 } 120 136 121 - /* 122 - * Allow only one task to hold it open 123 - */ 124 - static int omap_wdt_open(struct inode *inode, struct file *file) 137 + static int omap_wdt_start(struct watchdog_device *wdog) 125 138 { 126 - struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev); 139 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 127 140 void __iomem *base = wdev->base; 128 141 129 - if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) 130 - return -EBUSY; 142 + mutex_lock(&wdev->lock); 143 + 144 + wdev->omap_wdt_users = true; 131 145 132 146 pm_runtime_get_sync(wdev->dev); 133 147 ··· 137 155 while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) 138 156 cpu_relax(); 139 157 140 - file->private_data = (void *) wdev; 141 - 142 - omap_wdt_set_timeout(wdev); 143 - omap_wdt_ping(wdev); /* trigger loading of new timeout value */ 158 + omap_wdt_set_timer(wdev, wdog->timeout); 159 + omap_wdt_reload(wdev); /* trigger loading of new timeout value */ 144 160 omap_wdt_enable(wdev); 145 161 146 - return nonseekable_open(inode, file); 147 - } 148 - 149 - static int omap_wdt_release(struct inode *inode, struct file *file) 150 - { 151 - struct omap_wdt_dev *wdev = file->private_data; 152 - 153 - /* 154 - * Shut off the timer unless NOWAYOUT is defined. 155 - */ 156 - #ifndef CONFIG_WATCHDOG_NOWAYOUT 157 - omap_wdt_disable(wdev); 158 - 159 - pm_runtime_put_sync(wdev->dev); 160 - #else 161 - pr_crit("Unexpected close, not stopping!\n"); 162 - #endif 163 - wdev->omap_wdt_users = 0; 162 + mutex_unlock(&wdev->lock); 164 163 165 164 return 0; 166 165 } 167 166 168 - static ssize_t omap_wdt_write(struct file *file, const char __user *data, 169 - size_t len, loff_t *ppos) 167 + static int omap_wdt_stop(struct watchdog_device *wdog) 170 168 { 171 - struct omap_wdt_dev *wdev = file->private_data; 169 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 172 170 173 - /* Refresh LOAD_TIME. */ 174 - if (len) { 175 - spin_lock(&wdt_lock); 176 - omap_wdt_ping(wdev); 177 - spin_unlock(&wdt_lock); 178 - } 179 - return len; 171 + mutex_lock(&wdev->lock); 172 + omap_wdt_disable(wdev); 173 + pm_runtime_put_sync(wdev->dev); 174 + wdev->omap_wdt_users = false; 175 + mutex_unlock(&wdev->lock); 176 + return 0; 180 177 } 181 178 182 - static long omap_wdt_ioctl(struct file *file, unsigned int cmd, 183 - unsigned long arg) 179 + static int omap_wdt_ping(struct watchdog_device *wdog) 184 180 { 185 - struct omap_wd_timer_platform_data *pdata; 186 - struct omap_wdt_dev *wdev; 187 - u32 rs; 188 - int new_margin, bs; 189 - static const struct watchdog_info ident = { 190 - .identity = "OMAP Watchdog", 191 - .options = WDIOF_SETTIMEOUT, 192 - .firmware_version = 0, 193 - }; 181 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 194 182 195 - wdev = file->private_data; 196 - pdata = wdev->dev->platform_data; 183 + mutex_lock(&wdev->lock); 184 + omap_wdt_reload(wdev); 185 + mutex_unlock(&wdev->lock); 197 186 198 - switch (cmd) { 199 - case WDIOC_GETSUPPORT: 200 - return copy_to_user((struct watchdog_info __user *)arg, &ident, 201 - sizeof(ident)); 202 - case WDIOC_GETSTATUS: 203 - return put_user(0, (int __user *)arg); 204 - case WDIOC_GETBOOTSTATUS: 205 - if (!pdata || !pdata->read_reset_sources) 206 - return put_user(0, (int __user *)arg); 207 - rs = pdata->read_reset_sources(); 208 - bs = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ? 209 - WDIOF_CARDRESET : 0; 210 - return put_user(bs, (int __user *)arg); 211 - case WDIOC_KEEPALIVE: 212 - spin_lock(&wdt_lock); 213 - omap_wdt_ping(wdev); 214 - spin_unlock(&wdt_lock); 215 - return 0; 216 - case WDIOC_SETTIMEOUT: 217 - if (get_user(new_margin, (int __user *)arg)) 218 - return -EFAULT; 219 - omap_wdt_adjust_timeout(new_margin); 220 - 221 - spin_lock(&wdt_lock); 222 - omap_wdt_disable(wdev); 223 - omap_wdt_set_timeout(wdev); 224 - omap_wdt_enable(wdev); 225 - 226 - omap_wdt_ping(wdev); 227 - spin_unlock(&wdt_lock); 228 - /* Fall */ 229 - case WDIOC_GETTIMEOUT: 230 - return put_user(timer_margin, (int __user *)arg); 231 - default: 232 - return -ENOTTY; 233 - } 187 + return 0; 234 188 } 235 189 236 - static const struct file_operations omap_wdt_fops = { 237 - .owner = THIS_MODULE, 238 - .write = omap_wdt_write, 239 - .unlocked_ioctl = omap_wdt_ioctl, 240 - .open = omap_wdt_open, 241 - .release = omap_wdt_release, 242 - .llseek = no_llseek, 190 + static int omap_wdt_set_timeout(struct watchdog_device *wdog, 191 + unsigned int timeout) 192 + { 193 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 194 + 195 + mutex_lock(&wdev->lock); 196 + omap_wdt_disable(wdev); 197 + omap_wdt_set_timer(wdev, timeout); 198 + omap_wdt_enable(wdev); 199 + omap_wdt_reload(wdev); 200 + wdog->timeout = timeout; 201 + mutex_unlock(&wdev->lock); 202 + 203 + return 0; 204 + } 205 + 206 + static const struct watchdog_info omap_wdt_info = { 207 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 208 + .identity = "OMAP Watchdog", 209 + }; 210 + 211 + static const struct watchdog_ops omap_wdt_ops = { 212 + .owner = THIS_MODULE, 213 + .start = omap_wdt_start, 214 + .stop = omap_wdt_stop, 215 + .ping = omap_wdt_ping, 216 + .set_timeout = omap_wdt_set_timeout, 243 217 }; 244 218 245 219 static int omap_wdt_probe(struct platform_device *pdev) 246 220 { 221 + struct omap_wd_timer_platform_data *pdata = pdev->dev.platform_data; 222 + bool nowayout = WATCHDOG_NOWAYOUT; 223 + struct watchdog_device *omap_wdt; 247 224 struct resource *res, *mem; 248 225 struct omap_wdt_dev *wdev; 226 + u32 rs; 249 227 int ret; 228 + 229 + omap_wdt = devm_kzalloc(&pdev->dev, sizeof(*omap_wdt), GFP_KERNEL); 230 + if (!omap_wdt) 231 + return -ENOMEM; 250 232 251 233 /* reserve static register mappings */ 252 234 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 253 - if (!res) { 254 - ret = -ENOENT; 255 - goto err_get_resource; 256 - } 235 + if (!res) 236 + return -ENOENT; 257 237 258 - if (omap_wdt_dev) { 259 - ret = -EBUSY; 260 - goto err_busy; 261 - } 238 + mem = devm_request_mem_region(&pdev->dev, res->start, 239 + resource_size(res), pdev->name); 240 + if (!mem) 241 + return -EBUSY; 262 242 263 - mem = request_mem_region(res->start, resource_size(res), pdev->name); 264 - if (!mem) { 265 - ret = -EBUSY; 266 - goto err_busy; 267 - } 243 + wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL); 244 + if (!wdev) 245 + return -ENOMEM; 268 246 269 - wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); 270 - if (!wdev) { 271 - ret = -ENOMEM; 272 - goto err_kzalloc; 273 - } 247 + wdev->omap_wdt_users = false; 248 + wdev->mem = mem; 249 + wdev->dev = &pdev->dev; 250 + wdev->wdt_trgr_pattern = 0x1234; 251 + mutex_init(&wdev->lock); 274 252 275 - wdev->omap_wdt_users = 0; 276 - wdev->mem = mem; 277 - wdev->dev = &pdev->dev; 253 + wdev->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 254 + if (!wdev->base) 255 + return -ENOMEM; 278 256 279 - wdev->base = ioremap(res->start, resource_size(res)); 280 - if (!wdev->base) { 281 - ret = -ENOMEM; 282 - goto err_ioremap; 283 - } 257 + omap_wdt->info = &omap_wdt_info; 258 + omap_wdt->ops = &omap_wdt_ops; 259 + omap_wdt->min_timeout = TIMER_MARGIN_MIN; 260 + omap_wdt->max_timeout = TIMER_MARGIN_MAX; 284 261 285 - platform_set_drvdata(pdev, wdev); 262 + if (timer_margin >= TIMER_MARGIN_MIN && 263 + timer_margin <= TIMER_MARGIN_MAX) 264 + omap_wdt->timeout = timer_margin; 265 + else 266 + omap_wdt->timeout = TIMER_MARGIN_DEFAULT; 267 + 268 + watchdog_set_drvdata(omap_wdt, wdev); 269 + watchdog_set_nowayout(omap_wdt, nowayout); 270 + 271 + platform_set_drvdata(pdev, omap_wdt); 286 272 287 273 pm_runtime_enable(wdev->dev); 288 274 pm_runtime_get_sync(wdev->dev); 289 275 276 + if (pdata && pdata->read_reset_sources) 277 + rs = pdata->read_reset_sources(); 278 + else 279 + rs = 0; 280 + omap_wdt->bootstatus = (rs & (1 << OMAP_MPU_WD_RST_SRC_ID_SHIFT)) ? 281 + WDIOF_CARDRESET : 0; 282 + 290 283 omap_wdt_disable(wdev); 291 - omap_wdt_adjust_timeout(timer_margin); 292 284 293 - wdev->omap_wdt_miscdev.parent = &pdev->dev; 294 - wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR; 295 - wdev->omap_wdt_miscdev.name = "watchdog"; 296 - wdev->omap_wdt_miscdev.fops = &omap_wdt_fops; 297 - 298 - ret = misc_register(&(wdev->omap_wdt_miscdev)); 299 - if (ret) 300 - goto err_misc; 285 + ret = watchdog_register_device(omap_wdt); 286 + if (ret) { 287 + pm_runtime_disable(wdev->dev); 288 + return ret; 289 + } 301 290 302 291 pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", 303 292 __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, 304 - timer_margin); 293 + omap_wdt->timeout); 305 294 306 295 pm_runtime_put_sync(wdev->dev); 307 296 308 - omap_wdt_dev = pdev; 309 - 310 297 return 0; 311 - 312 - err_misc: 313 - pm_runtime_disable(wdev->dev); 314 - platform_set_drvdata(pdev, NULL); 315 - iounmap(wdev->base); 316 - 317 - err_ioremap: 318 - wdev->base = NULL; 319 - kfree(wdev); 320 - 321 - err_kzalloc: 322 - release_mem_region(res->start, resource_size(res)); 323 - 324 - err_busy: 325 - err_get_resource: 326 - 327 - return ret; 328 298 } 329 299 330 300 static void omap_wdt_shutdown(struct platform_device *pdev) 331 301 { 332 - struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 302 + struct watchdog_device *wdog = platform_get_drvdata(pdev); 303 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 333 304 305 + mutex_lock(&wdev->lock); 334 306 if (wdev->omap_wdt_users) { 335 307 omap_wdt_disable(wdev); 336 308 pm_runtime_put_sync(wdev->dev); 337 309 } 310 + mutex_unlock(&wdev->lock); 338 311 } 339 312 340 313 static int omap_wdt_remove(struct platform_device *pdev) 341 314 { 342 - struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 315 + struct watchdog_device *wdog = platform_get_drvdata(pdev); 316 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 343 317 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 344 318 345 319 pm_runtime_disable(wdev->dev); 346 - if (!res) 347 - return -ENOENT; 348 - 349 - misc_deregister(&(wdev->omap_wdt_miscdev)); 350 - release_mem_region(res->start, resource_size(res)); 351 - platform_set_drvdata(pdev, NULL); 352 - 353 - iounmap(wdev->base); 354 - 355 - kfree(wdev); 356 - omap_wdt_dev = NULL; 320 + watchdog_unregister_device(wdog); 357 321 358 322 return 0; 359 323 } ··· 314 386 315 387 static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) 316 388 { 317 - struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 389 + struct watchdog_device *wdog = platform_get_drvdata(pdev); 390 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 318 391 392 + mutex_lock(&wdev->lock); 319 393 if (wdev->omap_wdt_users) { 320 394 omap_wdt_disable(wdev); 321 395 pm_runtime_put_sync(wdev->dev); 322 396 } 397 + mutex_unlock(&wdev->lock); 323 398 324 399 return 0; 325 400 } 326 401 327 402 static int omap_wdt_resume(struct platform_device *pdev) 328 403 { 329 - struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); 404 + struct watchdog_device *wdog = platform_get_drvdata(pdev); 405 + struct omap_wdt_dev *wdev = watchdog_get_drvdata(wdog); 330 406 407 + mutex_lock(&wdev->lock); 331 408 if (wdev->omap_wdt_users) { 332 409 pm_runtime_get_sync(wdev->dev); 333 410 omap_wdt_enable(wdev); 334 - omap_wdt_ping(wdev); 411 + omap_wdt_reload(wdev); 335 412 } 413 + mutex_unlock(&wdev->lock); 336 414 337 415 return 0; 338 416 } ··· 371 437 372 438 MODULE_AUTHOR("George G. Davis"); 373 439 MODULE_LICENSE("GPL"); 374 - MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 375 440 MODULE_ALIAS("platform:omap_wdt");
+2
drivers/watchdog/orion_wdt.c
··· 156 156 wdt_tclk = clk_get_rate(clk); 157 157 158 158 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 159 + if (!res) 160 + return -ENODEV; 159 161 wdt_reg = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 160 162 if (!wdt_reg) 161 163 return -ENOMEM;
+3 -3
drivers/watchdog/s3c2410_wdt.c
··· 354 354 goto err_map; 355 355 } 356 356 357 - clk_enable(wdt_clock); 357 + clk_prepare_enable(wdt_clock); 358 358 359 359 ret = s3c2410wdt_cpufreq_register(); 360 360 if (ret < 0) { ··· 421 421 s3c2410wdt_cpufreq_deregister(); 422 422 423 423 err_clk: 424 - clk_disable(wdt_clock); 424 + clk_disable_unprepare(wdt_clock); 425 425 clk_put(wdt_clock); 426 426 wdt_clock = NULL; 427 427 ··· 445 445 446 446 s3c2410wdt_cpufreq_deregister(); 447 447 448 - clk_disable(wdt_clock); 448 + clk_disable_unprepare(wdt_clock); 449 449 clk_put(wdt_clock); 450 450 wdt_clock = NULL; 451 451
+271 -50
drivers/watchdog/sp5100_tco.c
··· 13 13 * as published by the Free Software Foundation; either version 14 14 * 2 of the License, or (at your option) any later version. 15 15 * 16 - * See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide" 16 + * See AMD Publication 43009 "AMD SB700/710/750 Register Reference Guide", 17 + * AMD Publication 45482 "AMD SB800-Series Southbridges Register 18 + * Reference Guide" 17 19 */ 18 20 19 21 /* ··· 40 38 #include "sp5100_tco.h" 41 39 42 40 /* Module and version information */ 43 - #define TCO_VERSION "0.01" 41 + #define TCO_VERSION "0.03" 44 42 #define TCO_MODULE_NAME "SP5100 TCO timer" 45 43 #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION 46 44 47 45 /* internal variables */ 48 46 static u32 tcobase_phys; 47 + static u32 resbase_phys; 48 + static u32 tco_wdt_fired; 49 49 static void __iomem *tcobase; 50 50 static unsigned int pm_iobase; 51 51 static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */ 52 52 static unsigned long timer_alive; 53 53 static char tco_expect_close; 54 54 static struct pci_dev *sp5100_tco_pci; 55 + static struct resource wdt_res = { 56 + .name = "Watchdog Timer", 57 + .flags = IORESOURCE_MEM, 58 + }; 55 59 56 60 /* the watchdog platform device */ 57 61 static struct platform_device *sp5100_tco_platform_device; ··· 72 64 73 65 static bool nowayout = WATCHDOG_NOWAYOUT; 74 66 module_param(nowayout, bool, 0); 75 - MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started" 67 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started." 76 68 " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 69 + 70 + static unsigned int force_addr; 71 + module_param(force_addr, uint, 0); 72 + MODULE_PARM_DESC(force_addr, "Force the use of specified MMIO address." 73 + " ONLY USE THIS PARAMETER IF YOU REALLY KNOW" 74 + " WHAT YOU ARE DOING (default=none)"); 77 75 78 76 /* 79 77 * Some TCO specific functions ··· 134 120 135 121 heartbeat = t; 136 122 return 0; 123 + } 124 + 125 + static void tco_timer_enable(void) 126 + { 127 + int val; 128 + 129 + if (sp5100_tco_pci->revision >= 0x40) { 130 + /* For SB800 or later */ 131 + /* Set the Watchdog timer resolution to 1 sec */ 132 + outb(SB800_PM_WATCHDOG_CONFIG, SB800_IO_PM_INDEX_REG); 133 + val = inb(SB800_IO_PM_DATA_REG); 134 + val |= SB800_PM_WATCHDOG_SECOND_RES; 135 + outb(val, SB800_IO_PM_DATA_REG); 136 + 137 + /* Enable watchdog decode bit and watchdog timer */ 138 + outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG); 139 + val = inb(SB800_IO_PM_DATA_REG); 140 + val |= SB800_PCI_WATCHDOG_DECODE_EN; 141 + val &= ~SB800_PM_WATCHDOG_DISABLE; 142 + outb(val, SB800_IO_PM_DATA_REG); 143 + } else { 144 + /* For SP5100 or SB7x0 */ 145 + /* Enable watchdog decode bit */ 146 + pci_read_config_dword(sp5100_tco_pci, 147 + SP5100_PCI_WATCHDOG_MISC_REG, 148 + &val); 149 + 150 + val |= SP5100_PCI_WATCHDOG_DECODE_EN; 151 + 152 + pci_write_config_dword(sp5100_tco_pci, 153 + SP5100_PCI_WATCHDOG_MISC_REG, 154 + val); 155 + 156 + /* Enable Watchdog timer and set the resolution to 1 sec */ 157 + outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG); 158 + val = inb(SP5100_IO_PM_DATA_REG); 159 + val |= SP5100_PM_WATCHDOG_SECOND_RES; 160 + val &= ~SP5100_PM_WATCHDOG_DISABLE; 161 + outb(val, SP5100_IO_PM_DATA_REG); 162 + } 163 + } 164 + 165 + static void tco_timer_disable(void) 166 + { 167 + int val; 168 + 169 + if (sp5100_tco_pci->revision >= 0x40) { 170 + /* For SB800 or later */ 171 + /* Enable watchdog decode bit and Disable watchdog timer */ 172 + outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG); 173 + val = inb(SB800_IO_PM_DATA_REG); 174 + val |= SB800_PCI_WATCHDOG_DECODE_EN; 175 + val |= SB800_PM_WATCHDOG_DISABLE; 176 + outb(val, SB800_IO_PM_DATA_REG); 177 + } else { 178 + /* For SP5100 or SB7x0 */ 179 + /* Enable watchdog decode bit */ 180 + pci_read_config_dword(sp5100_tco_pci, 181 + SP5100_PCI_WATCHDOG_MISC_REG, 182 + &val); 183 + 184 + val |= SP5100_PCI_WATCHDOG_DECODE_EN; 185 + 186 + pci_write_config_dword(sp5100_tco_pci, 187 + SP5100_PCI_WATCHDOG_MISC_REG, 188 + val); 189 + 190 + /* Disable Watchdog timer */ 191 + outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG); 192 + val = inb(SP5100_IO_PM_DATA_REG); 193 + val |= SP5100_PM_WATCHDOG_DISABLE; 194 + outb(val, SP5100_IO_PM_DATA_REG); 195 + } 137 196 } 138 197 139 198 /* ··· 357 270 /* 358 271 * Init & exit routines 359 272 */ 360 - 361 273 static unsigned char sp5100_tco_setupdevice(void) 362 274 { 363 275 struct pci_dev *dev = NULL; 276 + const char *dev_name = NULL; 364 277 u32 val; 278 + u32 index_reg, data_reg, base_addr; 365 279 366 280 /* Match the PCI device */ 367 281 for_each_pci_dev(dev) { ··· 375 287 if (!sp5100_tco_pci) 376 288 return 0; 377 289 290 + pr_info("PCI Revision ID: 0x%x\n", sp5100_tco_pci->revision); 291 + 292 + /* 293 + * Determine type of southbridge chipset. 294 + */ 295 + if (sp5100_tco_pci->revision >= 0x40) { 296 + dev_name = SB800_DEVNAME; 297 + index_reg = SB800_IO_PM_INDEX_REG; 298 + data_reg = SB800_IO_PM_DATA_REG; 299 + base_addr = SB800_PM_WATCHDOG_BASE; 300 + } else { 301 + dev_name = SP5100_DEVNAME; 302 + index_reg = SP5100_IO_PM_INDEX_REG; 303 + data_reg = SP5100_IO_PM_DATA_REG; 304 + base_addr = SP5100_PM_WATCHDOG_BASE; 305 + } 306 + 378 307 /* Request the IO ports used by this driver */ 379 308 pm_iobase = SP5100_IO_PM_INDEX_REG; 380 - if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, "SP5100 TCO")) { 309 + if (!request_region(pm_iobase, SP5100_PM_IOPORTS_SIZE, dev_name)) { 381 310 pr_err("I/O address 0x%04x already in use\n", pm_iobase); 382 311 goto exit; 383 312 } 384 313 385 - /* Find the watchdog base address. */ 386 - outb(SP5100_PM_WATCHDOG_BASE3, SP5100_IO_PM_INDEX_REG); 387 - val = inb(SP5100_IO_PM_DATA_REG); 388 - outb(SP5100_PM_WATCHDOG_BASE2, SP5100_IO_PM_INDEX_REG); 389 - val = val << 8 | inb(SP5100_IO_PM_DATA_REG); 390 - outb(SP5100_PM_WATCHDOG_BASE1, SP5100_IO_PM_INDEX_REG); 391 - val = val << 8 | inb(SP5100_IO_PM_DATA_REG); 392 - outb(SP5100_PM_WATCHDOG_BASE0, SP5100_IO_PM_INDEX_REG); 393 - /* Low three bits of BASE0 are reserved. */ 394 - val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8); 314 + /* 315 + * First, Find the watchdog timer MMIO address from indirect I/O. 316 + */ 317 + outb(base_addr+3, index_reg); 318 + val = inb(data_reg); 319 + outb(base_addr+2, index_reg); 320 + val = val << 8 | inb(data_reg); 321 + outb(base_addr+1, index_reg); 322 + val = val << 8 | inb(data_reg); 323 + outb(base_addr+0, index_reg); 324 + /* Low three bits of BASE are reserved */ 325 + val = val << 8 | (inb(data_reg) & 0xf8); 326 + 327 + pr_debug("Got 0x%04x from indirect I/O\n", val); 328 + 329 + /* Check MMIO address conflict */ 330 + if (request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE, 331 + dev_name)) 332 + goto setup_wdt; 333 + else 334 + pr_debug("MMIO address 0x%04x already in use\n", val); 335 + 336 + /* 337 + * Secondly, Find the watchdog timer MMIO address 338 + * from SBResource_MMIO register. 339 + */ 340 + if (sp5100_tco_pci->revision >= 0x40) { 341 + /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */ 342 + outb(SB800_PM_ACPI_MMIO_EN+3, SB800_IO_PM_INDEX_REG); 343 + val = inb(SB800_IO_PM_DATA_REG); 344 + outb(SB800_PM_ACPI_MMIO_EN+2, SB800_IO_PM_INDEX_REG); 345 + val = val << 8 | inb(SB800_IO_PM_DATA_REG); 346 + outb(SB800_PM_ACPI_MMIO_EN+1, SB800_IO_PM_INDEX_REG); 347 + val = val << 8 | inb(SB800_IO_PM_DATA_REG); 348 + outb(SB800_PM_ACPI_MMIO_EN+0, SB800_IO_PM_INDEX_REG); 349 + val = val << 8 | inb(SB800_IO_PM_DATA_REG); 350 + } else { 351 + /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */ 352 + pci_read_config_dword(sp5100_tco_pci, 353 + SP5100_SB_RESOURCE_MMIO_BASE, &val); 354 + } 355 + 356 + /* The SBResource_MMIO is enabled and mapped memory space? */ 357 + if ((val & (SB800_ACPI_MMIO_DECODE_EN | SB800_ACPI_MMIO_SEL)) == 358 + SB800_ACPI_MMIO_DECODE_EN) { 359 + /* Clear unnecessary the low twelve bits */ 360 + val &= ~0xFFF; 361 + /* Add the Watchdog Timer offset to base address. */ 362 + val += SB800_PM_WDT_MMIO_OFFSET; 363 + /* Check MMIO address conflict */ 364 + if (request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE, 365 + dev_name)) { 366 + pr_debug("Got 0x%04x from SBResource_MMIO register\n", 367 + val); 368 + goto setup_wdt; 369 + } else 370 + pr_debug("MMIO address 0x%04x already in use\n", val); 371 + } else 372 + pr_debug("SBResource_MMIO is disabled(0x%04x)\n", val); 373 + 374 + /* 375 + * Lastly re-programming the watchdog timer MMIO address, 376 + * This method is a last resort... 377 + * 378 + * Before re-programming, to ensure that the watchdog timer 379 + * is disabled, disable the watchdog timer. 380 + */ 381 + tco_timer_disable(); 382 + 383 + if (force_addr) { 384 + /* 385 + * Force the use of watchdog timer MMIO address, and aligned to 386 + * 8byte boundary. 387 + */ 388 + force_addr &= ~0x7; 389 + val = force_addr; 390 + 391 + pr_info("Force the use of 0x%04x as MMIO address\n", val); 392 + } else { 393 + /* 394 + * Get empty slot into the resource tree for watchdog timer. 395 + */ 396 + if (allocate_resource(&iomem_resource, 397 + &wdt_res, 398 + SP5100_WDT_MEM_MAP_SIZE, 399 + 0xf0000000, 400 + 0xfffffff8, 401 + 0x8, 402 + NULL, 403 + NULL)) { 404 + pr_err("MMIO allocation failed\n"); 405 + goto unreg_region; 406 + } 407 + 408 + val = resbase_phys = wdt_res.start; 409 + pr_debug("Got 0x%04x from resource tree\n", val); 410 + } 411 + 412 + /* Restore to the low three bits, if chipset is SB8x0(or later) */ 413 + if (sp5100_tco_pci->revision >= 0x40) { 414 + u8 reserved_bit; 415 + reserved_bit = inb(base_addr) & 0x7; 416 + val |= (u32)reserved_bit; 417 + } 418 + 419 + /* Re-programming the watchdog timer base address */ 420 + outb(base_addr+0, index_reg); 421 + /* Low three bits of BASE are reserved */ 422 + outb((val >> 0) & 0xf8, data_reg); 423 + outb(base_addr+1, index_reg); 424 + outb((val >> 8) & 0xff, data_reg); 425 + outb(base_addr+2, index_reg); 426 + outb((val >> 16) & 0xff, data_reg); 427 + outb(base_addr+3, index_reg); 428 + outb((val >> 24) & 0xff, data_reg); 429 + 430 + /* 431 + * Clear unnecessary the low three bits, 432 + * if chipset is SB8x0(or later) 433 + */ 434 + if (sp5100_tco_pci->revision >= 0x40) 435 + val &= ~0x7; 395 436 396 437 if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE, 397 - "SP5100 TCO")) { 398 - pr_err("mmio address 0x%04x already in use\n", val); 399 - goto unreg_region; 438 + dev_name)) { 439 + pr_err("MMIO address 0x%04x already in use\n", val); 440 + goto unreg_resource; 400 441 } 442 + 443 + setup_wdt: 401 444 tcobase_phys = val; 402 445 403 446 tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE); ··· 537 318 goto unreg_mem_region; 538 319 } 539 320 540 - /* Enable watchdog decode bit */ 541 - pci_read_config_dword(sp5100_tco_pci, 542 - SP5100_PCI_WATCHDOG_MISC_REG, 543 - &val); 321 + pr_info("Using 0x%04x for watchdog MMIO address\n", val); 544 322 545 - val |= SP5100_PCI_WATCHDOG_DECODE_EN; 323 + /* Setup the watchdog timer */ 324 + tco_timer_enable(); 546 325 547 - pci_write_config_dword(sp5100_tco_pci, 548 - SP5100_PCI_WATCHDOG_MISC_REG, 549 - val); 550 - 551 - /* Enable Watchdog timer and set the resolution to 1 sec. */ 552 - outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG); 553 - val = inb(SP5100_IO_PM_DATA_REG); 554 - val |= SP5100_PM_WATCHDOG_SECOND_RES; 555 - val &= ~SP5100_PM_WATCHDOG_DISABLE; 556 - outb(val, SP5100_IO_PM_DATA_REG); 557 - 558 - /* Check that the watchdog action is set to reset the system. */ 326 + /* Check that the watchdog action is set to reset the system */ 559 327 val = readl(SP5100_WDT_CONTROL(tcobase)); 328 + /* 329 + * Save WatchDogFired status, because WatchDogFired flag is 330 + * cleared here. 331 + */ 332 + tco_wdt_fired = val & SP5100_PM_WATCHDOG_FIRED; 560 333 val &= ~SP5100_PM_WATCHDOG_ACTION_RESET; 561 334 writel(val, SP5100_WDT_CONTROL(tcobase)); 562 335 ··· 566 355 567 356 unreg_mem_region: 568 357 release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); 358 + unreg_resource: 359 + if (resbase_phys) 360 + release_resource(&wdt_res); 569 361 unreg_region: 570 362 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); 571 363 exit: ··· 578 364 static int sp5100_tco_init(struct platform_device *dev) 579 365 { 580 366 int ret; 581 - u32 val; 367 + char addr_str[16]; 582 368 583 - /* Check whether or not the hardware watchdog is there. If found, then 369 + /* 370 + * Check whether or not the hardware watchdog is there. If found, then 584 371 * set it up. 585 372 */ 586 373 if (!sp5100_tco_setupdevice()) 587 374 return -ENODEV; 588 375 589 376 /* Check to see if last reboot was due to watchdog timeout */ 590 - pr_info("Watchdog reboot %sdetected\n", 591 - readl(SP5100_WDT_CONTROL(tcobase)) & SP5100_PM_WATCHDOG_FIRED ? 592 - "" : "not "); 593 - 594 - /* Clear out the old status */ 595 - val = readl(SP5100_WDT_CONTROL(tcobase)); 596 - val &= ~SP5100_PM_WATCHDOG_FIRED; 597 - writel(val, SP5100_WDT_CONTROL(tcobase)); 377 + pr_info("Last reboot was %striggered by watchdog.\n", 378 + tco_wdt_fired ? "" : "not "); 598 379 599 380 /* 600 381 * Check that the heartbeat value is within it's range. ··· 609 400 610 401 clear_bit(0, &timer_alive); 611 402 612 - pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", 613 - tcobase, heartbeat, nowayout); 403 + /* Show module parameters */ 404 + if (force_addr == tcobase_phys) 405 + /* The force_addr is vaild */ 406 + sprintf(addr_str, "0x%04x", force_addr); 407 + else 408 + strcpy(addr_str, "none"); 409 + 410 + pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d, " 411 + "force_addr=%s)\n", 412 + tcobase, heartbeat, nowayout, addr_str); 614 413 615 414 return 0; 616 415 617 416 exit: 618 417 iounmap(tcobase); 619 418 release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); 419 + if (resbase_phys) 420 + release_resource(&wdt_res); 620 421 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); 621 422 return ret; 622 423 } ··· 641 422 misc_deregister(&sp5100_tco_miscdev); 642 423 iounmap(tcobase); 643 424 release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); 425 + if (resbase_phys) 426 + release_resource(&wdt_res); 644 427 release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); 645 428 } 646 429 ··· 672 451 { 673 452 int err; 674 453 675 - pr_info("SP5100 TCO WatchDog Timer Driver v%s\n", TCO_VERSION); 454 + pr_info("SP5100/SB800 TCO WatchDog Timer Driver v%s\n", TCO_VERSION); 676 455 677 456 err = platform_driver_register(&sp5100_tco_driver); 678 457 if (err) ··· 696 475 { 697 476 platform_device_unregister(sp5100_tco_platform_device); 698 477 platform_driver_unregister(&sp5100_tco_driver); 699 - pr_info("SP5100 TCO Watchdog Module Unloaded\n"); 478 + pr_info("SP5100/SB800 TCO Watchdog Module Unloaded\n"); 700 479 } 701 480 702 481 module_init(sp5100_tco_init_module); 703 482 module_exit(sp5100_tco_cleanup_module); 704 483 705 484 MODULE_AUTHOR("Priyanka Gupta"); 706 - MODULE_DESCRIPTION("TCO timer driver for SP5100 chipset"); 485 + MODULE_DESCRIPTION("TCO timer driver for SP5100/SB800 chipset"); 707 486 MODULE_LICENSE("GPL"); 708 487 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+35 -11
drivers/watchdog/sp5100_tco.h
··· 9 9 /* 10 10 * Some address definitions for the Watchdog 11 11 */ 12 - 13 12 #define SP5100_WDT_MEM_MAP_SIZE 0x08 14 13 #define SP5100_WDT_CONTROL(base) ((base) + 0x00) /* Watchdog Control */ 15 14 #define SP5100_WDT_COUNT(base) ((base) + 0x04) /* Watchdog Count */ 16 15 17 - #define SP5100_WDT_START_STOP_BIT 1 16 + #define SP5100_WDT_START_STOP_BIT (1 << 0) 18 17 #define SP5100_WDT_TRIGGER_BIT (1 << 7) 19 - 20 - #define SP5100_PCI_WATCHDOG_MISC_REG 0x41 21 - #define SP5100_PCI_WATCHDOG_DECODE_EN (1 << 3) 22 18 23 19 #define SP5100_PM_IOPORTS_SIZE 0x02 24 20 25 - /* These two IO registers are hardcoded and there doesn't seem to be a way to 21 + /* 22 + * These two IO registers are hardcoded and there doesn't seem to be a way to 26 23 * read them from a register. 27 24 */ 25 + 26 + /* For SP5100/SB7x0 chipset */ 28 27 #define SP5100_IO_PM_INDEX_REG 0xCD6 29 28 #define SP5100_IO_PM_DATA_REG 0xCD7 30 29 30 + #define SP5100_SB_RESOURCE_MMIO_BASE 0x9C 31 + 31 32 #define SP5100_PM_WATCHDOG_CONTROL 0x69 32 - #define SP5100_PM_WATCHDOG_BASE0 0x6C 33 - #define SP5100_PM_WATCHDOG_BASE1 0x6D 34 - #define SP5100_PM_WATCHDOG_BASE2 0x6E 35 - #define SP5100_PM_WATCHDOG_BASE3 0x6F 33 + #define SP5100_PM_WATCHDOG_BASE 0x6C 36 34 37 35 #define SP5100_PM_WATCHDOG_FIRED (1 << 1) 38 36 #define SP5100_PM_WATCHDOG_ACTION_RESET (1 << 2) 39 37 40 - #define SP5100_PM_WATCHDOG_DISABLE 1 38 + #define SP5100_PCI_WATCHDOG_MISC_REG 0x41 39 + #define SP5100_PCI_WATCHDOG_DECODE_EN (1 << 3) 40 + 41 + #define SP5100_PM_WATCHDOG_DISABLE (1 << 0) 41 42 #define SP5100_PM_WATCHDOG_SECOND_RES (3 << 1) 43 + 44 + #define SP5100_DEVNAME "SP5100 TCO" 45 + 46 + 47 + /* For SB8x0(or later) chipset */ 48 + #define SB800_IO_PM_INDEX_REG 0xCD6 49 + #define SB800_IO_PM_DATA_REG 0xCD7 50 + 51 + #define SB800_PM_ACPI_MMIO_EN 0x24 52 + #define SB800_PM_WATCHDOG_CONTROL 0x48 53 + #define SB800_PM_WATCHDOG_BASE 0x48 54 + #define SB800_PM_WATCHDOG_CONFIG 0x4C 55 + 56 + #define SB800_PCI_WATCHDOG_DECODE_EN (1 << 0) 57 + #define SB800_PM_WATCHDOG_DISABLE (1 << 2) 58 + #define SB800_PM_WATCHDOG_SECOND_RES (3 << 0) 59 + #define SB800_ACPI_MMIO_DECODE_EN (1 << 0) 60 + #define SB800_ACPI_MMIO_SEL (1 << 2) 61 + 62 + 63 + #define SB800_PM_WDT_MMIO_OFFSET 0xB00 64 + 65 + #define SB800_DEVNAME "SB800 TCO"
+2 -9
drivers/watchdog/sp805_wdt.c
··· 130 130 int ret; 131 131 132 132 if (!ping) { 133 - ret = clk_prepare(wdt->clk); 134 - if (ret) { 135 - dev_err(&wdt->adev->dev, "clock prepare fail"); 136 - return ret; 137 - } 138 133 139 - ret = clk_enable(wdt->clk); 134 + ret = clk_prepare_enable(wdt->clk); 140 135 if (ret) { 141 136 dev_err(&wdt->adev->dev, "clock enable fail"); 142 - clk_unprepare(wdt->clk); 143 137 return ret; 144 138 } 145 139 } ··· 184 190 readl_relaxed(wdt->base + WDTLOCK); 185 191 spin_unlock(&wdt->lock); 186 192 187 - clk_disable(wdt->clk); 188 - clk_unprepare(wdt->clk); 193 + clk_disable_unprepare(wdt->clk); 189 194 190 195 return 0; 191 196 }
+35 -150
drivers/watchdog/twl4030_wdt.c
··· 22 22 #include <linux/types.h> 23 23 #include <linux/slab.h> 24 24 #include <linux/kernel.h> 25 - #include <linux/fs.h> 26 25 #include <linux/watchdog.h> 27 26 #include <linux/platform_device.h> 28 - #include <linux/miscdevice.h> 29 - #include <linux/uaccess.h> 30 27 #include <linux/i2c/twl.h> 31 28 32 29 #define TWL4030_WATCHDOG_CFG_REG_OFFS 0x3 33 - 34 - #define TWL4030_WDT_STATE_OPEN 0x1 35 - #define TWL4030_WDT_STATE_ACTIVE 0x8 36 - 37 - static struct platform_device *twl4030_wdt_dev; 38 - 39 - struct twl4030_wdt { 40 - struct miscdevice miscdev; 41 - int timer_margin; 42 - unsigned long state; 43 - }; 44 30 45 31 static bool nowayout = WATCHDOG_NOWAYOUT; 46 32 module_param(nowayout, bool, 0); ··· 35 49 36 50 static int twl4030_wdt_write(unsigned char val) 37 51 { 38 - return twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val, 52 + return twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, val, 39 53 TWL4030_WATCHDOG_CFG_REG_OFFS); 40 54 } 41 55 42 - static int twl4030_wdt_enable(struct twl4030_wdt *wdt) 56 + static int twl4030_wdt_start(struct watchdog_device *wdt) 43 57 { 44 - return twl4030_wdt_write(wdt->timer_margin + 1); 58 + return twl4030_wdt_write(wdt->timeout + 1); 45 59 } 46 60 47 - static int twl4030_wdt_disable(struct twl4030_wdt *wdt) 61 + static int twl4030_wdt_stop(struct watchdog_device *wdt) 48 62 { 49 63 return twl4030_wdt_write(0); 50 64 } 51 65 52 - static int twl4030_wdt_set_timeout(struct twl4030_wdt *wdt, int timeout) 66 + static int twl4030_wdt_set_timeout(struct watchdog_device *wdt, 67 + unsigned int timeout) 53 68 { 54 - if (timeout < 0 || timeout > 30) { 55 - dev_warn(wdt->miscdev.parent, 56 - "Timeout can only be in the range [0-30] seconds"); 57 - return -EINVAL; 58 - } 59 - wdt->timer_margin = timeout; 60 - return twl4030_wdt_enable(wdt); 61 - } 62 - 63 - static ssize_t twl4030_wdt_write_fop(struct file *file, 64 - const char __user *data, size_t len, loff_t *ppos) 65 - { 66 - struct twl4030_wdt *wdt = file->private_data; 67 - 68 - if (len) 69 - twl4030_wdt_enable(wdt); 70 - 71 - return len; 72 - } 73 - 74 - static long twl4030_wdt_ioctl(struct file *file, 75 - unsigned int cmd, unsigned long arg) 76 - { 77 - void __user *argp = (void __user *)arg; 78 - int __user *p = argp; 79 - int new_margin; 80 - struct twl4030_wdt *wdt = file->private_data; 81 - 82 - static const struct watchdog_info twl4030_wd_ident = { 83 - .identity = "TWL4030 Watchdog", 84 - .options = WDIOF_SETTIMEOUT, 85 - .firmware_version = 0, 86 - }; 87 - 88 - switch (cmd) { 89 - case WDIOC_GETSUPPORT: 90 - return copy_to_user(argp, &twl4030_wd_ident, 91 - sizeof(twl4030_wd_ident)) ? -EFAULT : 0; 92 - 93 - case WDIOC_GETSTATUS: 94 - case WDIOC_GETBOOTSTATUS: 95 - return put_user(0, p); 96 - 97 - case WDIOC_KEEPALIVE: 98 - twl4030_wdt_enable(wdt); 99 - break; 100 - 101 - case WDIOC_SETTIMEOUT: 102 - if (get_user(new_margin, p)) 103 - return -EFAULT; 104 - if (twl4030_wdt_set_timeout(wdt, new_margin)) 105 - return -EINVAL; 106 - return put_user(wdt->timer_margin, p); 107 - 108 - case WDIOC_GETTIMEOUT: 109 - return put_user(wdt->timer_margin, p); 110 - 111 - default: 112 - return -ENOTTY; 113 - } 114 - 69 + wdt->timeout = timeout; 115 70 return 0; 116 71 } 117 72 118 - static int twl4030_wdt_open(struct inode *inode, struct file *file) 119 - { 120 - struct twl4030_wdt *wdt = platform_get_drvdata(twl4030_wdt_dev); 73 + static const struct watchdog_info twl4030_wdt_info = { 74 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 75 + .identity = "TWL4030 Watchdog", 76 + }; 121 77 122 - /* /dev/watchdog can only be opened once */ 123 - if (test_and_set_bit(0, &wdt->state)) 124 - return -EBUSY; 125 - 126 - wdt->state |= TWL4030_WDT_STATE_ACTIVE; 127 - file->private_data = (void *) wdt; 128 - 129 - twl4030_wdt_enable(wdt); 130 - return nonseekable_open(inode, file); 131 - } 132 - 133 - static int twl4030_wdt_release(struct inode *inode, struct file *file) 134 - { 135 - struct twl4030_wdt *wdt = file->private_data; 136 - if (nowayout) { 137 - dev_alert(wdt->miscdev.parent, 138 - "Unexpected close, watchdog still running!\n"); 139 - twl4030_wdt_enable(wdt); 140 - } else { 141 - if (twl4030_wdt_disable(wdt)) 142 - return -EFAULT; 143 - wdt->state &= ~TWL4030_WDT_STATE_ACTIVE; 144 - } 145 - 146 - clear_bit(0, &wdt->state); 147 - return 0; 148 - } 149 - 150 - static const struct file_operations twl4030_wdt_fops = { 78 + static const struct watchdog_ops twl4030_wdt_ops = { 151 79 .owner = THIS_MODULE, 152 - .llseek = no_llseek, 153 - .open = twl4030_wdt_open, 154 - .release = twl4030_wdt_release, 155 - .unlocked_ioctl = twl4030_wdt_ioctl, 156 - .write = twl4030_wdt_write_fop, 80 + .start = twl4030_wdt_start, 81 + .stop = twl4030_wdt_stop, 82 + .set_timeout = twl4030_wdt_set_timeout, 157 83 }; 158 84 159 85 static int twl4030_wdt_probe(struct platform_device *pdev) 160 86 { 161 87 int ret = 0; 162 - struct twl4030_wdt *wdt; 88 + struct watchdog_device *wdt; 163 89 164 - wdt = kzalloc(sizeof(struct twl4030_wdt), GFP_KERNEL); 90 + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 165 91 if (!wdt) 166 92 return -ENOMEM; 167 93 168 - wdt->state = 0; 169 - wdt->timer_margin = 30; 170 - wdt->miscdev.parent = &pdev->dev; 171 - wdt->miscdev.fops = &twl4030_wdt_fops; 172 - wdt->miscdev.minor = WATCHDOG_MINOR; 173 - wdt->miscdev.name = "watchdog"; 94 + wdt->info = &twl4030_wdt_info; 95 + wdt->ops = &twl4030_wdt_ops; 96 + wdt->status = 0; 97 + wdt->timeout = 30; 98 + wdt->min_timeout = 1; 99 + wdt->max_timeout = 30; 174 100 101 + watchdog_set_nowayout(wdt, nowayout); 175 102 platform_set_drvdata(pdev, wdt); 176 103 177 - twl4030_wdt_dev = pdev; 104 + twl4030_wdt_stop(wdt); 178 105 179 - twl4030_wdt_disable(wdt); 180 - 181 - ret = misc_register(&wdt->miscdev); 106 + ret = watchdog_register_device(wdt); 182 107 if (ret) { 183 - dev_err(wdt->miscdev.parent, 184 - "Failed to register misc device\n"); 185 108 platform_set_drvdata(pdev, NULL); 186 - kfree(wdt); 187 - twl4030_wdt_dev = NULL; 188 109 return ret; 189 110 } 111 + 190 112 return 0; 191 113 } 192 114 193 115 static int twl4030_wdt_remove(struct platform_device *pdev) 194 116 { 195 - struct twl4030_wdt *wdt = platform_get_drvdata(pdev); 117 + struct watchdog_device *wdt = platform_get_drvdata(pdev); 196 118 197 - if (wdt->state & TWL4030_WDT_STATE_ACTIVE) 198 - if (twl4030_wdt_disable(wdt)) 199 - return -EFAULT; 200 - 201 - wdt->state &= ~TWL4030_WDT_STATE_ACTIVE; 202 - misc_deregister(&wdt->miscdev); 203 - 119 + watchdog_unregister_device(wdt); 204 120 platform_set_drvdata(pdev, NULL); 205 - kfree(wdt); 206 - twl4030_wdt_dev = NULL; 207 121 208 122 return 0; 209 123 } ··· 111 225 #ifdef CONFIG_PM 112 226 static int twl4030_wdt_suspend(struct platform_device *pdev, pm_message_t state) 113 227 { 114 - struct twl4030_wdt *wdt = platform_get_drvdata(pdev); 115 - if (wdt->state & TWL4030_WDT_STATE_ACTIVE) 116 - return twl4030_wdt_disable(wdt); 228 + struct watchdog_device *wdt = platform_get_drvdata(pdev); 229 + if (watchdog_active(wdt)) 230 + return twl4030_wdt_stop(wdt); 117 231 118 232 return 0; 119 233 } 120 234 121 235 static int twl4030_wdt_resume(struct platform_device *pdev) 122 236 { 123 - struct twl4030_wdt *wdt = platform_get_drvdata(pdev); 124 - if (wdt->state & TWL4030_WDT_STATE_ACTIVE) 125 - return twl4030_wdt_enable(wdt); 237 + struct watchdog_device *wdt = platform_get_drvdata(pdev); 238 + if (watchdog_active(wdt)) 239 + return twl4030_wdt_start(wdt); 126 240 127 241 return 0; 128 242 } ··· 146 260 147 261 MODULE_AUTHOR("Nokia Corporation"); 148 262 MODULE_LICENSE("GPL"); 149 - MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 150 263 MODULE_ALIAS("platform:twl4030_wdt"); 151 264
+1 -1
include/linux/watchdog.h
··· 129 129 return wdd->driver_data; 130 130 } 131 131 132 - /* drivers/watchdog/core/watchdog_core.c */ 132 + /* drivers/watchdog/watchdog_core.c */ 133 133 extern int watchdog_register_device(struct watchdog_device *); 134 134 extern void watchdog_unregister_device(struct watchdog_device *); 135 135