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 contains:
- fixes and improvements
- devicetree bindings
- conversion to watchdog generic framework of the following drivers:
- booke_wdt
- bcm47xx_wdt.c
- at91sam9_wdt
- Removal of old STMP3xxx driver
- Addition of following new drivers:
- new driver for STMP3xxx and i.MX23/28
- Retu watchdog driver"

* git://www.linux-watchdog.org/linux-watchdog: (30 commits)
watchdog: sp805_wdt depends on ARM
watchdog: davinci_wdt: update to devm_* API
watchdog: davinci_wdt: use devm managed clk get
watchdog: at91rm9200: add DT support
watchdog: add timeout-sec property binding
watchdog: at91sam9_wdt: Convert to use the watchdog framework
watchdog: omap_wdt: Add option nowayout
watchdog: core: dt: add support for the timeout-sec dt property
watchdog: bcm47xx_wdt.c: add hard timer
watchdog: bcm47xx_wdt.c: rename wdt_time to timeout
watchdog: bcm47xx_wdt.c: rename ops methods
watchdog: bcm47xx_wdt.c: use platform device
watchdog: bcm47xx_wdt.c: convert to watchdog core api
watchdog: Convert BookE watchdog driver to watchdog infrastructure
watchdog: s3c2410_wdt: Use devm_* functions
watchdog: remove old STMP3xxx driver
watchdog: add new driver for STMP3xxx and i.MX23/28
rtc: stmp3xxx: add wdt-accessor function
watchdog: introduce retu_wdt driver
watchdog: intel_scu_watchdog: fix Kconfig dependency
...

+912 -880
+9
Documentation/devicetree/bindings/watchdog/atmel-at91rm9200-wdt.txt
··· 1 + Atmel AT91RM9200 System Timer Watchdog 2 + 3 + Required properties: 4 + - compatible: must be "atmel,at91sam9260-wdt". 5 + 6 + Example: 7 + watchdog@fffffd00 { 8 + compatible = "atmel,at91rm9200-wdt"; 9 + };
+4
Documentation/devicetree/bindings/watchdog/atmel-wdt.txt
··· 7 7 - reg: physical base address of the controller and length of memory mapped 8 8 region. 9 9 10 + Optional properties: 11 + - timeout-sec: contains the watchdog timeout in seconds. 12 + 10 13 Example: 11 14 12 15 watchdog@fffffd40 { 13 16 compatible = "atmel,at91sam9260-wdt"; 14 17 reg = <0xfffffd40 0x10>; 18 + timeout-sec = <10>; 15 19 };
+5
Documentation/devicetree/bindings/watchdog/marvel.txt
··· 5 5 - Compatibility : "marvell,orion-wdt" 6 6 - reg : Address of the timer registers 7 7 8 + Optional properties: 9 + 10 + - timeout-sec : Contains the watchdog timeout in seconds 11 + 8 12 Example: 9 13 10 14 wdt@20300 { 11 15 compatible = "marvell,orion-wdt"; 12 16 reg = <0x20300 0x28>; 17 + timeout-sec = <10>; 13 18 status = "okay"; 14 19 };
+4
Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt
··· 5 5 - reg: physical base address of the controller and length of memory mapped 6 6 region. 7 7 8 + Optional properties: 9 + - timeout-sec: contains the watchdog timeout in seconds. 10 + 8 11 Example: 9 12 10 13 watchdog@4003C000 { 11 14 compatible = "nxp,pnx4008-wdt"; 12 15 reg = <0x4003C000 0x1000>; 16 + timeout-sec = <10>; 13 17 };
+13
Documentation/devicetree/bindings/watchdog/qca-ar7130-wdt.txt
··· 1 + * Qualcomm Atheros AR7130 Watchdog Timer (WDT) Controller 2 + 3 + Required properties: 4 + - compatible: must be "qca,ar7130-wdt" 5 + - reg: physical base address of the controller and length of memory mapped 6 + region. 7 + 8 + Example: 9 + 10 + wdt@18060008 { 11 + compatible = "qca,ar9330-wdt", "qca,ar7130-wdt"; 12 + reg = <0x18060008 0x8>; 13 + };
+3
Documentation/devicetree/bindings/watchdog/samsung-wdt.txt
··· 9 9 - reg : base physical address of the controller and length of memory mapped 10 10 region. 11 11 - interrupts : interrupt number to the cpu. 12 + 13 + Optional properties: 14 + - timeout-sec : contains the watchdog timeout in seconds.
+13 -1
Documentation/watchdog/watchdog-kernel-api.txt
··· 1 1 The Linux WatchDog Timer Driver Core kernel API. 2 2 =============================================== 3 - Last reviewed: 22-May-2012 3 + Last reviewed: 12-Feb-2013 4 4 5 5 Wim Van Sebroeck <wim@iguana.be> 6 6 ··· 212 212 The watchdog_get_drvdata function allows you to retrieve driver specific data. 213 213 The argument of this function is the watchdog device where you want to retrieve 214 214 data from. The function returns the pointer to the driver specific data. 215 + 216 + To initialize the timeout field, the following function can be used: 217 + 218 + extern int watchdog_init_timeout(struct watchdog_device *wdd, 219 + unsigned int timeout_parm, struct device *dev); 220 + 221 + The watchdog_init_timeout function allows you to initialize the timeout field 222 + using the module timeout parameter or by retrieving the timeout-sec property from 223 + the device tree (if the module timeout parameter is invalid). Best practice is 224 + to set the default timeout value as timeout value in the watchdog_device and 225 + then use this function to set the user "preferred" timeout value. 226 + This routine returns zero on success and a negative errno code for failure.
+9 -6
arch/mips/ath79/dev-common.c
··· 102 102 } 103 103 } 104 104 105 - static struct platform_device ath79_wdt_device = { 106 - .name = "ath79-wdt", 107 - .id = -1, 108 - }; 109 - 110 105 void __init ath79_register_wdt(void) 111 106 { 112 - platform_device_register(&ath79_wdt_device); 107 + struct resource res; 108 + 109 + memset(&res, 0, sizeof(res)); 110 + 111 + res.flags = IORESOURCE_MEM; 112 + res.start = AR71XX_RESET_BASE + AR71XX_RESET_REG_WDOG_CTRL; 113 + res.end = res.start + 0x8 - 1; 114 + 115 + platform_device_register_simple("ath79-wdt", -1, &res, 1); 113 116 }
+64
drivers/rtc/rtc-stmp3xxx.c
··· 27 27 #include <linux/slab.h> 28 28 #include <linux/of_device.h> 29 29 #include <linux/of.h> 30 + #include <linux/stmp_device.h> 31 + #include <linux/stmp3xxx_rtc_wdt.h> 30 32 31 33 #include <mach/common.h> 32 34 ··· 38 36 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001 39 37 #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002 40 38 #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004 39 + #define STMP3XXX_RTC_CTRL_WATCHDOGEN 0x00000010 41 40 42 41 #define STMP3XXX_RTC_STAT 0x10 43 42 #define STMP3XXX_RTC_STAT_STALE_SHIFT 16 ··· 48 45 49 46 #define STMP3XXX_RTC_ALARM 0x40 50 47 48 + #define STMP3XXX_RTC_WATCHDOG 0x50 49 + 51 50 #define STMP3XXX_RTC_PERSISTENT0 0x60 52 51 #define STMP3XXX_RTC_PERSISTENT0_SET 0x64 53 52 #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68 ··· 57 52 #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004 58 53 #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080 59 54 55 + #define STMP3XXX_RTC_PERSISTENT1 0x70 56 + /* missing bitmask in headers */ 57 + #define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000 58 + 60 59 struct stmp3xxx_rtc_data { 61 60 struct rtc_device *rtc; 62 61 void __iomem *io; 63 62 int irq_alarm; 64 63 }; 64 + 65 + #if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG) 66 + /** 67 + * stmp3xxx_wdt_set_timeout - configure the watchdog inside the STMP3xxx RTC 68 + * @dev: the parent device of the watchdog (= the RTC) 69 + * @timeout: the desired value for the timeout register of the watchdog. 70 + * 0 disables the watchdog 71 + * 72 + * The watchdog needs one register and two bits which are in the RTC domain. 73 + * To handle the resource conflict, the RTC driver will create another 74 + * platform_device for the watchdog driver as a child of the RTC device. 75 + * The watchdog driver is passed the below accessor function via platform_data 76 + * to configure the watchdog. Locking is not needed because accessing SET/CLR 77 + * registers is atomic. 78 + */ 79 + 80 + static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout) 81 + { 82 + struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); 83 + 84 + if (timeout) { 85 + writel(timeout, rtc_data->io + STMP3XXX_RTC_WATCHDOG); 86 + writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, 87 + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET); 88 + writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, 89 + rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET); 90 + } else { 91 + writel(STMP3XXX_RTC_CTRL_WATCHDOGEN, 92 + rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR); 93 + writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER, 94 + rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR); 95 + } 96 + } 97 + 98 + static struct stmp3xxx_wdt_pdata wdt_pdata = { 99 + .wdt_set_timeout = stmp3xxx_wdt_set_timeout, 100 + }; 101 + 102 + static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) 103 + { 104 + struct platform_device *wdt_pdev = 105 + platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id); 106 + 107 + if (wdt_pdev) { 108 + wdt_pdev->dev.parent = &rtc_pdev->dev; 109 + wdt_pdev->dev.platform_data = &wdt_pdata; 110 + platform_device_add(wdt_pdev); 111 + } 112 + } 113 + #else 114 + static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev) 115 + { 116 + } 117 + #endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */ 65 118 66 119 static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) 67 120 { ··· 296 233 goto out_irq_alarm; 297 234 } 298 235 236 + stmp3xxx_wdt_register(pdev); 299 237 return 0; 300 238 301 239 out_irq_alarm:
+26 -9
drivers/watchdog/Kconfig
··· 79 79 config DA9055_WATCHDOG 80 80 tristate "Dialog Semiconductor DA9055 Watchdog" 81 81 depends on MFD_DA9055 82 + select WATCHDOG_CORE 82 83 help 83 84 If you say yes here you get support for watchdog on the Dialog 84 85 Semiconductor DA9055 PMIC. ··· 109 108 110 109 config ARM_SP805_WATCHDOG 111 110 tristate "ARM SP805 Watchdog" 112 - depends on ARM_AMBA 111 + depends on ARM && ARM_AMBA 113 112 select WATCHDOG_CORE 114 113 help 115 114 ARM Primecell SP805 Watchdog timer. This will reboot your system when ··· 117 116 118 117 config AT91RM9200_WATCHDOG 119 118 tristate "AT91RM9200 watchdog" 120 - depends on ARCH_AT91RM9200 119 + depends on ARCH_AT91 121 120 help 122 121 Watchdog timer embedded into AT91RM9200 chips. This will reboot your 123 122 system when the timeout is reached. ··· 125 124 config AT91SAM9X_WATCHDOG 126 125 tristate "AT91SAM9X / AT91CAP9 watchdog" 127 126 depends on ARCH_AT91 && !ARCH_AT91RM9200 127 + select WATCHDOG_CORE 128 128 help 129 129 Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will 130 130 reboot your system when the timeout is reached. ··· 318 316 Support for TI TWL4030 watchdog. Say 'Y' here to enable the 319 317 watchdog timer support for TWL4030 chips. 320 318 321 - config STMP3XXX_WATCHDOG 322 - tristate "Freescale STMP3XXX watchdog" 323 - depends on ARCH_STMP3XXX 319 + config STMP3XXX_RTC_WATCHDOG 320 + tristate "Freescale STMP3XXX & i.MX23/28 watchdog" 321 + depends on RTC_DRV_STMP 322 + select WATCHDOG_CORE 324 323 help 325 - Say Y here if to include support for the watchdog timer 326 - for the Sigmatel STMP37XX/378X SoC. 324 + Say Y here to include support for the watchdog timer inside 325 + the RTC for the STMP37XX/378X or i.MX23/28 SoC. 327 326 To compile this driver as a module, choose M here: the 328 - module will be called stmp3xxx_wdt. 327 + module will be called stmp3xxx_rtc_wdt. 329 328 330 329 config NUC900_WATCHDOG 331 330 tristate "Nuvoton NUC900 watchdog" ··· 378 375 379 376 To compile this driver as a module, choose M here: the 380 377 module will be called ux500_wdt. 378 + 379 + config RETU_WATCHDOG 380 + tristate "Retu watchdog" 381 + depends on MFD_RETU 382 + select WATCHDOG_CORE 383 + help 384 + Retu watchdog driver for Nokia Internet Tablets (770, N800, 385 + N810). At least on N800 the watchdog cannot be disabled, so 386 + this driver is essential and you should enable it. 387 + 388 + To compile this driver as a module, choose M here: the 389 + module will be called retu_wdt. 381 390 382 391 # AVR32 Architecture 383 392 ··· 608 593 609 594 config INTEL_SCU_WATCHDOG 610 595 bool "Intel SCU Watchdog for Mobile Platforms" 611 - depends on X86_MRST 596 + depends on X86_INTEL_MID 612 597 ---help--- 613 598 Hardware driver for the watchdog time built into the Intel SCU 614 599 for Intel Mobile Platforms. ··· 998 983 config BCM47XX_WDT 999 984 tristate "Broadcom BCM47xx Watchdog Timer" 1000 985 depends on BCM47XX 986 + select WATCHDOG_CORE 1001 987 help 1002 988 Hardware driver for the Broadcom BCM47xx Watchdog Timer. 1003 989 ··· 1147 1131 config BOOKE_WDT 1148 1132 tristate "PowerPC Book-E Watchdog Timer" 1149 1133 depends on BOOKE || 4xx 1134 + select WATCHDOG_CORE 1150 1135 ---help--- 1151 1136 Watchdog driver for PowerPC Book-E chips, such as the Freescale 1152 1137 MPC85xx SOCs and the IBM PowerPC 440.
+2 -1
drivers/watchdog/Makefile
··· 48 48 obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o 49 49 obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o 50 50 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o 51 - obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o 51 + obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o 52 52 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o 53 53 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o 54 54 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o 55 55 obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o 56 + obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o 56 57 57 58 # AVR32 Architecture 58 59 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
+9
drivers/watchdog/at91rm9200_wdt.c
··· 24 24 #include <linux/types.h> 25 25 #include <linux/watchdog.h> 26 26 #include <linux/uaccess.h> 27 + #include <linux/of.h> 28 + #include <linux/of_device.h> 27 29 #include <mach/at91_st.h> 28 30 29 31 #define WDT_DEFAULT_TIME 5 /* seconds */ ··· 254 252 #define at91wdt_resume NULL 255 253 #endif 256 254 255 + static const struct of_device_id at91_wdt_dt_ids[] = { 256 + { .compatible = "atmel,at91rm9200-wdt" }, 257 + { /* sentinel */ } 258 + }; 259 + MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids); 260 + 257 261 static struct platform_driver at91wdt_driver = { 258 262 .probe = at91wdt_probe, 259 263 .remove = at91wdt_remove, ··· 269 261 .driver = { 270 262 .name = "at91_wdt", 271 263 .owner = THIS_MODULE, 264 + .of_match_table = of_match_ptr(at91_wdt_dt_ids), 272 265 }, 273 266 }; 274 267
+47 -123
drivers/watchdog/at91sam9_wdt.c
··· 18 18 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 19 20 20 #include <linux/errno.h> 21 - #include <linux/fs.h> 22 21 #include <linux/init.h> 23 22 #include <linux/io.h> 24 23 #include <linux/kernel.h> 25 - #include <linux/miscdevice.h> 26 24 #include <linux/module.h> 27 25 #include <linux/moduleparam.h> 28 26 #include <linux/platform_device.h> ··· 56 58 57 59 /* User land timeout */ 58 60 #define WDT_HEARTBEAT 15 59 - static int heartbeat = WDT_HEARTBEAT; 61 + static int heartbeat; 60 62 module_param(heartbeat, int, 0); 61 63 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. " 62 64 "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")"); ··· 66 68 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 67 69 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 68 70 71 + static struct watchdog_device at91_wdt_dev; 69 72 static void at91_ping(unsigned long data); 70 73 71 74 static struct { 72 75 void __iomem *base; 73 76 unsigned long next_heartbeat; /* the next_heartbeat for the timer */ 74 - unsigned long open; 75 - char expect_close; 76 77 struct timer_list timer; /* The timer that pings the watchdog */ 77 78 } at91wdt_private; 78 79 79 80 /* ......................................................................... */ 80 - 81 81 82 82 /* 83 83 * Reload the watchdog timer. (ie, pat the watchdog) ··· 91 95 static void at91_ping(unsigned long data) 92 96 { 93 97 if (time_before(jiffies, at91wdt_private.next_heartbeat) || 94 - (!nowayout && !at91wdt_private.open)) { 98 + (!watchdog_active(&at91_wdt_dev))) { 95 99 at91_wdt_reset(); 96 100 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); 97 101 } else 98 102 pr_crit("I will reset your machine !\n"); 99 103 } 100 104 101 - /* 102 - * Watchdog device is opened, and watchdog starts running. 103 - */ 104 - static int at91_wdt_open(struct inode *inode, struct file *file) 105 + static int at91_wdt_ping(struct watchdog_device *wdd) 105 106 { 106 - if (test_and_set_bit(0, &at91wdt_private.open)) 107 - return -EBUSY; 108 - 109 - at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; 110 - mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); 111 - 112 - return nonseekable_open(inode, file); 107 + /* calculate when the next userspace timeout will be */ 108 + at91wdt_private.next_heartbeat = jiffies + wdd->timeout * HZ; 109 + return 0; 113 110 } 114 111 115 - /* 116 - * Close the watchdog device. 117 - */ 118 - static int at91_wdt_close(struct inode *inode, struct file *file) 112 + static int at91_wdt_start(struct watchdog_device *wdd) 119 113 { 120 - clear_bit(0, &at91wdt_private.open); 114 + /* calculate the next userspace timeout and modify the timer */ 115 + at91_wdt_ping(wdd); 116 + mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); 117 + return 0; 118 + } 121 119 122 - /* stop internal ping */ 123 - if (!at91wdt_private.expect_close) 124 - del_timer(&at91wdt_private.timer); 120 + static int at91_wdt_stop(struct watchdog_device *wdd) 121 + { 122 + /* The watchdog timer hardware can not be stopped... */ 123 + return 0; 124 + } 125 125 126 - at91wdt_private.expect_close = 0; 126 + static int at91_wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout) 127 + { 128 + wdd->timeout = new_timeout; 127 129 return 0; 128 130 } 129 131 ··· 157 163 return 0; 158 164 } 159 165 166 + /* ......................................................................... */ 167 + 160 168 static const struct watchdog_info at91_wdt_info = { 161 169 .identity = DRV_NAME, 162 170 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | 163 171 WDIOF_MAGICCLOSE, 164 172 }; 165 173 166 - /* 167 - * Handle commands from user-space. 168 - */ 169 - static long at91_wdt_ioctl(struct file *file, 170 - unsigned int cmd, unsigned long arg) 171 - { 172 - void __user *argp = (void __user *)arg; 173 - int __user *p = argp; 174 - int new_value; 175 - 176 - switch (cmd) { 177 - case WDIOC_GETSUPPORT: 178 - return copy_to_user(argp, &at91_wdt_info, 179 - sizeof(at91_wdt_info)) ? -EFAULT : 0; 180 - 181 - case WDIOC_GETSTATUS: 182 - case WDIOC_GETBOOTSTATUS: 183 - return put_user(0, p); 184 - 185 - case WDIOC_KEEPALIVE: 186 - at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; 187 - return 0; 188 - 189 - case WDIOC_SETTIMEOUT: 190 - if (get_user(new_value, p)) 191 - return -EFAULT; 192 - 193 - heartbeat = new_value; 194 - at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; 195 - 196 - return put_user(new_value, p); /* return current value */ 197 - 198 - case WDIOC_GETTIMEOUT: 199 - return put_user(heartbeat, p); 200 - } 201 - return -ENOTTY; 202 - } 203 - 204 - /* 205 - * Pat the watchdog whenever device is written to. 206 - */ 207 - static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, 208 - loff_t *ppos) 209 - { 210 - if (!len) 211 - return 0; 212 - 213 - /* Scan for magic character */ 214 - if (!nowayout) { 215 - size_t i; 216 - 217 - at91wdt_private.expect_close = 0; 218 - 219 - for (i = 0; i < len; i++) { 220 - char c; 221 - if (get_user(c, data + i)) 222 - return -EFAULT; 223 - if (c == 'V') { 224 - at91wdt_private.expect_close = 42; 225 - break; 226 - } 227 - } 228 - } 229 - 230 - at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; 231 - 232 - return len; 233 - } 234 - 235 - /* ......................................................................... */ 236 - 237 - static const struct file_operations at91wdt_fops = { 238 - .owner = THIS_MODULE, 239 - .llseek = no_llseek, 240 - .unlocked_ioctl = at91_wdt_ioctl, 241 - .open = at91_wdt_open, 242 - .release = at91_wdt_close, 243 - .write = at91_wdt_write, 174 + static const struct watchdog_ops at91_wdt_ops = { 175 + .owner = THIS_MODULE, 176 + .start = at91_wdt_start, 177 + .stop = at91_wdt_stop, 178 + .ping = at91_wdt_ping, 179 + .set_timeout = at91_wdt_set_timeout, 244 180 }; 245 181 246 - static struct miscdevice at91wdt_miscdev = { 247 - .minor = WATCHDOG_MINOR, 248 - .name = "watchdog", 249 - .fops = &at91wdt_fops, 182 + static struct watchdog_device at91_wdt_dev = { 183 + .info = &at91_wdt_info, 184 + .ops = &at91_wdt_ops, 185 + .timeout = WDT_HEARTBEAT, 186 + .min_timeout = 1, 187 + .max_timeout = 0xFFFF, 250 188 }; 251 189 252 190 static int __init at91wdt_probe(struct platform_device *pdev) 253 191 { 254 192 struct resource *r; 255 193 int res; 256 - 257 - if (at91wdt_miscdev.parent) 258 - return -EBUSY; 259 - at91wdt_miscdev.parent = &pdev->dev; 260 194 261 195 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 262 196 if (!r) ··· 195 273 return -ENOMEM; 196 274 } 197 275 276 + at91_wdt_dev.parent = &pdev->dev; 277 + watchdog_init_timeout(&at91_wdt_dev, heartbeat, &pdev->dev); 278 + watchdog_set_nowayout(&at91_wdt_dev, nowayout); 279 + 198 280 /* Set watchdog */ 199 281 res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000)); 200 282 if (res) 201 283 return res; 202 284 203 - res = misc_register(&at91wdt_miscdev); 285 + res = watchdog_register_device(&at91_wdt_dev); 204 286 if (res) 205 287 return res; 206 288 207 - at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; 289 + at91wdt_private.next_heartbeat = jiffies + at91_wdt_dev.timeout * HZ; 208 290 setup_timer(&at91wdt_private.timer, at91_ping, 0); 209 291 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); 210 292 211 293 pr_info("enabled (heartbeat=%d sec, nowayout=%d)\n", 212 - heartbeat, nowayout); 294 + at91_wdt_dev.timeout, nowayout); 213 295 214 296 return 0; 215 297 } 216 298 217 299 static int __exit at91wdt_remove(struct platform_device *pdev) 218 300 { 219 - int res; 301 + watchdog_unregister_device(&at91_wdt_dev); 220 302 221 - res = misc_deregister(&at91wdt_miscdev); 222 - if (!res) 223 - at91wdt_miscdev.parent = NULL; 303 + pr_warn("I quit now, hardware will probably reboot!\n"); 304 + del_timer(&at91wdt_private.timer); 224 305 225 - return res; 306 + return 0; 226 307 } 227 308 228 309 #if defined(CONFIG_OF) 229 - static const struct of_device_id at91_wdt_dt_ids[] __initconst = { 310 + static const struct of_device_id at91_wdt_dt_ids[] = { 230 311 { .compatible = "atmel,at91sam9260-wdt" }, 231 312 { /* sentinel */ } 232 313 }; ··· 251 326 MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>"); 252 327 MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors"); 253 328 MODULE_LICENSE("GPL"); 254 - MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+51 -15
drivers/watchdog/ath79_wdt.c
··· 23 23 #include <linux/errno.h> 24 24 #include <linux/fs.h> 25 25 #include <linux/init.h> 26 + #include <linux/io.h> 26 27 #include <linux/kernel.h> 27 28 #include <linux/miscdevice.h> 28 29 #include <linux/module.h> ··· 33 32 #include <linux/watchdog.h> 34 33 #include <linux/clk.h> 35 34 #include <linux/err.h> 36 - 37 - #include <asm/mach-ath79/ath79.h> 38 - #include <asm/mach-ath79/ar71xx_regs.h> 35 + #include <linux/of.h> 36 + #include <linux/of_platform.h> 39 37 40 38 #define DRIVER_NAME "ath79-wdt" 41 39 42 40 #define WDT_TIMEOUT 15 /* seconds */ 41 + 42 + #define WDOG_REG_CTRL 0x00 43 + #define WDOG_REG_TIMER 0x04 43 44 44 45 #define WDOG_CTRL_LAST_RESET BIT(31) 45 46 #define WDOG_CTRL_ACTION_MASK 3 ··· 69 66 static unsigned long wdt_freq; 70 67 static int boot_status; 71 68 static int max_timeout; 69 + static void __iomem *wdt_base; 70 + 71 + static inline void ath79_wdt_wr(unsigned reg, u32 val) 72 + { 73 + iowrite32(val, wdt_base + reg); 74 + } 75 + 76 + static inline u32 ath79_wdt_rr(unsigned reg) 77 + { 78 + return ioread32(wdt_base + reg); 79 + } 72 80 73 81 static inline void ath79_wdt_keepalive(void) 74 82 { 75 - ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout); 83 + ath79_wdt_wr(WDOG_REG_TIMER, wdt_freq * timeout); 76 84 /* flush write */ 77 - ath79_reset_rr(AR71XX_RESET_REG_WDOG); 85 + ath79_wdt_rr(WDOG_REG_TIMER); 78 86 } 79 87 80 88 static inline void ath79_wdt_enable(void) 81 89 { 82 90 ath79_wdt_keepalive(); 83 - ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR); 91 + ath79_wdt_wr(WDOG_REG_CTRL, WDOG_CTRL_ACTION_FCR); 84 92 /* flush write */ 85 - ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); 93 + ath79_wdt_rr(WDOG_REG_CTRL); 86 94 } 87 95 88 96 static inline void ath79_wdt_disable(void) 89 97 { 90 - ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE); 98 + ath79_wdt_wr(WDOG_REG_CTRL, WDOG_CTRL_ACTION_NONE); 91 99 /* flush write */ 92 - ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); 100 + ath79_wdt_rr(WDOG_REG_CTRL); 93 101 } 94 102 95 103 static int ath79_wdt_set_timeout(int val) ··· 240 226 241 227 static int ath79_wdt_probe(struct platform_device *pdev) 242 228 { 229 + struct resource *res; 243 230 u32 ctrl; 244 231 int err; 245 232 246 - wdt_clk = clk_get(&pdev->dev, "wdt"); 233 + if (wdt_base) 234 + return -EBUSY; 235 + 236 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 237 + if (!res) { 238 + dev_err(&pdev->dev, "no memory resource found\n"); 239 + return -EINVAL; 240 + } 241 + 242 + wdt_base = devm_request_and_ioremap(&pdev->dev, res); 243 + if (!wdt_base) { 244 + dev_err(&pdev->dev, "unable to remap memory region\n"); 245 + return -ENOMEM; 246 + } 247 + 248 + wdt_clk = devm_clk_get(&pdev->dev, "wdt"); 247 249 if (IS_ERR(wdt_clk)) 248 250 return PTR_ERR(wdt_clk); 249 251 250 252 err = clk_enable(wdt_clk); 251 253 if (err) 252 - goto err_clk_put; 254 + return err; 253 255 254 256 wdt_freq = clk_get_rate(wdt_clk); 255 257 if (!wdt_freq) { ··· 281 251 max_timeout, timeout); 282 252 } 283 253 284 - ctrl = ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL); 254 + ctrl = ath79_wdt_rr(WDOG_REG_CTRL); 285 255 boot_status = (ctrl & WDOG_CTRL_LAST_RESET) ? WDIOF_CARDRESET : 0; 286 256 287 257 err = misc_register(&ath79_wdt_miscdev); ··· 295 265 296 266 err_clk_disable: 297 267 clk_disable(wdt_clk); 298 - err_clk_put: 299 - clk_put(wdt_clk); 300 268 return err; 301 269 } 302 270 ··· 302 274 { 303 275 misc_deregister(&ath79_wdt_miscdev); 304 276 clk_disable(wdt_clk); 305 - clk_put(wdt_clk); 306 277 return 0; 307 278 } 308 279 ··· 310 283 ath79_wdt_disable(); 311 284 } 312 285 286 + #ifdef CONFIG_OF 287 + static const struct of_device_id ath79_wdt_match[] = { 288 + { .compatible = "qca,ar7130-wdt" }, 289 + {}, 290 + }; 291 + MODULE_DEVICE_TABLE(of, ath79_wdt_match); 292 + #endif 293 + 313 294 static struct platform_driver ath79_wdt_driver = { 314 295 .probe = ath79_wdt_probe, 315 296 .remove = ath79_wdt_remove, ··· 325 290 .driver = { 326 291 .name = DRIVER_NAME, 327 292 .owner = THIS_MODULE, 293 + .of_match_table = of_match_ptr(ath79_wdt_match), 328 294 }, 329 295 }; 330 296
+157 -208
drivers/watchdog/bcm47xx_wdt.c
··· 3 3 * 4 4 * Copyright (C) 2008 Aleksandar Radovanovic <biblbroks@sezampro.rs> 5 5 * Copyright (C) 2009 Matthieu CASTET <castet.matthieu@free.fr> 6 + * Copyright (C) 2012-2013 Hauke Mehrtens <hauke@hauke-m.de> 6 7 * 7 8 * This program is free software; you can redistribute it and/or 8 9 * modify it under the terms of the GNU General Public License ··· 13 12 14 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 14 15 + #include <linux/bcm47xx_wdt.h> 16 16 #include <linux/bitops.h> 17 17 #include <linux/errno.h> 18 - #include <linux/fs.h> 19 18 #include <linux/init.h> 20 19 #include <linux/kernel.h> 21 - #include <linux/miscdevice.h> 22 20 #include <linux/module.h> 23 21 #include <linux/moduleparam.h> 22 + #include <linux/platform_device.h> 24 23 #include <linux/reboot.h> 25 24 #include <linux/types.h> 26 - #include <linux/uaccess.h> 27 25 #include <linux/watchdog.h> 28 26 #include <linux/timer.h> 29 27 #include <linux/jiffies.h> 30 - #include <linux/ssb/ssb_embedded.h> 31 - #include <asm/mach-bcm47xx/bcm47xx.h> 32 28 33 29 #define DRV_NAME "bcm47xx_wdt" 34 30 35 31 #define WDT_DEFAULT_TIME 30 /* seconds */ 36 - #define WDT_MAX_TIME 255 /* seconds */ 32 + #define WDT_SOFTTIMER_MAX 255 /* seconds */ 33 + #define WDT_SOFTTIMER_THRESHOLD 60 /* seconds */ 37 34 38 - static int wdt_time = WDT_DEFAULT_TIME; 35 + static int timeout = WDT_DEFAULT_TIME; 39 36 static bool nowayout = WATCHDOG_NOWAYOUT; 40 37 41 - module_param(wdt_time, int, 0); 42 - MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default=" 38 + module_param(timeout, int, 0); 39 + MODULE_PARM_DESC(timeout, "Watchdog time in seconds. (default=" 43 40 __MODULE_STRING(WDT_DEFAULT_TIME) ")"); 44 41 45 - #ifdef CONFIG_WATCHDOG_NOWAYOUT 46 42 module_param(nowayout, bool, 0); 47 43 MODULE_PARM_DESC(nowayout, 48 44 "Watchdog cannot be stopped once started (default=" 49 45 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 50 - #endif 51 46 52 - static unsigned long bcm47xx_wdt_busy; 53 - static char expect_release; 54 - static struct timer_list wdt_timer; 55 - static atomic_t ticks; 56 - 57 - static inline void bcm47xx_wdt_hw_start(void) 47 + static inline struct bcm47xx_wdt *bcm47xx_wdt_get(struct watchdog_device *wdd) 58 48 { 59 - /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */ 60 - switch (bcm47xx_bus_type) { 61 - #ifdef CONFIG_BCM47XX_SSB 62 - case BCM47XX_BUS_TYPE_SSB: 63 - ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff); 64 - break; 65 - #endif 66 - #ifdef CONFIG_BCM47XX_BCMA 67 - case BCM47XX_BUS_TYPE_BCMA: 68 - bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 69 - 0xfffffff); 70 - break; 71 - #endif 72 - } 49 + return container_of(wdd, struct bcm47xx_wdt, wdd); 73 50 } 74 51 75 - static inline int bcm47xx_wdt_hw_stop(void) 52 + static int bcm47xx_wdt_hard_keepalive(struct watchdog_device *wdd) 76 53 { 77 - switch (bcm47xx_bus_type) { 78 - #ifdef CONFIG_BCM47XX_SSB 79 - case BCM47XX_BUS_TYPE_SSB: 80 - return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0); 81 - #endif 82 - #ifdef CONFIG_BCM47XX_BCMA 83 - case BCM47XX_BUS_TYPE_BCMA: 84 - bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0); 85 - return 0; 86 - #endif 87 - } 88 - return -EINVAL; 54 + struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); 55 + 56 + wdt->timer_set_ms(wdt, wdd->timeout * 1000); 57 + 58 + return 0; 89 59 } 90 60 91 - static void bcm47xx_timer_tick(unsigned long unused) 61 + static int bcm47xx_wdt_hard_start(struct watchdog_device *wdd) 92 62 { 93 - if (!atomic_dec_and_test(&ticks)) { 94 - bcm47xx_wdt_hw_start(); 95 - mod_timer(&wdt_timer, jiffies + HZ); 63 + return 0; 64 + } 65 + 66 + static int bcm47xx_wdt_hard_stop(struct watchdog_device *wdd) 67 + { 68 + struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); 69 + 70 + wdt->timer_set(wdt, 0); 71 + 72 + return 0; 73 + } 74 + 75 + static int bcm47xx_wdt_hard_set_timeout(struct watchdog_device *wdd, 76 + unsigned int new_time) 77 + { 78 + struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); 79 + u32 max_timer = wdt->max_timer_ms; 80 + 81 + if (new_time < 1 || new_time > max_timer / 1000) { 82 + pr_warn("timeout value must be 1<=x<=%d, using %d\n", 83 + max_timer / 1000, new_time); 84 + return -EINVAL; 85 + } 86 + 87 + wdd->timeout = new_time; 88 + return 0; 89 + } 90 + 91 + static struct watchdog_ops bcm47xx_wdt_hard_ops = { 92 + .owner = THIS_MODULE, 93 + .start = bcm47xx_wdt_hard_start, 94 + .stop = bcm47xx_wdt_hard_stop, 95 + .ping = bcm47xx_wdt_hard_keepalive, 96 + .set_timeout = bcm47xx_wdt_hard_set_timeout, 97 + }; 98 + 99 + static void bcm47xx_wdt_soft_timer_tick(unsigned long data) 100 + { 101 + struct bcm47xx_wdt *wdt = (struct bcm47xx_wdt *)data; 102 + u32 next_tick = min(wdt->wdd.timeout * 1000, wdt->max_timer_ms); 103 + 104 + if (!atomic_dec_and_test(&wdt->soft_ticks)) { 105 + wdt->timer_set_ms(wdt, next_tick); 106 + mod_timer(&wdt->soft_timer, jiffies + HZ); 96 107 } else { 97 108 pr_crit("Watchdog will fire soon!!!\n"); 98 109 } 99 110 } 100 111 101 - static inline void bcm47xx_wdt_pet(void) 112 + static int bcm47xx_wdt_soft_keepalive(struct watchdog_device *wdd) 102 113 { 103 - atomic_set(&ticks, wdt_time); 114 + struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); 115 + 116 + atomic_set(&wdt->soft_ticks, wdd->timeout); 117 + 118 + return 0; 104 119 } 105 120 106 - static void bcm47xx_wdt_start(void) 121 + static int bcm47xx_wdt_soft_start(struct watchdog_device *wdd) 107 122 { 108 - bcm47xx_wdt_pet(); 109 - bcm47xx_timer_tick(0); 123 + struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); 124 + 125 + bcm47xx_wdt_soft_keepalive(wdd); 126 + bcm47xx_wdt_soft_timer_tick((unsigned long)wdt); 127 + 128 + return 0; 110 129 } 111 130 112 - static void bcm47xx_wdt_pause(void) 131 + static int bcm47xx_wdt_soft_stop(struct watchdog_device *wdd) 113 132 { 114 - del_timer_sync(&wdt_timer); 115 - bcm47xx_wdt_hw_stop(); 133 + struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); 134 + 135 + del_timer_sync(&wdt->soft_timer); 136 + wdt->timer_set(wdt, 0); 137 + 138 + return 0; 116 139 } 117 140 118 - static void bcm47xx_wdt_stop(void) 141 + static int bcm47xx_wdt_soft_set_timeout(struct watchdog_device *wdd, 142 + unsigned int new_time) 119 143 { 120 - bcm47xx_wdt_pause(); 121 - } 122 - 123 - static int bcm47xx_wdt_settimeout(int new_time) 124 - { 125 - if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) 144 + if (new_time < 1 || new_time > WDT_SOFTTIMER_MAX) { 145 + pr_warn("timeout value must be 1<=x<=%d, using %d\n", 146 + WDT_SOFTTIMER_MAX, new_time); 126 147 return -EINVAL; 127 - 128 - wdt_time = new_time; 129 - return 0; 130 - } 131 - 132 - static int bcm47xx_wdt_open(struct inode *inode, struct file *file) 133 - { 134 - if (test_and_set_bit(0, &bcm47xx_wdt_busy)) 135 - return -EBUSY; 136 - 137 - bcm47xx_wdt_start(); 138 - return nonseekable_open(inode, file); 139 - } 140 - 141 - static int bcm47xx_wdt_release(struct inode *inode, struct file *file) 142 - { 143 - if (expect_release == 42) { 144 - bcm47xx_wdt_stop(); 145 - } else { 146 - pr_crit("Unexpected close, not stopping watchdog!\n"); 147 - bcm47xx_wdt_start(); 148 148 } 149 149 150 - clear_bit(0, &bcm47xx_wdt_busy); 151 - expect_release = 0; 150 + wdd->timeout = new_time; 152 151 return 0; 153 - } 154 - 155 - static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data, 156 - size_t len, loff_t *ppos) 157 - { 158 - if (len) { 159 - if (!nowayout) { 160 - size_t i; 161 - 162 - expect_release = 0; 163 - 164 - for (i = 0; i != len; i++) { 165 - char c; 166 - if (get_user(c, data + i)) 167 - return -EFAULT; 168 - if (c == 'V') 169 - expect_release = 42; 170 - } 171 - } 172 - bcm47xx_wdt_pet(); 173 - } 174 - return len; 175 152 } 176 153 177 154 static const struct watchdog_info bcm47xx_wdt_info = { ··· 159 180 WDIOF_MAGICCLOSE, 160 181 }; 161 182 162 - static long bcm47xx_wdt_ioctl(struct file *file, 163 - unsigned int cmd, unsigned long arg) 164 - { 165 - void __user *argp = (void __user *)arg; 166 - int __user *p = argp; 167 - int new_value, retval = -EINVAL; 168 - 169 - switch (cmd) { 170 - case WDIOC_GETSUPPORT: 171 - return copy_to_user(argp, &bcm47xx_wdt_info, 172 - sizeof(bcm47xx_wdt_info)) ? -EFAULT : 0; 173 - 174 - case WDIOC_GETSTATUS: 175 - case WDIOC_GETBOOTSTATUS: 176 - return put_user(0, p); 177 - 178 - case WDIOC_SETOPTIONS: 179 - if (get_user(new_value, p)) 180 - return -EFAULT; 181 - 182 - if (new_value & WDIOS_DISABLECARD) { 183 - bcm47xx_wdt_stop(); 184 - retval = 0; 185 - } 186 - 187 - if (new_value & WDIOS_ENABLECARD) { 188 - bcm47xx_wdt_start(); 189 - retval = 0; 190 - } 191 - 192 - return retval; 193 - 194 - case WDIOC_KEEPALIVE: 195 - bcm47xx_wdt_pet(); 196 - return 0; 197 - 198 - case WDIOC_SETTIMEOUT: 199 - if (get_user(new_value, p)) 200 - return -EFAULT; 201 - 202 - if (bcm47xx_wdt_settimeout(new_value)) 203 - return -EINVAL; 204 - 205 - bcm47xx_wdt_pet(); 206 - 207 - case WDIOC_GETTIMEOUT: 208 - return put_user(wdt_time, p); 209 - 210 - default: 211 - return -ENOTTY; 212 - } 213 - } 214 - 215 183 static int bcm47xx_wdt_notify_sys(struct notifier_block *this, 216 - unsigned long code, void *unused) 184 + unsigned long code, void *unused) 217 185 { 186 + struct bcm47xx_wdt *wdt; 187 + 188 + wdt = container_of(this, struct bcm47xx_wdt, notifier); 218 189 if (code == SYS_DOWN || code == SYS_HALT) 219 - bcm47xx_wdt_stop(); 190 + wdt->wdd.ops->stop(&wdt->wdd); 220 191 return NOTIFY_DONE; 221 192 } 222 193 223 - static const struct file_operations bcm47xx_wdt_fops = { 194 + static struct watchdog_ops bcm47xx_wdt_soft_ops = { 224 195 .owner = THIS_MODULE, 225 - .llseek = no_llseek, 226 - .unlocked_ioctl = bcm47xx_wdt_ioctl, 227 - .open = bcm47xx_wdt_open, 228 - .release = bcm47xx_wdt_release, 229 - .write = bcm47xx_wdt_write, 196 + .start = bcm47xx_wdt_soft_start, 197 + .stop = bcm47xx_wdt_soft_stop, 198 + .ping = bcm47xx_wdt_soft_keepalive, 199 + .set_timeout = bcm47xx_wdt_soft_set_timeout, 230 200 }; 231 201 232 - static struct miscdevice bcm47xx_wdt_miscdev = { 233 - .minor = WATCHDOG_MINOR, 234 - .name = "watchdog", 235 - .fops = &bcm47xx_wdt_fops, 236 - }; 237 - 238 - static struct notifier_block bcm47xx_wdt_notifier = { 239 - .notifier_call = bcm47xx_wdt_notify_sys, 240 - }; 241 - 242 - static int __init bcm47xx_wdt_init(void) 202 + static int bcm47xx_wdt_probe(struct platform_device *pdev) 243 203 { 244 204 int ret; 205 + bool soft; 206 + struct bcm47xx_wdt *wdt = dev_get_platdata(&pdev->dev); 245 207 246 - if (bcm47xx_wdt_hw_stop() < 0) 247 - return -ENODEV; 208 + if (!wdt) 209 + return -ENXIO; 248 210 249 - setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L); 211 + soft = wdt->max_timer_ms < WDT_SOFTTIMER_THRESHOLD * 1000; 250 212 251 - if (bcm47xx_wdt_settimeout(wdt_time)) { 252 - bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME); 253 - pr_info("wdt_time value must be 0 < wdt_time < %d, using %d\n", 254 - (WDT_MAX_TIME + 1), wdt_time); 213 + if (soft) { 214 + wdt->wdd.ops = &bcm47xx_wdt_soft_ops; 215 + setup_timer(&wdt->soft_timer, bcm47xx_wdt_soft_timer_tick, 216 + (long unsigned int)wdt); 217 + } else { 218 + wdt->wdd.ops = &bcm47xx_wdt_hard_ops; 255 219 } 256 220 257 - ret = register_reboot_notifier(&bcm47xx_wdt_notifier); 221 + wdt->wdd.info = &bcm47xx_wdt_info; 222 + wdt->wdd.timeout = WDT_DEFAULT_TIME; 223 + ret = wdt->wdd.ops->set_timeout(&wdt->wdd, timeout); 258 224 if (ret) 259 - return ret; 225 + goto err_timer; 226 + watchdog_set_nowayout(&wdt->wdd, nowayout); 260 227 261 - ret = misc_register(&bcm47xx_wdt_miscdev); 262 - if (ret) { 263 - unregister_reboot_notifier(&bcm47xx_wdt_notifier); 264 - return ret; 265 - } 228 + wdt->notifier.notifier_call = &bcm47xx_wdt_notify_sys; 266 229 267 - pr_info("BCM47xx Watchdog Timer enabled (%d seconds%s)\n", 268 - wdt_time, nowayout ? ", nowayout" : ""); 230 + ret = register_reboot_notifier(&wdt->notifier); 231 + if (ret) 232 + goto err_timer; 233 + 234 + ret = watchdog_register_device(&wdt->wdd); 235 + if (ret) 236 + goto err_notifier; 237 + 238 + dev_info(&pdev->dev, "BCM47xx Watchdog Timer enabled (%d seconds%s%s)\n", 239 + timeout, nowayout ? ", nowayout" : "", 240 + soft ? ", Software Timer" : ""); 241 + return 0; 242 + 243 + err_notifier: 244 + unregister_reboot_notifier(&wdt->notifier); 245 + err_timer: 246 + if (soft) 247 + del_timer_sync(&wdt->soft_timer); 248 + 249 + return ret; 250 + } 251 + 252 + static int bcm47xx_wdt_remove(struct platform_device *pdev) 253 + { 254 + struct bcm47xx_wdt *wdt = dev_get_platdata(&pdev->dev); 255 + 256 + if (!wdt) 257 + return -ENXIO; 258 + 259 + watchdog_unregister_device(&wdt->wdd); 260 + unregister_reboot_notifier(&wdt->notifier); 261 + 269 262 return 0; 270 263 } 271 264 272 - static void __exit bcm47xx_wdt_exit(void) 273 - { 274 - if (!nowayout) 275 - bcm47xx_wdt_stop(); 265 + static struct platform_driver bcm47xx_wdt_driver = { 266 + .driver = { 267 + .owner = THIS_MODULE, 268 + .name = "bcm47xx-wdt", 269 + }, 270 + .probe = bcm47xx_wdt_probe, 271 + .remove = bcm47xx_wdt_remove, 272 + }; 276 273 277 - misc_deregister(&bcm47xx_wdt_miscdev); 278 - 279 - unregister_reboot_notifier(&bcm47xx_wdt_notifier); 280 - } 281 - 282 - module_init(bcm47xx_wdt_init); 283 - module_exit(bcm47xx_wdt_exit); 274 + module_platform_driver(bcm47xx_wdt_driver); 284 275 285 276 MODULE_AUTHOR("Aleksandar Radovanovic"); 277 + MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>"); 286 278 MODULE_DESCRIPTION("Watchdog driver for Broadcom BCM47xx"); 287 279 MODULE_LICENSE("GPL"); 288 - MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+75 -130
drivers/watchdog/booke_wdt.c
··· 15 15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 16 16 17 17 #include <linux/module.h> 18 - #include <linux/fs.h> 19 18 #include <linux/smp.h> 20 - #include <linux/miscdevice.h> 21 - #include <linux/notifier.h> 22 19 #include <linux/watchdog.h> 23 - #include <linux/uaccess.h> 24 20 25 21 #include <asm/reg_booke.h> 26 22 #include <asm/time.h> ··· 41 45 #define WDTP_MASK (TCR_WP_MASK) 42 46 #endif 43 47 44 - static DEFINE_SPINLOCK(booke_wdt_lock); 48 + #ifdef CONFIG_PPC_FSL_BOOK3E 45 49 46 50 /* For the specified period, determine the number of seconds 47 51 * corresponding to the reset time. There will be a watchdog ··· 82 86 return 0; 83 87 } 84 88 89 + #define MAX_WDT_TIMEOUT period_to_sec(1) 90 + 91 + #else /* CONFIG_PPC_FSL_BOOK3E */ 92 + 93 + static unsigned long long period_to_sec(unsigned int period) 94 + { 95 + return period; 96 + } 97 + 98 + static unsigned int sec_to_period(unsigned int secs) 99 + { 100 + return secs; 101 + } 102 + 103 + #define MAX_WDT_TIMEOUT 3 /* from Kconfig */ 104 + 105 + #endif /* !CONFIG_PPC_FSL_BOOK3E */ 106 + 85 107 static void __booke_wdt_set(void *data) 86 108 { 87 109 u32 val; ··· 121 107 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); 122 108 } 123 109 124 - static void booke_wdt_ping(void) 110 + static int booke_wdt_ping(struct watchdog_device *wdog) 125 111 { 126 112 on_each_cpu(__booke_wdt_ping, NULL, 0); 113 + 114 + return 0; 127 115 } 128 116 129 117 static void __booke_wdt_enable(void *data) ··· 162 146 163 147 } 164 148 165 - static ssize_t booke_wdt_write(struct file *file, const char __user *buf, 166 - size_t count, loff_t *ppos) 149 + static void __booke_wdt_start(struct watchdog_device *wdog) 167 150 { 168 - booke_wdt_ping(); 169 - return count; 151 + on_each_cpu(__booke_wdt_enable, NULL, 0); 152 + pr_debug("watchdog enabled (timeout = %u sec)\n", wdog->timeout); 170 153 } 171 154 172 - static struct watchdog_info ident = { 155 + static int booke_wdt_start(struct watchdog_device *wdog) 156 + { 157 + if (booke_wdt_enabled == 0) { 158 + booke_wdt_enabled = 1; 159 + __booke_wdt_start(wdog); 160 + } 161 + return 0; 162 + } 163 + 164 + static int booke_wdt_stop(struct watchdog_device *wdog) 165 + { 166 + on_each_cpu(__booke_wdt_disable, NULL, 0); 167 + booke_wdt_enabled = 0; 168 + pr_debug("watchdog disabled\n"); 169 + 170 + return 0; 171 + } 172 + 173 + static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev, 174 + unsigned int timeout) 175 + { 176 + if (timeout > MAX_WDT_TIMEOUT) 177 + return -EINVAL; 178 + booke_wdt_period = sec_to_period(timeout); 179 + wdt_dev->timeout = timeout; 180 + booke_wdt_set(); 181 + 182 + return 0; 183 + } 184 + 185 + static struct watchdog_info booke_wdt_info = { 173 186 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 174 187 .identity = "PowerPC Book-E Watchdog", 175 188 }; 176 189 177 - static long booke_wdt_ioctl(struct file *file, 178 - unsigned int cmd, unsigned long arg) 179 - { 180 - u32 tmp = 0; 181 - u32 __user *p = (u32 __user *)arg; 182 - 183 - switch (cmd) { 184 - case WDIOC_GETSUPPORT: 185 - return copy_to_user(p, &ident, sizeof(ident)) ? -EFAULT : 0; 186 - case WDIOC_GETSTATUS: 187 - return put_user(0, p); 188 - case WDIOC_GETBOOTSTATUS: 189 - /* XXX: something is clearing TSR */ 190 - tmp = mfspr(SPRN_TSR) & TSR_WRS(3); 191 - /* returns CARDRESET if last reset was caused by the WDT */ 192 - return put_user((tmp ? WDIOF_CARDRESET : 0), p); 193 - case WDIOC_SETOPTIONS: 194 - if (get_user(tmp, p)) 195 - return -EFAULT; 196 - if (tmp == WDIOS_ENABLECARD) { 197 - booke_wdt_ping(); 198 - break; 199 - } else 200 - return -EINVAL; 201 - return 0; 202 - case WDIOC_KEEPALIVE: 203 - booke_wdt_ping(); 204 - return 0; 205 - case WDIOC_SETTIMEOUT: 206 - if (get_user(tmp, p)) 207 - return -EFAULT; 208 - #ifdef CONFIG_PPC_FSL_BOOK3E 209 - /* period of 1 gives the largest possible timeout */ 210 - if (tmp > period_to_sec(1)) 211 - return -EINVAL; 212 - booke_wdt_period = sec_to_period(tmp); 213 - #else 214 - booke_wdt_period = tmp; 215 - #endif 216 - booke_wdt_set(); 217 - /* Fall */ 218 - case WDIOC_GETTIMEOUT: 219 - #ifdef CONFIG_FSL_BOOKE 220 - return put_user(period_to_sec(booke_wdt_period), p); 221 - #else 222 - return put_user(booke_wdt_period, p); 223 - #endif 224 - default: 225 - return -ENOTTY; 226 - } 227 - 228 - return 0; 229 - } 230 - 231 - /* wdt_is_active stores whether or not the /dev/watchdog device is opened */ 232 - static unsigned long wdt_is_active; 233 - 234 - static int booke_wdt_open(struct inode *inode, struct file *file) 235 - { 236 - /* /dev/watchdog can only be opened once */ 237 - if (test_and_set_bit(0, &wdt_is_active)) 238 - return -EBUSY; 239 - 240 - spin_lock(&booke_wdt_lock); 241 - if (booke_wdt_enabled == 0) { 242 - booke_wdt_enabled = 1; 243 - on_each_cpu(__booke_wdt_enable, NULL, 0); 244 - pr_debug("watchdog enabled (timeout = %llu sec)\n", 245 - period_to_sec(booke_wdt_period)); 246 - } 247 - spin_unlock(&booke_wdt_lock); 248 - 249 - return nonseekable_open(inode, file); 250 - } 251 - 252 - static int booke_wdt_release(struct inode *inode, struct file *file) 253 - { 254 - #ifndef CONFIG_WATCHDOG_NOWAYOUT 255 - /* Normally, the watchdog is disabled when /dev/watchdog is closed, but 256 - * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the 257 - * watchdog should remain enabled. So we disable it only if 258 - * CONFIG_WATCHDOG_NOWAYOUT is not defined. 259 - */ 260 - on_each_cpu(__booke_wdt_disable, NULL, 0); 261 - booke_wdt_enabled = 0; 262 - pr_debug("watchdog disabled\n"); 263 - #endif 264 - 265 - clear_bit(0, &wdt_is_active); 266 - 267 - return 0; 268 - } 269 - 270 - static const struct file_operations booke_wdt_fops = { 190 + static struct watchdog_ops booke_wdt_ops = { 271 191 .owner = THIS_MODULE, 272 - .llseek = no_llseek, 273 - .write = booke_wdt_write, 274 - .unlocked_ioctl = booke_wdt_ioctl, 275 - .open = booke_wdt_open, 276 - .release = booke_wdt_release, 192 + .start = booke_wdt_start, 193 + .stop = booke_wdt_stop, 194 + .ping = booke_wdt_ping, 195 + .set_timeout = booke_wdt_set_timeout, 277 196 }; 278 197 279 - static struct miscdevice booke_wdt_miscdev = { 280 - .minor = WATCHDOG_MINOR, 281 - .name = "watchdog", 282 - .fops = &booke_wdt_fops, 198 + static struct watchdog_device booke_wdt_dev = { 199 + .info = &booke_wdt_info, 200 + .ops = &booke_wdt_ops, 201 + .min_timeout = 1, 202 + .max_timeout = 0xFFFF 283 203 }; 284 204 285 205 static void __exit booke_wdt_exit(void) 286 206 { 287 - misc_deregister(&booke_wdt_miscdev); 207 + watchdog_unregister_device(&booke_wdt_dev); 288 208 } 289 209 290 210 static int __init booke_wdt_init(void) 291 211 { 292 212 int ret = 0; 213 + bool nowayout = WATCHDOG_NOWAYOUT; 293 214 294 215 pr_info("powerpc book-e watchdog driver loaded\n"); 295 - ident.firmware_version = cur_cpu_spec->pvr_value; 216 + booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value; 217 + booke_wdt_set_timeout(&booke_wdt_dev, 218 + period_to_sec(CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT)); 219 + watchdog_set_nowayout(&booke_wdt_dev, nowayout); 220 + if (booke_wdt_enabled) 221 + __booke_wdt_start(&booke_wdt_dev); 296 222 297 - ret = misc_register(&booke_wdt_miscdev); 298 - if (ret) { 299 - pr_err("cannot register device (minor=%u, ret=%i)\n", 300 - WATCHDOG_MINOR, ret); 301 - return ret; 302 - } 303 - 304 - spin_lock(&booke_wdt_lock); 305 - if (booke_wdt_enabled == 1) { 306 - pr_info("watchdog enabled (timeout = %llu sec)\n", 307 - period_to_sec(booke_wdt_period)); 308 - on_each_cpu(__booke_wdt_enable, NULL, 0); 309 - } 310 - spin_unlock(&booke_wdt_lock); 223 + ret = watchdog_register_device(&booke_wdt_dev); 311 224 312 225 return ret; 313 226 }
+6 -23
drivers/watchdog/davinci_wdt.c
··· 69 69 #define WDT_REGION_INITED 2 70 70 #define WDT_DEVICE_INITED 3 71 71 72 - static struct resource *wdt_mem; 73 72 static void __iomem *wdt_base; 74 73 struct clk *wdt_clk; 75 74 ··· 200 201 201 202 static int davinci_wdt_probe(struct platform_device *pdev) 202 203 { 203 - int ret = 0, size; 204 + int ret = 0; 204 205 struct device *dev = &pdev->dev; 206 + struct resource *wdt_mem; 205 207 206 - wdt_clk = clk_get(dev, NULL); 208 + wdt_clk = devm_clk_get(dev, NULL); 207 209 if (WARN_ON(IS_ERR(wdt_clk))) 208 210 return PTR_ERR(wdt_clk); 209 211 ··· 221 221 return -ENOENT; 222 222 } 223 223 224 - size = resource_size(wdt_mem); 225 - if (!request_mem_region(wdt_mem->start, size, pdev->name)) { 226 - dev_err(dev, "failed to get memory region\n"); 227 - return -ENOENT; 228 - } 229 - 230 - wdt_base = ioremap(wdt_mem->start, size); 224 + wdt_base = devm_request_and_ioremap(dev, wdt_mem); 231 225 if (!wdt_base) { 232 - dev_err(dev, "failed to map memory region\n"); 233 - release_mem_region(wdt_mem->start, size); 234 - wdt_mem = NULL; 235 - return -ENOMEM; 226 + dev_err(dev, "ioremap failed\n"); 227 + return -EADDRNOTAVAIL; 236 228 } 237 229 238 230 ret = misc_register(&davinci_wdt_miscdev); 239 231 if (ret < 0) { 240 232 dev_err(dev, "cannot register misc device\n"); 241 - release_mem_region(wdt_mem->start, size); 242 - wdt_mem = NULL; 243 233 } else { 244 234 set_bit(WDT_DEVICE_INITED, &wdt_status); 245 235 } 246 236 247 - iounmap(wdt_base); 248 237 return ret; 249 238 } 250 239 251 240 static int davinci_wdt_remove(struct platform_device *pdev) 252 241 { 253 242 misc_deregister(&davinci_wdt_miscdev); 254 - if (wdt_mem) { 255 - release_mem_region(wdt_mem->start, resource_size(wdt_mem)); 256 - wdt_mem = NULL; 257 - } 258 - 259 243 clk_disable_unprepare(wdt_clk); 260 - clk_put(wdt_clk); 261 244 262 245 return 0; 263 246 }
+1
drivers/watchdog/gef_wdt.c
··· 310 310 .of_match_table = gef_wdt_ids, 311 311 }, 312 312 .probe = gef_wdt_probe, 313 + .remove = gef_wdt_remove, 313 314 }; 314 315 315 316 static int __init gef_wdt_init(void)
+5 -1
drivers/watchdog/omap_wdt.c
··· 45 45 46 46 #include "omap_wdt.h" 47 47 48 + static bool nowayout = WATCHDOG_NOWAYOUT; 49 + module_param(nowayout, bool, 0); 50 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 51 + "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 52 + 48 53 static unsigned timer_margin; 49 54 module_param(timer_margin, uint, 0); 50 55 MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); ··· 206 201 static int omap_wdt_probe(struct platform_device *pdev) 207 202 { 208 203 struct omap_wd_timer_platform_data *pdata = pdev->dev.platform_data; 209 - bool nowayout = WATCHDOG_NOWAYOUT; 210 204 struct watchdog_device *omap_wdt; 211 205 struct resource *res, *mem; 212 206 struct omap_wdt_dev *wdev;
+5 -6
drivers/watchdog/orion_wdt.c
··· 140 140 static struct watchdog_device orion_wdt = { 141 141 .info = &orion_wdt_info, 142 142 .ops = &orion_wdt_ops, 143 + .min_timeout = 1, 143 144 }; 144 145 145 146 static int orion_wdt_probe(struct platform_device *pdev) ··· 165 164 166 165 wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; 167 166 168 - if ((heartbeat < 1) || (heartbeat > wdt_max_duration)) 169 - heartbeat = wdt_max_duration; 170 - 171 - orion_wdt.timeout = heartbeat; 172 - orion_wdt.min_timeout = 1; 167 + orion_wdt.timeout = wdt_max_duration; 173 168 orion_wdt.max_timeout = wdt_max_duration; 169 + watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev); 174 170 175 171 watchdog_set_nowayout(&orion_wdt, nowayout); 176 172 ret = watchdog_register_device(&orion_wdt); ··· 177 179 } 178 180 179 181 pr_info("Initial timeout %d sec%s\n", 180 - heartbeat, nowayout ? ", nowayout" : ""); 182 + orion_wdt.timeout, nowayout ? ", nowayout" : ""); 181 183 return 0; 182 184 } 183 185 ··· 223 225 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 224 226 225 227 MODULE_LICENSE("GPL"); 228 + MODULE_ALIAS("platform:orion_wdt"); 226 229 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+3 -4
drivers/watchdog/pnx4008_wdt.c
··· 142 142 static struct watchdog_device pnx4008_wdd = { 143 143 .info = &pnx4008_wdt_ident, 144 144 .ops = &pnx4008_wdt_ops, 145 + .timeout = DEFAULT_HEARTBEAT, 145 146 .min_timeout = 1, 146 147 .max_timeout = MAX_HEARTBEAT, 147 148 }; ··· 152 151 struct resource *r; 153 152 int ret = 0; 154 153 155 - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 156 - heartbeat = DEFAULT_HEARTBEAT; 154 + watchdog_init_timeout(&pnx4008_wdd, heartbeat, &pdev->dev); 157 155 158 156 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 159 157 wdt_base = devm_ioremap_resource(&pdev->dev, r); ··· 167 167 if (ret) 168 168 goto out; 169 169 170 - pnx4008_wdd.timeout = heartbeat; 171 170 pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? 172 171 WDIOF_CARDRESET : 0; 173 172 watchdog_set_nowayout(&pnx4008_wdd, nowayout); ··· 180 181 } 181 182 182 183 dev_info(&pdev->dev, "PNX4008 Watchdog Timer: heartbeat %d sec\n", 183 - heartbeat); 184 + pnx4008_wdd.timeout); 184 185 185 186 return 0; 186 187
+178
drivers/watchdog/retu_wdt.c
··· 1 + /* 2 + * Retu watchdog driver 3 + * 4 + * Copyright (C) 2004, 2005 Nokia Corporation 5 + * 6 + * Based on code written by Amit Kucheria and Michael Buesch. 7 + * Rewritten by Aaro Koskinen. 8 + * 9 + * This file is subject to the terms and conditions of the GNU General 10 + * Public License. See the file "COPYING" in the main directory of this 11 + * archive for more details. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + */ 18 + 19 + #include <linux/init.h> 20 + #include <linux/slab.h> 21 + #include <linux/errno.h> 22 + #include <linux/device.h> 23 + #include <linux/kernel.h> 24 + #include <linux/module.h> 25 + #include <linux/mfd/retu.h> 26 + #include <linux/watchdog.h> 27 + #include <linux/platform_device.h> 28 + 29 + /* Watchdog timer values in seconds */ 30 + #define RETU_WDT_MAX_TIMER 63 31 + 32 + struct retu_wdt_dev { 33 + struct retu_dev *rdev; 34 + struct device *dev; 35 + struct delayed_work ping_work; 36 + }; 37 + 38 + /* 39 + * Since Retu watchdog cannot be disabled in hardware, we must kick it 40 + * with a timer until userspace watchdog software takes over. If 41 + * CONFIG_WATCHDOG_NOWAYOUT is set, we never start the feeding. 42 + */ 43 + static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev) 44 + { 45 + retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER); 46 + schedule_delayed_work(&wdev->ping_work, 47 + round_jiffies_relative(RETU_WDT_MAX_TIMER * HZ / 2)); 48 + } 49 + 50 + static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev) 51 + { 52 + retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER); 53 + cancel_delayed_work_sync(&wdev->ping_work); 54 + } 55 + 56 + static void retu_wdt_ping_work(struct work_struct *work) 57 + { 58 + struct retu_wdt_dev *wdev = container_of(to_delayed_work(work), 59 + struct retu_wdt_dev, ping_work); 60 + retu_wdt_ping_enable(wdev); 61 + } 62 + 63 + static int retu_wdt_start(struct watchdog_device *wdog) 64 + { 65 + struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog); 66 + 67 + retu_wdt_ping_disable(wdev); 68 + 69 + return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout); 70 + } 71 + 72 + static int retu_wdt_stop(struct watchdog_device *wdog) 73 + { 74 + struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog); 75 + 76 + retu_wdt_ping_enable(wdev); 77 + 78 + return 0; 79 + } 80 + 81 + static int retu_wdt_ping(struct watchdog_device *wdog) 82 + { 83 + struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog); 84 + 85 + return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout); 86 + } 87 + 88 + static int retu_wdt_set_timeout(struct watchdog_device *wdog, 89 + unsigned int timeout) 90 + { 91 + struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog); 92 + 93 + wdog->timeout = timeout; 94 + return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout); 95 + } 96 + 97 + static const struct watchdog_info retu_wdt_info = { 98 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 99 + .identity = "Retu watchdog", 100 + }; 101 + 102 + static const struct watchdog_ops retu_wdt_ops = { 103 + .owner = THIS_MODULE, 104 + .start = retu_wdt_start, 105 + .stop = retu_wdt_stop, 106 + .ping = retu_wdt_ping, 107 + .set_timeout = retu_wdt_set_timeout, 108 + }; 109 + 110 + static int retu_wdt_probe(struct platform_device *pdev) 111 + { 112 + struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent); 113 + bool nowayout = WATCHDOG_NOWAYOUT; 114 + struct watchdog_device *retu_wdt; 115 + struct retu_wdt_dev *wdev; 116 + int ret; 117 + 118 + retu_wdt = devm_kzalloc(&pdev->dev, sizeof(*retu_wdt), GFP_KERNEL); 119 + if (!retu_wdt) 120 + return -ENOMEM; 121 + 122 + wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL); 123 + if (!wdev) 124 + return -ENOMEM; 125 + 126 + retu_wdt->info = &retu_wdt_info; 127 + retu_wdt->ops = &retu_wdt_ops; 128 + retu_wdt->timeout = RETU_WDT_MAX_TIMER; 129 + retu_wdt->min_timeout = 0; 130 + retu_wdt->max_timeout = RETU_WDT_MAX_TIMER; 131 + 132 + watchdog_set_drvdata(retu_wdt, wdev); 133 + watchdog_set_nowayout(retu_wdt, nowayout); 134 + 135 + wdev->rdev = rdev; 136 + wdev->dev = &pdev->dev; 137 + 138 + INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work); 139 + 140 + ret = watchdog_register_device(retu_wdt); 141 + if (ret < 0) 142 + return ret; 143 + 144 + if (nowayout) 145 + retu_wdt_ping(retu_wdt); 146 + else 147 + retu_wdt_ping_enable(wdev); 148 + 149 + platform_set_drvdata(pdev, retu_wdt); 150 + 151 + return 0; 152 + } 153 + 154 + static int retu_wdt_remove(struct platform_device *pdev) 155 + { 156 + struct watchdog_device *wdog = platform_get_drvdata(pdev); 157 + struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog); 158 + 159 + watchdog_unregister_device(wdog); 160 + cancel_delayed_work_sync(&wdev->ping_work); 161 + 162 + return 0; 163 + } 164 + 165 + static struct platform_driver retu_wdt_driver = { 166 + .probe = retu_wdt_probe, 167 + .remove = retu_wdt_remove, 168 + .driver = { 169 + .name = "retu-wdt", 170 + }, 171 + }; 172 + module_platform_driver(retu_wdt_driver); 173 + 174 + MODULE_ALIAS("platform:retu-wdt"); 175 + MODULE_DESCRIPTION("Retu watchdog"); 176 + MODULE_AUTHOR("Amit Kucheria"); 177 + MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>"); 178 + MODULE_LICENSE("GPL");
+13 -35
drivers/watchdog/s3c2410_wdt.c
··· 53 53 #define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15) 54 54 55 55 static bool nowayout = WATCHDOG_NOWAYOUT; 56 - static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; 56 + static int tmr_margin; 57 57 static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; 58 58 static int soft_noboot; 59 59 static int debug; ··· 226 226 static struct watchdog_device s3c2410_wdd = { 227 227 .info = &s3c2410_wdt_ident, 228 228 .ops = &s3c2410wdt_ops, 229 + .timeout = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME, 229 230 }; 230 231 231 232 /* interrupt handler code */ ··· 310 309 unsigned int wtcon; 311 310 int started = 0; 312 311 int ret; 313 - int size; 314 312 315 313 DBG("%s: probe=%p\n", __func__, pdev); 316 314 ··· 330 330 } 331 331 332 332 /* get the memory region for the watchdog timer */ 333 - 334 - size = resource_size(wdt_mem); 335 - if (!request_mem_region(wdt_mem->start, size, pdev->name)) { 336 - dev_err(dev, "failed to get memory region\n"); 337 - ret = -EBUSY; 338 - goto err; 339 - } 340 - 341 - wdt_base = ioremap(wdt_mem->start, size); 333 + wdt_base = devm_request_and_ioremap(dev, wdt_mem); 342 334 if (wdt_base == NULL) { 343 - dev_err(dev, "failed to ioremap() region\n"); 344 - ret = -EINVAL; 345 - goto err_req; 335 + dev_err(dev, "failed to devm_request_and_ioremap() region\n"); 336 + ret = -ENOMEM; 337 + goto err; 346 338 } 347 339 348 340 DBG("probe: mapped wdt_base=%p\n", wdt_base); 349 341 350 - wdt_clock = clk_get(&pdev->dev, "watchdog"); 342 + wdt_clock = devm_clk_get(dev, "watchdog"); 351 343 if (IS_ERR(wdt_clock)) { 352 344 dev_err(dev, "failed to find watchdog clock source\n"); 353 345 ret = PTR_ERR(wdt_clock); 354 - goto err_map; 346 + goto err; 355 347 } 356 348 357 349 clk_prepare_enable(wdt_clock); ··· 357 365 /* see if we can actually set the requested timer margin, and if 358 366 * not, try the default value */ 359 367 360 - if (s3c2410wdt_set_heartbeat(&s3c2410_wdd, tmr_margin)) { 368 + watchdog_init_timeout(&s3c2410_wdd, tmr_margin, &pdev->dev); 369 + if (s3c2410wdt_set_heartbeat(&s3c2410_wdd, s3c2410_wdd.timeout)) { 361 370 started = s3c2410wdt_set_heartbeat(&s3c2410_wdd, 362 371 CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME); 363 372 ··· 371 378 "cannot start\n"); 372 379 } 373 380 374 - ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev); 381 + ret = devm_request_irq(dev, wdt_irq->start, s3c2410wdt_irq, 0, 382 + pdev->name, pdev); 375 383 if (ret != 0) { 376 384 dev_err(dev, "failed to install irq (%d)\n", ret); 377 385 goto err_cpufreq; ··· 383 389 ret = watchdog_register_device(&s3c2410_wdd); 384 390 if (ret) { 385 391 dev_err(dev, "cannot register watchdog (%d)\n", ret); 386 - goto err_irq; 392 + goto err_cpufreq; 387 393 } 388 394 389 395 if (tmr_atboot && started == 0) { ··· 408 414 409 415 return 0; 410 416 411 - err_irq: 412 - free_irq(wdt_irq->start, pdev); 413 - 414 417 err_cpufreq: 415 418 s3c2410wdt_cpufreq_deregister(); 416 419 417 420 err_clk: 418 421 clk_disable_unprepare(wdt_clock); 419 - clk_put(wdt_clock); 420 422 wdt_clock = NULL; 421 - 422 - err_map: 423 - iounmap(wdt_base); 424 - 425 - err_req: 426 - release_mem_region(wdt_mem->start, size); 427 423 428 424 err: 429 425 wdt_irq = NULL; ··· 425 441 { 426 442 watchdog_unregister_device(&s3c2410_wdd); 427 443 428 - free_irq(wdt_irq->start, dev); 429 - 430 444 s3c2410wdt_cpufreq_deregister(); 431 445 432 446 clk_disable_unprepare(wdt_clock); 433 - clk_put(wdt_clock); 434 447 wdt_clock = NULL; 435 448 436 - iounmap(wdt_base); 437 - 438 - release_mem_region(wdt_mem->start, resource_size(wdt_mem)); 439 449 wdt_irq = NULL; 440 450 wdt_mem = NULL; 441 451 return 0;
+8 -19
drivers/watchdog/sp5100_tco.c
··· 361 361 { 362 362 struct pci_dev *dev = NULL; 363 363 const char *dev_name = NULL; 364 - u32 val; 364 + u32 val, tmp_val; 365 365 u32 index_reg, data_reg, base_addr; 366 366 367 367 /* Match the PCI device */ ··· 497 497 pr_debug("Got 0x%04x from resource tree\n", val); 498 498 } 499 499 500 - /* Restore to the low three bits, if chipset is SB8x0(or later) */ 501 - if (sp5100_tco_pci->revision >= 0x40) { 502 - u8 reserved_bit; 503 - reserved_bit = inb(base_addr) & 0x7; 504 - val |= (u32)reserved_bit; 505 - } 500 + /* Restore to the low three bits */ 501 + outb(base_addr+0, index_reg); 502 + tmp_val = val | (inb(data_reg) & 0x7); 506 503 507 504 /* Re-programming the watchdog timer base address */ 508 505 outb(base_addr+0, index_reg); 509 - /* Low three bits of BASE are reserved */ 510 - outb((val >> 0) & 0xf8, data_reg); 506 + outb((tmp_val >> 0) & 0xff, data_reg); 511 507 outb(base_addr+1, index_reg); 512 - outb((val >> 8) & 0xff, data_reg); 508 + outb((tmp_val >> 8) & 0xff, data_reg); 513 509 outb(base_addr+2, index_reg); 514 - outb((val >> 16) & 0xff, data_reg); 510 + outb((tmp_val >> 16) & 0xff, data_reg); 515 511 outb(base_addr+3, index_reg); 516 - outb((val >> 24) & 0xff, data_reg); 517 - 518 - /* 519 - * Clear unnecessary the low three bits, 520 - * if chipset is SB8x0(or later) 521 - */ 522 - if (sp5100_tco_pci->revision >= 0x40) 523 - val &= ~0x7; 512 + outb((tmp_val >> 24) & 0xff, data_reg); 524 513 525 514 if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE, 526 515 dev_name)) {
+111
drivers/watchdog/stmp3xxx_rtc_wdt.c
··· 1 + /* 2 + * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28 3 + * 4 + * Author: Wolfram Sang <w.sang@pengutronix.de> 5 + * 6 + * Copyright (C) 2011-12 Wolfram Sang, Pengutronix 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License version 2 as published by 10 + * the Free Software Foundation. 11 + */ 12 + #include <linux/init.h> 13 + #include <linux/kernel.h> 14 + #include <linux/module.h> 15 + #include <linux/miscdevice.h> 16 + #include <linux/watchdog.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/stmp3xxx_rtc_wdt.h> 19 + 20 + #define WDOG_TICK_RATE 1000 /* 1 kHz clock */ 21 + #define STMP3XXX_DEFAULT_TIMEOUT 19 22 + #define STMP3XXX_MAX_TIMEOUT (UINT_MAX / WDOG_TICK_RATE) 23 + 24 + static int heartbeat = STMP3XXX_DEFAULT_TIMEOUT; 25 + module_param(heartbeat, uint, 0); 26 + MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat period in seconds from 1 to " 27 + __MODULE_STRING(STMP3XXX_MAX_TIMEOUT) ", default " 28 + __MODULE_STRING(STMP3XXX_DEFAULT_TIMEOUT)); 29 + 30 + static int wdt_start(struct watchdog_device *wdd) 31 + { 32 + struct device *dev = watchdog_get_drvdata(wdd); 33 + struct stmp3xxx_wdt_pdata *pdata = dev->platform_data; 34 + 35 + pdata->wdt_set_timeout(dev->parent, wdd->timeout * WDOG_TICK_RATE); 36 + return 0; 37 + } 38 + 39 + static int wdt_stop(struct watchdog_device *wdd) 40 + { 41 + struct device *dev = watchdog_get_drvdata(wdd); 42 + struct stmp3xxx_wdt_pdata *pdata = dev->platform_data; 43 + 44 + pdata->wdt_set_timeout(dev->parent, 0); 45 + return 0; 46 + } 47 + 48 + static int wdt_set_timeout(struct watchdog_device *wdd, unsigned new_timeout) 49 + { 50 + wdd->timeout = new_timeout; 51 + return wdt_start(wdd); 52 + } 53 + 54 + static const struct watchdog_info stmp3xxx_wdt_ident = { 55 + .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 56 + .identity = "STMP3XXX RTC Watchdog", 57 + }; 58 + 59 + static const struct watchdog_ops stmp3xxx_wdt_ops = { 60 + .owner = THIS_MODULE, 61 + .start = wdt_start, 62 + .stop = wdt_stop, 63 + .set_timeout = wdt_set_timeout, 64 + }; 65 + 66 + static struct watchdog_device stmp3xxx_wdd = { 67 + .info = &stmp3xxx_wdt_ident, 68 + .ops = &stmp3xxx_wdt_ops, 69 + .min_timeout = 1, 70 + .max_timeout = STMP3XXX_MAX_TIMEOUT, 71 + .status = WATCHDOG_NOWAYOUT_INIT_STATUS, 72 + }; 73 + 74 + static int stmp3xxx_wdt_probe(struct platform_device *pdev) 75 + { 76 + int ret; 77 + 78 + watchdog_set_drvdata(&stmp3xxx_wdd, &pdev->dev); 79 + 80 + stmp3xxx_wdd.timeout = clamp_t(unsigned, heartbeat, 1, STMP3XXX_MAX_TIMEOUT); 81 + 82 + ret = watchdog_register_device(&stmp3xxx_wdd); 83 + if (ret < 0) { 84 + dev_err(&pdev->dev, "cannot register watchdog device\n"); 85 + return ret; 86 + } 87 + 88 + dev_info(&pdev->dev, "initialized watchdog with heartbeat %ds\n", 89 + stmp3xxx_wdd.timeout); 90 + return 0; 91 + } 92 + 93 + static int stmp3xxx_wdt_remove(struct platform_device *pdev) 94 + { 95 + watchdog_unregister_device(&stmp3xxx_wdd); 96 + return 0; 97 + } 98 + 99 + static struct platform_driver stmp3xxx_wdt_driver = { 100 + .driver = { 101 + .name = "stmp3xxx_rtc_wdt", 102 + }, 103 + .probe = stmp3xxx_wdt_probe, 104 + .remove = stmp3xxx_wdt_remove, 105 + }; 106 + module_platform_driver(stmp3xxx_wdt_driver); 107 + 108 + MODULE_DESCRIPTION("STMP3XXX RTC Watchdog Driver"); 109 + MODULE_LICENSE("GPL v2"); 110 + MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); 111 + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-288
drivers/watchdog/stmp3xxx_wdt.c
··· 1 - /* 2 - * Watchdog driver for Freescale STMP37XX/STMP378X 3 - * 4 - * Author: Vitaly Wool <vital@embeddedalley.com> 5 - * 6 - * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. 7 - * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. 8 - */ 9 - 10 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 - 12 - #include <linux/init.h> 13 - #include <linux/kernel.h> 14 - #include <linux/fs.h> 15 - #include <linux/miscdevice.h> 16 - #include <linux/watchdog.h> 17 - #include <linux/platform_device.h> 18 - #include <linux/spinlock.h> 19 - #include <linux/uaccess.h> 20 - #include <linux/module.h> 21 - 22 - #include <mach/platform.h> 23 - #include <mach/regs-rtc.h> 24 - 25 - #define DEFAULT_HEARTBEAT 19 26 - #define MAX_HEARTBEAT (0x10000000 >> 6) 27 - 28 - /* missing bitmask in headers */ 29 - #define BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER 0x80000000 30 - 31 - #define WDT_IN_USE 0 32 - #define WDT_OK_TO_CLOSE 1 33 - 34 - #define WDOG_COUNTER_RATE 1000 /* 1 kHz clock */ 35 - 36 - static DEFINE_SPINLOCK(stmp3xxx_wdt_io_lock); 37 - static unsigned long wdt_status; 38 - static const bool nowayout = WATCHDOG_NOWAYOUT; 39 - static int heartbeat = DEFAULT_HEARTBEAT; 40 - static unsigned long boot_status; 41 - 42 - static void wdt_enable(u32 value) 43 - { 44 - spin_lock(&stmp3xxx_wdt_io_lock); 45 - __raw_writel(value, REGS_RTC_BASE + HW_RTC_WATCHDOG); 46 - stmp3xxx_setl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL); 47 - stmp3xxx_setl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, 48 - REGS_RTC_BASE + HW_RTC_PERSISTENT1); 49 - spin_unlock(&stmp3xxx_wdt_io_lock); 50 - } 51 - 52 - static void wdt_disable(void) 53 - { 54 - spin_lock(&stmp3xxx_wdt_io_lock); 55 - stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, 56 - REGS_RTC_BASE + HW_RTC_PERSISTENT1); 57 - stmp3xxx_clearl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL); 58 - spin_unlock(&stmp3xxx_wdt_io_lock); 59 - } 60 - 61 - static void wdt_ping(void) 62 - { 63 - wdt_enable(heartbeat * WDOG_COUNTER_RATE); 64 - } 65 - 66 - static int stmp3xxx_wdt_open(struct inode *inode, struct file *file) 67 - { 68 - if (test_and_set_bit(WDT_IN_USE, &wdt_status)) 69 - return -EBUSY; 70 - 71 - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 72 - wdt_ping(); 73 - 74 - return nonseekable_open(inode, file); 75 - } 76 - 77 - static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data, 78 - size_t len, loff_t *ppos) 79 - { 80 - if (len) { 81 - if (!nowayout) { 82 - size_t i; 83 - 84 - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 85 - 86 - for (i = 0; i != len; i++) { 87 - char c; 88 - 89 - if (get_user(c, data + i)) 90 - return -EFAULT; 91 - if (c == 'V') 92 - set_bit(WDT_OK_TO_CLOSE, &wdt_status); 93 - } 94 - } 95 - wdt_ping(); 96 - } 97 - 98 - return len; 99 - } 100 - 101 - static const struct watchdog_info ident = { 102 - .options = WDIOF_CARDRESET | 103 - WDIOF_MAGICCLOSE | 104 - WDIOF_SETTIMEOUT | 105 - WDIOF_KEEPALIVEPING, 106 - .identity = "STMP3XXX Watchdog", 107 - }; 108 - 109 - static long stmp3xxx_wdt_ioctl(struct file *file, unsigned int cmd, 110 - unsigned long arg) 111 - { 112 - void __user *argp = (void __user *)arg; 113 - int __user *p = argp; 114 - int new_heartbeat, opts; 115 - int ret = -ENOTTY; 116 - 117 - switch (cmd) { 118 - case WDIOC_GETSUPPORT: 119 - ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 120 - break; 121 - 122 - case WDIOC_GETSTATUS: 123 - ret = put_user(0, p); 124 - break; 125 - 126 - case WDIOC_GETBOOTSTATUS: 127 - ret = put_user(boot_status, p); 128 - break; 129 - 130 - case WDIOC_SETOPTIONS: 131 - if (get_user(opts, p)) { 132 - ret = -EFAULT; 133 - break; 134 - } 135 - if (opts & WDIOS_DISABLECARD) 136 - wdt_disable(); 137 - else if (opts & WDIOS_ENABLECARD) 138 - wdt_ping(); 139 - else { 140 - pr_debug("%s: unknown option 0x%x\n", __func__, opts); 141 - ret = -EINVAL; 142 - break; 143 - } 144 - ret = 0; 145 - break; 146 - 147 - case WDIOC_KEEPALIVE: 148 - wdt_ping(); 149 - ret = 0; 150 - break; 151 - 152 - case WDIOC_SETTIMEOUT: 153 - if (get_user(new_heartbeat, p)) { 154 - ret = -EFAULT; 155 - break; 156 - } 157 - if (new_heartbeat <= 0 || new_heartbeat > MAX_HEARTBEAT) { 158 - ret = -EINVAL; 159 - break; 160 - } 161 - 162 - heartbeat = new_heartbeat; 163 - wdt_ping(); 164 - /* Fall through */ 165 - 166 - case WDIOC_GETTIMEOUT: 167 - ret = put_user(heartbeat, p); 168 - break; 169 - } 170 - return ret; 171 - } 172 - 173 - static int stmp3xxx_wdt_release(struct inode *inode, struct file *file) 174 - { 175 - int ret = 0; 176 - 177 - if (!nowayout) { 178 - if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { 179 - wdt_ping(); 180 - pr_debug("%s: Device closed unexpectedly\n", __func__); 181 - ret = -EINVAL; 182 - } else { 183 - wdt_disable(); 184 - clear_bit(WDT_OK_TO_CLOSE, &wdt_status); 185 - } 186 - } 187 - clear_bit(WDT_IN_USE, &wdt_status); 188 - 189 - return ret; 190 - } 191 - 192 - static const struct file_operations stmp3xxx_wdt_fops = { 193 - .owner = THIS_MODULE, 194 - .llseek = no_llseek, 195 - .write = stmp3xxx_wdt_write, 196 - .unlocked_ioctl = stmp3xxx_wdt_ioctl, 197 - .open = stmp3xxx_wdt_open, 198 - .release = stmp3xxx_wdt_release, 199 - }; 200 - 201 - static struct miscdevice stmp3xxx_wdt_miscdev = { 202 - .minor = WATCHDOG_MINOR, 203 - .name = "watchdog", 204 - .fops = &stmp3xxx_wdt_fops, 205 - }; 206 - 207 - static int stmp3xxx_wdt_probe(struct platform_device *pdev) 208 - { 209 - int ret = 0; 210 - 211 - if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 212 - heartbeat = DEFAULT_HEARTBEAT; 213 - 214 - boot_status = __raw_readl(REGS_RTC_BASE + HW_RTC_PERSISTENT1) & 215 - BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER; 216 - boot_status = !!boot_status; 217 - stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER, 218 - REGS_RTC_BASE + HW_RTC_PERSISTENT1); 219 - wdt_disable(); /* disable for now */ 220 - 221 - ret = misc_register(&stmp3xxx_wdt_miscdev); 222 - if (ret < 0) { 223 - dev_err(&pdev->dev, "cannot register misc device\n"); 224 - return ret; 225 - } 226 - 227 - pr_info("initialized, heartbeat %d sec\n", heartbeat); 228 - 229 - return ret; 230 - } 231 - 232 - static int stmp3xxx_wdt_remove(struct platform_device *pdev) 233 - { 234 - misc_deregister(&stmp3xxx_wdt_miscdev); 235 - return 0; 236 - } 237 - 238 - #ifdef CONFIG_PM 239 - static int wdt_suspended; 240 - static u32 wdt_saved_time; 241 - 242 - static int stmp3xxx_wdt_suspend(struct platform_device *pdev, 243 - pm_message_t state) 244 - { 245 - if (__raw_readl(REGS_RTC_BASE + HW_RTC_CTRL) & 246 - BM_RTC_CTRL_WATCHDOGEN) { 247 - wdt_suspended = 1; 248 - wdt_saved_time = __raw_readl(REGS_RTC_BASE + HW_RTC_WATCHDOG); 249 - wdt_disable(); 250 - } 251 - return 0; 252 - } 253 - 254 - static int stmp3xxx_wdt_resume(struct platform_device *pdev) 255 - { 256 - if (wdt_suspended) { 257 - wdt_enable(wdt_saved_time); 258 - wdt_suspended = 0; 259 - } 260 - return 0; 261 - } 262 - #else 263 - #define stmp3xxx_wdt_suspend NULL 264 - #define stmp3xxx_wdt_resume NULL 265 - #endif 266 - 267 - static struct platform_driver platform_wdt_driver = { 268 - .driver = { 269 - .name = "stmp3xxx_wdt", 270 - }, 271 - .probe = stmp3xxx_wdt_probe, 272 - .remove = stmp3xxx_wdt_remove, 273 - .suspend = stmp3xxx_wdt_suspend, 274 - .resume = stmp3xxx_wdt_resume, 275 - }; 276 - 277 - module_platform_driver(platform_wdt_driver); 278 - 279 - MODULE_DESCRIPTION("STMP3XXX Watchdog Driver"); 280 - MODULE_LICENSE("GPL"); 281 - 282 - module_param(heartbeat, int, 0); 283 - MODULE_PARM_DESC(heartbeat, 284 - "Watchdog heartbeat period in seconds from 1 to " 285 - __MODULE_STRING(MAX_HEARTBEAT) ", default " 286 - __MODULE_STRING(DEFAULT_HEARTBEAT)); 287 - 288 - MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+57 -9
drivers/watchdog/watchdog_core.c
··· 36 36 #include <linux/init.h> /* For __init/__exit/... */ 37 37 #include <linux/idr.h> /* For ida_* macros */ 38 38 #include <linux/err.h> /* For IS_ERR macros */ 39 + #include <linux/of.h> /* For of_get_timeout_sec */ 39 40 40 41 #include "watchdog_core.h" /* For watchdog_dev_register/... */ 41 42 42 43 static DEFINE_IDA(watchdog_ida); 43 44 static struct class *watchdog_class; 45 + 46 + static void watchdog_check_min_max_timeout(struct watchdog_device *wdd) 47 + { 48 + /* 49 + * Check that we have valid min and max timeout values, if 50 + * not reset them both to 0 (=not used or unknown) 51 + */ 52 + if (wdd->min_timeout > wdd->max_timeout) { 53 + pr_info("Invalid min and max timeout values, resetting to 0!\n"); 54 + wdd->min_timeout = 0; 55 + wdd->max_timeout = 0; 56 + } 57 + } 58 + 59 + /** 60 + * watchdog_init_timeout() - initialize the timeout field 61 + * @timeout_parm: timeout module parameter 62 + * @dev: Device that stores the timeout-sec property 63 + * 64 + * Initialize the timeout field of the watchdog_device struct with either the 65 + * timeout module parameter (if it is valid value) or the timeout-sec property 66 + * (only if it is a valid value and the timeout_parm is out of bounds). 67 + * If none of them are valid then we keep the old value (which should normally 68 + * be the default timeout value. 69 + * 70 + * A zero is returned on success and -EINVAL for failure. 71 + */ 72 + int watchdog_init_timeout(struct watchdog_device *wdd, 73 + unsigned int timeout_parm, struct device *dev) 74 + { 75 + unsigned int t = 0; 76 + int ret = 0; 77 + 78 + watchdog_check_min_max_timeout(wdd); 79 + 80 + /* try to get the tiemout module parameter first */ 81 + if (!watchdog_timeout_invalid(wdd, timeout_parm)) { 82 + wdd->timeout = timeout_parm; 83 + return ret; 84 + } 85 + if (timeout_parm) 86 + ret = -EINVAL; 87 + 88 + /* try to get the timeout_sec property */ 89 + if (dev == NULL || dev->of_node == NULL) 90 + return ret; 91 + of_property_read_u32(dev->of_node, "timeout-sec", &t); 92 + if (!watchdog_timeout_invalid(wdd, t)) 93 + wdd->timeout = t; 94 + else 95 + ret = -EINVAL; 96 + 97 + return ret; 98 + } 99 + EXPORT_SYMBOL_GPL(watchdog_init_timeout); 44 100 45 101 /** 46 102 * watchdog_register_device() - register a watchdog device ··· 119 63 if (wdd->ops->start == NULL || wdd->ops->stop == NULL) 120 64 return -EINVAL; 121 65 122 - /* 123 - * Check that we have valid min and max timeout values, if 124 - * not reset them both to 0 (=not used or unknown) 125 - */ 126 - if (wdd->min_timeout > wdd->max_timeout) { 127 - pr_info("Invalid min and max timeout values, resetting to 0!\n"); 128 - wdd->min_timeout = 0; 129 - wdd->max_timeout = 0; 130 - } 66 + watchdog_check_min_max_timeout(wdd); 131 67 132 68 /* 133 69 * Note: now that all watchdog_device data has been verified, we
+1 -2
drivers/watchdog/watchdog_dev.c
··· 200 200 !(wddev->info->options & WDIOF_SETTIMEOUT)) 201 201 return -EOPNOTSUPP; 202 202 203 - if ((wddev->max_timeout != 0) && 204 - (timeout < wddev->min_timeout || timeout > wddev->max_timeout)) 203 + if (watchdog_timeout_invalid(wddev, timeout)) 205 204 return -EINVAL; 206 205 207 206 mutex_lock(&wddev->lock);
+9
include/linux/bcm47xx_wdt.h
··· 1 1 #ifndef LINUX_BCM47XX_WDT_H_ 2 2 #define LINUX_BCM47XX_WDT_H_ 3 3 4 + #include <linux/notifier.h> 5 + #include <linux/timer.h> 4 6 #include <linux/types.h> 7 + #include <linux/watchdog.h> 5 8 6 9 7 10 struct bcm47xx_wdt { ··· 13 10 u32 max_timer_ms; 14 11 15 12 void *driver_data; 13 + 14 + struct watchdog_device wdd; 15 + struct notifier_block notifier; 16 + 17 + struct timer_list soft_timer; 18 + atomic_t soft_ticks; 16 19 }; 17 20 18 21 static inline void *bcm47xx_wdt_get_drvdata(struct bcm47xx_wdt *wdt)
+15
include/linux/stmp3xxx_rtc_wdt.h
··· 1 + /* 2 + * stmp3xxx_rtc_wdt.h 3 + * 4 + * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. 5 + * 6 + * This file is released under the GPLv2. 7 + */ 8 + #ifndef __LINUX_STMP3XXX_RTC_WDT_H 9 + #define __LINUX_STMP3XXX_RTC_WDT_H 10 + 11 + struct stmp3xxx_wdt_pdata { 12 + void (*wdt_set_timeout)(struct device *dev, u32 timeout); 13 + }; 14 + 15 + #endif /* __LINUX_STMP3XXX_RTC_WDT_H */
+9
include/linux/watchdog.h
··· 118 118 set_bit(WDOG_NO_WAY_OUT, &wdd->status); 119 119 } 120 120 121 + /* Use the following function to check if a timeout value is invalid */ 122 + static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t) 123 + { 124 + return ((wdd->max_timeout != 0) && 125 + (t < wdd->min_timeout || t > wdd->max_timeout)); 126 + } 127 + 121 128 /* Use the following functions to manipulate watchdog driver specific data */ 122 129 static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data) 123 130 { ··· 137 130 } 138 131 139 132 /* drivers/watchdog/watchdog_core.c */ 133 + extern int watchdog_init_timeout(struct watchdog_device *wdd, 134 + unsigned int timeout_parm, struct device *dev); 140 135 extern int watchdog_register_device(struct watchdog_device *); 141 136 extern void watchdog_unregister_device(struct watchdog_device *); 142 137