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

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

Pull watchdog updates from Wim Van Sebroeck:
"This adds following items:

- watchdog restart handler support
- watchdog reboot notifier support
- watchdog sysfs attributes
- support for the following new devices: AMD Mullins platform, AMD
Carrizo platform, meson8b SoC, CSRatlas7, TS-4800, Alphascale
asm9260-wdt, Zodiac, Sigma Designs SMP86xx/SMP87xx
- Changes in refcounting for the watchdog core
- watchdog core improvements
- and small fixes"

* git://www.linux-watchdog.org/linux-watchdog: (60 commits)
watchdog: asm9260: remove __init and __exit annotations
watchdog: Drop pointer to watchdog device from struct watchdog_device
watchdog: ziirave: Use watchdog infrastructure to create sysfs attributes
watchdog: Add support for creating driver specific sysfs attributes
watchdog: kill unref/ref ops
watchdog: stmp3xxx: Remove unused variables
watchdog: add MT7621 watchdog support
hwmon: (sch56xx) Drop watchdog driver data reference count callbacks
watchdog: da9055_wdt: Drop reference counting
watchdog: da9052_wdt: Drop reference counting
watchdog: Separate and maintain variables based on variable lifetime
watchdog: diag288: Stop re-using watchdog core internal flags
watchdog: Create watchdog device in watchdog_dev.c
watchdog: qcom-wdt: Do not set 'dev' in struct watchdog_device
watchdog: mena21: Do not use device pointer from struct watchdog_device
watchdog: gpio: Do not use device pointer from struct watchdog_device
watchdog: tangox: Print info message using pointer to platform device
watchdog: bcm2835_wdt: Drop log message if watchdog is stopped
devicetree: watchdog: add binding for Sigma Designs SMP8642 watchdog
watchdog: add support for Sigma Designs SMP86xx/SMP87xx
...

+2693 -837
+51
Documentation/ABI/testing/sysfs-class-watchdog
··· 1 + What: /sys/class/watchdog/watchdogn/bootstatus 2 + Date: August 2015 3 + Contact: Wim Van Sebroeck <wim@iguana.be> 4 + Description: 5 + It is a read only file. It contains status of the watchdog 6 + device at boot. It is equivalent to WDIOC_GETBOOTSTATUS of 7 + ioctl interface. 8 + 9 + What: /sys/class/watchdog/watchdogn/identity 10 + Date: August 2015 11 + Contact: Wim Van Sebroeck <wim@iguana.be> 12 + Description: 13 + It is a read only file. It contains identity string of 14 + watchdog device. 15 + 16 + What: /sys/class/watchdog/watchdogn/nowayout 17 + Date: August 2015 18 + Contact: Wim Van Sebroeck <wim@iguana.be> 19 + Description: 20 + It is a read only file. While reading, it gives '1' if that 21 + device supports nowayout feature else, it gives '0'. 22 + 23 + What: /sys/class/watchdog/watchdogn/state 24 + Date: August 2015 25 + Contact: Wim Van Sebroeck <wim@iguana.be> 26 + Description: 27 + It is a read only file. It gives active/inactive status of 28 + watchdog device. 29 + 30 + What: /sys/class/watchdog/watchdogn/status 31 + Date: August 2015 32 + Contact: Wim Van Sebroeck <wim@iguana.be> 33 + Description: 34 + It is a read only file. It contains watchdog device's 35 + internal status bits. It is equivalent to WDIOC_GETSTATUS 36 + of ioctl interface. 37 + 38 + What: /sys/class/watchdog/watchdogn/timeleft 39 + Date: August 2015 40 + Contact: Wim Van Sebroeck <wim@iguana.be> 41 + Description: 42 + It is a read only file. It contains value of time left for 43 + reset generation. It is equivalent to WDIOC_GETTIMELEFT of 44 + ioctl interface. 45 + 46 + What: /sys/class/watchdog/watchdogn/timeout 47 + Date: August 2015 48 + Contact: Wim Van Sebroeck <wim@iguana.be> 49 + Description: 50 + It is a read only file. It is read to know about current 51 + value of timeout programmed.
+35
Documentation/devicetree/bindings/watchdog/alphascale-asm9260.txt
··· 1 + Alphascale asm9260 Watchdog timer 2 + 3 + Required properties: 4 + 5 + - compatible : should be "alphascale,asm9260-wdt". 6 + - reg : Specifies base physical address and size of the registers. 7 + - clocks : the clocks feeding the watchdog timer. See clock-bindings.txt 8 + - clock-names : should be set to 9 + "mod" - source for tick counter. 10 + "ahb" - ahb gate. 11 + - resets : phandle pointing to the system reset controller with 12 + line index for the watchdog. 13 + - reset-names : should be set to "wdt_rst". 14 + 15 + Optional properties: 16 + - timeout-sec : shall contain the default watchdog timeout in seconds, 17 + if unset, the default timeout is 30 seconds. 18 + - alphascale,mode : three modes are supported 19 + "hw" - hw reset (default). 20 + "sw" - sw reset. 21 + "debug" - no action is taken. 22 + 23 + Example: 24 + 25 + watchdog0: watchdog@80048000 { 26 + compatible = "alphascale,asm9260-wdt"; 27 + reg = <0x80048000 0x10>; 28 + clocks = <&acc CLKID_SYS_WDT>, <&acc CLKID_AHB_WDT>; 29 + clock-names = "mod", "ahb"; 30 + interrupts = <55>; 31 + resets = <&rst WDT_RESET>; 32 + reset-names = "wdt_rst"; 33 + timeout-sec = <30>; 34 + alphascale,mode = "hw"; 35 + };
+12
Documentation/devicetree/bindings/watchdog/mt7621-wdt.txt
··· 1 + Ralink Watchdog Timers 2 + 3 + Required properties: 4 + - compatible: must be "mediatek,mt7621-wdt" 5 + - reg: physical base address of the controller and length of the register range 6 + 7 + Example: 8 + 9 + watchdog@100 { 10 + compatible = "mediatek,mt7621-wdt"; 11 + reg = <0x100 0x10>; 12 + };
+18
Documentation/devicetree/bindings/watchdog/sigma,smp8642-wdt.txt
··· 1 + Sigma Designs SMP86xx/SMP87xx watchdog 2 + 3 + Required properties: 4 + - compatible: Should be "sigma,smp8642-wdt" 5 + - reg: Specifies the physical address region 6 + - clocks: Should be a phandle to the clock 7 + 8 + Optional properties: 9 + - timeout-sec: watchdog timeout in seconds 10 + 11 + Example: 12 + 13 + watchdog@1fd00 { 14 + compatible = "sigma,smp8642-wdt"; 15 + reg = <0x1fd00 8>; 16 + clocks = <&xtal_in_clk>; 17 + timeout-sec = <30>; 18 + };
+25
Documentation/devicetree/bindings/watchdog/ts4800-wdt.txt
··· 1 + Technologic Systems Watchdog 2 + 3 + Required properties: 4 + - compatible: must be "technologic,ts4800-wdt" 5 + - syscon: phandle / integer array that points to the syscon node which 6 + describes the FPGA's syscon registers. 7 + - phandle to FPGA's syscon 8 + - offset to the watchdog register 9 + 10 + Optional property: 11 + - timeout-sec: contains the watchdog timeout in seconds. 12 + 13 + Example: 14 + 15 + syscon: syscon@b0010000 { 16 + compatible = "syscon", "simple-mfd"; 17 + reg = <0xb0010000 0x3d>; 18 + reg-io-width = <2>; 19 + 20 + wdt@e { 21 + compatible = "technologic,ts4800-wdt"; 22 + syscon = <&syscon 0xe>; 23 + timeout-sec = <10>; 24 + }; 25 + }
+19
Documentation/devicetree/bindings/watchdog/ziirave-wdt.txt
··· 1 + Zodiac RAVE Watchdog Timer 2 + 3 + Required properties: 4 + - compatible: must be "zii,rave-wdt" 5 + - reg: i2c slave address of device, usually 0x38 6 + 7 + Optional Properties: 8 + - timeout-sec: Watchdog timeout value in seconds. 9 + - reset-duration-ms: Duration of the pulse generated when the watchdog times 10 + out. Value in milliseconds. 11 + 12 + Example: 13 + 14 + watchdog@38 { 15 + compatible = "zii,rave-wdt"; 16 + reg = <0x38>; 17 + timeout-sec = <30>; 18 + reset-duration-ms = <30>; 19 + };
+37 -40
Documentation/watchdog/watchdog-kernel-api.txt
··· 44 44 45 45 struct watchdog_device { 46 46 int id; 47 - struct cdev cdev; 48 - struct device *dev; 49 47 struct device *parent; 48 + const struct attribute_group **groups; 50 49 const struct watchdog_info *info; 51 50 const struct watchdog_ops *ops; 52 51 unsigned int bootstatus; 53 52 unsigned int timeout; 54 53 unsigned int min_timeout; 55 54 unsigned int max_timeout; 55 + struct notifier_block reboot_nb; 56 + struct notifier_block restart_nb; 56 57 void *driver_data; 57 - struct mutex lock; 58 + struct watchdog_core_data *wd_data; 58 59 unsigned long status; 59 60 struct list_head deferred; 60 61 }; ··· 65 64 /dev/watchdog0 cdev (dynamic major, minor 0) as well as the old 66 65 /dev/watchdog miscdev. The id is set automatically when calling 67 66 watchdog_register_device. 68 - * cdev: cdev for the dynamic /dev/watchdog<id> device nodes. This 69 - field is also populated by watchdog_register_device. 70 - * dev: device under the watchdog class (created by watchdog_register_device). 71 67 * parent: set this to the parent device (or NULL) before calling 72 68 watchdog_register_device. 69 + * groups: List of sysfs attribute groups to create when creating the watchdog 70 + device. 73 71 * info: a pointer to a watchdog_info structure. This structure gives some 74 72 additional information about the watchdog timer itself. (Like it's unique name) 75 73 * ops: a pointer to the list of watchdog operations that the watchdog supports. 76 74 * timeout: the watchdog timer's timeout value (in seconds). 77 75 * min_timeout: the watchdog timer's minimum timeout value (in seconds). 78 76 * max_timeout: the watchdog timer's maximum timeout value (in seconds). 77 + * reboot_nb: notifier block that is registered for reboot notifications, for 78 + internal use only. If the driver calls watchdog_stop_on_reboot, watchdog core 79 + will stop the watchdog on such notifications. 80 + * restart_nb: notifier block that is registered for machine restart, for 81 + internal use only. If a watchdog is capable of restarting the machine, it 82 + should define ops->restart. Priority can be changed through 83 + watchdog_set_restart_priority. 79 84 * bootstatus: status of the device after booting (reported with watchdog 80 85 WDIOF_* status bits). 81 86 * driver_data: a pointer to the drivers private data of a watchdog device. 82 87 This data should only be accessed via the watchdog_set_drvdata and 83 88 watchdog_get_drvdata routines. 84 - * lock: Mutex for WatchDog Timer Driver Core internal use only. 89 + * wd_data: a pointer to watchdog core internal data. 85 90 * status: this field contains a number of status bits that give extra 86 91 information about the status of the device (Like: is the watchdog timer 87 - running/active, is the nowayout bit set, is the device opened via 88 - the /dev/watchdog interface or not, ...). 92 + running/active, or is the nowayout bit set). 89 93 * deferred: entry in wtd_deferred_reg_list which is used to 90 94 register early initialized watchdogs. 91 95 ··· 106 100 unsigned int (*status)(struct watchdog_device *); 107 101 int (*set_timeout)(struct watchdog_device *, unsigned int); 108 102 unsigned int (*get_timeleft)(struct watchdog_device *); 109 - void (*ref)(struct watchdog_device *); 110 - void (*unref)(struct watchdog_device *); 103 + int (*restart)(struct watchdog_device *); 104 + void (*ref)(struct watchdog_device *) __deprecated; 105 + void (*unref)(struct watchdog_device *) __deprecated; 111 106 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); 112 107 }; 113 108 ··· 116 109 driver's operations. This module owner will be used to lock the module when 117 110 the watchdog is active. (This to avoid a system crash when you unload the 118 111 module and /dev/watchdog is still open). 119 - 120 - If the watchdog_device struct is dynamically allocated, just locking the module 121 - is not enough and a driver also needs to define the ref and unref operations to 122 - ensure the structure holding the watchdog_device does not go away. 123 - 124 - The simplest (and usually sufficient) implementation of this is to: 125 - 1) Add a kref struct to the same structure which is holding the watchdog_device 126 - 2) Define a release callback for the kref which frees the struct holding both 127 - 3) Call kref_init on this kref *before* calling watchdog_register_device() 128 - 4) Define a ref operation calling kref_get on this kref 129 - 5) Define a unref operation calling kref_put on this kref 130 - 6) When it is time to cleanup: 131 - * Do not kfree() the struct holding both, the last kref_put will do this! 132 - * *After* calling watchdog_unregister_device() call kref_put on the kref 133 112 134 113 Some operations are mandatory and some are optional. The mandatory operations 135 114 are: ··· 157 164 (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the 158 165 watchdog's info structure). 159 166 * get_timeleft: this routines returns the time that's left before a reset. 160 - * ref: the operation that calls kref_get on the kref of a dynamically 161 - allocated watchdog_device struct. 162 - * unref: the operation that calls kref_put on the kref of a dynamically 163 - allocated watchdog_device struct. 167 + * restart: this routine restarts the machine. It returns 0 on success or a 168 + negative errno code for failure. 164 169 * ioctl: if this routine is present then it will be called first before we do 165 170 our own internal ioctl call handling. This routine should return -ENOIOCTLCMD 166 171 if a command is not supported. The parameters that are passed to the ioctl 167 172 call are: watchdog_device, cmd and arg. 173 + 174 + The 'ref' and 'unref' operations are no longer used and deprecated. 168 175 169 176 The status bits should (preferably) be set with the set_bit and clear_bit alike 170 177 bit-operations. The status bits that are defined are: ··· 172 179 is active or not. When the watchdog is active after booting, then you should 173 180 set this status bit (Note: when you register the watchdog timer device with 174 181 this bit set, then opening /dev/watchdog will skip the start operation) 175 - * WDOG_DEV_OPEN: this status bit shows whether or not the watchdog device 176 - was opened via /dev/watchdog. 177 - (This bit should only be used by the WatchDog Timer Driver Core). 178 - * WDOG_ALLOW_RELEASE: this bit stores whether or not the magic close character 179 - has been sent (so that we can support the magic close feature). 180 - (This bit should only be used by the WatchDog Timer Driver Core). 181 182 * WDOG_NO_WAY_OUT: this bit stores the nowayout setting for the watchdog. 182 183 If this bit is set then the watchdog timer will not be able to stop. 183 - * WDOG_UNREGISTERED: this bit gets set by the WatchDog Timer Driver Core 184 - after calling watchdog_unregister_device, and then checked before calling 185 - any watchdog_ops, so that you can be sure that no operations (other then 186 - unref) will get called after unregister, even if userspace still holds a 187 - reference to /dev/watchdog 188 184 189 185 To set the WDOG_NO_WAY_OUT status bit (before registering your watchdog 190 186 timer device) you can either: ··· 213 231 to set the default timeout value as timeout value in the watchdog_device and 214 232 then use this function to set the user "preferred" timeout value. 215 233 This routine returns zero on success and a negative errno code for failure. 234 + 235 + To disable the watchdog on reboot, the user must call the following helper: 236 + 237 + static inline void watchdog_stop_on_reboot(struct watchdog_device *wdd); 238 + 239 + To change the priority of the restart handler the following helper should be 240 + used: 241 + 242 + void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority); 243 + 244 + User should follow the following guidelines for setting the priority: 245 + * 0: should be called in last resort, has limited restart capabilities 246 + * 128: default restart handler, use if no other handler is expected to be 247 + available, and/or if restart is sufficient to restart the entire system 248 + * 255: highest priority, will preempt all other restart handlers
+1
MAINTAINERS
··· 11676 11676 11677 11677 WATCHDOG DEVICE DRIVERS 11678 11678 M: Wim Van Sebroeck <wim@iguana.be> 11679 + R: Guenter Roeck <linux@roeck-us.net> 11679 11680 L: linux-watchdog@vger.kernel.org 11680 11681 W: http://www.linux-watchdog.org/ 11681 11682 T: git git://www.linux-watchdog.org/linux-watchdog.git
+1 -30
drivers/hwmon/sch56xx-common.c
··· 30 30 #include <linux/watchdog.h> 31 31 #include <linux/miscdevice.h> 32 32 #include <linux/uaccess.h> 33 - #include <linux/kref.h> 34 33 #include <linux/slab.h> 35 34 #include "sch56xx-common.h" 36 35 ··· 66 67 struct sch56xx_watchdog_data { 67 68 u16 addr; 68 69 struct mutex *io_lock; 69 - struct kref kref; 70 70 struct watchdog_info wdinfo; 71 71 struct watchdog_device wddev; 72 72 u8 watchdog_preset; ··· 256 258 * Watchdog routines 257 259 */ 258 260 259 - /* Release our data struct when we're unregistered *and* 260 - all references to our watchdog device are released */ 261 - static void watchdog_release_resources(struct kref *r) 262 - { 263 - struct sch56xx_watchdog_data *data = 264 - container_of(r, struct sch56xx_watchdog_data, kref); 265 - kfree(data); 266 - } 267 - 268 261 static int watchdog_set_timeout(struct watchdog_device *wddev, 269 262 unsigned int timeout) 270 263 { ··· 384 395 return 0; 385 396 } 386 397 387 - static void watchdog_ref(struct watchdog_device *wddev) 388 - { 389 - struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev); 390 - 391 - kref_get(&data->kref); 392 - } 393 - 394 - static void watchdog_unref(struct watchdog_device *wddev) 395 - { 396 - struct sch56xx_watchdog_data *data = watchdog_get_drvdata(wddev); 397 - 398 - kref_put(&data->kref, watchdog_release_resources); 399 - } 400 - 401 398 static const struct watchdog_ops watchdog_ops = { 402 399 .owner = THIS_MODULE, 403 400 .start = watchdog_start, 404 401 .stop = watchdog_stop, 405 402 .ping = watchdog_trigger, 406 403 .set_timeout = watchdog_set_timeout, 407 - .ref = watchdog_ref, 408 - .unref = watchdog_unref, 409 404 }; 410 405 411 406 struct sch56xx_watchdog_data *sch56xx_watchdog_register(struct device *parent, ··· 421 448 422 449 data->addr = addr; 423 450 data->io_lock = io_lock; 424 - kref_init(&data->kref); 425 451 426 452 strlcpy(data->wdinfo.identity, "sch56xx watchdog", 427 453 sizeof(data->wdinfo.identity)); ··· 466 494 void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data) 467 495 { 468 496 watchdog_unregister_device(&data->wddev); 469 - kref_put(&data->kref, watchdog_release_resources); 470 - /* Don't touch data after this it may have been free-ed! */ 497 + kfree(data); 471 498 } 472 499 EXPORT_SYMBOL(sch56xx_watchdog_unregister); 473 500
+65
drivers/watchdog/Kconfig
··· 46 46 get killed. If you say Y here, the watchdog cannot be stopped once 47 47 it has been started. 48 48 49 + config WATCHDOG_SYSFS 50 + bool "Read different watchdog information through sysfs" 51 + default n 52 + help 53 + Say Y here if you want to enable watchdog device status read through 54 + sysfs attributes. 55 + 49 56 # 50 57 # General Watchdog drivers 51 58 # ··· 142 135 This driver can also be built as a module. If so the module 143 136 will be called menf21bmc_wdt. 144 137 138 + config TANGOX_WATCHDOG 139 + tristate "Sigma Designs SMP86xx/SMP87xx watchdog" 140 + select WATCHDOG_CORE 141 + depends on ARCH_TANGOX || COMPILE_TEST 142 + help 143 + Support for the watchdog in Sigma Designs SMP86xx (tango3) 144 + and SMP87xx (tango4) family chips. 145 + 146 + This driver can be built as a module. The module name is tangox_wdt. 147 + 145 148 config WM831X_WATCHDOG 146 149 tristate "WM831x watchdog" 147 150 depends on MFD_WM831X ··· 178 161 To compile this driver as a module, choose M here: the 179 162 module will be called of_xilinx_wdt. 180 163 164 + config ZIIRAVE_WATCHDOG 165 + tristate "Zodiac RAVE Watchdog Timer" 166 + depends on I2C 167 + select WATCHDOG_CORE 168 + help 169 + Watchdog driver for the Zodiac Aerospace RAVE Switch Watchdog 170 + Processor. 171 + 172 + To compile this driver as a module, choose M here: the 173 + module will be called ziirave_wdt. 174 + 181 175 # ALPHA Architecture 182 176 183 177 # ARM Architecture ··· 200 172 help 201 173 ARM Primecell SP805 Watchdog timer. This will reboot your system when 202 174 the timeout is reached. 175 + 176 + config ASM9260_WATCHDOG 177 + tristate "Alphascale ASM9260 watchdog" 178 + depends on MACH_ASM9260 179 + depends on OF 180 + select WATCHDOG_CORE 181 + select RESET_CONTROLLER 182 + help 183 + Watchdog timer embedded into Alphascale asm9260 chips. This will reboot your 184 + system when the timeout is reached. 203 185 204 186 config AT91RM9200_WATCHDOG 205 187 tristate "AT91RM9200 watchdog" ··· 464 426 To compile this driver as a module, choose M here: the 465 427 module will be called nuc900_wdt. 466 428 429 + config TS4800_WATCHDOG 430 + tristate "TS-4800 Watchdog" 431 + depends on HAS_IOMEM && OF 432 + select WATCHDOG_CORE 433 + select MFD_SYSCON 434 + help 435 + Technologic Systems TS-4800 has watchdog timer implemented in 436 + an external FPGA. Say Y here if you want to support for the 437 + watchdog timer on TS-4800 board. 438 + 467 439 config TS72XX_WATCHDOG 468 440 tristate "TS-72XX SBC Watchdog" 469 441 depends on MACH_TS72XX ··· 625 577 processors. 626 578 To compile this driver as a module, choose M here: the 627 579 module will be called lpc18xx_wdt. 580 + 581 + config ATLAS7_WATCHDOG 582 + tristate "CSRatlas7 watchdog" 583 + depends on ARCH_ATLAS7 584 + help 585 + Say Y here to include Watchdog timer support for the watchdog 586 + existing on the CSRatlas7 series platforms. 587 + 588 + To compile this driver as a module, choose M here: the 589 + module will be called atlas7_wdt. 628 590 629 591 # AVR32 Architecture 630 592 ··· 1402 1344 depends on RALINK 1403 1345 help 1404 1346 Hardware driver for the Ralink SoC Watchdog Timer. 1347 + 1348 + config MT7621_WDT 1349 + tristate "Mediatek SoC watchdog" 1350 + select WATCHDOG_CORE 1351 + depends on SOC_MT7620 || SOC_MT7621 1352 + help 1353 + Hardware driver for the Mediatek/Ralink MT7621/8 SoC Watchdog Timer. 1405 1354 1406 1355 # PARISC Architecture 1407 1356
+6
drivers/watchdog/Makefile
··· 30 30 31 31 # ARM Architecture 32 32 obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o 33 + obj-$(CONFIG_ASM9260_WATCHDOG) += asm9260_wdt.o 33 34 obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o 34 35 obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o 35 36 obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o ··· 54 53 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o 55 54 obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o 56 55 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o 56 + obj-$(CONFIG_TS4800_WATCHDOG) += ts4800_wdt.o 57 57 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o 58 58 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o 59 59 obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o ··· 71 69 obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o 72 70 obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o 73 71 obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o 72 + obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o 74 73 75 74 # AVR32 Architecture 76 75 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o ··· 152 149 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o 153 150 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o 154 151 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o 152 + obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o 155 153 156 154 # PARISC Architecture 157 155 ··· 191 187 obj-$(CONFIG_DA9062_WATCHDOG) += da9062_wdt.o 192 188 obj-$(CONFIG_DA9063_WATCHDOG) += da9063_wdt.o 193 189 obj-$(CONFIG_GPIO_WATCHDOG) += gpio_wdt.o 190 + obj-$(CONFIG_TANGOX_WATCHDOG) += tangox_wdt.o 194 191 obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o 195 192 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o 196 193 obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o 194 + obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o 197 195 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o 198 196 obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
+403
drivers/watchdog/asm9260_wdt.c
··· 1 + /* 2 + * Watchdog driver for Alphascale ASM9260. 3 + * 4 + * Copyright (c) 2014 Oleksij Rempel <linux@rempel-privat.de> 5 + * 6 + * Licensed under GPLv2 or later. 7 + */ 8 + 9 + #include <linux/bitops.h> 10 + #include <linux/clk.h> 11 + #include <linux/delay.h> 12 + #include <linux/interrupt.h> 13 + #include <linux/io.h> 14 + #include <linux/module.h> 15 + #include <linux/of.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/reboot.h> 18 + #include <linux/reset.h> 19 + #include <linux/watchdog.h> 20 + 21 + #define CLOCK_FREQ 1000000 22 + 23 + /* Watchdog Mode register */ 24 + #define HW_WDMOD 0x00 25 + /* Wake interrupt. Set by HW, can't be cleared. */ 26 + #define BM_MOD_WDINT BIT(3) 27 + /* This bit set if timeout reached. Cleared by SW. */ 28 + #define BM_MOD_WDTOF BIT(2) 29 + /* HW Reset on timeout */ 30 + #define BM_MOD_WDRESET BIT(1) 31 + /* WD enable */ 32 + #define BM_MOD_WDEN BIT(0) 33 + 34 + /* 35 + * Watchdog Timer Constant register 36 + * Minimal value is 0xff, the meaning of this value 37 + * depends on used clock: T = WDCLK * (0xff + 1) * 4 38 + */ 39 + #define HW_WDTC 0x04 40 + #define BM_WDTC_MAX(freq) (0x7fffffff / (freq)) 41 + 42 + /* Watchdog Feed register */ 43 + #define HW_WDFEED 0x08 44 + 45 + /* Watchdog Timer Value register */ 46 + #define HW_WDTV 0x0c 47 + 48 + #define ASM9260_WDT_DEFAULT_TIMEOUT 30 49 + 50 + enum asm9260_wdt_mode { 51 + HW_RESET, 52 + SW_RESET, 53 + DEBUG, 54 + }; 55 + 56 + struct asm9260_wdt_priv { 57 + struct device *dev; 58 + struct watchdog_device wdd; 59 + struct clk *clk; 60 + struct clk *clk_ahb; 61 + struct reset_control *rst; 62 + struct notifier_block restart_handler; 63 + 64 + void __iomem *iobase; 65 + int irq; 66 + unsigned long wdt_freq; 67 + enum asm9260_wdt_mode mode; 68 + }; 69 + 70 + static int asm9260_wdt_feed(struct watchdog_device *wdd) 71 + { 72 + struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd); 73 + 74 + iowrite32(0xaa, priv->iobase + HW_WDFEED); 75 + iowrite32(0x55, priv->iobase + HW_WDFEED); 76 + 77 + return 0; 78 + } 79 + 80 + static unsigned int asm9260_wdt_gettimeleft(struct watchdog_device *wdd) 81 + { 82 + struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd); 83 + u32 counter; 84 + 85 + counter = ioread32(priv->iobase + HW_WDTV); 86 + 87 + return DIV_ROUND_CLOSEST(counter, priv->wdt_freq); 88 + } 89 + 90 + static int asm9260_wdt_updatetimeout(struct watchdog_device *wdd) 91 + { 92 + struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd); 93 + u32 counter; 94 + 95 + counter = wdd->timeout * priv->wdt_freq; 96 + 97 + iowrite32(counter, priv->iobase + HW_WDTC); 98 + 99 + return 0; 100 + } 101 + 102 + static int asm9260_wdt_enable(struct watchdog_device *wdd) 103 + { 104 + struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd); 105 + u32 mode = 0; 106 + 107 + if (priv->mode == HW_RESET) 108 + mode = BM_MOD_WDRESET; 109 + 110 + iowrite32(BM_MOD_WDEN | mode, priv->iobase + HW_WDMOD); 111 + 112 + asm9260_wdt_updatetimeout(wdd); 113 + 114 + asm9260_wdt_feed(wdd); 115 + 116 + return 0; 117 + } 118 + 119 + static int asm9260_wdt_disable(struct watchdog_device *wdd) 120 + { 121 + struct asm9260_wdt_priv *priv = watchdog_get_drvdata(wdd); 122 + 123 + /* The only way to disable WD is to reset it. */ 124 + reset_control_assert(priv->rst); 125 + reset_control_deassert(priv->rst); 126 + 127 + return 0; 128 + } 129 + 130 + static int asm9260_wdt_settimeout(struct watchdog_device *wdd, unsigned int to) 131 + { 132 + wdd->timeout = to; 133 + asm9260_wdt_updatetimeout(wdd); 134 + 135 + return 0; 136 + } 137 + 138 + static void asm9260_wdt_sys_reset(struct asm9260_wdt_priv *priv) 139 + { 140 + /* init WD if it was not started */ 141 + 142 + iowrite32(BM_MOD_WDEN | BM_MOD_WDRESET, priv->iobase + HW_WDMOD); 143 + 144 + iowrite32(0xff, priv->iobase + HW_WDTC); 145 + /* first pass correct sequence */ 146 + asm9260_wdt_feed(&priv->wdd); 147 + /* 148 + * Then write wrong pattern to the feed to trigger reset 149 + * ASAP. 150 + */ 151 + iowrite32(0xff, priv->iobase + HW_WDFEED); 152 + 153 + mdelay(1000); 154 + } 155 + 156 + static irqreturn_t asm9260_wdt_irq(int irq, void *devid) 157 + { 158 + struct asm9260_wdt_priv *priv = devid; 159 + u32 stat; 160 + 161 + stat = ioread32(priv->iobase + HW_WDMOD); 162 + if (!(stat & BM_MOD_WDINT)) 163 + return IRQ_NONE; 164 + 165 + if (priv->mode == DEBUG) { 166 + dev_info(priv->dev, "Watchdog Timeout. Do nothing.\n"); 167 + } else { 168 + dev_info(priv->dev, "Watchdog Timeout. Doing SW Reset.\n"); 169 + asm9260_wdt_sys_reset(priv); 170 + } 171 + 172 + return IRQ_HANDLED; 173 + } 174 + 175 + static int asm9260_restart_handler(struct notifier_block *this, 176 + unsigned long mode, void *cmd) 177 + { 178 + struct asm9260_wdt_priv *priv = 179 + container_of(this, struct asm9260_wdt_priv, restart_handler); 180 + 181 + asm9260_wdt_sys_reset(priv); 182 + 183 + return NOTIFY_DONE; 184 + } 185 + 186 + static const struct watchdog_info asm9260_wdt_ident = { 187 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING 188 + | WDIOF_MAGICCLOSE, 189 + .identity = "Alphascale asm9260 Watchdog", 190 + }; 191 + 192 + static struct watchdog_ops asm9260_wdt_ops = { 193 + .owner = THIS_MODULE, 194 + .start = asm9260_wdt_enable, 195 + .stop = asm9260_wdt_disable, 196 + .get_timeleft = asm9260_wdt_gettimeleft, 197 + .ping = asm9260_wdt_feed, 198 + .set_timeout = asm9260_wdt_settimeout, 199 + }; 200 + 201 + static int asm9260_wdt_get_dt_clks(struct asm9260_wdt_priv *priv) 202 + { 203 + int err; 204 + unsigned long clk; 205 + 206 + priv->clk = devm_clk_get(priv->dev, "mod"); 207 + if (IS_ERR(priv->clk)) { 208 + dev_err(priv->dev, "Failed to get \"mod\" clk\n"); 209 + return PTR_ERR(priv->clk); 210 + } 211 + 212 + /* configure AHB clock */ 213 + priv->clk_ahb = devm_clk_get(priv->dev, "ahb"); 214 + if (IS_ERR(priv->clk_ahb)) { 215 + dev_err(priv->dev, "Failed to get \"ahb\" clk\n"); 216 + return PTR_ERR(priv->clk_ahb); 217 + } 218 + 219 + err = clk_prepare_enable(priv->clk_ahb); 220 + if (err) { 221 + dev_err(priv->dev, "Failed to enable ahb_clk!\n"); 222 + return err; 223 + } 224 + 225 + err = clk_set_rate(priv->clk, CLOCK_FREQ); 226 + if (err) { 227 + clk_disable_unprepare(priv->clk_ahb); 228 + dev_err(priv->dev, "Failed to set rate!\n"); 229 + return err; 230 + } 231 + 232 + err = clk_prepare_enable(priv->clk); 233 + if (err) { 234 + clk_disable_unprepare(priv->clk_ahb); 235 + dev_err(priv->dev, "Failed to enable clk!\n"); 236 + return err; 237 + } 238 + 239 + /* wdt has internal divider */ 240 + clk = clk_get_rate(priv->clk); 241 + if (!clk) { 242 + clk_disable_unprepare(priv->clk); 243 + clk_disable_unprepare(priv->clk_ahb); 244 + dev_err(priv->dev, "Failed, clk is 0!\n"); 245 + return -EINVAL; 246 + } 247 + 248 + priv->wdt_freq = clk / 2; 249 + 250 + return 0; 251 + } 252 + 253 + static void asm9260_wdt_get_dt_mode(struct asm9260_wdt_priv *priv) 254 + { 255 + const char *tmp; 256 + int ret; 257 + 258 + /* default mode */ 259 + priv->mode = HW_RESET; 260 + 261 + ret = of_property_read_string(priv->dev->of_node, 262 + "alphascale,mode", &tmp); 263 + if (ret < 0) 264 + return; 265 + 266 + if (!strcmp(tmp, "hw")) 267 + priv->mode = HW_RESET; 268 + else if (!strcmp(tmp, "sw")) 269 + priv->mode = SW_RESET; 270 + else if (!strcmp(tmp, "debug")) 271 + priv->mode = DEBUG; 272 + else 273 + dev_warn(priv->dev, "unknown reset-type: %s. Using default \"hw\" mode.", 274 + tmp); 275 + } 276 + 277 + static int asm9260_wdt_probe(struct platform_device *pdev) 278 + { 279 + struct asm9260_wdt_priv *priv; 280 + struct watchdog_device *wdd; 281 + struct resource *res; 282 + int ret; 283 + const char * const mode_name[] = { "hw", "sw", "debug", }; 284 + 285 + priv = devm_kzalloc(&pdev->dev, sizeof(struct asm9260_wdt_priv), 286 + GFP_KERNEL); 287 + if (!priv) 288 + return -ENOMEM; 289 + 290 + priv->dev = &pdev->dev; 291 + 292 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 293 + priv->iobase = devm_ioremap_resource(&pdev->dev, res); 294 + if (IS_ERR(priv->iobase)) 295 + return PTR_ERR(priv->iobase); 296 + 297 + ret = asm9260_wdt_get_dt_clks(priv); 298 + if (ret) 299 + return ret; 300 + 301 + priv->rst = devm_reset_control_get(&pdev->dev, "wdt_rst"); 302 + if (IS_ERR(priv->rst)) 303 + return PTR_ERR(priv->rst); 304 + 305 + wdd = &priv->wdd; 306 + wdd->info = &asm9260_wdt_ident; 307 + wdd->ops = &asm9260_wdt_ops; 308 + wdd->min_timeout = 1; 309 + wdd->max_timeout = BM_WDTC_MAX(priv->wdt_freq); 310 + wdd->parent = &pdev->dev; 311 + 312 + watchdog_set_drvdata(wdd, priv); 313 + 314 + /* 315 + * If 'timeout-sec' unspecified in devicetree, assume a 30 second 316 + * default, unless the max timeout is less than 30 seconds, then use 317 + * the max instead. 318 + */ 319 + wdd->timeout = ASM9260_WDT_DEFAULT_TIMEOUT; 320 + watchdog_init_timeout(wdd, 0, &pdev->dev); 321 + 322 + asm9260_wdt_get_dt_mode(priv); 323 + 324 + if (priv->mode != HW_RESET) 325 + priv->irq = platform_get_irq(pdev, 0); 326 + 327 + if (priv->irq > 0) { 328 + /* 329 + * Not all supported platforms specify an interrupt for the 330 + * watchdog, so let's make it optional. 331 + */ 332 + ret = devm_request_irq(&pdev->dev, priv->irq, 333 + asm9260_wdt_irq, 0, pdev->name, priv); 334 + if (ret < 0) 335 + dev_warn(&pdev->dev, "failed to request IRQ\n"); 336 + } 337 + 338 + ret = watchdog_register_device(wdd); 339 + if (ret) 340 + goto clk_off; 341 + 342 + platform_set_drvdata(pdev, priv); 343 + 344 + priv->restart_handler.notifier_call = asm9260_restart_handler; 345 + priv->restart_handler.priority = 128; 346 + ret = register_restart_handler(&priv->restart_handler); 347 + if (ret) 348 + dev_warn(&pdev->dev, "cannot register restart handler\n"); 349 + 350 + dev_info(&pdev->dev, "Watchdog enabled (timeout: %d sec, mode: %s)\n", 351 + wdd->timeout, mode_name[priv->mode]); 352 + return 0; 353 + 354 + clk_off: 355 + clk_disable_unprepare(priv->clk); 356 + clk_disable_unprepare(priv->clk_ahb); 357 + return ret; 358 + } 359 + 360 + static void asm9260_wdt_shutdown(struct platform_device *pdev) 361 + { 362 + struct asm9260_wdt_priv *priv = platform_get_drvdata(pdev); 363 + 364 + asm9260_wdt_disable(&priv->wdd); 365 + } 366 + 367 + static int asm9260_wdt_remove(struct platform_device *pdev) 368 + { 369 + struct asm9260_wdt_priv *priv = platform_get_drvdata(pdev); 370 + 371 + asm9260_wdt_disable(&priv->wdd); 372 + 373 + unregister_restart_handler(&priv->restart_handler); 374 + 375 + watchdog_unregister_device(&priv->wdd); 376 + 377 + clk_disable_unprepare(priv->clk); 378 + clk_disable_unprepare(priv->clk_ahb); 379 + 380 + return 0; 381 + } 382 + 383 + static const struct of_device_id asm9260_wdt_of_match[] = { 384 + { .compatible = "alphascale,asm9260-wdt"}, 385 + {}, 386 + }; 387 + MODULE_DEVICE_TABLE(of, asm9260_wdt_of_match); 388 + 389 + static struct platform_driver asm9260_wdt_driver = { 390 + .driver = { 391 + .name = "asm9260-wdt", 392 + .owner = THIS_MODULE, 393 + .of_match_table = asm9260_wdt_of_match, 394 + }, 395 + .probe = asm9260_wdt_probe, 396 + .remove = asm9260_wdt_remove, 397 + .shutdown = asm9260_wdt_shutdown, 398 + }; 399 + module_platform_driver(asm9260_wdt_driver); 400 + 401 + MODULE_DESCRIPTION("asm9260 WatchDog Timer Driver"); 402 + MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>"); 403 + MODULE_LICENSE("GPL");
+242
drivers/watchdog/atlas7_wdt.c
··· 1 + /* 2 + * Watchdog driver for CSR Atlas7 3 + * 4 + * Copyright (c) 2015 Cambridge Silicon Radio Limited, a CSR plc group company. 5 + * 6 + * Licensed under GPLv2. 7 + */ 8 + 9 + #include <linux/clk.h> 10 + #include <linux/io.h> 11 + #include <linux/module.h> 12 + #include <linux/moduleparam.h> 13 + #include <linux/of.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/watchdog.h> 16 + 17 + #define ATLAS7_TIMER_WDT_INDEX 5 18 + #define ATLAS7_WDT_DEFAULT_TIMEOUT 20 19 + 20 + #define ATLAS7_WDT_CNT_CTRL (0 + 4 * ATLAS7_TIMER_WDT_INDEX) 21 + #define ATLAS7_WDT_CNT_MATCH (0x18 + 4 * ATLAS7_TIMER_WDT_INDEX) 22 + #define ATLAS7_WDT_CNT (0x48 + 4 * ATLAS7_TIMER_WDT_INDEX) 23 + #define ATLAS7_WDT_CNT_EN (BIT(0) | BIT(1)) 24 + #define ATLAS7_WDT_EN 0x64 25 + 26 + static unsigned int timeout = ATLAS7_WDT_DEFAULT_TIMEOUT; 27 + static bool nowayout = WATCHDOG_NOWAYOUT; 28 + 29 + module_param(timeout, uint, 0); 30 + module_param(nowayout, bool, 0); 31 + 32 + MODULE_PARM_DESC(timeout, "Default watchdog timeout (in seconds)"); 33 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 34 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 35 + 36 + struct atlas7_wdog { 37 + struct device *dev; 38 + void __iomem *base; 39 + unsigned long tick_rate; 40 + struct clk *clk; 41 + }; 42 + 43 + static unsigned int atlas7_wdt_gettimeleft(struct watchdog_device *wdd) 44 + { 45 + struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); 46 + u32 counter, match, delta; 47 + 48 + counter = readl(wdt->base + ATLAS7_WDT_CNT); 49 + match = readl(wdt->base + ATLAS7_WDT_CNT_MATCH); 50 + delta = match - counter; 51 + 52 + return delta / wdt->tick_rate; 53 + } 54 + 55 + static int atlas7_wdt_ping(struct watchdog_device *wdd) 56 + { 57 + struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); 58 + u32 counter, match, delta; 59 + 60 + counter = readl(wdt->base + ATLAS7_WDT_CNT); 61 + delta = wdd->timeout * wdt->tick_rate; 62 + match = counter + delta; 63 + 64 + writel(match, wdt->base + ATLAS7_WDT_CNT_MATCH); 65 + 66 + return 0; 67 + } 68 + 69 + static int atlas7_wdt_enable(struct watchdog_device *wdd) 70 + { 71 + struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); 72 + 73 + atlas7_wdt_ping(wdd); 74 + 75 + writel(readl(wdt->base + ATLAS7_WDT_CNT_CTRL) | ATLAS7_WDT_CNT_EN, 76 + wdt->base + ATLAS7_WDT_CNT_CTRL); 77 + writel(1, wdt->base + ATLAS7_WDT_EN); 78 + 79 + return 0; 80 + } 81 + 82 + static int atlas7_wdt_disable(struct watchdog_device *wdd) 83 + { 84 + struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); 85 + 86 + writel(0, wdt->base + ATLAS7_WDT_EN); 87 + writel(readl(wdt->base + ATLAS7_WDT_CNT_CTRL) & ~ATLAS7_WDT_CNT_EN, 88 + wdt->base + ATLAS7_WDT_CNT_CTRL); 89 + 90 + return 0; 91 + } 92 + 93 + static int atlas7_wdt_settimeout(struct watchdog_device *wdd, unsigned int to) 94 + { 95 + wdd->timeout = to; 96 + 97 + return 0; 98 + } 99 + 100 + #define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE) 101 + 102 + static const struct watchdog_info atlas7_wdt_ident = { 103 + .options = OPTIONS, 104 + .firmware_version = 0, 105 + .identity = "atlas7 Watchdog", 106 + }; 107 + 108 + static struct watchdog_ops atlas7_wdt_ops = { 109 + .owner = THIS_MODULE, 110 + .start = atlas7_wdt_enable, 111 + .stop = atlas7_wdt_disable, 112 + .get_timeleft = atlas7_wdt_gettimeleft, 113 + .ping = atlas7_wdt_ping, 114 + .set_timeout = atlas7_wdt_settimeout, 115 + }; 116 + 117 + static struct watchdog_device atlas7_wdd = { 118 + .info = &atlas7_wdt_ident, 119 + .ops = &atlas7_wdt_ops, 120 + .timeout = ATLAS7_WDT_DEFAULT_TIMEOUT, 121 + }; 122 + 123 + static const struct of_device_id atlas7_wdt_ids[] = { 124 + { .compatible = "sirf,atlas7-tick"}, 125 + {} 126 + }; 127 + 128 + static int atlas7_wdt_probe(struct platform_device *pdev) 129 + { 130 + struct device_node *np = pdev->dev.of_node; 131 + struct atlas7_wdog *wdt; 132 + struct resource *res; 133 + struct clk *clk; 134 + int ret; 135 + 136 + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 137 + if (!wdt) 138 + return -ENOMEM; 139 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 140 + wdt->base = devm_ioremap_resource(&pdev->dev, res); 141 + if (IS_ERR(wdt->base)) 142 + return PTR_ERR(wdt->base); 143 + 144 + clk = of_clk_get(np, 0); 145 + if (IS_ERR(clk)) 146 + return PTR_ERR(clk); 147 + ret = clk_prepare_enable(clk); 148 + if (ret) { 149 + dev_err(&pdev->dev, "clk enable failed\n"); 150 + goto err; 151 + } 152 + 153 + /* disable watchdog hardware */ 154 + writel(0, wdt->base + ATLAS7_WDT_CNT_CTRL); 155 + 156 + wdt->tick_rate = clk_get_rate(clk); 157 + wdt->clk = clk; 158 + atlas7_wdd.min_timeout = 1; 159 + atlas7_wdd.max_timeout = UINT_MAX / wdt->tick_rate; 160 + 161 + watchdog_init_timeout(&atlas7_wdd, 0, &pdev->dev); 162 + watchdog_set_nowayout(&atlas7_wdd, nowayout); 163 + 164 + watchdog_set_drvdata(&atlas7_wdd, wdt); 165 + platform_set_drvdata(pdev, &atlas7_wdd); 166 + 167 + ret = watchdog_register_device(&atlas7_wdd); 168 + if (ret) 169 + goto err1; 170 + 171 + return 0; 172 + 173 + err1: 174 + clk_disable_unprepare(clk); 175 + err: 176 + clk_put(clk); 177 + return ret; 178 + } 179 + 180 + static void atlas7_wdt_shutdown(struct platform_device *pdev) 181 + { 182 + struct watchdog_device *wdd = platform_get_drvdata(pdev); 183 + struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); 184 + 185 + atlas7_wdt_disable(wdd); 186 + clk_disable_unprepare(wdt->clk); 187 + } 188 + 189 + static int atlas7_wdt_remove(struct platform_device *pdev) 190 + { 191 + struct watchdog_device *wdd = platform_get_drvdata(pdev); 192 + struct atlas7_wdog *wdt = watchdog_get_drvdata(wdd); 193 + 194 + atlas7_wdt_shutdown(pdev); 195 + clk_put(wdt->clk); 196 + return 0; 197 + } 198 + 199 + static int __maybe_unused atlas7_wdt_suspend(struct device *dev) 200 + { 201 + /* 202 + * NOTE:timer controller registers settings are saved 203 + * and restored back by the timer-atlas7.c 204 + */ 205 + return 0; 206 + } 207 + 208 + static int __maybe_unused atlas7_wdt_resume(struct device *dev) 209 + { 210 + struct watchdog_device *wdd = dev_get_drvdata(dev); 211 + 212 + /* 213 + * NOTE: Since timer controller registers settings are saved 214 + * and restored back by the timer-atlas7.c, so we need not 215 + * update WD settings except refreshing timeout. 216 + */ 217 + atlas7_wdt_ping(wdd); 218 + 219 + return 0; 220 + } 221 + 222 + static SIMPLE_DEV_PM_OPS(atlas7_wdt_pm_ops, 223 + atlas7_wdt_suspend, atlas7_wdt_resume); 224 + 225 + MODULE_DEVICE_TABLE(of, atlas7_wdt_ids); 226 + 227 + static struct platform_driver atlas7_wdt_driver = { 228 + .driver = { 229 + .name = "atlas7-wdt", 230 + .pm = &atlas7_wdt_pm_ops, 231 + .of_match_table = atlas7_wdt_ids, 232 + }, 233 + .probe = atlas7_wdt_probe, 234 + .remove = atlas7_wdt_remove, 235 + .shutdown = atlas7_wdt_shutdown, 236 + }; 237 + module_platform_driver(atlas7_wdt_driver); 238 + 239 + MODULE_DESCRIPTION("CSRatlas7 watchdog driver"); 240 + MODULE_AUTHOR("Guo Zeng <Guo.Zeng@csr.com>"); 241 + MODULE_LICENSE("GPL v2"); 242 + MODULE_ALIAS("platform:atlas7-wdt");
-1
drivers/watchdog/bcm2835_wdt.c
··· 79 79 struct bcm2835_wdt *wdt = watchdog_get_drvdata(wdog); 80 80 81 81 writel_relaxed(PM_PASSWORD | PM_RSTC_RESET, wdt->base + PM_RSTC); 82 - dev_info(wdog->dev, "Watchdog timer stopped"); 83 82 return 0; 84 83 } 85 84
+14 -41
drivers/watchdog/bcm47xx_wdt.c
··· 20 20 #include <linux/module.h> 21 21 #include <linux/moduleparam.h> 22 22 #include <linux/platform_device.h> 23 - #include <linux/reboot.h> 24 23 #include <linux/types.h> 25 24 #include <linux/watchdog.h> 26 25 #include <linux/timer.h> ··· 87 88 return 0; 88 89 } 89 90 91 + static int bcm47xx_wdt_restart(struct watchdog_device *wdd) 92 + { 93 + struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd); 94 + 95 + wdt->timer_set(wdt, 1); 96 + 97 + return 0; 98 + } 99 + 90 100 static struct watchdog_ops bcm47xx_wdt_hard_ops = { 91 101 .owner = THIS_MODULE, 92 102 .start = bcm47xx_wdt_hard_start, 93 103 .stop = bcm47xx_wdt_hard_stop, 94 104 .ping = bcm47xx_wdt_hard_keepalive, 95 105 .set_timeout = bcm47xx_wdt_hard_set_timeout, 106 + .restart = bcm47xx_wdt_restart, 96 107 }; 97 108 98 109 static void bcm47xx_wdt_soft_timer_tick(unsigned long data) ··· 167 158 WDIOF_MAGICCLOSE, 168 159 }; 169 160 170 - static int bcm47xx_wdt_notify_sys(struct notifier_block *this, 171 - unsigned long code, void *unused) 172 - { 173 - struct bcm47xx_wdt *wdt; 174 - 175 - wdt = container_of(this, struct bcm47xx_wdt, notifier); 176 - if (code == SYS_DOWN || code == SYS_HALT) 177 - wdt->wdd.ops->stop(&wdt->wdd); 178 - return NOTIFY_DONE; 179 - } 180 - 181 - static int bcm47xx_wdt_restart(struct notifier_block *this, unsigned long mode, 182 - void *cmd) 183 - { 184 - struct bcm47xx_wdt *wdt; 185 - 186 - wdt = container_of(this, struct bcm47xx_wdt, restart_handler); 187 - wdt->timer_set(wdt, 1); 188 - 189 - return NOTIFY_DONE; 190 - } 191 - 192 161 static struct watchdog_ops bcm47xx_wdt_soft_ops = { 193 162 .owner = THIS_MODULE, 194 163 .start = bcm47xx_wdt_soft_start, 195 164 .stop = bcm47xx_wdt_soft_stop, 196 165 .ping = bcm47xx_wdt_soft_keepalive, 197 166 .set_timeout = bcm47xx_wdt_soft_set_timeout, 167 + .restart = bcm47xx_wdt_restart, 198 168 }; 199 169 200 170 static int bcm47xx_wdt_probe(struct platform_device *pdev) ··· 202 214 if (ret) 203 215 goto err_timer; 204 216 watchdog_set_nowayout(&wdt->wdd, nowayout); 205 - 206 - wdt->notifier.notifier_call = &bcm47xx_wdt_notify_sys; 207 - 208 - ret = register_reboot_notifier(&wdt->notifier); 209 - if (ret) 210 - goto err_timer; 211 - 212 - wdt->restart_handler.notifier_call = &bcm47xx_wdt_restart; 213 - wdt->restart_handler.priority = 64; 214 - ret = register_restart_handler(&wdt->restart_handler); 215 - if (ret) 216 - goto err_notifier; 217 + watchdog_set_restart_priority(&wdt->wdd, 64); 218 + watchdog_stop_on_reboot(&wdt->wdd); 217 219 218 220 ret = watchdog_register_device(&wdt->wdd); 219 221 if (ret) 220 - goto err_handler; 222 + goto err_timer; 221 223 222 224 dev_info(&pdev->dev, "BCM47xx Watchdog Timer enabled (%d seconds%s%s)\n", 223 225 timeout, nowayout ? ", nowayout" : "", 224 226 soft ? ", Software Timer" : ""); 225 227 return 0; 226 228 227 - err_handler: 228 - unregister_restart_handler(&wdt->restart_handler); 229 - err_notifier: 230 - unregister_reboot_notifier(&wdt->notifier); 231 229 err_timer: 232 230 if (soft) 233 231 del_timer_sync(&wdt->soft_timer); ··· 229 255 return -ENXIO; 230 256 231 257 watchdog_unregister_device(&wdt->wdd); 232 - unregister_reboot_notifier(&wdt->notifier); 233 258 234 259 return 0; 235 260 }
+3 -39
drivers/watchdog/cadence_wdt.c
··· 18 18 #include <linux/module.h> 19 19 #include <linux/of.h> 20 20 #include <linux/platform_device.h> 21 - #include <linux/reboot.h> 22 21 #include <linux/watchdog.h> 23 22 24 23 #define CDNS_WDT_DEFAULT_TIMEOUT 10 ··· 71 72 * @ctrl_clksel: counter clock prescaler selection 72 73 * @io_lock: spinlock for IO register access 73 74 * @cdns_wdt_device: watchdog device structure 74 - * @cdns_wdt_notifier: notifier structure 75 75 * 76 76 * Structure containing parameters specific to cadence watchdog. 77 77 */ ··· 82 84 u32 ctrl_clksel; 83 85 spinlock_t io_lock; 84 86 struct watchdog_device cdns_wdt_device; 85 - struct notifier_block cdns_wdt_notifier; 86 87 }; 87 88 88 89 /* Write access to Registers */ ··· 277 280 .set_timeout = cdns_wdt_settimeout, 278 281 }; 279 282 280 - /** 281 - * cdns_wdt_notify_sys - Notifier for reboot or shutdown. 282 - * 283 - * @this: handle to notifier block 284 - * @code: turn off indicator 285 - * @unused: unused 286 - * Return: NOTIFY_DONE 287 - * 288 - * This notifier is invoked whenever the system reboot or shutdown occur 289 - * because we need to disable the WDT before system goes down as WDT might 290 - * reset on the next boot. 291 - */ 292 - static int cdns_wdt_notify_sys(struct notifier_block *this, unsigned long code, 293 - void *unused) 294 - { 295 - struct cdns_wdt *wdt = container_of(this, struct cdns_wdt, 296 - cdns_wdt_notifier); 297 - if (code == SYS_DOWN || code == SYS_HALT) 298 - cdns_wdt_stop(&wdt->cdns_wdt_device); 299 - 300 - return NOTIFY_DONE; 301 - } 302 - 303 283 /************************Platform Operations*****************************/ 304 284 /** 305 285 * cdns_wdt_probe - Probe call for the device. ··· 334 360 } 335 361 336 362 watchdog_set_nowayout(cdns_wdt_device, nowayout); 363 + watchdog_stop_on_reboot(cdns_wdt_device); 337 364 watchdog_set_drvdata(cdns_wdt_device, wdt); 338 365 339 366 wdt->clk = devm_clk_get(&pdev->dev, NULL); ··· 360 385 } 361 386 362 387 spin_lock_init(&wdt->io_lock); 363 - 364 - wdt->cdns_wdt_notifier.notifier_call = &cdns_wdt_notify_sys; 365 - ret = register_reboot_notifier(&wdt->cdns_wdt_notifier); 366 - if (ret != 0) { 367 - dev_err(&pdev->dev, "cannot register reboot notifier err=%d)\n", 368 - ret); 369 - goto err_clk_disable; 370 - } 371 388 372 389 ret = watchdog_register_device(cdns_wdt_device); 373 390 if (ret) { ··· 394 427 395 428 cdns_wdt_stop(&wdt->cdns_wdt_device); 396 429 watchdog_unregister_device(&wdt->cdns_wdt_device); 397 - unregister_reboot_notifier(&wdt->cdns_wdt_notifier); 398 430 clk_disable_unprepare(wdt->clk); 399 431 400 432 return 0; ··· 421 455 */ 422 456 static int __maybe_unused cdns_wdt_suspend(struct device *dev) 423 457 { 424 - struct platform_device *pdev = container_of(dev, 425 - struct platform_device, dev); 458 + struct platform_device *pdev = to_platform_device(dev); 426 459 struct cdns_wdt *wdt = platform_get_drvdata(pdev); 427 460 428 461 cdns_wdt_stop(&wdt->cdns_wdt_device); ··· 439 474 static int __maybe_unused cdns_wdt_resume(struct device *dev) 440 475 { 441 476 int ret; 442 - struct platform_device *pdev = container_of(dev, 443 - struct platform_device, dev); 477 + struct platform_device *pdev = to_platform_device(dev); 444 478 struct cdns_wdt *wdt = platform_get_drvdata(pdev); 445 479 446 480 ret = clk_prepare_enable(wdt->clk);
-24
drivers/watchdog/da9052_wdt.c
··· 31 31 struct da9052_wdt_data { 32 32 struct watchdog_device wdt; 33 33 struct da9052 *da9052; 34 - struct kref kref; 35 34 unsigned long jpast; 36 35 }; 37 36 ··· 49 50 { 7, 131 }, 50 51 }; 51 52 52 - 53 - static void da9052_wdt_release_resources(struct kref *r) 54 - { 55 - } 56 53 57 54 static int da9052_wdt_set_timeout(struct watchdog_device *wdt_dev, 58 55 unsigned int timeout) ··· 97 102 } 98 103 99 104 return 0; 100 - } 101 - 102 - static void da9052_wdt_ref(struct watchdog_device *wdt_dev) 103 - { 104 - struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 105 - 106 - kref_get(&driver_data->kref); 107 - } 108 - 109 - static void da9052_wdt_unref(struct watchdog_device *wdt_dev) 110 - { 111 - struct da9052_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 112 - 113 - kref_put(&driver_data->kref, da9052_wdt_release_resources); 114 105 } 115 106 116 107 static int da9052_wdt_start(struct watchdog_device *wdt_dev) ··· 151 170 .stop = da9052_wdt_stop, 152 171 .ping = da9052_wdt_ping, 153 172 .set_timeout = da9052_wdt_set_timeout, 154 - .ref = da9052_wdt_ref, 155 - .unref = da9052_wdt_unref, 156 173 }; 157 174 158 175 ··· 177 198 da9052_wdt->parent = &pdev->dev; 178 199 watchdog_set_drvdata(da9052_wdt, driver_data); 179 200 180 - kref_init(&driver_data->kref); 181 - 182 201 ret = da9052_reg_update(da9052, DA9052_CONTROL_D_REG, 183 202 DA9052_CONTROLD_TWDSCALE, 0); 184 203 if (ret < 0) { ··· 202 225 struct da9052_wdt_data *driver_data = platform_get_drvdata(pdev); 203 226 204 227 watchdog_unregister_device(&driver_data->wdt); 205 - kref_put(&driver_data->kref, da9052_wdt_release_resources); 206 228 207 229 return 0; 208 230 }
-24
drivers/watchdog/da9055_wdt.c
··· 35 35 struct da9055_wdt_data { 36 36 struct watchdog_device wdt; 37 37 struct da9055 *da9055; 38 - struct kref kref; 39 38 }; 40 39 41 40 static const struct { ··· 98 99 DA9055_WATCHDOG_MASK, 1); 99 100 } 100 101 101 - static void da9055_wdt_release_resources(struct kref *r) 102 - { 103 - } 104 - 105 - static void da9055_wdt_ref(struct watchdog_device *wdt_dev) 106 - { 107 - struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 108 - 109 - kref_get(&driver_data->kref); 110 - } 111 - 112 - static void da9055_wdt_unref(struct watchdog_device *wdt_dev) 113 - { 114 - struct da9055_wdt_data *driver_data = watchdog_get_drvdata(wdt_dev); 115 - 116 - kref_put(&driver_data->kref, da9055_wdt_release_resources); 117 - } 118 - 119 102 static int da9055_wdt_start(struct watchdog_device *wdt_dev) 120 103 { 121 104 return da9055_wdt_set_timeout(wdt_dev, wdt_dev->timeout); ··· 119 138 .stop = da9055_wdt_stop, 120 139 .ping = da9055_wdt_ping, 121 140 .set_timeout = da9055_wdt_set_timeout, 122 - .ref = da9055_wdt_ref, 123 - .unref = da9055_wdt_unref, 124 141 }; 125 142 126 143 static int da9055_wdt_probe(struct platform_device *pdev) ··· 144 165 watchdog_set_nowayout(da9055_wdt, nowayout); 145 166 watchdog_set_drvdata(da9055_wdt, driver_data); 146 167 147 - kref_init(&driver_data->kref); 148 - 149 168 ret = da9055_wdt_stop(da9055_wdt); 150 169 if (ret < 0) { 151 170 dev_err(&pdev->dev, "Failed to stop watchdog, %d\n", ret); ··· 166 189 struct da9055_wdt_data *driver_data = platform_get_drvdata(pdev); 167 190 168 191 watchdog_unregister_device(&driver_data->wdt); 169 - kref_put(&driver_data->kref, da9055_wdt_release_resources); 170 192 171 193 return 0; 172 194 }
+6 -17
drivers/watchdog/da9063_wdt.c
··· 20 20 #include <linux/delay.h> 21 21 #include <linux/mfd/da9063/registers.h> 22 22 #include <linux/mfd/da9063/core.h> 23 - #include <linux/reboot.h> 24 23 #include <linux/regmap.h> 25 24 26 25 /* ··· 38 39 struct da9063_watchdog { 39 40 struct da9063 *da9063; 40 41 struct watchdog_device wdtdev; 41 - struct notifier_block restart_handler; 42 42 }; 43 43 44 44 static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs) ··· 119 121 return ret; 120 122 } 121 123 122 - static int da9063_wdt_restart_handler(struct notifier_block *this, 123 - unsigned long mode, void *cmd) 124 + static int da9063_wdt_restart(struct watchdog_device *wdd) 124 125 { 125 - struct da9063_watchdog *wdt = container_of(this, 126 - struct da9063_watchdog, 127 - restart_handler); 126 + struct da9063_watchdog *wdt = watchdog_get_drvdata(wdd); 128 127 int ret; 129 128 130 129 ret = regmap_write(wdt->da9063->regmap, DA9063_REG_CONTROL_F, ··· 130 135 dev_alert(wdt->da9063->dev, "Failed to shutdown (err = %d)\n", 131 136 ret); 132 137 133 - return NOTIFY_DONE; 138 + return ret; 134 139 } 135 140 136 141 static const struct watchdog_info da9063_watchdog_info = { ··· 144 149 .stop = da9063_wdt_stop, 145 150 .ping = da9063_wdt_ping, 146 151 .set_timeout = da9063_wdt_set_timeout, 152 + .restart = da9063_wdt_restart, 147 153 }; 148 154 149 155 static int da9063_wdt_probe(struct platform_device *pdev) ··· 175 179 176 180 wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS; 177 181 182 + watchdog_set_restart_priority(&wdt->wdtdev, 128); 183 + 178 184 watchdog_set_drvdata(&wdt->wdtdev, wdt); 179 185 dev_set_drvdata(&pdev->dev, wdt); 180 186 ··· 184 186 if (ret) 185 187 return ret; 186 188 187 - wdt->restart_handler.notifier_call = da9063_wdt_restart_handler; 188 - wdt->restart_handler.priority = 128; 189 - ret = register_restart_handler(&wdt->restart_handler); 190 - if (ret) 191 - dev_err(wdt->da9063->dev, 192 - "Failed to register restart handler (err = %d)\n", ret); 193 - 194 189 return 0; 195 190 } 196 191 197 192 static int da9063_wdt_remove(struct platform_device *pdev) 198 193 { 199 194 struct da9063_watchdog *wdt = dev_get_drvdata(&pdev->dev); 200 - 201 - unregister_restart_handler(&wdt->restart_handler); 202 195 203 196 watchdog_unregister_device(&wdt->wdtdev); 204 197
+16 -10
drivers/watchdog/diag288_wdt.c
··· 106 106 return __diag288(func, timeout, action, 0); 107 107 } 108 108 109 + static unsigned long wdt_status; 110 + 111 + #define DIAG_WDOG_BUSY 0 112 + 109 113 static int wdt_start(struct watchdog_device *dev) 110 114 { 111 115 char *ebc_cmd; ··· 117 113 int ret; 118 114 unsigned int func; 119 115 116 + if (test_and_set_bit(DIAG_WDOG_BUSY, &wdt_status)) 117 + return -EBUSY; 118 + 120 119 ret = -ENODEV; 121 120 122 121 if (MACHINE_IS_VM) { 123 122 ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL); 124 - if (!ebc_cmd) 123 + if (!ebc_cmd) { 124 + clear_bit(DIAG_WDOG_BUSY, &wdt_status); 125 125 return -ENOMEM; 126 + } 126 127 len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN); 127 128 ASCEBC(ebc_cmd, MAX_CMDLEN); 128 129 EBC_TOUPPER(ebc_cmd, MAX_CMDLEN); ··· 144 135 145 136 if (ret) { 146 137 pr_err("The watchdog cannot be activated\n"); 138 + clear_bit(DIAG_WDOG_BUSY, &wdt_status); 147 139 return ret; 148 140 } 149 141 return 0; ··· 156 146 157 147 diag_stat_inc(DIAG_STAT_X288); 158 148 ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0); 149 + 150 + clear_bit(DIAG_WDOG_BUSY, &wdt_status); 151 + 159 152 return ret; 160 153 } 161 154 ··· 233 220 * It makes no sense to go into suspend while the watchdog is running. 234 221 * Depending on the memory size, the watchdog might trigger, while we 235 222 * are still saving the memory. 236 - * We reuse the open flag to ensure that suspend and watchdog open are 237 - * exclusive operations 238 223 */ 239 224 static int wdt_suspend(void) 240 225 { 241 - if (test_and_set_bit(WDOG_DEV_OPEN, &wdt_dev.status)) { 242 - pr_err("Linux cannot be suspended while the watchdog is in use\n"); 243 - return notifier_from_errno(-EBUSY); 244 - } 245 - if (test_bit(WDOG_ACTIVE, &wdt_dev.status)) { 246 - clear_bit(WDOG_DEV_OPEN, &wdt_dev.status); 226 + if (test_and_set_bit(DIAG_WDOG_BUSY, &wdt_status)) { 247 227 pr_err("Linux cannot be suspended while the watchdog is in use\n"); 248 228 return notifier_from_errno(-EBUSY); 249 229 } ··· 245 239 246 240 static int wdt_resume(void) 247 241 { 248 - clear_bit(WDOG_DEV_OPEN, &wdt_dev.status); 242 + clear_bit(DIAG_WDOG_BUSY, &wdt_status); 249 243 return NOTIFY_DONE; 250 244 } 251 245
+5 -13
drivers/watchdog/digicolor_wdt.c
··· 15 15 #include <linux/delay.h> 16 16 #include <linux/clk.h> 17 17 #include <linux/watchdog.h> 18 - #include <linux/reboot.h> 19 18 #include <linux/platform_device.h> 20 19 #include <linux/of_address.h> 21 20 ··· 27 28 struct dc_wdt { 28 29 void __iomem *base; 29 30 struct clk *clk; 30 - struct notifier_block restart_handler; 31 31 spinlock_t lock; 32 32 }; 33 33 ··· 48 50 spin_unlock_irqrestore(&wdt->lock, flags); 49 51 } 50 52 51 - static int dc_restart_handler(struct notifier_block *this, unsigned long mode, 52 - void *cmd) 53 + static int dc_wdt_restart(struct watchdog_device *wdog) 53 54 { 54 - struct dc_wdt *wdt = container_of(this, struct dc_wdt, restart_handler); 55 + struct dc_wdt *wdt = watchdog_get_drvdata(wdog); 55 56 56 57 dc_wdt_set(wdt, 1); 57 58 /* wait for reset to assert... */ 58 59 mdelay(500); 59 60 60 - return NOTIFY_DONE; 61 + return 0; 61 62 } 62 63 63 64 static int dc_wdt_start(struct watchdog_device *wdog) ··· 101 104 .stop = dc_wdt_stop, 102 105 .set_timeout = dc_wdt_set_timeout, 103 106 .get_timeleft = dc_wdt_get_timeleft, 107 + .restart = dc_wdt_restart, 104 108 }; 105 109 106 110 static struct watchdog_info dc_wdt_info = { ··· 146 148 spin_lock_init(&wdt->lock); 147 149 148 150 watchdog_set_drvdata(&dc_wdt_wdd, wdt); 151 + watchdog_set_restart_priority(&dc_wdt_wdd, 128); 149 152 watchdog_init_timeout(&dc_wdt_wdd, timeout, dev); 150 153 ret = watchdog_register_device(&dc_wdt_wdd); 151 154 if (ret) { 152 155 dev_err(dev, "Failed to register watchdog device"); 153 156 goto err_iounmap; 154 157 } 155 - 156 - wdt->restart_handler.notifier_call = dc_restart_handler; 157 - wdt->restart_handler.priority = 128; 158 - ret = register_restart_handler(&wdt->restart_handler); 159 - if (ret) 160 - dev_warn(&pdev->dev, "cannot register restart handler\n"); 161 158 162 159 return 0; 163 160 ··· 165 172 { 166 173 struct dc_wdt *wdt = platform_get_drvdata(pdev); 167 174 168 - unregister_restart_handler(&wdt->restart_handler); 169 175 watchdog_unregister_device(&dc_wdt_wdd); 170 176 iounmap(wdt->base); 171 177
+1 -1
drivers/watchdog/dw_wdt.c
··· 81 81 * There are 16 possible timeout values in 0..15 where the number of 82 82 * cycles is 2 ^ (16 + i) and the watchdog counts down. 83 83 */ 84 - return (1 << (16 + top)) / clk_get_rate(dw_wdt.clk); 84 + return (1U << (16 + top)) / clk_get_rate(dw_wdt.clk); 85 85 } 86 86 87 87 static int dw_wdt_get_top(void)
+4 -34
drivers/watchdog/gpio_wdt.c
··· 12 12 #include <linux/err.h> 13 13 #include <linux/delay.h> 14 14 #include <linux/module.h> 15 - #include <linux/notifier.h> 16 15 #include <linux/of_gpio.h> 17 16 #include <linux/platform_device.h> 18 - #include <linux/reboot.h> 19 17 #include <linux/watchdog.h> 20 18 21 19 #define SOFT_TIMEOUT_MIN 1 ··· 34 36 unsigned int hw_algo; 35 37 unsigned int hw_margin; 36 38 unsigned long last_jiffies; 37 - struct notifier_block notifier; 38 39 struct timer_list timer; 39 40 struct watchdog_device wdd; 40 41 }; ··· 54 57 55 58 if (priv->armed && time_after(jiffies, priv->last_jiffies + 56 59 msecs_to_jiffies(wdd->timeout * 1000))) { 57 - dev_crit(wdd->dev, "Timer expired. System will reboot soon!\n"); 60 + dev_crit(wdd->parent, 61 + "Timer expired. System will reboot soon!\n"); 58 62 return; 59 63 } 60 64 ··· 122 124 wdd->timeout = t; 123 125 124 126 return gpio_wdt_ping(wdd); 125 - } 126 - 127 - static int gpio_wdt_notify_sys(struct notifier_block *nb, unsigned long code, 128 - void *unused) 129 - { 130 - struct gpio_wdt_priv *priv = container_of(nb, struct gpio_wdt_priv, 131 - notifier); 132 - 133 - mod_timer(&priv->timer, 0); 134 - 135 - switch (code) { 136 - case SYS_HALT: 137 - case SYS_POWER_OFF: 138 - gpio_wdt_disable(priv); 139 - break; 140 - default: 141 - break; 142 - } 143 - 144 - return NOTIFY_DONE; 145 127 } 146 128 147 129 static const struct watchdog_info gpio_wdt_ident = { ··· 202 224 203 225 setup_timer(&priv->timer, gpio_wdt_hwping, (unsigned long)&priv->wdd); 204 226 227 + watchdog_stop_on_reboot(&priv->wdd); 228 + 205 229 ret = watchdog_register_device(&priv->wdd); 206 230 if (ret) 207 231 return ret; 208 - 209 - priv->notifier.notifier_call = gpio_wdt_notify_sys; 210 - ret = register_reboot_notifier(&priv->notifier); 211 - if (ret) 212 - goto error_unregister; 213 232 214 233 if (priv->always_running) 215 234 gpio_wdt_start_impl(priv); 216 235 217 236 return 0; 218 - 219 - error_unregister: 220 - watchdog_unregister_device(&priv->wdd); 221 - return ret; 222 237 } 223 238 224 239 static int gpio_wdt_remove(struct platform_device *pdev) ··· 219 248 struct gpio_wdt_priv *priv = platform_get_drvdata(pdev); 220 249 221 250 del_timer_sync(&priv->timer); 222 - unregister_reboot_notifier(&priv->notifier); 223 251 watchdog_unregister_device(&priv->wdd); 224 252 225 253 return 0;
+6 -6
drivers/watchdog/hpwdt.c
··· 1 1 /* 2 - * HP WatchDog Driver 2 + * HPE WatchDog Driver 3 3 * based on 4 4 * 5 5 * SoftDog 0.05: A Software Watchdog Device 6 6 * 7 - * (c) Copyright 2007 Hewlett-Packard Development Company, L.P. 8 - * Thomas Mingarelli <thomas.mingarelli@hp.com> 7 + * (c) Copyright 2015 Hewlett Packard Enterprise Development LP 8 + * Thomas Mingarelli <thomas.mingarelli@hpe.com> 9 9 * 10 10 * This program is free software; you can redistribute it and/or 11 11 * modify it under the terms of the GNU General Public License ··· 580 580 .options = WDIOF_SETTIMEOUT | 581 581 WDIOF_KEEPALIVEPING | 582 582 WDIOF_MAGICCLOSE, 583 - .identity = "HP iLO2+ HW Watchdog Timer", 583 + .identity = "HPE iLO2+ HW Watchdog Timer", 584 584 }; 585 585 586 586 static long hpwdt_ioctl(struct file *file, unsigned int cmd, ··· 758 758 goto error2; 759 759 760 760 dev_info(&dev->dev, 761 - "HP Watchdog Timer Driver: NMI decoding initialized" 761 + "HPE Watchdog Timer Driver: NMI decoding initialized" 762 762 ", allow kernel dump: %s (default = 1/ON)\n", 763 763 (allow_kdump == 0) ? "OFF" : "ON"); 764 764 return 0; ··· 863 863 goto error_misc_register; 864 864 } 865 865 866 - dev_info(&dev->dev, "HP Watchdog Timer Driver: %s" 866 + dev_info(&dev->dev, "HPE Watchdog Timer Driver: %s" 867 867 ", timer margin: %d seconds (nowayout=%d).\n", 868 868 HPWDT_VERSION, soft_margin, nowayout); 869 869 return 0;
+12 -22
drivers/watchdog/imgpdc_wdt.c
··· 45 45 #include <linux/log2.h> 46 46 #include <linux/module.h> 47 47 #include <linux/platform_device.h> 48 - #include <linux/reboot.h> 49 48 #include <linux/slab.h> 50 49 #include <linux/watchdog.h> 51 50 ··· 86 87 struct clk *wdt_clk; 87 88 struct clk *sys_clk; 88 89 void __iomem *base; 89 - struct notifier_block restart_handler; 90 90 }; 91 91 92 92 static int pdc_wdt_keepalive(struct watchdog_device *wdt_dev) ··· 150 152 return 0; 151 153 } 152 154 155 + static int pdc_wdt_restart(struct watchdog_device *wdt_dev) 156 + { 157 + struct pdc_wdt_dev *wdt = watchdog_get_drvdata(wdt_dev); 158 + 159 + /* Assert SOFT_RESET */ 160 + writel(0x1, wdt->base + PDC_WDT_SOFT_RESET); 161 + 162 + return 0; 163 + } 164 + 153 165 static struct watchdog_info pdc_wdt_info = { 154 166 .identity = "IMG PDC Watchdog", 155 167 .options = WDIOF_SETTIMEOUT | ··· 173 165 .stop = pdc_wdt_stop, 174 166 .ping = pdc_wdt_keepalive, 175 167 .set_timeout = pdc_wdt_set_timeout, 168 + .restart = pdc_wdt_restart, 176 169 }; 177 - 178 - static int pdc_wdt_restart(struct notifier_block *this, unsigned long mode, 179 - void *cmd) 180 - { 181 - struct pdc_wdt_dev *wdt = container_of(this, struct pdc_wdt_dev, 182 - restart_handler); 183 - 184 - /* Assert SOFT_RESET */ 185 - writel(0x1, wdt->base + PDC_WDT_SOFT_RESET); 186 - 187 - return NOTIFY_OK; 188 - } 189 170 190 171 static int pdc_wdt_probe(struct platform_device *pdev) 191 172 { ··· 279 282 } 280 283 281 284 watchdog_set_nowayout(&pdc_wdt->wdt_dev, nowayout); 285 + watchdog_set_restart_priority(&pdc_wdt->wdt_dev, 128); 282 286 283 287 platform_set_drvdata(pdev, pdc_wdt); 284 288 285 289 ret = watchdog_register_device(&pdc_wdt->wdt_dev); 286 290 if (ret) 287 291 goto disable_wdt_clk; 288 - 289 - pdc_wdt->restart_handler.notifier_call = pdc_wdt_restart; 290 - pdc_wdt->restart_handler.priority = 128; 291 - ret = register_restart_handler(&pdc_wdt->restart_handler); 292 - if (ret) 293 - dev_warn(&pdev->dev, "failed to register restart handler: %d\n", 294 - ret); 295 292 296 293 return 0; 297 294 ··· 307 316 { 308 317 struct pdc_wdt_dev *pdc_wdt = platform_get_drvdata(pdev); 309 318 310 - unregister_restart_handler(&pdc_wdt->restart_handler); 311 319 pdc_wdt_stop(&pdc_wdt->wdt_dev); 312 320 watchdog_unregister_device(&pdc_wdt->wdt_dev); 313 321 clk_disable_unprepare(pdc_wdt->wdt_clk);
+6 -17
drivers/watchdog/imx2_wdt.c
··· 29 29 #include <linux/kernel.h> 30 30 #include <linux/module.h> 31 31 #include <linux/moduleparam.h> 32 - #include <linux/notifier.h> 33 32 #include <linux/of_address.h> 34 33 #include <linux/platform_device.h> 35 - #include <linux/reboot.h> 36 34 #include <linux/regmap.h> 37 35 #include <linux/timer.h> 38 36 #include <linux/watchdog.h> ··· 62 64 struct regmap *regmap; 63 65 struct timer_list timer; /* Pings the watchdog when closed */ 64 66 struct watchdog_device wdog; 65 - struct notifier_block restart_handler; 66 67 }; 67 68 68 69 static bool nowayout = WATCHDOG_NOWAYOUT; ··· 80 83 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, 81 84 }; 82 85 83 - static int imx2_restart_handler(struct notifier_block *this, unsigned long mode, 84 - void *cmd) 86 + static int imx2_wdt_restart(struct watchdog_device *wdog) 85 87 { 88 + struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 86 89 unsigned int wcr_enable = IMX2_WDT_WCR_WDE; 87 - struct imx2_wdt_device *wdev = container_of(this, 88 - struct imx2_wdt_device, 89 - restart_handler); 90 + 90 91 /* Assert SRS signal */ 91 92 regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable); 92 93 /* ··· 100 105 /* wait for reset to assert... */ 101 106 mdelay(500); 102 107 103 - return NOTIFY_DONE; 108 + return 0; 104 109 } 105 110 106 111 static inline void imx2_wdt_setup(struct watchdog_device *wdog) ··· 208 213 .stop = imx2_wdt_stop, 209 214 .ping = imx2_wdt_ping, 210 215 .set_timeout = imx2_wdt_set_timeout, 216 + .restart = imx2_wdt_restart, 211 217 }; 212 218 213 219 static const struct regmap_config imx2_wdt_regmap_config = { ··· 271 275 platform_set_drvdata(pdev, wdog); 272 276 watchdog_set_drvdata(wdog, wdev); 273 277 watchdog_set_nowayout(wdog, nowayout); 278 + watchdog_set_restart_priority(wdog, 128); 274 279 watchdog_init_timeout(wdog, timeout, &pdev->dev); 275 280 276 281 setup_timer(&wdev->timer, imx2_wdt_timer_ping, (unsigned long)wdog); ··· 291 294 goto disable_clk; 292 295 } 293 296 294 - wdev->restart_handler.notifier_call = imx2_restart_handler; 295 - wdev->restart_handler.priority = 128; 296 - ret = register_restart_handler(&wdev->restart_handler); 297 - if (ret) 298 - dev_err(&pdev->dev, "cannot register restart handler\n"); 299 - 300 297 dev_info(&pdev->dev, "timeout %d sec (nowayout=%d)\n", 301 298 wdog->timeout, nowayout); 302 299 ··· 305 314 { 306 315 struct watchdog_device *wdog = platform_get_drvdata(pdev); 307 316 struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); 308 - 309 - unregister_restart_handler(&wdev->restart_handler); 310 317 311 318 watchdog_unregister_device(wdog); 312 319
+21 -31
drivers/watchdog/lpc18xx_wdt.c
··· 18 18 #include <linux/module.h> 19 19 #include <linux/of.h> 20 20 #include <linux/platform_device.h> 21 - #include <linux/reboot.h> 22 21 #include <linux/watchdog.h> 23 22 24 23 /* Registers */ ··· 58 59 unsigned long clk_rate; 59 60 void __iomem *base; 60 61 struct timer_list timer; 61 - struct notifier_block restart_handler; 62 62 spinlock_t lock; 63 63 }; 64 64 ··· 153 155 return 0; 154 156 } 155 157 156 - static struct watchdog_info lpc18xx_wdt_info = { 157 - .identity = "NXP LPC18xx Watchdog", 158 - .options = WDIOF_SETTIMEOUT | 159 - WDIOF_KEEPALIVEPING | 160 - WDIOF_MAGICCLOSE, 161 - }; 162 - 163 - static const struct watchdog_ops lpc18xx_wdt_ops = { 164 - .owner = THIS_MODULE, 165 - .start = lpc18xx_wdt_start, 166 - .stop = lpc18xx_wdt_stop, 167 - .ping = lpc18xx_wdt_feed, 168 - .set_timeout = lpc18xx_wdt_set_timeout, 169 - .get_timeleft = lpc18xx_wdt_get_timeleft, 170 - }; 171 - 172 - static int lpc18xx_wdt_restart(struct notifier_block *this, unsigned long mode, 173 - void *cmd) 158 + static int lpc18xx_wdt_restart(struct watchdog_device *wdt_dev) 174 159 { 175 - struct lpc18xx_wdt_dev *lpc18xx_wdt = container_of(this, 176 - struct lpc18xx_wdt_dev, restart_handler); 160 + struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev); 177 161 unsigned long flags; 178 162 int val; 179 163 ··· 177 197 178 198 spin_unlock_irqrestore(&lpc18xx_wdt->lock, flags); 179 199 180 - return NOTIFY_OK; 200 + return 0; 181 201 } 202 + 203 + static struct watchdog_info lpc18xx_wdt_info = { 204 + .identity = "NXP LPC18xx Watchdog", 205 + .options = WDIOF_SETTIMEOUT | 206 + WDIOF_KEEPALIVEPING | 207 + WDIOF_MAGICCLOSE, 208 + }; 209 + 210 + static const struct watchdog_ops lpc18xx_wdt_ops = { 211 + .owner = THIS_MODULE, 212 + .start = lpc18xx_wdt_start, 213 + .stop = lpc18xx_wdt_stop, 214 + .ping = lpc18xx_wdt_feed, 215 + .set_timeout = lpc18xx_wdt_set_timeout, 216 + .get_timeleft = lpc18xx_wdt_get_timeleft, 217 + .restart = lpc18xx_wdt_restart, 218 + }; 182 219 183 220 static int lpc18xx_wdt_probe(struct platform_device *pdev) 184 221 { ··· 270 273 (unsigned long)&lpc18xx_wdt->wdt_dev); 271 274 272 275 watchdog_set_nowayout(&lpc18xx_wdt->wdt_dev, nowayout); 276 + watchdog_set_restart_priority(&lpc18xx_wdt->wdt_dev, 128); 273 277 274 278 platform_set_drvdata(pdev, lpc18xx_wdt); 275 279 276 280 ret = watchdog_register_device(&lpc18xx_wdt->wdt_dev); 277 281 if (ret) 278 282 goto disable_wdt_clk; 279 - 280 - lpc18xx_wdt->restart_handler.notifier_call = lpc18xx_wdt_restart; 281 - lpc18xx_wdt->restart_handler.priority = 128; 282 - ret = register_restart_handler(&lpc18xx_wdt->restart_handler); 283 - if (ret) 284 - dev_warn(dev, "failed to register restart handler: %d\n", ret); 285 283 286 284 return 0; 287 285 ··· 297 305 static int lpc18xx_wdt_remove(struct platform_device *pdev) 298 306 { 299 307 struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); 300 - 301 - unregister_restart_handler(&lpc18xx_wdt->restart_handler); 302 308 303 309 dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n"); 304 310 del_timer(&lpc18xx_wdt->timer);
+2 -2
drivers/watchdog/mena21_wdt.c
··· 100 100 struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt); 101 101 102 102 if (timeout != 1 && timeout != 30) { 103 - dev_err(wdt->dev, "Only 1 and 30 allowed as timeout\n"); 103 + dev_err(wdt->parent, "Only 1 and 30 allowed as timeout\n"); 104 104 return -EINVAL; 105 105 } 106 106 107 107 if (timeout == 30 && wdt->timeout == 1) { 108 - dev_err(wdt->dev, 108 + dev_err(wdt->parent, 109 109 "Transition from fast to slow mode not allowed\n"); 110 110 return -EINVAL; 111 111 }
+53 -35
drivers/watchdog/meson_wdt.c
··· 17 17 #include <linux/kernel.h> 18 18 #include <linux/module.h> 19 19 #include <linux/moduleparam.h> 20 - #include <linux/notifier.h> 21 20 #include <linux/of.h> 21 + #include <linux/of_device.h> 22 22 #include <linux/platform_device.h> 23 - #include <linux/reboot.h> 24 23 #include <linux/types.h> 25 24 #include <linux/watchdog.h> 26 25 27 26 #define DRV_NAME "meson_wdt" 28 27 29 28 #define MESON_WDT_TC 0x00 30 - #define MESON_WDT_TC_EN BIT(22) 31 - #define MESON_WDT_TC_TM_MASK 0x3fffff 32 29 #define MESON_WDT_DC_RESET (3 << 24) 33 30 34 31 #define MESON_WDT_RESET 0x04 35 32 36 33 #define MESON_WDT_TIMEOUT 30 37 34 #define MESON_WDT_MIN_TIMEOUT 1 38 - #define MESON_WDT_MAX_TIMEOUT (MESON_WDT_TC_TM_MASK / 100000) 39 35 40 - #define MESON_SEC_TO_TC(s) ((s) * 100000) 36 + #define MESON_SEC_TO_TC(s, c) ((s) * (c)) 41 37 42 38 static bool nowayout = WATCHDOG_NOWAYOUT; 43 39 static unsigned int timeout = MESON_WDT_TIMEOUT; 44 40 41 + struct meson_wdt_data { 42 + unsigned int enable; 43 + unsigned int terminal_count_mask; 44 + unsigned int count_unit; 45 + }; 46 + 47 + static struct meson_wdt_data meson6_wdt_data = { 48 + .enable = BIT(22), 49 + .terminal_count_mask = 0x3fffff, 50 + .count_unit = 100000, /* 10 us */ 51 + }; 52 + 53 + static struct meson_wdt_data meson8b_wdt_data = { 54 + .enable = BIT(19), 55 + .terminal_count_mask = 0xffff, 56 + .count_unit = 7812, /* 128 us */ 57 + }; 58 + 45 59 struct meson_wdt_dev { 46 60 struct watchdog_device wdt_dev; 47 61 void __iomem *wdt_base; 48 - struct notifier_block restart_handler; 62 + const struct meson_wdt_data *data; 49 63 }; 50 64 51 - static int meson_restart_handle(struct notifier_block *this, unsigned long mode, 52 - void *cmd) 65 + static int meson_wdt_restart(struct watchdog_device *wdt_dev) 53 66 { 54 - u32 tc_reboot = MESON_WDT_DC_RESET | MESON_WDT_TC_EN; 55 - struct meson_wdt_dev *meson_wdt = container_of(this, 56 - struct meson_wdt_dev, 57 - restart_handler); 67 + struct meson_wdt_dev *meson_wdt = watchdog_get_drvdata(wdt_dev); 68 + u32 tc_reboot = MESON_WDT_DC_RESET; 69 + 70 + tc_reboot |= meson_wdt->data->enable; 58 71 59 72 while (1) { 60 73 writel(tc_reboot, meson_wdt->wdt_base + MESON_WDT_TC); 61 74 mdelay(5); 62 75 } 63 76 64 - return NOTIFY_DONE; 77 + return 0; 65 78 } 66 79 67 80 static int meson_wdt_ping(struct watchdog_device *wdt_dev) ··· 93 80 u32 reg; 94 81 95 82 reg = readl(meson_wdt->wdt_base + MESON_WDT_TC); 96 - reg &= ~MESON_WDT_TC_TM_MASK; 97 - reg |= MESON_SEC_TO_TC(timeout); 83 + reg &= ~meson_wdt->data->terminal_count_mask; 84 + reg |= MESON_SEC_TO_TC(timeout, meson_wdt->data->count_unit); 98 85 writel(reg, meson_wdt->wdt_base + MESON_WDT_TC); 99 86 } 100 87 ··· 115 102 u32 reg; 116 103 117 104 reg = readl(meson_wdt->wdt_base + MESON_WDT_TC); 118 - reg &= ~MESON_WDT_TC_EN; 105 + reg &= ~meson_wdt->data->enable; 119 106 writel(reg, meson_wdt->wdt_base + MESON_WDT_TC); 120 107 121 108 return 0; ··· 130 117 meson_wdt_ping(wdt_dev); 131 118 132 119 reg = readl(meson_wdt->wdt_base + MESON_WDT_TC); 133 - reg |= MESON_WDT_TC_EN; 120 + reg |= meson_wdt->data->enable; 134 121 writel(reg, meson_wdt->wdt_base + MESON_WDT_TC); 135 122 136 123 return 0; ··· 149 136 .stop = meson_wdt_stop, 150 137 .ping = meson_wdt_ping, 151 138 .set_timeout = meson_wdt_set_timeout, 139 + .restart = meson_wdt_restart, 152 140 }; 141 + 142 + static const struct of_device_id meson_wdt_dt_ids[] = { 143 + { .compatible = "amlogic,meson6-wdt", .data = &meson6_wdt_data }, 144 + { .compatible = "amlogic,meson8b-wdt", .data = &meson8b_wdt_data }, 145 + { /* sentinel */ } 146 + }; 147 + MODULE_DEVICE_TABLE(of, meson_wdt_dt_ids); 153 148 154 149 static int meson_wdt_probe(struct platform_device *pdev) 155 150 { 156 151 struct resource *res; 157 152 struct meson_wdt_dev *meson_wdt; 153 + const struct of_device_id *of_id; 158 154 int err; 159 155 160 156 meson_wdt = devm_kzalloc(&pdev->dev, sizeof(*meson_wdt), GFP_KERNEL); ··· 175 153 if (IS_ERR(meson_wdt->wdt_base)) 176 154 return PTR_ERR(meson_wdt->wdt_base); 177 155 156 + of_id = of_match_device(meson_wdt_dt_ids, &pdev->dev); 157 + if (!of_id) { 158 + dev_err(&pdev->dev, "Unable to initialize WDT data\n"); 159 + return -ENODEV; 160 + } 161 + meson_wdt->data = of_id->data; 162 + 178 163 meson_wdt->wdt_dev.parent = &pdev->dev; 179 164 meson_wdt->wdt_dev.info = &meson_wdt_info; 180 165 meson_wdt->wdt_dev.ops = &meson_wdt_ops; 181 - meson_wdt->wdt_dev.timeout = MESON_WDT_TIMEOUT; 182 - meson_wdt->wdt_dev.max_timeout = MESON_WDT_MAX_TIMEOUT; 166 + meson_wdt->wdt_dev.max_timeout = 167 + meson_wdt->data->terminal_count_mask / meson_wdt->data->count_unit; 183 168 meson_wdt->wdt_dev.min_timeout = MESON_WDT_MIN_TIMEOUT; 169 + meson_wdt->wdt_dev.timeout = min_t(unsigned int, 170 + MESON_WDT_TIMEOUT, 171 + meson_wdt->wdt_dev.max_timeout); 184 172 185 173 watchdog_set_drvdata(&meson_wdt->wdt_dev, meson_wdt); 186 174 187 175 watchdog_init_timeout(&meson_wdt->wdt_dev, timeout, &pdev->dev); 188 176 watchdog_set_nowayout(&meson_wdt->wdt_dev, nowayout); 177 + watchdog_set_restart_priority(&meson_wdt->wdt_dev, 128); 189 178 190 179 meson_wdt_stop(&meson_wdt->wdt_dev); 191 180 ··· 205 172 return err; 206 173 207 174 platform_set_drvdata(pdev, meson_wdt); 208 - 209 - meson_wdt->restart_handler.notifier_call = meson_restart_handle; 210 - meson_wdt->restart_handler.priority = 128; 211 - err = register_restart_handler(&meson_wdt->restart_handler); 212 - if (err) 213 - dev_err(&pdev->dev, 214 - "cannot register restart handler (err=%d)\n", err); 215 175 216 176 dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", 217 177 meson_wdt->wdt_dev.timeout, nowayout); ··· 215 189 static int meson_wdt_remove(struct platform_device *pdev) 216 190 { 217 191 struct meson_wdt_dev *meson_wdt = platform_get_drvdata(pdev); 218 - 219 - unregister_restart_handler(&meson_wdt->restart_handler); 220 192 221 193 watchdog_unregister_device(&meson_wdt->wdt_dev); 222 194 ··· 227 203 228 204 meson_wdt_stop(&meson_wdt->wdt_dev); 229 205 } 230 - 231 - static const struct of_device_id meson_wdt_dt_ids[] = { 232 - { .compatible = "amlogic,meson6-wdt" }, 233 - { /* sentinel */ } 234 - }; 235 - MODULE_DEVICE_TABLE(of, meson_wdt_dt_ids); 236 206 237 207 static struct platform_driver meson_wdt_driver = { 238 208 .probe = meson_wdt_probe,
+6 -17
drivers/watchdog/moxart_wdt.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/err.h> 17 17 #include <linux/kernel.h> 18 - #include <linux/notifier.h> 19 18 #include <linux/platform_device.h> 20 - #include <linux/reboot.h> 21 19 #include <linux/watchdog.h> 22 20 #include <linux/moduleparam.h> 23 21 ··· 27 29 struct watchdog_device dev; 28 30 void __iomem *base; 29 31 unsigned int clock_frequency; 30 - struct notifier_block restart_handler; 31 32 }; 32 33 33 34 static int heartbeat; 34 35 35 - static int moxart_restart_handle(struct notifier_block *this, 36 - unsigned long mode, void *cmd) 36 + static int moxart_wdt_restart(struct watchdog_device *wdt_dev) 37 37 { 38 - struct moxart_wdt_dev *moxart_wdt = container_of(this, 39 - struct moxart_wdt_dev, 40 - restart_handler); 38 + struct moxart_wdt_dev *moxart_wdt = watchdog_get_drvdata(wdt_dev); 39 + 41 40 writel(1, moxart_wdt->base + REG_COUNT); 42 41 writel(0x5ab9, moxart_wdt->base + REG_MODE); 43 42 writel(0x03, moxart_wdt->base + REG_ENABLE); 44 43 45 - return NOTIFY_DONE; 44 + return 0; 46 45 } 47 46 48 47 static int moxart_wdt_stop(struct watchdog_device *wdt_dev) ··· 82 87 .start = moxart_wdt_start, 83 88 .stop = moxart_wdt_stop, 84 89 .set_timeout = moxart_wdt_set_timeout, 90 + .restart = moxart_wdt_restart, 85 91 }; 86 92 87 93 static int moxart_wdt_probe(struct platform_device *pdev) ··· 130 134 131 135 watchdog_init_timeout(&moxart_wdt->dev, heartbeat, dev); 132 136 watchdog_set_nowayout(&moxart_wdt->dev, nowayout); 137 + watchdog_set_restart_priority(&moxart_wdt->dev, 128); 133 138 134 139 watchdog_set_drvdata(&moxart_wdt->dev, moxart_wdt); 135 140 136 141 err = watchdog_register_device(&moxart_wdt->dev); 137 142 if (err) 138 143 return err; 139 - 140 - moxart_wdt->restart_handler.notifier_call = moxart_restart_handle; 141 - moxart_wdt->restart_handler.priority = 128; 142 - err = register_restart_handler(&moxart_wdt->restart_handler); 143 - if (err) 144 - dev_err(dev, "cannot register restart notifier (err=%d)\n", 145 - err); 146 144 147 145 dev_dbg(dev, "Watchdog enabled (heartbeat=%d sec, nowayout=%d)\n", 148 146 moxart_wdt->dev.timeout, nowayout); ··· 148 158 { 149 159 struct moxart_wdt_dev *moxart_wdt = platform_get_drvdata(pdev); 150 160 151 - unregister_restart_handler(&moxart_wdt->restart_handler); 152 161 moxart_wdt_stop(&moxart_wdt->dev); 153 162 154 163 return 0;
+186
drivers/watchdog/mt7621_wdt.c
··· 1 + /* 2 + * Ralink MT7621/MT7628 built-in hardware watchdog timer 3 + * 4 + * Copyright (C) 2014 John Crispin <blogic@openwrt.org> 5 + * 6 + * This driver was based on: drivers/watchdog/rt2880_wdt.c 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 10 + * by the Free Software Foundation. 11 + */ 12 + 13 + #include <linux/clk.h> 14 + #include <linux/reset.h> 15 + #include <linux/module.h> 16 + #include <linux/kernel.h> 17 + #include <linux/watchdog.h> 18 + #include <linux/moduleparam.h> 19 + #include <linux/platform_device.h> 20 + 21 + #include <asm/mach-ralink/ralink_regs.h> 22 + 23 + #define SYSC_RSTSTAT 0x38 24 + #define WDT_RST_CAUSE BIT(1) 25 + 26 + #define RALINK_WDT_TIMEOUT 30 27 + 28 + #define TIMER_REG_TMRSTAT 0x00 29 + #define TIMER_REG_TMR1LOAD 0x24 30 + #define TIMER_REG_TMR1CTL 0x20 31 + 32 + #define TMR1CTL_ENABLE BIT(7) 33 + #define TMR1CTL_RESTART BIT(9) 34 + #define TMR1CTL_PRESCALE_SHIFT 16 35 + 36 + static void __iomem *mt7621_wdt_base; 37 + static struct reset_control *mt7621_wdt_reset; 38 + 39 + static bool nowayout = WATCHDOG_NOWAYOUT; 40 + module_param(nowayout, bool, 0); 41 + MODULE_PARM_DESC(nowayout, 42 + "Watchdog cannot be stopped once started (default=" 43 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 44 + 45 + static inline void rt_wdt_w32(unsigned reg, u32 val) 46 + { 47 + iowrite32(val, mt7621_wdt_base + reg); 48 + } 49 + 50 + static inline u32 rt_wdt_r32(unsigned reg) 51 + { 52 + return ioread32(mt7621_wdt_base + reg); 53 + } 54 + 55 + static int mt7621_wdt_ping(struct watchdog_device *w) 56 + { 57 + rt_wdt_w32(TIMER_REG_TMRSTAT, TMR1CTL_RESTART); 58 + 59 + return 0; 60 + } 61 + 62 + static int mt7621_wdt_set_timeout(struct watchdog_device *w, unsigned int t) 63 + { 64 + w->timeout = t; 65 + rt_wdt_w32(TIMER_REG_TMR1LOAD, t * 1000); 66 + mt7621_wdt_ping(w); 67 + 68 + return 0; 69 + } 70 + 71 + static int mt7621_wdt_start(struct watchdog_device *w) 72 + { 73 + u32 t; 74 + 75 + /* set the prescaler to 1ms == 1000us */ 76 + rt_wdt_w32(TIMER_REG_TMR1CTL, 1000 << TMR1CTL_PRESCALE_SHIFT); 77 + 78 + mt7621_wdt_set_timeout(w, w->timeout); 79 + 80 + t = rt_wdt_r32(TIMER_REG_TMR1CTL); 81 + t |= TMR1CTL_ENABLE; 82 + rt_wdt_w32(TIMER_REG_TMR1CTL, t); 83 + 84 + return 0; 85 + } 86 + 87 + static int mt7621_wdt_stop(struct watchdog_device *w) 88 + { 89 + u32 t; 90 + 91 + mt7621_wdt_ping(w); 92 + 93 + t = rt_wdt_r32(TIMER_REG_TMR1CTL); 94 + t &= ~TMR1CTL_ENABLE; 95 + rt_wdt_w32(TIMER_REG_TMR1CTL, t); 96 + 97 + return 0; 98 + } 99 + 100 + static int mt7621_wdt_bootcause(void) 101 + { 102 + if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE) 103 + return WDIOF_CARDRESET; 104 + 105 + return 0; 106 + } 107 + 108 + static struct watchdog_info mt7621_wdt_info = { 109 + .identity = "Mediatek Watchdog", 110 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 111 + }; 112 + 113 + static struct watchdog_ops mt7621_wdt_ops = { 114 + .owner = THIS_MODULE, 115 + .start = mt7621_wdt_start, 116 + .stop = mt7621_wdt_stop, 117 + .ping = mt7621_wdt_ping, 118 + .set_timeout = mt7621_wdt_set_timeout, 119 + }; 120 + 121 + static struct watchdog_device mt7621_wdt_dev = { 122 + .info = &mt7621_wdt_info, 123 + .ops = &mt7621_wdt_ops, 124 + .min_timeout = 1, 125 + .max_timeout = 0xfffful / 1000, 126 + }; 127 + 128 + static int mt7621_wdt_probe(struct platform_device *pdev) 129 + { 130 + struct resource *res; 131 + int ret; 132 + 133 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 134 + mt7621_wdt_base = devm_ioremap_resource(&pdev->dev, res); 135 + if (IS_ERR(mt7621_wdt_base)) 136 + return PTR_ERR(mt7621_wdt_base); 137 + 138 + mt7621_wdt_reset = devm_reset_control_get(&pdev->dev, NULL); 139 + if (!IS_ERR(mt7621_wdt_reset)) 140 + reset_control_deassert(mt7621_wdt_reset); 141 + 142 + mt7621_wdt_dev.dev = &pdev->dev; 143 + mt7621_wdt_dev.bootstatus = mt7621_wdt_bootcause(); 144 + 145 + watchdog_init_timeout(&mt7621_wdt_dev, mt7621_wdt_dev.max_timeout, 146 + &pdev->dev); 147 + watchdog_set_nowayout(&mt7621_wdt_dev, nowayout); 148 + 149 + ret = watchdog_register_device(&mt7621_wdt_dev); 150 + 151 + return 0; 152 + } 153 + 154 + static int mt7621_wdt_remove(struct platform_device *pdev) 155 + { 156 + watchdog_unregister_device(&mt7621_wdt_dev); 157 + 158 + return 0; 159 + } 160 + 161 + static void mt7621_wdt_shutdown(struct platform_device *pdev) 162 + { 163 + mt7621_wdt_stop(&mt7621_wdt_dev); 164 + } 165 + 166 + static const struct of_device_id mt7621_wdt_match[] = { 167 + { .compatible = "mediatek,mt7621-wdt" }, 168 + {}, 169 + }; 170 + MODULE_DEVICE_TABLE(of, mt7621_wdt_match); 171 + 172 + static struct platform_driver mt7621_wdt_driver = { 173 + .probe = mt7621_wdt_probe, 174 + .remove = mt7621_wdt_remove, 175 + .shutdown = mt7621_wdt_shutdown, 176 + .driver = { 177 + .name = KBUILD_MODNAME, 178 + .of_match_table = mt7621_wdt_match, 179 + }, 180 + }; 181 + 182 + module_platform_driver(mt7621_wdt_driver); 183 + 184 + MODULE_DESCRIPTION("MediaTek MT762x hardware watchdog driver"); 185 + MODULE_AUTHOR("John Crispin <blogic@openwrt.org"); 186 + MODULE_LICENSE("GPL v2");
+5 -17
drivers/watchdog/mtk_wdt.c
··· 28 28 #include <linux/platform_device.h> 29 29 #include <linux/types.h> 30 30 #include <linux/watchdog.h> 31 - #include <linux/notifier.h> 32 - #include <linux/reboot.h> 33 31 #include <linux/delay.h> 34 32 35 33 #define WDT_MAX_TIMEOUT 31 ··· 62 64 struct mtk_wdt_dev { 63 65 struct watchdog_device wdt_dev; 64 66 void __iomem *wdt_base; 65 - struct notifier_block restart_handler; 66 67 }; 67 68 68 - static int mtk_reset_handler(struct notifier_block *this, unsigned long mode, 69 - void *cmd) 69 + static int mtk_wdt_restart(struct watchdog_device *wdt_dev) 70 70 { 71 - struct mtk_wdt_dev *mtk_wdt; 71 + struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); 72 72 void __iomem *wdt_base; 73 73 74 - mtk_wdt = container_of(this, struct mtk_wdt_dev, restart_handler); 75 74 wdt_base = mtk_wdt->wdt_base; 76 75 77 76 while (1) { ··· 76 81 mdelay(5); 77 82 } 78 83 79 - return NOTIFY_DONE; 84 + return 0; 80 85 } 81 86 82 87 static int mtk_wdt_ping(struct watchdog_device *wdt_dev) ··· 156 161 .stop = mtk_wdt_stop, 157 162 .ping = mtk_wdt_ping, 158 163 .set_timeout = mtk_wdt_set_timeout, 164 + .restart = mtk_wdt_restart, 159 165 }; 160 166 161 167 static int mtk_wdt_probe(struct platform_device *pdev) ··· 185 189 186 190 watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, &pdev->dev); 187 191 watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); 192 + watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); 188 193 189 194 watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); 190 195 ··· 194 197 err = watchdog_register_device(&mtk_wdt->wdt_dev); 195 198 if (unlikely(err)) 196 199 return err; 197 - 198 - mtk_wdt->restart_handler.notifier_call = mtk_reset_handler; 199 - mtk_wdt->restart_handler.priority = 128; 200 - err = register_restart_handler(&mtk_wdt->restart_handler); 201 - if (err) 202 - dev_warn(&pdev->dev, 203 - "cannot register restart handler (err=%d)\n", err); 204 200 205 201 dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", 206 202 mtk_wdt->wdt_dev.timeout, nowayout); ··· 212 222 static int mtk_wdt_remove(struct platform_device *pdev) 213 223 { 214 224 struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); 215 - 216 - unregister_restart_handler(&mtk_wdt->restart_handler); 217 225 218 226 watchdog_unregister_device(&mtk_wdt->wdt_dev); 219 227
+4 -3
drivers/watchdog/omap_wdt.c
··· 271 271 wdev->wdog.bootstatus = WDIOF_CARDRESET; 272 272 } 273 273 274 - omap_wdt_disable(wdev); 274 + if (!early_enable) 275 + omap_wdt_disable(wdev); 275 276 276 277 ret = watchdog_register_device(&wdev->wdog); 277 278 if (ret) { ··· 284 283 readl_relaxed(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, 285 284 wdev->wdog.timeout); 286 285 287 - pm_runtime_put_sync(wdev->dev); 288 - 289 286 if (early_enable) 290 287 omap_wdt_start(&wdev->wdog); 288 + 289 + pm_runtime_put(wdev->dev); 291 290 292 291 return 0; 293 292 }
+19 -31
drivers/watchdog/qcom-wdt.c
··· 17 17 #include <linux/module.h> 18 18 #include <linux/of.h> 19 19 #include <linux/platform_device.h> 20 - #include <linux/reboot.h> 21 20 #include <linux/watchdog.h> 22 21 23 22 #define WDT_RST 0x38 ··· 27 28 struct watchdog_device wdd; 28 29 struct clk *clk; 29 30 unsigned long rate; 30 - struct notifier_block restart_nb; 31 31 void __iomem *base; 32 32 }; 33 33 ··· 70 72 return qcom_wdt_start(wdd); 71 73 } 72 74 73 - static const struct watchdog_ops qcom_wdt_ops = { 74 - .start = qcom_wdt_start, 75 - .stop = qcom_wdt_stop, 76 - .ping = qcom_wdt_ping, 77 - .set_timeout = qcom_wdt_set_timeout, 78 - .owner = THIS_MODULE, 79 - }; 80 - 81 - static const struct watchdog_info qcom_wdt_info = { 82 - .options = WDIOF_KEEPALIVEPING 83 - | WDIOF_MAGICCLOSE 84 - | WDIOF_SETTIMEOUT, 85 - .identity = KBUILD_MODNAME, 86 - }; 87 - 88 - static int qcom_wdt_restart(struct notifier_block *nb, unsigned long action, 89 - void *data) 75 + static int qcom_wdt_restart(struct watchdog_device *wdd) 90 76 { 91 - struct qcom_wdt *wdt = container_of(nb, struct qcom_wdt, restart_nb); 77 + struct qcom_wdt *wdt = to_qcom_wdt(wdd); 92 78 u32 timeout; 93 79 94 80 /* ··· 92 110 wmb(); 93 111 94 112 msleep(150); 95 - return NOTIFY_DONE; 113 + return 0; 96 114 } 115 + 116 + static const struct watchdog_ops qcom_wdt_ops = { 117 + .start = qcom_wdt_start, 118 + .stop = qcom_wdt_stop, 119 + .ping = qcom_wdt_ping, 120 + .set_timeout = qcom_wdt_set_timeout, 121 + .restart = qcom_wdt_restart, 122 + .owner = THIS_MODULE, 123 + }; 124 + 125 + static const struct watchdog_info qcom_wdt_info = { 126 + .options = WDIOF_KEEPALIVEPING 127 + | WDIOF_MAGICCLOSE 128 + | WDIOF_SETTIMEOUT, 129 + .identity = KBUILD_MODNAME, 130 + }; 97 131 98 132 static int qcom_wdt_probe(struct platform_device *pdev) 99 133 { ··· 164 166 goto err_clk_unprepare; 165 167 } 166 168 167 - wdt->wdd.dev = &pdev->dev; 168 169 wdt->wdd.info = &qcom_wdt_info; 169 170 wdt->wdd.ops = &qcom_wdt_ops; 170 171 wdt->wdd.min_timeout = 1; ··· 184 187 goto err_clk_unprepare; 185 188 } 186 189 187 - /* 188 - * WDT restart notifier has priority 0 (use as a last resort) 189 - */ 190 - wdt->restart_nb.notifier_call = qcom_wdt_restart; 191 - ret = register_restart_handler(&wdt->restart_nb); 192 - if (ret) 193 - dev_err(&pdev->dev, "failed to setup restart handler\n"); 194 - 195 190 platform_set_drvdata(pdev, wdt); 196 191 return 0; 197 192 ··· 196 207 { 197 208 struct qcom_wdt *wdt = platform_get_drvdata(pdev); 198 209 199 - unregister_restart_handler(&wdt->restart_nb); 200 210 watchdog_unregister_device(&wdt->wdd); 201 211 clk_disable_unprepare(wdt->clk); 202 212 return 0;
+25 -35
drivers/watchdog/s3c2410_wdt.c
··· 41 41 #include <linux/of.h> 42 42 #include <linux/mfd/syscon.h> 43 43 #include <linux/regmap.h> 44 - #include <linux/reboot.h> 45 44 #include <linux/delay.h> 46 45 47 46 #define S3C2410_WTCON 0x00 ··· 129 130 unsigned long wtdat_save; 130 131 struct watchdog_device wdt_device; 131 132 struct notifier_block freq_transition; 132 - struct notifier_block restart_handler; 133 133 struct s3c2410_wdt_variant *drv_data; 134 134 struct regmap *pmureg; 135 135 }; ··· 349 351 return 0; 350 352 } 351 353 354 + static int s3c2410wdt_restart(struct watchdog_device *wdd) 355 + { 356 + struct s3c2410_wdt *wdt = watchdog_get_drvdata(wdd); 357 + void __iomem *wdt_base = wdt->reg_base; 358 + 359 + /* disable watchdog, to be safe */ 360 + writel(0, wdt_base + S3C2410_WTCON); 361 + 362 + /* put initial values into count and data */ 363 + writel(0x80, wdt_base + S3C2410_WTCNT); 364 + writel(0x80, wdt_base + S3C2410_WTDAT); 365 + 366 + /* set the watchdog to go and reset... */ 367 + writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV16 | 368 + S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x20), 369 + wdt_base + S3C2410_WTCON); 370 + 371 + /* wait for reset to assert... */ 372 + mdelay(500); 373 + 374 + return 0; 375 + } 376 + 352 377 #define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE) 353 378 354 379 static const struct watchdog_info s3c2410_wdt_ident = { ··· 386 365 .stop = s3c2410wdt_stop, 387 366 .ping = s3c2410wdt_keepalive, 388 367 .set_timeout = s3c2410wdt_set_heartbeat, 368 + .restart = s3c2410wdt_restart, 389 369 }; 390 370 391 371 static struct watchdog_device s3c2410_wdd = { ··· 473 451 { 474 452 } 475 453 #endif 476 - 477 - static int s3c2410wdt_restart(struct notifier_block *this, 478 - unsigned long mode, void *cmd) 479 - { 480 - struct s3c2410_wdt *wdt = container_of(this, struct s3c2410_wdt, 481 - restart_handler); 482 - void __iomem *wdt_base = wdt->reg_base; 483 - 484 - /* disable watchdog, to be safe */ 485 - writel(0, wdt_base + S3C2410_WTCON); 486 - 487 - /* put initial values into count and data */ 488 - writel(0x80, wdt_base + S3C2410_WTCNT); 489 - writel(0x80, wdt_base + S3C2410_WTDAT); 490 - 491 - /* set the watchdog to go and reset... */ 492 - writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV16 | 493 - S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x20), 494 - wdt_base + S3C2410_WTCON); 495 - 496 - /* wait for reset to assert... */ 497 - mdelay(500); 498 - 499 - return NOTIFY_DONE; 500 - } 501 454 502 455 static inline unsigned int s3c2410wdt_get_bootstatus(struct s3c2410_wdt *wdt) 503 456 { ··· 602 605 } 603 606 604 607 watchdog_set_nowayout(&wdt->wdt_device, nowayout); 608 + watchdog_set_restart_priority(&wdt->wdt_device, 128); 605 609 606 610 wdt->wdt_device.bootstatus = s3c2410wdt_get_bootstatus(wdt); 607 611 wdt->wdt_device.parent = &pdev->dev; ··· 629 631 } 630 632 631 633 platform_set_drvdata(pdev, wdt); 632 - 633 - wdt->restart_handler.notifier_call = s3c2410wdt_restart; 634 - wdt->restart_handler.priority = 128; 635 - ret = register_restart_handler(&wdt->restart_handler); 636 - if (ret) 637 - pr_err("cannot register restart handler, %d\n", ret); 638 634 639 635 /* print out a statement of readiness */ 640 636 ··· 658 666 { 659 667 int ret; 660 668 struct s3c2410_wdt *wdt = platform_get_drvdata(dev); 661 - 662 - unregister_restart_handler(&wdt->restart_handler); 663 669 664 670 ret = s3c2410wdt_mask_and_disable_reset(wdt, true); 665 671 if (ret < 0)
+8 -30
drivers/watchdog/softdog.c
··· 43 43 #include <linux/types.h> 44 44 #include <linux/timer.h> 45 45 #include <linux/watchdog.h> 46 - #include <linux/notifier.h> 47 46 #include <linux/reboot.h> 48 47 #include <linux/init.h> 49 48 #include <linux/jiffies.h> ··· 86 87 87 88 static void watchdog_fire(unsigned long data) 88 89 { 90 + module_put(THIS_MODULE); 89 91 if (soft_noboot) 90 92 pr_crit("Triggered - Reboot ignored\n"); 91 93 else if (soft_panic) { ··· 105 105 106 106 static int softdog_ping(struct watchdog_device *w) 107 107 { 108 - mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ)); 108 + if (!mod_timer(&watchdog_ticktock, jiffies+(w->timeout*HZ))) 109 + __module_get(THIS_MODULE); 109 110 return 0; 110 111 } 111 112 112 113 static int softdog_stop(struct watchdog_device *w) 113 114 { 114 - del_timer(&watchdog_ticktock); 115 + if (del_timer(&watchdog_ticktock)) 116 + module_put(THIS_MODULE); 117 + 115 118 return 0; 116 119 } 117 120 ··· 125 122 } 126 123 127 124 /* 128 - * Notifier for system down 129 - */ 130 - 131 - static int softdog_notify_sys(struct notifier_block *this, unsigned long code, 132 - void *unused) 133 - { 134 - if (code == SYS_DOWN || code == SYS_HALT) 135 - /* Turn the WDT off */ 136 - softdog_stop(NULL); 137 - return NOTIFY_DONE; 138 - } 139 - 140 - /* 141 125 * Kernel Interfaces 142 126 */ 143 - 144 - static struct notifier_block softdog_notifier = { 145 - .notifier_call = softdog_notify_sys, 146 - }; 147 127 148 128 static struct watchdog_info softdog_info = { 149 129 .identity = "Software Watchdog", ··· 161 175 softdog_dev.timeout = soft_margin; 162 176 163 177 watchdog_set_nowayout(&softdog_dev, nowayout); 164 - 165 - ret = register_reboot_notifier(&softdog_notifier); 166 - if (ret) { 167 - pr_err("cannot register reboot notifier (err=%d)\n", ret); 168 - return ret; 169 - } 178 + watchdog_stop_on_reboot(&softdog_dev); 170 179 171 180 ret = watchdog_register_device(&softdog_dev); 172 - if (ret) { 173 - unregister_reboot_notifier(&softdog_notifier); 181 + if (ret) 174 182 return ret; 175 - } 176 183 177 184 pr_info("Software Watchdog Timer: 0.08 initialized. soft_noboot=%d soft_margin=%d sec soft_panic=%d (nowayout=%d)\n", 178 185 soft_noboot, soft_margin, soft_panic, nowayout); ··· 176 197 static void __exit watchdog_exit(void) 177 198 { 178 199 watchdog_unregister_device(&softdog_dev); 179 - unregister_reboot_notifier(&softdog_notifier); 180 200 } 181 201 182 202 module_init(watchdog_init);
+20 -12
drivers/watchdog/sp5100_tco.c
··· 306 306 static const struct pci_device_id sp5100_tco_pci_tbl[] = { 307 307 { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID, 308 308 PCI_ANY_ID, }, 309 + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID, 310 + PCI_ANY_ID, }, 311 + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, PCI_ANY_ID, 312 + PCI_ANY_ID, }, 309 313 { 0, }, /* End of list */ 310 314 }; 311 315 MODULE_DEVICE_TABLE(pci, sp5100_tco_pci_tbl); ··· 335 331 if (!sp5100_tco_pci) 336 332 return 0; 337 333 338 - pr_info("PCI Revision ID: 0x%x\n", sp5100_tco_pci->revision); 334 + pr_info("PCI Vendor ID: 0x%x, Device ID: 0x%x, Revision ID: 0x%x\n", 335 + sp5100_tco_pci->vendor, sp5100_tco_pci->device, 336 + sp5100_tco_pci->revision); 339 337 340 338 /* 341 339 * Determine type of southbridge chipset. 342 340 */ 343 - if (sp5100_tco_pci->revision >= 0x40) { 344 - dev_name = SB800_DEVNAME; 345 - index_reg = SB800_IO_PM_INDEX_REG; 346 - data_reg = SB800_IO_PM_DATA_REG; 347 - base_addr = SB800_PM_WATCHDOG_BASE; 348 - } else { 341 + if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && 342 + sp5100_tco_pci->revision < 0x40) { 349 343 dev_name = SP5100_DEVNAME; 350 344 index_reg = SP5100_IO_PM_INDEX_REG; 351 345 data_reg = SP5100_IO_PM_DATA_REG; 352 346 base_addr = SP5100_PM_WATCHDOG_BASE; 347 + } else { 348 + dev_name = SB800_DEVNAME; 349 + index_reg = SB800_IO_PM_INDEX_REG; 350 + data_reg = SB800_IO_PM_DATA_REG; 351 + base_addr = SB800_PM_WATCHDOG_BASE; 353 352 } 354 353 355 354 /* Request the IO ports used by this driver */ ··· 388 381 * Secondly, Find the watchdog timer MMIO address 389 382 * from SBResource_MMIO register. 390 383 */ 391 - if (sp5100_tco_pci->revision >= 0x40) { 384 + if (sp5100_tco_pci->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && 385 + sp5100_tco_pci->revision < 0x40) { 386 + /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */ 387 + pci_read_config_dword(sp5100_tco_pci, 388 + SP5100_SB_RESOURCE_MMIO_BASE, &val); 389 + } else { 392 390 /* Read SBResource_MMIO from AcpiMmioEn(PM_Reg: 24h) */ 393 391 outb(SB800_PM_ACPI_MMIO_EN+3, SB800_IO_PM_INDEX_REG); 394 392 val = inb(SB800_IO_PM_DATA_REG); ··· 403 391 val = val << 8 | inb(SB800_IO_PM_DATA_REG); 404 392 outb(SB800_PM_ACPI_MMIO_EN+0, SB800_IO_PM_INDEX_REG); 405 393 val = val << 8 | inb(SB800_IO_PM_DATA_REG); 406 - } else { 407 - /* Read SBResource_MMIO from PCI config(PCI_Reg: 9Ch) */ 408 - pci_read_config_dword(sp5100_tco_pci, 409 - SP5100_SB_RESOURCE_MMIO_BASE, &val); 410 394 } 411 395 412 396 /* The SBResource_MMIO is enabled and mapped memory space? */
+25
drivers/watchdog/stmp3xxx_rtc_wdt.c
··· 14 14 #include <linux/watchdog.h> 15 15 #include <linux/platform_device.h> 16 16 #include <linux/stmp3xxx_rtc_wdt.h> 17 + #include <linux/notifier.h> 18 + #include <linux/reboot.h> 17 19 18 20 #define WDOG_TICK_RATE 1000 /* 1 kHz clock */ 19 21 #define STMP3XXX_DEFAULT_TIMEOUT 19 ··· 71 69 .status = WATCHDOG_NOWAYOUT_INIT_STATUS, 72 70 }; 73 71 72 + static int wdt_notify_sys(struct notifier_block *nb, unsigned long code, 73 + void *unused) 74 + { 75 + switch (code) { 76 + case SYS_DOWN: /* keep enabled, system might crash while going down */ 77 + break; 78 + case SYS_HALT: /* allow the system to actually halt */ 79 + case SYS_POWER_OFF: 80 + wdt_stop(&stmp3xxx_wdd); 81 + break; 82 + } 83 + 84 + return NOTIFY_DONE; 85 + } 86 + 87 + static struct notifier_block wdt_notifier = { 88 + .notifier_call = wdt_notify_sys, 89 + }; 90 + 74 91 static int stmp3xxx_wdt_probe(struct platform_device *pdev) 75 92 { 76 93 int ret; ··· 105 84 return ret; 106 85 } 107 86 87 + if (register_reboot_notifier(&wdt_notifier)) 88 + dev_warn(&pdev->dev, "cannot register reboot notifier\n"); 89 + 108 90 dev_info(&pdev->dev, "initialized watchdog with heartbeat %ds\n", 109 91 stmp3xxx_wdd.timeout); 110 92 return 0; ··· 115 91 116 92 static int stmp3xxx_wdt_remove(struct platform_device *pdev) 117 93 { 94 + unregister_reboot_notifier(&wdt_notifier); 118 95 watchdog_unregister_device(&stmp3xxx_wdd); 119 96 return 0; 120 97 }
+5 -18
drivers/watchdog/sunxi_wdt.c
··· 21 21 #include <linux/kernel.h> 22 22 #include <linux/module.h> 23 23 #include <linux/moduleparam.h> 24 - #include <linux/notifier.h> 25 24 #include <linux/of.h> 26 25 #include <linux/of_device.h> 27 26 #include <linux/platform_device.h> 28 - #include <linux/reboot.h> 29 27 #include <linux/types.h> 30 28 #include <linux/watchdog.h> 31 29 ··· 58 60 struct watchdog_device wdt_dev; 59 61 void __iomem *wdt_base; 60 62 const struct sunxi_wdt_reg *wdt_regs; 61 - struct notifier_block restart_handler; 62 63 }; 63 64 64 65 /* ··· 83 86 }; 84 87 85 88 86 - static int sunxi_restart_handle(struct notifier_block *this, unsigned long mode, 87 - void *cmd) 89 + static int sunxi_wdt_restart(struct watchdog_device *wdt_dev) 88 90 { 89 - struct sunxi_wdt_dev *sunxi_wdt = container_of(this, 90 - struct sunxi_wdt_dev, 91 - restart_handler); 91 + struct sunxi_wdt_dev *sunxi_wdt = watchdog_get_drvdata(wdt_dev); 92 92 void __iomem *wdt_base = sunxi_wdt->wdt_base; 93 93 const struct sunxi_wdt_reg *regs = sunxi_wdt->wdt_regs; 94 94 u32 val; ··· 114 120 val |= WDT_MODE_EN; 115 121 writel(val, wdt_base + regs->wdt_mode); 116 122 } 117 - return NOTIFY_DONE; 123 + return 0; 118 124 } 119 125 120 126 static int sunxi_wdt_ping(struct watchdog_device *wdt_dev) ··· 202 208 .stop = sunxi_wdt_stop, 203 209 .ping = sunxi_wdt_ping, 204 210 .set_timeout = sunxi_wdt_set_timeout, 211 + .restart = sunxi_wdt_restart, 205 212 }; 206 213 207 214 static const struct sunxi_wdt_reg sun4i_wdt_reg = { ··· 263 268 264 269 watchdog_init_timeout(&sunxi_wdt->wdt_dev, timeout, &pdev->dev); 265 270 watchdog_set_nowayout(&sunxi_wdt->wdt_dev, nowayout); 271 + watchdog_set_restart_priority(&sunxi_wdt->wdt_dev, 128); 266 272 267 273 watchdog_set_drvdata(&sunxi_wdt->wdt_dev, sunxi_wdt); 268 274 ··· 272 276 err = watchdog_register_device(&sunxi_wdt->wdt_dev); 273 277 if (unlikely(err)) 274 278 return err; 275 - 276 - sunxi_wdt->restart_handler.notifier_call = sunxi_restart_handle; 277 - sunxi_wdt->restart_handler.priority = 128; 278 - err = register_restart_handler(&sunxi_wdt->restart_handler); 279 - if (err) 280 - dev_err(&pdev->dev, 281 - "cannot register restart handler (err=%d)\n", err); 282 279 283 280 dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)", 284 281 sunxi_wdt->wdt_dev.timeout, nowayout); ··· 282 293 static int sunxi_wdt_remove(struct platform_device *pdev) 283 294 { 284 295 struct sunxi_wdt_dev *sunxi_wdt = platform_get_drvdata(pdev); 285 - 286 - unregister_restart_handler(&sunxi_wdt->restart_handler); 287 296 288 297 watchdog_unregister_device(&sunxi_wdt->wdt_dev); 289 298 watchdog_set_drvdata(&sunxi_wdt->wdt_dev, NULL);
+225
drivers/watchdog/tangox_wdt.c
··· 1 + /* 2 + * Copyright (C) 2015 Mans Rullgard <mans@mansr.com> 3 + * SMP86xx/SMP87xx Watchdog driver 4 + * 5 + * This program is free software; you can redistribute it and/or modify it 6 + * under the terms of the GNU General Public License as published by the 7 + * Free Software Foundation; either version 2 of the License, or (at your 8 + * option) any later version. 9 + */ 10 + 11 + #include <linux/bitops.h> 12 + #include <linux/clk.h> 13 + #include <linux/delay.h> 14 + #include <linux/io.h> 15 + #include <linux/kernel.h> 16 + #include <linux/module.h> 17 + #include <linux/moduleparam.h> 18 + #include <linux/notifier.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/reboot.h> 21 + #include <linux/watchdog.h> 22 + 23 + #define DEFAULT_TIMEOUT 30 24 + 25 + static bool nowayout = WATCHDOG_NOWAYOUT; 26 + module_param(nowayout, bool, 0); 27 + MODULE_PARM_DESC(nowayout, 28 + "Watchdog cannot be stopped once started (default=" 29 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 30 + 31 + static unsigned int timeout; 32 + module_param(timeout, int, 0); 33 + MODULE_PARM_DESC(timeout, "Watchdog timeout"); 34 + 35 + /* 36 + * Counter counts down from programmed value. Reset asserts when 37 + * the counter reaches 1. 38 + */ 39 + #define WD_COUNTER 0 40 + 41 + #define WD_CONFIG 4 42 + #define WD_CONFIG_XTAL_IN BIT(0) 43 + #define WD_CONFIG_DISABLE BIT(31) 44 + 45 + struct tangox_wdt_device { 46 + struct watchdog_device wdt; 47 + void __iomem *base; 48 + unsigned long clk_rate; 49 + struct clk *clk; 50 + struct notifier_block restart; 51 + }; 52 + 53 + static int tangox_wdt_set_timeout(struct watchdog_device *wdt, 54 + unsigned int new_timeout) 55 + { 56 + wdt->timeout = new_timeout; 57 + 58 + return 0; 59 + } 60 + 61 + static int tangox_wdt_start(struct watchdog_device *wdt) 62 + { 63 + struct tangox_wdt_device *dev = watchdog_get_drvdata(wdt); 64 + u32 ticks; 65 + 66 + ticks = 1 + wdt->timeout * dev->clk_rate; 67 + writel(ticks, dev->base + WD_COUNTER); 68 + 69 + return 0; 70 + } 71 + 72 + static int tangox_wdt_stop(struct watchdog_device *wdt) 73 + { 74 + struct tangox_wdt_device *dev = watchdog_get_drvdata(wdt); 75 + 76 + writel(0, dev->base + WD_COUNTER); 77 + 78 + return 0; 79 + } 80 + 81 + static unsigned int tangox_wdt_get_timeleft(struct watchdog_device *wdt) 82 + { 83 + struct tangox_wdt_device *dev = watchdog_get_drvdata(wdt); 84 + u32 count; 85 + 86 + count = readl(dev->base + WD_COUNTER); 87 + 88 + if (!count) 89 + return 0; 90 + 91 + return (count - 1) / dev->clk_rate; 92 + } 93 + 94 + static const struct watchdog_info tangox_wdt_info = { 95 + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 96 + .identity = "tangox watchdog", 97 + }; 98 + 99 + static const struct watchdog_ops tangox_wdt_ops = { 100 + .start = tangox_wdt_start, 101 + .stop = tangox_wdt_stop, 102 + .set_timeout = tangox_wdt_set_timeout, 103 + .get_timeleft = tangox_wdt_get_timeleft, 104 + }; 105 + 106 + static int tangox_wdt_restart(struct notifier_block *nb, unsigned long action, 107 + void *data) 108 + { 109 + struct tangox_wdt_device *dev = 110 + container_of(nb, struct tangox_wdt_device, restart); 111 + 112 + writel(1, dev->base + WD_COUNTER); 113 + 114 + return NOTIFY_DONE; 115 + } 116 + 117 + static int tangox_wdt_probe(struct platform_device *pdev) 118 + { 119 + struct tangox_wdt_device *dev; 120 + struct resource *res; 121 + u32 config; 122 + int err; 123 + 124 + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 125 + if (!dev) 126 + return -ENOMEM; 127 + 128 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 129 + dev->base = devm_ioremap_resource(&pdev->dev, res); 130 + if (IS_ERR(dev->base)) 131 + return PTR_ERR(dev->base); 132 + 133 + dev->clk = devm_clk_get(&pdev->dev, NULL); 134 + if (IS_ERR(dev->clk)) 135 + return PTR_ERR(dev->clk); 136 + 137 + err = clk_prepare_enable(dev->clk); 138 + if (err) 139 + return err; 140 + 141 + dev->clk_rate = clk_get_rate(dev->clk); 142 + 143 + dev->wdt.parent = &pdev->dev; 144 + dev->wdt.info = &tangox_wdt_info; 145 + dev->wdt.ops = &tangox_wdt_ops; 146 + dev->wdt.timeout = DEFAULT_TIMEOUT; 147 + dev->wdt.min_timeout = 1; 148 + dev->wdt.max_timeout = (U32_MAX - 1) / dev->clk_rate; 149 + 150 + watchdog_init_timeout(&dev->wdt, timeout, &pdev->dev); 151 + watchdog_set_nowayout(&dev->wdt, nowayout); 152 + watchdog_set_drvdata(&dev->wdt, dev); 153 + 154 + /* 155 + * Deactivate counter if disable bit is set to avoid 156 + * accidental reset. 157 + */ 158 + config = readl(dev->base + WD_CONFIG); 159 + if (config & WD_CONFIG_DISABLE) 160 + writel(0, dev->base + WD_COUNTER); 161 + 162 + writel(WD_CONFIG_XTAL_IN, dev->base + WD_CONFIG); 163 + 164 + /* 165 + * Mark as active and restart with configured timeout if 166 + * already running. 167 + */ 168 + if (readl(dev->base + WD_COUNTER)) { 169 + set_bit(WDOG_ACTIVE, &dev->wdt.status); 170 + tangox_wdt_start(&dev->wdt); 171 + } 172 + 173 + err = watchdog_register_device(&dev->wdt); 174 + if (err) { 175 + clk_disable_unprepare(dev->clk); 176 + return err; 177 + } 178 + 179 + platform_set_drvdata(pdev, dev); 180 + 181 + dev->restart.notifier_call = tangox_wdt_restart; 182 + dev->restart.priority = 128; 183 + err = register_restart_handler(&dev->restart); 184 + if (err) 185 + dev_warn(&pdev->dev, "failed to register restart handler\n"); 186 + 187 + dev_info(&pdev->dev, "SMP86xx/SMP87xx watchdog registered\n"); 188 + 189 + return 0; 190 + } 191 + 192 + static int tangox_wdt_remove(struct platform_device *pdev) 193 + { 194 + struct tangox_wdt_device *dev = platform_get_drvdata(pdev); 195 + 196 + tangox_wdt_stop(&dev->wdt); 197 + clk_disable_unprepare(dev->clk); 198 + 199 + unregister_restart_handler(&dev->restart); 200 + watchdog_unregister_device(&dev->wdt); 201 + 202 + return 0; 203 + } 204 + 205 + static const struct of_device_id tangox_wdt_dt_ids[] = { 206 + { .compatible = "sigma,smp8642-wdt" }, 207 + { .compatible = "sigma,smp8759-wdt" }, 208 + { } 209 + }; 210 + MODULE_DEVICE_TABLE(of, tangox_wdt_dt_ids); 211 + 212 + static struct platform_driver tangox_wdt_driver = { 213 + .probe = tangox_wdt_probe, 214 + .remove = tangox_wdt_remove, 215 + .driver = { 216 + .name = "tangox-wdt", 217 + .of_match_table = tangox_wdt_dt_ids, 218 + }, 219 + }; 220 + 221 + module_platform_driver(tangox_wdt_driver); 222 + 223 + MODULE_AUTHOR("Mans Rullgard <mans@mansr.com>"); 224 + MODULE_DESCRIPTION("SMP86xx/SMP87xx Watchdog driver"); 225 + MODULE_LICENSE("GPL");
+215
drivers/watchdog/ts4800_wdt.c
··· 1 + /* 2 + * Watchdog driver for TS-4800 based boards 3 + * 4 + * Copyright (c) 2015 - Savoir-faire Linux 5 + * 6 + * This file is licensed under the terms of the GNU General Public 7 + * License version 2. This program is licensed "as is" without any 8 + * warranty of any kind, whether express or implied. 9 + */ 10 + 11 + #include <linux/kernel.h> 12 + #include <linux/mfd/syscon.h> 13 + #include <linux/module.h> 14 + #include <linux/of.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/regmap.h> 17 + #include <linux/watchdog.h> 18 + 19 + static bool nowayout = WATCHDOG_NOWAYOUT; 20 + module_param(nowayout, bool, 0); 21 + MODULE_PARM_DESC(nowayout, 22 + "Watchdog cannot be stopped once started (default=" 23 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 24 + 25 + /* possible feed values */ 26 + #define TS4800_WDT_FEED_2S 0x1 27 + #define TS4800_WDT_FEED_10S 0x2 28 + #define TS4800_WDT_DISABLE 0x3 29 + 30 + struct ts4800_wdt { 31 + struct watchdog_device wdd; 32 + struct regmap *regmap; 33 + u32 feed_offset; 34 + u32 feed_val; 35 + }; 36 + 37 + /* 38 + * TS-4800 supports the following timeout values: 39 + * 40 + * value desc 41 + * --------------------- 42 + * 0 feed for 338ms 43 + * 1 feed for 2.706s 44 + * 2 feed for 10.824s 45 + * 3 disable watchdog 46 + * 47 + * Keep the regmap/timeout map ordered by timeout 48 + */ 49 + static const struct { 50 + const int timeout; 51 + const int regval; 52 + } ts4800_wdt_map[] = { 53 + { 2, TS4800_WDT_FEED_2S }, 54 + { 10, TS4800_WDT_FEED_10S }, 55 + }; 56 + 57 + #define MAX_TIMEOUT_INDEX (ARRAY_SIZE(ts4800_wdt_map) - 1) 58 + 59 + static void ts4800_write_feed(struct ts4800_wdt *wdt, u32 val) 60 + { 61 + regmap_write(wdt->regmap, wdt->feed_offset, val); 62 + } 63 + 64 + static int ts4800_wdt_start(struct watchdog_device *wdd) 65 + { 66 + struct ts4800_wdt *wdt = watchdog_get_drvdata(wdd); 67 + 68 + ts4800_write_feed(wdt, wdt->feed_val); 69 + return 0; 70 + } 71 + 72 + static int ts4800_wdt_stop(struct watchdog_device *wdd) 73 + { 74 + struct ts4800_wdt *wdt = watchdog_get_drvdata(wdd); 75 + 76 + ts4800_write_feed(wdt, TS4800_WDT_DISABLE); 77 + return 0; 78 + } 79 + 80 + static int ts4800_wdt_set_timeout(struct watchdog_device *wdd, 81 + unsigned int timeout) 82 + { 83 + struct ts4800_wdt *wdt = watchdog_get_drvdata(wdd); 84 + int i; 85 + 86 + for (i = 0; i < MAX_TIMEOUT_INDEX; i++) { 87 + if (ts4800_wdt_map[i].timeout >= timeout) 88 + break; 89 + } 90 + 91 + wdd->timeout = ts4800_wdt_map[i].timeout; 92 + wdt->feed_val = ts4800_wdt_map[i].regval; 93 + 94 + return 0; 95 + } 96 + 97 + static const struct watchdog_ops ts4800_wdt_ops = { 98 + .owner = THIS_MODULE, 99 + .start = ts4800_wdt_start, 100 + .stop = ts4800_wdt_stop, 101 + .set_timeout = ts4800_wdt_set_timeout, 102 + }; 103 + 104 + static const struct watchdog_info ts4800_wdt_info = { 105 + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, 106 + .identity = "TS-4800 Watchdog", 107 + }; 108 + 109 + static int ts4800_wdt_probe(struct platform_device *pdev) 110 + { 111 + struct device_node *np = pdev->dev.of_node; 112 + struct device_node *syscon_np; 113 + struct watchdog_device *wdd; 114 + struct ts4800_wdt *wdt; 115 + u32 reg; 116 + int ret; 117 + 118 + syscon_np = of_parse_phandle(np, "syscon", 0); 119 + if (!syscon_np) { 120 + dev_err(&pdev->dev, "no syscon property\n"); 121 + return -ENODEV; 122 + } 123 + 124 + ret = of_property_read_u32_index(np, "syscon", 1, &reg); 125 + if (ret < 0) { 126 + dev_err(&pdev->dev, "no offset in syscon\n"); 127 + return ret; 128 + } 129 + 130 + /* allocate memory for watchdog struct */ 131 + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); 132 + if (!wdt) 133 + return -ENOMEM; 134 + 135 + /* set regmap and offset to know where to write */ 136 + wdt->feed_offset = reg; 137 + wdt->regmap = syscon_node_to_regmap(syscon_np); 138 + if (IS_ERR(wdt->regmap)) { 139 + dev_err(&pdev->dev, "cannot get parent's regmap\n"); 140 + return PTR_ERR(wdt->regmap); 141 + } 142 + 143 + /* Initialize struct watchdog_device */ 144 + wdd = &wdt->wdd; 145 + wdd->parent = &pdev->dev; 146 + wdd->info = &ts4800_wdt_info; 147 + wdd->ops = &ts4800_wdt_ops; 148 + wdd->min_timeout = ts4800_wdt_map[0].timeout; 149 + wdd->max_timeout = ts4800_wdt_map[MAX_TIMEOUT_INDEX].timeout; 150 + 151 + watchdog_set_drvdata(wdd, wdt); 152 + watchdog_set_nowayout(wdd, nowayout); 153 + watchdog_init_timeout(wdd, 0, &pdev->dev); 154 + 155 + /* 156 + * As this watchdog supports only a few values, ts4800_wdt_set_timeout 157 + * must be called to initialize timeout and feed_val with valid values. 158 + * Default to maximum timeout if none, or an invalid one, is provided in 159 + * device tree. 160 + */ 161 + if (!wdd->timeout) 162 + wdd->timeout = wdd->max_timeout; 163 + ts4800_wdt_set_timeout(wdd, wdd->timeout); 164 + 165 + /* 166 + * The feed register is write-only, so it is not possible to determine 167 + * watchdog's state. Disable it to be in a known state. 168 + */ 169 + ts4800_wdt_stop(wdd); 170 + 171 + ret = watchdog_register_device(wdd); 172 + if (ret) { 173 + dev_err(&pdev->dev, 174 + "failed to register watchdog device\n"); 175 + return ret; 176 + } 177 + 178 + platform_set_drvdata(pdev, wdt); 179 + 180 + dev_info(&pdev->dev, 181 + "initialized (timeout = %d sec, nowayout = %d)\n", 182 + wdd->timeout, nowayout); 183 + 184 + return 0; 185 + } 186 + 187 + static int ts4800_wdt_remove(struct platform_device *pdev) 188 + { 189 + struct ts4800_wdt *wdt = platform_get_drvdata(pdev); 190 + 191 + watchdog_unregister_device(&wdt->wdd); 192 + 193 + return 0; 194 + } 195 + 196 + static const struct of_device_id ts4800_wdt_of_match[] = { 197 + { .compatible = "technologic,ts4800-wdt", }, 198 + { }, 199 + }; 200 + MODULE_DEVICE_TABLE(of, ts4800_wdt_of_match); 201 + 202 + static struct platform_driver ts4800_wdt_driver = { 203 + .probe = ts4800_wdt_probe, 204 + .remove = ts4800_wdt_remove, 205 + .driver = { 206 + .name = "ts4800_wdt", 207 + .of_match_table = ts4800_wdt_of_match, 208 + }, 209 + }; 210 + 211 + module_platform_driver(ts4800_wdt_driver); 212 + 213 + MODULE_AUTHOR("Damien Riegel <damien.riegel@savoirfairelinux.com>"); 214 + MODULE_LICENSE("GPL v2"); 215 + MODULE_ALIAS("platform:ts4800_wdt");
+2 -30
drivers/watchdog/w83627hf_wdt.c
··· 36 36 #include <linux/types.h> 37 37 #include <linux/watchdog.h> 38 38 #include <linux/ioport.h> 39 - #include <linux/notifier.h> 40 - #include <linux/reboot.h> 41 39 #include <linux/init.h> 42 40 #include <linux/io.h> 43 41 ··· 286 288 } 287 289 288 290 /* 289 - * Notifier for system down 290 - */ 291 - static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 292 - void *unused) 293 - { 294 - if (code == SYS_DOWN || code == SYS_HALT) 295 - wdt_set_time(0); /* Turn the WDT off */ 296 - 297 - return NOTIFY_DONE; 298 - } 299 - 300 - /* 301 291 * Kernel Interfaces 302 292 */ 303 293 ··· 314 328 * The WDT needs to learn about soft shutdowns in order to 315 329 * turn the timebomb registers off. 316 330 */ 317 - 318 - static struct notifier_block wdt_notifier = { 319 - .notifier_call = wdt_notify_sys, 320 - }; 321 331 322 332 static int wdt_find(int addr) 323 333 { ··· 438 456 439 457 watchdog_init_timeout(&wdt_dev, timeout, NULL); 440 458 watchdog_set_nowayout(&wdt_dev, nowayout); 459 + watchdog_stop_on_reboot(&wdt_dev); 441 460 442 461 ret = w83627hf_init(&wdt_dev, chip); 443 462 if (ret) { ··· 446 463 return ret; 447 464 } 448 465 449 - ret = register_reboot_notifier(&wdt_notifier); 450 - if (ret != 0) { 451 - pr_err("cannot register reboot notifier (err=%d)\n", ret); 452 - return ret; 453 - } 454 - 455 466 ret = watchdog_register_device(&wdt_dev); 456 467 if (ret) 457 - goto unreg_reboot; 468 + return ret; 458 469 459 470 pr_info("initialized. timeout=%d sec (nowayout=%d)\n", 460 471 wdt_dev.timeout, nowayout); 461 472 462 - return ret; 463 - 464 - unreg_reboot: 465 - unregister_reboot_notifier(&wdt_notifier); 466 473 return ret; 467 474 } 468 475 469 476 static void __exit wdt_exit(void) 470 477 { 471 478 watchdog_unregister_device(&wdt_dev); 472 - unregister_reboot_notifier(&wdt_notifier); 473 479 } 474 480 475 481 module_init(wdt_init);
+84 -31
drivers/watchdog/watchdog_core.c
··· 32 32 #include <linux/types.h> /* For standard types */ 33 33 #include <linux/errno.h> /* For the -ENODEV/... values */ 34 34 #include <linux/kernel.h> /* For printk/panic/... */ 35 + #include <linux/reboot.h> /* For restart handler */ 35 36 #include <linux/watchdog.h> /* For watchdog specific items */ 36 37 #include <linux/init.h> /* For __init/__exit/... */ 37 38 #include <linux/idr.h> /* For ida_* macros */ ··· 42 41 #include "watchdog_core.h" /* For watchdog_dev_register/... */ 43 42 44 43 static DEFINE_IDA(watchdog_ida); 45 - static struct class *watchdog_class; 46 44 47 45 /* 48 46 * Deferred Registration infrastructure. ··· 137 137 } 138 138 EXPORT_SYMBOL_GPL(watchdog_init_timeout); 139 139 140 + static int watchdog_reboot_notifier(struct notifier_block *nb, 141 + unsigned long code, void *data) 142 + { 143 + struct watchdog_device *wdd = container_of(nb, struct watchdog_device, 144 + reboot_nb); 145 + 146 + if (code == SYS_DOWN || code == SYS_HALT) { 147 + if (watchdog_active(wdd)) { 148 + int ret; 149 + 150 + ret = wdd->ops->stop(wdd); 151 + if (ret) 152 + return NOTIFY_BAD; 153 + } 154 + } 155 + 156 + return NOTIFY_DONE; 157 + } 158 + 159 + static int watchdog_restart_notifier(struct notifier_block *nb, 160 + unsigned long action, void *data) 161 + { 162 + struct watchdog_device *wdd = container_of(nb, struct watchdog_device, 163 + restart_nb); 164 + 165 + int ret; 166 + 167 + ret = wdd->ops->restart(wdd); 168 + if (ret) 169 + return NOTIFY_BAD; 170 + 171 + return NOTIFY_DONE; 172 + } 173 + 174 + /** 175 + * watchdog_set_restart_priority - Change priority of restart handler 176 + * @wdd: watchdog device 177 + * @priority: priority of the restart handler, should follow these guidelines: 178 + * 0: use watchdog's restart function as last resort, has limited restart 179 + * capabilies 180 + * 128: default restart handler, use if no other handler is expected to be 181 + * available and/or if restart is sufficient to restart the entire system 182 + * 255: preempt all other handlers 183 + * 184 + * If a wdd->ops->restart function is provided when watchdog_register_device is 185 + * called, it will be registered as a restart handler with the priority given 186 + * here. 187 + */ 188 + void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority) 189 + { 190 + wdd->restart_nb.priority = priority; 191 + } 192 + EXPORT_SYMBOL_GPL(watchdog_set_restart_priority); 193 + 140 194 static int __watchdog_register_device(struct watchdog_device *wdd) 141 195 { 142 - int ret, id = -1, devno; 196 + int ret, id = -1; 143 197 144 198 if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL) 145 199 return -EINVAL; ··· 209 155 * will not check this anymore in other functions. If data gets 210 156 * corrupted in a later stage then we expect a kernel panic! 211 157 */ 212 - 213 - mutex_init(&wdd->lock); 214 158 215 159 /* Use alias for watchdog id if possible */ 216 160 if (wdd->parent) { ··· 244 192 } 245 193 } 246 194 247 - devno = wdd->cdev.dev; 248 - wdd->dev = device_create(watchdog_class, wdd->parent, devno, 249 - NULL, "watchdog%d", wdd->id); 250 - if (IS_ERR(wdd->dev)) { 251 - watchdog_dev_unregister(wdd); 252 - ida_simple_remove(&watchdog_ida, id); 253 - ret = PTR_ERR(wdd->dev); 254 - return ret; 195 + if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) { 196 + wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; 197 + 198 + ret = register_reboot_notifier(&wdd->reboot_nb); 199 + if (ret) { 200 + pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", 201 + wdd->id, ret); 202 + watchdog_dev_unregister(wdd); 203 + ida_simple_remove(&watchdog_ida, wdd->id); 204 + return ret; 205 + } 206 + } 207 + 208 + if (wdd->ops->restart) { 209 + wdd->restart_nb.notifier_call = watchdog_restart_notifier; 210 + 211 + ret = register_restart_handler(&wdd->restart_nb); 212 + if (ret) 213 + pr_warn("watchog%d: Cannot register restart handler (%d)\n", 214 + wdd->id, ret); 255 215 } 256 216 257 217 return 0; ··· 296 232 297 233 static void __watchdog_unregister_device(struct watchdog_device *wdd) 298 234 { 299 - int ret; 300 - int devno; 301 - 302 235 if (wdd == NULL) 303 236 return; 304 237 305 - devno = wdd->cdev.dev; 306 - ret = watchdog_dev_unregister(wdd); 307 - if (ret) 308 - pr_err("error unregistering /dev/watchdog (err=%d)\n", ret); 309 - device_destroy(watchdog_class, devno); 238 + if (wdd->ops->restart) 239 + unregister_restart_handler(&wdd->restart_nb); 240 + 241 + if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) 242 + unregister_reboot_notifier(&wdd->reboot_nb); 243 + 244 + watchdog_dev_unregister(wdd); 310 245 ida_simple_remove(&watchdog_ida, wdd->id); 311 - wdd->dev = NULL; 312 246 } 313 247 314 248 /** ··· 349 287 { 350 288 int err; 351 289 352 - watchdog_class = class_create(THIS_MODULE, "watchdog"); 353 - if (IS_ERR(watchdog_class)) { 354 - pr_err("couldn't create class\n"); 355 - return PTR_ERR(watchdog_class); 356 - } 357 - 358 290 err = watchdog_dev_init(); 359 - if (err < 0) { 360 - class_destroy(watchdog_class); 291 + if (err < 0) 361 292 return err; 362 - } 363 293 364 294 watchdog_deferred_registration(); 365 295 return 0; ··· 360 306 static void __exit watchdog_exit(void) 361 307 { 362 308 watchdog_dev_exit(); 363 - class_destroy(watchdog_class); 364 309 ida_destroy(&watchdog_ida); 365 310 } 366 311
+1 -1
drivers/watchdog/watchdog_core.h
··· 32 32 * Functions/procedures to be called by the core 33 33 */ 34 34 extern int watchdog_dev_register(struct watchdog_device *); 35 - extern int watchdog_dev_unregister(struct watchdog_device *); 35 + extern void watchdog_dev_unregister(struct watchdog_device *); 36 36 extern int __init watchdog_dev_init(void); 37 37 extern void __exit watchdog_dev_exit(void);
+409 -207
drivers/watchdog/watchdog_dev.c
··· 32 32 33 33 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 34 34 35 - #include <linux/module.h> /* For module stuff/... */ 36 - #include <linux/types.h> /* For standard types (like size_t) */ 35 + #include <linux/cdev.h> /* For character device */ 37 36 #include <linux/errno.h> /* For the -ENODEV/... values */ 38 - #include <linux/kernel.h> /* For printk/panic/... */ 39 37 #include <linux/fs.h> /* For file operations */ 40 - #include <linux/watchdog.h> /* For watchdog specific items */ 41 - #include <linux/miscdevice.h> /* For handling misc devices */ 42 38 #include <linux/init.h> /* For __init/__exit/... */ 39 + #include <linux/kernel.h> /* For printk/panic/... */ 40 + #include <linux/kref.h> /* For data references */ 41 + #include <linux/miscdevice.h> /* For handling misc devices */ 42 + #include <linux/module.h> /* For module stuff/... */ 43 + #include <linux/mutex.h> /* For mutexes */ 44 + #include <linux/slab.h> /* For memory functions */ 45 + #include <linux/types.h> /* For standard types (like size_t) */ 46 + #include <linux/watchdog.h> /* For watchdog specific items */ 43 47 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ 44 48 45 49 #include "watchdog_core.h" 46 50 51 + /* 52 + * struct watchdog_core_data - watchdog core internal data 53 + * @kref: Reference count. 54 + * @cdev: The watchdog's Character device. 55 + * @wdd: Pointer to watchdog device. 56 + * @lock: Lock for watchdog core. 57 + * @status: Watchdog core internal status bits. 58 + */ 59 + struct watchdog_core_data { 60 + struct kref kref; 61 + struct cdev cdev; 62 + struct watchdog_device *wdd; 63 + struct mutex lock; 64 + unsigned long status; /* Internal status bits */ 65 + #define _WDOG_DEV_OPEN 0 /* Opened ? */ 66 + #define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ 67 + }; 68 + 47 69 /* the dev_t structure to store the dynamically allocated watchdog devices */ 48 70 static dev_t watchdog_devt; 49 - /* the watchdog device behind /dev/watchdog */ 50 - static struct watchdog_device *old_wdd; 71 + /* Reference to watchdog device behind /dev/watchdog */ 72 + static struct watchdog_core_data *old_wd_data; 51 73 52 74 /* 53 75 * watchdog_ping: ping the watchdog. 54 76 * @wdd: the watchdog device to ping 77 + * 78 + * The caller must hold wd_data->lock. 55 79 * 56 80 * If the watchdog has no own ping operation then it needs to be 57 81 * restarted via the start operation. This wrapper function does ··· 85 61 86 62 static int watchdog_ping(struct watchdog_device *wdd) 87 63 { 88 - int err = 0; 89 - 90 - mutex_lock(&wdd->lock); 91 - 92 - if (test_bit(WDOG_UNREGISTERED, &wdd->status)) { 93 - err = -ENODEV; 94 - goto out_ping; 95 - } 64 + int err; 96 65 97 66 if (!watchdog_active(wdd)) 98 - goto out_ping; 67 + return 0; 99 68 100 69 if (wdd->ops->ping) 101 70 err = wdd->ops->ping(wdd); /* ping the watchdog */ 102 71 else 103 72 err = wdd->ops->start(wdd); /* restart watchdog */ 104 73 105 - out_ping: 106 - mutex_unlock(&wdd->lock); 107 74 return err; 108 75 } 109 76 110 77 /* 111 78 * watchdog_start: wrapper to start the watchdog. 112 79 * @wdd: the watchdog device to start 80 + * 81 + * The caller must hold wd_data->lock. 113 82 * 114 83 * Start the watchdog if it is not active and mark it active. 115 84 * This function returns zero on success or a negative errno code for ··· 111 94 112 95 static int watchdog_start(struct watchdog_device *wdd) 113 96 { 114 - int err = 0; 115 - 116 - mutex_lock(&wdd->lock); 117 - 118 - if (test_bit(WDOG_UNREGISTERED, &wdd->status)) { 119 - err = -ENODEV; 120 - goto out_start; 121 - } 97 + int err; 122 98 123 99 if (watchdog_active(wdd)) 124 - goto out_start; 100 + return 0; 125 101 126 102 err = wdd->ops->start(wdd); 127 103 if (err == 0) 128 104 set_bit(WDOG_ACTIVE, &wdd->status); 129 105 130 - out_start: 131 - mutex_unlock(&wdd->lock); 132 106 return err; 133 107 } 134 108 135 109 /* 136 110 * watchdog_stop: wrapper to stop the watchdog. 137 111 * @wdd: the watchdog device to stop 112 + * 113 + * The caller must hold wd_data->lock. 138 114 * 139 115 * Stop the watchdog if it is still active and unmark it active. 140 116 * This function returns zero on success or a negative errno code for ··· 137 127 138 128 static int watchdog_stop(struct watchdog_device *wdd) 139 129 { 140 - int err = 0; 141 - 142 - mutex_lock(&wdd->lock); 143 - 144 - if (test_bit(WDOG_UNREGISTERED, &wdd->status)) { 145 - err = -ENODEV; 146 - goto out_stop; 147 - } 130 + int err; 148 131 149 132 if (!watchdog_active(wdd)) 150 - goto out_stop; 133 + return 0; 151 134 152 135 if (test_bit(WDOG_NO_WAY_OUT, &wdd->status)) { 153 - dev_info(wdd->dev, "nowayout prevents watchdog being stopped!\n"); 154 - err = -EBUSY; 155 - goto out_stop; 136 + pr_info("watchdog%d: nowayout prevents watchdog being stopped!\n", 137 + wdd->id); 138 + return -EBUSY; 156 139 } 157 140 158 141 err = wdd->ops->stop(wdd); 159 142 if (err == 0) 160 143 clear_bit(WDOG_ACTIVE, &wdd->status); 161 144 162 - out_stop: 163 - mutex_unlock(&wdd->lock); 164 145 return err; 165 146 } 166 147 167 148 /* 168 149 * watchdog_get_status: wrapper to get the watchdog status 169 150 * @wdd: the watchdog device to get the status from 170 - * @status: the status of the watchdog device 151 + * 152 + * The caller must hold wd_data->lock. 171 153 * 172 154 * Get the watchdog's status flags. 173 155 */ 174 156 175 - static int watchdog_get_status(struct watchdog_device *wdd, 176 - unsigned int *status) 157 + static unsigned int watchdog_get_status(struct watchdog_device *wdd) 177 158 { 178 - int err = 0; 179 - 180 - *status = 0; 181 159 if (!wdd->ops->status) 182 - return -EOPNOTSUPP; 160 + return 0; 183 161 184 - mutex_lock(&wdd->lock); 185 - 186 - if (test_bit(WDOG_UNREGISTERED, &wdd->status)) { 187 - err = -ENODEV; 188 - goto out_status; 189 - } 190 - 191 - *status = wdd->ops->status(wdd); 192 - 193 - out_status: 194 - mutex_unlock(&wdd->lock); 195 - return err; 162 + return wdd->ops->status(wdd); 196 163 } 197 164 198 165 /* 199 166 * watchdog_set_timeout: set the watchdog timer timeout 200 167 * @wdd: the watchdog device to set the timeout for 201 168 * @timeout: timeout to set in seconds 169 + * 170 + * The caller must hold wd_data->lock. 202 171 */ 203 172 204 173 static int watchdog_set_timeout(struct watchdog_device *wdd, 205 174 unsigned int timeout) 206 175 { 207 - int err; 208 - 209 176 if (!wdd->ops->set_timeout || !(wdd->info->options & WDIOF_SETTIMEOUT)) 210 177 return -EOPNOTSUPP; 211 178 212 179 if (watchdog_timeout_invalid(wdd, timeout)) 213 180 return -EINVAL; 214 181 215 - mutex_lock(&wdd->lock); 216 - 217 - if (test_bit(WDOG_UNREGISTERED, &wdd->status)) { 218 - err = -ENODEV; 219 - goto out_timeout; 220 - } 221 - 222 - err = wdd->ops->set_timeout(wdd, timeout); 223 - 224 - out_timeout: 225 - mutex_unlock(&wdd->lock); 226 - return err; 182 + return wdd->ops->set_timeout(wdd, timeout); 227 183 } 228 184 229 185 /* ··· 197 221 * @wdd: the watchdog device to get the remaining time from 198 222 * @timeleft: the time that's left 199 223 * 224 + * The caller must hold wd_data->lock. 225 + * 200 226 * Get the time before a watchdog will reboot (if not pinged). 201 227 */ 202 228 203 229 static int watchdog_get_timeleft(struct watchdog_device *wdd, 204 230 unsigned int *timeleft) 205 231 { 206 - int err = 0; 207 - 208 232 *timeleft = 0; 233 + 209 234 if (!wdd->ops->get_timeleft) 210 235 return -EOPNOTSUPP; 211 236 212 - mutex_lock(&wdd->lock); 213 - 214 - if (test_bit(WDOG_UNREGISTERED, &wdd->status)) { 215 - err = -ENODEV; 216 - goto out_timeleft; 217 - } 218 - 219 237 *timeleft = wdd->ops->get_timeleft(wdd); 220 238 221 - out_timeleft: 222 - mutex_unlock(&wdd->lock); 223 - return err; 239 + return 0; 224 240 } 241 + 242 + #ifdef CONFIG_WATCHDOG_SYSFS 243 + static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr, 244 + char *buf) 245 + { 246 + struct watchdog_device *wdd = dev_get_drvdata(dev); 247 + 248 + return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status)); 249 + } 250 + static DEVICE_ATTR_RO(nowayout); 251 + 252 + static ssize_t status_show(struct device *dev, struct device_attribute *attr, 253 + char *buf) 254 + { 255 + struct watchdog_device *wdd = dev_get_drvdata(dev); 256 + struct watchdog_core_data *wd_data = wdd->wd_data; 257 + unsigned int status; 258 + 259 + mutex_lock(&wd_data->lock); 260 + status = watchdog_get_status(wdd); 261 + mutex_unlock(&wd_data->lock); 262 + 263 + return sprintf(buf, "%u\n", status); 264 + } 265 + static DEVICE_ATTR_RO(status); 266 + 267 + static ssize_t bootstatus_show(struct device *dev, 268 + struct device_attribute *attr, char *buf) 269 + { 270 + struct watchdog_device *wdd = dev_get_drvdata(dev); 271 + 272 + return sprintf(buf, "%u\n", wdd->bootstatus); 273 + } 274 + static DEVICE_ATTR_RO(bootstatus); 275 + 276 + static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, 277 + char *buf) 278 + { 279 + struct watchdog_device *wdd = dev_get_drvdata(dev); 280 + struct watchdog_core_data *wd_data = wdd->wd_data; 281 + ssize_t status; 282 + unsigned int val; 283 + 284 + mutex_lock(&wd_data->lock); 285 + status = watchdog_get_timeleft(wdd, &val); 286 + mutex_unlock(&wd_data->lock); 287 + if (!status) 288 + status = sprintf(buf, "%u\n", val); 289 + 290 + return status; 291 + } 292 + static DEVICE_ATTR_RO(timeleft); 293 + 294 + static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, 295 + char *buf) 296 + { 297 + struct watchdog_device *wdd = dev_get_drvdata(dev); 298 + 299 + return sprintf(buf, "%u\n", wdd->timeout); 300 + } 301 + static DEVICE_ATTR_RO(timeout); 302 + 303 + static ssize_t identity_show(struct device *dev, struct device_attribute *attr, 304 + char *buf) 305 + { 306 + struct watchdog_device *wdd = dev_get_drvdata(dev); 307 + 308 + return sprintf(buf, "%s\n", wdd->info->identity); 309 + } 310 + static DEVICE_ATTR_RO(identity); 311 + 312 + static ssize_t state_show(struct device *dev, struct device_attribute *attr, 313 + char *buf) 314 + { 315 + struct watchdog_device *wdd = dev_get_drvdata(dev); 316 + 317 + if (watchdog_active(wdd)) 318 + return sprintf(buf, "active\n"); 319 + 320 + return sprintf(buf, "inactive\n"); 321 + } 322 + static DEVICE_ATTR_RO(state); 323 + 324 + static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr, 325 + int n) 326 + { 327 + struct device *dev = container_of(kobj, struct device, kobj); 328 + struct watchdog_device *wdd = dev_get_drvdata(dev); 329 + umode_t mode = attr->mode; 330 + 331 + if (attr == &dev_attr_status.attr && !wdd->ops->status) 332 + mode = 0; 333 + else if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft) 334 + mode = 0; 335 + 336 + return mode; 337 + } 338 + static struct attribute *wdt_attrs[] = { 339 + &dev_attr_state.attr, 340 + &dev_attr_identity.attr, 341 + &dev_attr_timeout.attr, 342 + &dev_attr_timeleft.attr, 343 + &dev_attr_bootstatus.attr, 344 + &dev_attr_status.attr, 345 + &dev_attr_nowayout.attr, 346 + NULL, 347 + }; 348 + 349 + static const struct attribute_group wdt_group = { 350 + .attrs = wdt_attrs, 351 + .is_visible = wdt_is_visible, 352 + }; 353 + __ATTRIBUTE_GROUPS(wdt); 354 + #else 355 + #define wdt_groups NULL 356 + #endif 225 357 226 358 /* 227 359 * watchdog_ioctl_op: call the watchdog drivers ioctl op if defined 228 360 * @wdd: the watchdog device to do the ioctl on 229 361 * @cmd: watchdog command 230 362 * @arg: argument pointer 363 + * 364 + * The caller must hold wd_data->lock. 231 365 */ 232 366 233 367 static int watchdog_ioctl_op(struct watchdog_device *wdd, unsigned int cmd, 234 368 unsigned long arg) 235 369 { 236 - int err; 237 - 238 370 if (!wdd->ops->ioctl) 239 371 return -ENOIOCTLCMD; 240 372 241 - mutex_lock(&wdd->lock); 242 - 243 - if (test_bit(WDOG_UNREGISTERED, &wdd->status)) { 244 - err = -ENODEV; 245 - goto out_ioctl; 246 - } 247 - 248 - err = wdd->ops->ioctl(wdd, cmd, arg); 249 - 250 - out_ioctl: 251 - mutex_unlock(&wdd->lock); 252 - return err; 373 + return wdd->ops->ioctl(wdd, cmd, arg); 253 374 } 254 375 255 376 /* ··· 364 291 static ssize_t watchdog_write(struct file *file, const char __user *data, 365 292 size_t len, loff_t *ppos) 366 293 { 367 - struct watchdog_device *wdd = file->private_data; 294 + struct watchdog_core_data *wd_data = file->private_data; 295 + struct watchdog_device *wdd; 296 + int err; 368 297 size_t i; 369 298 char c; 370 - int err; 371 299 372 300 if (len == 0) 373 301 return 0; ··· 377 303 * Note: just in case someone wrote the magic character 378 304 * five months ago... 379 305 */ 380 - clear_bit(WDOG_ALLOW_RELEASE, &wdd->status); 306 + clear_bit(_WDOG_ALLOW_RELEASE, &wd_data->status); 381 307 382 308 /* scan to see whether or not we got the magic character */ 383 309 for (i = 0; i != len; i++) { 384 310 if (get_user(c, data + i)) 385 311 return -EFAULT; 386 312 if (c == 'V') 387 - set_bit(WDOG_ALLOW_RELEASE, &wdd->status); 313 + set_bit(_WDOG_ALLOW_RELEASE, &wd_data->status); 388 314 } 389 315 390 316 /* someone wrote to us, so we send the watchdog a keepalive ping */ 391 - err = watchdog_ping(wdd); 317 + 318 + err = -ENODEV; 319 + mutex_lock(&wd_data->lock); 320 + wdd = wd_data->wdd; 321 + if (wdd) 322 + err = watchdog_ping(wdd); 323 + mutex_unlock(&wd_data->lock); 324 + 392 325 if (err < 0) 393 326 return err; 394 327 ··· 415 334 static long watchdog_ioctl(struct file *file, unsigned int cmd, 416 335 unsigned long arg) 417 336 { 418 - struct watchdog_device *wdd = file->private_data; 337 + struct watchdog_core_data *wd_data = file->private_data; 419 338 void __user *argp = (void __user *)arg; 339 + struct watchdog_device *wdd; 420 340 int __user *p = argp; 421 341 unsigned int val; 422 342 int err; 423 343 344 + mutex_lock(&wd_data->lock); 345 + 346 + wdd = wd_data->wdd; 347 + if (!wdd) { 348 + err = -ENODEV; 349 + goto out_ioctl; 350 + } 351 + 424 352 err = watchdog_ioctl_op(wdd, cmd, arg); 425 353 if (err != -ENOIOCTLCMD) 426 - return err; 354 + goto out_ioctl; 427 355 428 356 switch (cmd) { 429 357 case WDIOC_GETSUPPORT: 430 - return copy_to_user(argp, wdd->info, 358 + err = copy_to_user(argp, wdd->info, 431 359 sizeof(struct watchdog_info)) ? -EFAULT : 0; 360 + break; 432 361 case WDIOC_GETSTATUS: 433 - err = watchdog_get_status(wdd, &val); 434 - if (err == -ENODEV) 435 - return err; 436 - return put_user(val, p); 362 + val = watchdog_get_status(wdd); 363 + err = put_user(val, p); 364 + break; 437 365 case WDIOC_GETBOOTSTATUS: 438 - return put_user(wdd->bootstatus, p); 366 + err = put_user(wdd->bootstatus, p); 367 + break; 439 368 case WDIOC_SETOPTIONS: 440 - if (get_user(val, p)) 441 - return -EFAULT; 369 + if (get_user(val, p)) { 370 + err = -EFAULT; 371 + break; 372 + } 442 373 if (val & WDIOS_DISABLECARD) { 443 374 err = watchdog_stop(wdd); 444 375 if (err < 0) 445 - return err; 376 + break; 446 377 } 447 - if (val & WDIOS_ENABLECARD) { 378 + if (val & WDIOS_ENABLECARD) 448 379 err = watchdog_start(wdd); 449 - if (err < 0) 450 - return err; 451 - } 452 - return 0; 380 + break; 453 381 case WDIOC_KEEPALIVE: 454 - if (!(wdd->info->options & WDIOF_KEEPALIVEPING)) 455 - return -EOPNOTSUPP; 456 - return watchdog_ping(wdd); 382 + if (!(wdd->info->options & WDIOF_KEEPALIVEPING)) { 383 + err = -EOPNOTSUPP; 384 + break; 385 + } 386 + err = watchdog_ping(wdd); 387 + break; 457 388 case WDIOC_SETTIMEOUT: 458 - if (get_user(val, p)) 459 - return -EFAULT; 389 + if (get_user(val, p)) { 390 + err = -EFAULT; 391 + break; 392 + } 460 393 err = watchdog_set_timeout(wdd, val); 461 394 if (err < 0) 462 - return err; 395 + break; 463 396 /* If the watchdog is active then we send a keepalive ping 464 397 * to make sure that the watchdog keep's running (and if 465 398 * possible that it takes the new timeout) */ 466 399 err = watchdog_ping(wdd); 467 400 if (err < 0) 468 - return err; 401 + break; 469 402 /* Fall */ 470 403 case WDIOC_GETTIMEOUT: 471 404 /* timeout == 0 means that we don't know the timeout */ 472 - if (wdd->timeout == 0) 473 - return -EOPNOTSUPP; 474 - return put_user(wdd->timeout, p); 405 + if (wdd->timeout == 0) { 406 + err = -EOPNOTSUPP; 407 + break; 408 + } 409 + err = put_user(wdd->timeout, p); 410 + break; 475 411 case WDIOC_GETTIMELEFT: 476 412 err = watchdog_get_timeleft(wdd, &val); 477 - if (err) 478 - return err; 479 - return put_user(val, p); 413 + if (err < 0) 414 + break; 415 + err = put_user(val, p); 416 + break; 480 417 default: 481 - return -ENOTTY; 418 + err = -ENOTTY; 419 + break; 482 420 } 421 + 422 + out_ioctl: 423 + mutex_unlock(&wd_data->lock); 424 + return err; 483 425 } 484 426 485 427 /* ··· 517 413 518 414 static int watchdog_open(struct inode *inode, struct file *file) 519 415 { 520 - int err = -EBUSY; 416 + struct watchdog_core_data *wd_data; 521 417 struct watchdog_device *wdd; 418 + int err; 522 419 523 420 /* Get the corresponding watchdog device */ 524 421 if (imajor(inode) == MISC_MAJOR) 525 - wdd = old_wdd; 422 + wd_data = old_wd_data; 526 423 else 527 - wdd = container_of(inode->i_cdev, struct watchdog_device, cdev); 424 + wd_data = container_of(inode->i_cdev, struct watchdog_core_data, 425 + cdev); 528 426 529 427 /* the watchdog is single open! */ 530 - if (test_and_set_bit(WDOG_DEV_OPEN, &wdd->status)) 428 + if (test_and_set_bit(_WDOG_DEV_OPEN, &wd_data->status)) 531 429 return -EBUSY; 430 + 431 + wdd = wd_data->wdd; 532 432 533 433 /* 534 434 * If the /dev/watchdog device is open, we don't want the module 535 435 * to be unloaded. 536 436 */ 537 - if (!try_module_get(wdd->ops->owner)) 538 - goto out; 437 + if (!try_module_get(wdd->ops->owner)) { 438 + err = -EBUSY; 439 + goto out_clear; 440 + } 539 441 540 442 err = watchdog_start(wdd); 541 443 if (err < 0) 542 444 goto out_mod; 543 445 544 - file->private_data = wdd; 446 + file->private_data = wd_data; 545 447 546 - if (wdd->ops->ref) 547 - wdd->ops->ref(wdd); 448 + kref_get(&wd_data->kref); 548 449 549 450 /* dev/watchdog is a virtual (and thus non-seekable) filesystem */ 550 451 return nonseekable_open(inode, file); 551 452 552 453 out_mod: 553 - module_put(wdd->ops->owner); 554 - out: 555 - clear_bit(WDOG_DEV_OPEN, &wdd->status); 454 + module_put(wd_data->wdd->ops->owner); 455 + out_clear: 456 + clear_bit(_WDOG_DEV_OPEN, &wd_data->status); 556 457 return err; 458 + } 459 + 460 + static void watchdog_core_data_release(struct kref *kref) 461 + { 462 + struct watchdog_core_data *wd_data; 463 + 464 + wd_data = container_of(kref, struct watchdog_core_data, kref); 465 + 466 + kfree(wd_data); 557 467 } 558 468 559 469 /* ··· 582 464 583 465 static int watchdog_release(struct inode *inode, struct file *file) 584 466 { 585 - struct watchdog_device *wdd = file->private_data; 467 + struct watchdog_core_data *wd_data = file->private_data; 468 + struct watchdog_device *wdd; 586 469 int err = -EBUSY; 470 + 471 + mutex_lock(&wd_data->lock); 472 + 473 + wdd = wd_data->wdd; 474 + if (!wdd) 475 + goto done; 587 476 588 477 /* 589 478 * We only stop the watchdog if we received the magic character ··· 599 474 */ 600 475 if (!test_bit(WDOG_ACTIVE, &wdd->status)) 601 476 err = 0; 602 - else if (test_and_clear_bit(WDOG_ALLOW_RELEASE, &wdd->status) || 477 + else if (test_and_clear_bit(_WDOG_ALLOW_RELEASE, &wd_data->status) || 603 478 !(wdd->info->options & WDIOF_MAGICCLOSE)) 604 479 err = watchdog_stop(wdd); 605 480 606 481 /* If the watchdog was not stopped, send a keepalive ping */ 607 482 if (err < 0) { 608 - mutex_lock(&wdd->lock); 609 - if (!test_bit(WDOG_UNREGISTERED, &wdd->status)) 610 - dev_crit(wdd->dev, "watchdog did not stop!\n"); 611 - mutex_unlock(&wdd->lock); 483 + pr_crit("watchdog%d: watchdog did not stop!\n", wdd->id); 612 484 watchdog_ping(wdd); 613 485 } 614 486 615 - /* Allow the owner module to be unloaded again */ 616 - module_put(wdd->ops->owner); 617 - 618 487 /* make sure that /dev/watchdog can be re-opened */ 619 - clear_bit(WDOG_DEV_OPEN, &wdd->status); 488 + clear_bit(_WDOG_DEV_OPEN, &wd_data->status); 620 489 621 - /* Note wdd may be gone after this, do not use after this! */ 622 - if (wdd->ops->unref) 623 - wdd->ops->unref(wdd); 624 - 490 + done: 491 + mutex_unlock(&wd_data->lock); 492 + /* Allow the owner module to be unloaded again */ 493 + module_put(wd_data->cdev.owner); 494 + kref_put(&wd_data->kref, watchdog_core_data_release); 625 495 return 0; 626 496 } 627 497 ··· 635 515 }; 636 516 637 517 /* 518 + * watchdog_cdev_register: register watchdog character device 519 + * @wdd: watchdog device 520 + * @devno: character device number 521 + * 522 + * Register a watchdog character device including handling the legacy 523 + * /dev/watchdog node. /dev/watchdog is actually a miscdevice and 524 + * thus we set it up like that. 525 + */ 526 + 527 + static int watchdog_cdev_register(struct watchdog_device *wdd, dev_t devno) 528 + { 529 + struct watchdog_core_data *wd_data; 530 + int err; 531 + 532 + wd_data = kzalloc(sizeof(struct watchdog_core_data), GFP_KERNEL); 533 + if (!wd_data) 534 + return -ENOMEM; 535 + kref_init(&wd_data->kref); 536 + mutex_init(&wd_data->lock); 537 + 538 + wd_data->wdd = wdd; 539 + wdd->wd_data = wd_data; 540 + 541 + if (wdd->id == 0) { 542 + old_wd_data = wd_data; 543 + watchdog_miscdev.parent = wdd->parent; 544 + err = misc_register(&watchdog_miscdev); 545 + if (err != 0) { 546 + pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n", 547 + wdd->info->identity, WATCHDOG_MINOR, err); 548 + if (err == -EBUSY) 549 + pr_err("%s: a legacy watchdog module is probably present.\n", 550 + wdd->info->identity); 551 + old_wd_data = NULL; 552 + kfree(wd_data); 553 + return err; 554 + } 555 + } 556 + 557 + /* Fill in the data structures */ 558 + cdev_init(&wd_data->cdev, &watchdog_fops); 559 + wd_data->cdev.owner = wdd->ops->owner; 560 + 561 + /* Add the device */ 562 + err = cdev_add(&wd_data->cdev, devno, 1); 563 + if (err) { 564 + pr_err("watchdog%d unable to add device %d:%d\n", 565 + wdd->id, MAJOR(watchdog_devt), wdd->id); 566 + if (wdd->id == 0) { 567 + misc_deregister(&watchdog_miscdev); 568 + old_wd_data = NULL; 569 + kref_put(&wd_data->kref, watchdog_core_data_release); 570 + } 571 + } 572 + return err; 573 + } 574 + 575 + /* 576 + * watchdog_cdev_unregister: unregister watchdog character device 577 + * @watchdog: watchdog device 578 + * 579 + * Unregister watchdog character device and if needed the legacy 580 + * /dev/watchdog device. 581 + */ 582 + 583 + static void watchdog_cdev_unregister(struct watchdog_device *wdd) 584 + { 585 + struct watchdog_core_data *wd_data = wdd->wd_data; 586 + 587 + cdev_del(&wd_data->cdev); 588 + if (wdd->id == 0) { 589 + misc_deregister(&watchdog_miscdev); 590 + old_wd_data = NULL; 591 + } 592 + 593 + mutex_lock(&wd_data->lock); 594 + wd_data->wdd = NULL; 595 + wdd->wd_data = NULL; 596 + mutex_unlock(&wd_data->lock); 597 + 598 + kref_put(&wd_data->kref, watchdog_core_data_release); 599 + } 600 + 601 + static struct class watchdog_class = { 602 + .name = "watchdog", 603 + .owner = THIS_MODULE, 604 + .dev_groups = wdt_groups, 605 + }; 606 + 607 + /* 638 608 * watchdog_dev_register: register a watchdog device 639 609 * @wdd: watchdog device 640 610 * ··· 735 525 736 526 int watchdog_dev_register(struct watchdog_device *wdd) 737 527 { 738 - int err, devno; 528 + struct device *dev; 529 + dev_t devno; 530 + int ret; 739 531 740 - if (wdd->id == 0) { 741 - old_wdd = wdd; 742 - watchdog_miscdev.parent = wdd->parent; 743 - err = misc_register(&watchdog_miscdev); 744 - if (err != 0) { 745 - pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n", 746 - wdd->info->identity, WATCHDOG_MINOR, err); 747 - if (err == -EBUSY) 748 - pr_err("%s: a legacy watchdog module is probably present.\n", 749 - wdd->info->identity); 750 - old_wdd = NULL; 751 - return err; 752 - } 753 - } 754 - 755 - /* Fill in the data structures */ 756 532 devno = MKDEV(MAJOR(watchdog_devt), wdd->id); 757 - cdev_init(&wdd->cdev, &watchdog_fops); 758 - wdd->cdev.owner = wdd->ops->owner; 759 533 760 - /* Add the device */ 761 - err = cdev_add(&wdd->cdev, devno, 1); 762 - if (err) { 763 - pr_err("watchdog%d unable to add device %d:%d\n", 764 - wdd->id, MAJOR(watchdog_devt), wdd->id); 765 - if (wdd->id == 0) { 766 - misc_deregister(&watchdog_miscdev); 767 - old_wdd = NULL; 768 - } 534 + ret = watchdog_cdev_register(wdd, devno); 535 + if (ret) 536 + return ret; 537 + 538 + dev = device_create_with_groups(&watchdog_class, wdd->parent, 539 + devno, wdd, wdd->groups, 540 + "watchdog%d", wdd->id); 541 + if (IS_ERR(dev)) { 542 + watchdog_cdev_unregister(wdd); 543 + return PTR_ERR(dev); 769 544 } 770 - return err; 545 + 546 + return ret; 771 547 } 772 548 773 549 /* 774 550 * watchdog_dev_unregister: unregister a watchdog device 775 551 * @watchdog: watchdog device 776 552 * 777 - * Unregister the watchdog and if needed the legacy /dev/watchdog device. 553 + * Unregister watchdog device and if needed the legacy 554 + * /dev/watchdog device. 778 555 */ 779 556 780 - int watchdog_dev_unregister(struct watchdog_device *wdd) 557 + void watchdog_dev_unregister(struct watchdog_device *wdd) 781 558 { 782 - mutex_lock(&wdd->lock); 783 - set_bit(WDOG_UNREGISTERED, &wdd->status); 784 - mutex_unlock(&wdd->lock); 785 - 786 - cdev_del(&wdd->cdev); 787 - if (wdd->id == 0) { 788 - misc_deregister(&watchdog_miscdev); 789 - old_wdd = NULL; 790 - } 791 - return 0; 559 + device_destroy(&watchdog_class, wdd->wd_data->cdev.dev); 560 + watchdog_cdev_unregister(wdd); 792 561 } 793 562 794 563 /* ··· 778 589 779 590 int __init watchdog_dev_init(void) 780 591 { 781 - int err = alloc_chrdev_region(&watchdog_devt, 0, MAX_DOGS, "watchdog"); 782 - if (err < 0) 592 + int err; 593 + 594 + err = class_register(&watchdog_class); 595 + if (err < 0) { 596 + pr_err("couldn't register class\n"); 597 + return err; 598 + } 599 + 600 + err = alloc_chrdev_region(&watchdog_devt, 0, MAX_DOGS, "watchdog"); 601 + if (err < 0) { 783 602 pr_err("watchdog: unable to allocate char dev region\n"); 784 - return err; 603 + class_unregister(&watchdog_class); 604 + return err; 605 + } 606 + 607 + return 0; 785 608 } 786 609 787 610 /* ··· 805 604 void __exit watchdog_dev_exit(void) 806 605 { 807 606 unregister_chrdev_region(watchdog_devt, MAX_DOGS); 607 + class_unregister(&watchdog_class); 808 608 }
+367
drivers/watchdog/ziirave_wdt.c
··· 1 + /* 2 + * Copyright (C) 2015 Zodiac Inflight Innovations 3 + * 4 + * Author: Martyn Welch <martyn.welch@collabora.co.uk> 5 + * 6 + * Based on twl4030_wdt.c by Timo Kokkonen <timo.t.kokkonen at nokia.com>: 7 + * 8 + * Copyright (C) Nokia Corporation 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + */ 20 + 21 + #include <linux/i2c.h> 22 + #include <linux/kernel.h> 23 + #include <linux/module.h> 24 + #include <linux/slab.h> 25 + #include <linux/sysfs.h> 26 + #include <linux/types.h> 27 + #include <linux/version.h> 28 + #include <linux/watchdog.h> 29 + 30 + #define ZIIRAVE_TIMEOUT_MIN 3 31 + #define ZIIRAVE_TIMEOUT_MAX 255 32 + 33 + #define ZIIRAVE_PING_VALUE 0x0 34 + 35 + #define ZIIRAVE_STATE_INITIAL 0x0 36 + #define ZIIRAVE_STATE_OFF 0x1 37 + #define ZIIRAVE_STATE_ON 0x2 38 + 39 + static char *ziirave_reasons[] = {"power cycle", "triggered", NULL, NULL, 40 + "host request", NULL, "illegal configuration", 41 + "illegal instruction", "illegal trap", 42 + "unknown"}; 43 + 44 + #define ZIIRAVE_WDT_FIRM_VER_MAJOR 0x1 45 + #define ZIIRAVE_WDT_BOOT_VER_MAJOR 0x3 46 + #define ZIIRAVE_WDT_RESET_REASON 0x5 47 + #define ZIIRAVE_WDT_STATE 0x6 48 + #define ZIIRAVE_WDT_TIMEOUT 0x7 49 + #define ZIIRAVE_WDT_TIME_LEFT 0x8 50 + #define ZIIRAVE_WDT_PING 0x9 51 + #define ZIIRAVE_WDT_RESET_DURATION 0xa 52 + 53 + struct ziirave_wdt_rev { 54 + unsigned char major; 55 + unsigned char minor; 56 + }; 57 + 58 + struct ziirave_wdt_data { 59 + struct watchdog_device wdd; 60 + struct ziirave_wdt_rev bootloader_rev; 61 + struct ziirave_wdt_rev firmware_rev; 62 + int reset_reason; 63 + }; 64 + 65 + static int wdt_timeout; 66 + module_param(wdt_timeout, int, 0); 67 + MODULE_PARM_DESC(wdt_timeout, "Watchdog timeout in seconds"); 68 + 69 + static int reset_duration; 70 + module_param(reset_duration, int, 0); 71 + MODULE_PARM_DESC(reset_duration, 72 + "Watchdog reset pulse duration in milliseconds"); 73 + 74 + static bool nowayout = WATCHDOG_NOWAYOUT; 75 + module_param(nowayout, bool, 0); 76 + MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started default=" 77 + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 78 + 79 + static int ziirave_wdt_revision(struct i2c_client *client, 80 + struct ziirave_wdt_rev *rev, u8 command) 81 + { 82 + int ret; 83 + 84 + ret = i2c_smbus_read_byte_data(client, command); 85 + if (ret < 0) 86 + return ret; 87 + 88 + rev->major = ret; 89 + 90 + ret = i2c_smbus_read_byte_data(client, command + 1); 91 + if (ret < 0) 92 + return ret; 93 + 94 + rev->minor = ret; 95 + 96 + return 0; 97 + } 98 + 99 + static int ziirave_wdt_set_state(struct watchdog_device *wdd, int state) 100 + { 101 + struct i2c_client *client = to_i2c_client(wdd->parent); 102 + 103 + return i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_STATE, state); 104 + } 105 + 106 + static int ziirave_wdt_start(struct watchdog_device *wdd) 107 + { 108 + return ziirave_wdt_set_state(wdd, ZIIRAVE_STATE_ON); 109 + } 110 + 111 + static int ziirave_wdt_stop(struct watchdog_device *wdd) 112 + { 113 + return ziirave_wdt_set_state(wdd, ZIIRAVE_STATE_OFF); 114 + } 115 + 116 + static int ziirave_wdt_ping(struct watchdog_device *wdd) 117 + { 118 + struct i2c_client *client = to_i2c_client(wdd->parent); 119 + 120 + return i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_PING, 121 + ZIIRAVE_PING_VALUE); 122 + } 123 + 124 + static int ziirave_wdt_set_timeout(struct watchdog_device *wdd, 125 + unsigned int timeout) 126 + { 127 + struct i2c_client *client = to_i2c_client(wdd->parent); 128 + int ret; 129 + 130 + ret = i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_TIMEOUT, timeout); 131 + if (!ret) 132 + wdd->timeout = timeout; 133 + 134 + return ret; 135 + } 136 + 137 + static unsigned int ziirave_wdt_get_timeleft(struct watchdog_device *wdd) 138 + { 139 + struct i2c_client *client = to_i2c_client(wdd->parent); 140 + int ret; 141 + 142 + ret = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_TIME_LEFT); 143 + if (ret < 0) 144 + ret = 0; 145 + 146 + return ret; 147 + } 148 + 149 + static const struct watchdog_info ziirave_wdt_info = { 150 + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, 151 + .identity = "Zodiac RAVE Watchdog", 152 + }; 153 + 154 + static const struct watchdog_ops ziirave_wdt_ops = { 155 + .owner = THIS_MODULE, 156 + .start = ziirave_wdt_start, 157 + .stop = ziirave_wdt_stop, 158 + .ping = ziirave_wdt_ping, 159 + .set_timeout = ziirave_wdt_set_timeout, 160 + .get_timeleft = ziirave_wdt_get_timeleft, 161 + }; 162 + 163 + static ssize_t ziirave_wdt_sysfs_show_firm(struct device *dev, 164 + struct device_attribute *attr, 165 + char *buf) 166 + { 167 + struct i2c_client *client = to_i2c_client(dev->parent); 168 + struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client); 169 + 170 + return sprintf(buf, "02.%02u.%02u", w_priv->firmware_rev.major, 171 + w_priv->firmware_rev.minor); 172 + } 173 + 174 + static DEVICE_ATTR(firmware_version, S_IRUGO, ziirave_wdt_sysfs_show_firm, 175 + NULL); 176 + 177 + static ssize_t ziirave_wdt_sysfs_show_boot(struct device *dev, 178 + struct device_attribute *attr, 179 + char *buf) 180 + { 181 + struct i2c_client *client = to_i2c_client(dev->parent); 182 + struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client); 183 + 184 + return sprintf(buf, "01.%02u.%02u", w_priv->bootloader_rev.major, 185 + w_priv->bootloader_rev.minor); 186 + } 187 + 188 + static DEVICE_ATTR(bootloader_version, S_IRUGO, ziirave_wdt_sysfs_show_boot, 189 + NULL); 190 + 191 + static ssize_t ziirave_wdt_sysfs_show_reason(struct device *dev, 192 + struct device_attribute *attr, 193 + char *buf) 194 + { 195 + struct i2c_client *client = to_i2c_client(dev->parent); 196 + struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client); 197 + 198 + return sprintf(buf, "%s", ziirave_reasons[w_priv->reset_reason]); 199 + } 200 + 201 + static DEVICE_ATTR(reset_reason, S_IRUGO, ziirave_wdt_sysfs_show_reason, 202 + NULL); 203 + 204 + static struct attribute *ziirave_wdt_attrs[] = { 205 + &dev_attr_firmware_version.attr, 206 + &dev_attr_bootloader_version.attr, 207 + &dev_attr_reset_reason.attr, 208 + NULL 209 + }; 210 + ATTRIBUTE_GROUPS(ziirave_wdt); 211 + 212 + static int ziirave_wdt_init_duration(struct i2c_client *client) 213 + { 214 + int ret; 215 + 216 + if (!reset_duration) { 217 + /* See if the reset pulse duration is provided in an of_node */ 218 + if (!client->dev.of_node) 219 + ret = -ENODEV; 220 + else 221 + ret = of_property_read_u32(client->dev.of_node, 222 + "reset-duration-ms", 223 + &reset_duration); 224 + if (ret) { 225 + dev_info(&client->dev, 226 + "Unable to set reset pulse duration, using default\n"); 227 + return 0; 228 + } 229 + } 230 + 231 + if (reset_duration < 1 || reset_duration > 255) 232 + return -EINVAL; 233 + 234 + dev_info(&client->dev, "Setting reset duration to %dms", 235 + reset_duration); 236 + 237 + return i2c_smbus_write_byte_data(client, ZIIRAVE_WDT_RESET_DURATION, 238 + reset_duration); 239 + } 240 + 241 + static int ziirave_wdt_probe(struct i2c_client *client, 242 + const struct i2c_device_id *id) 243 + { 244 + int ret; 245 + struct ziirave_wdt_data *w_priv; 246 + int val; 247 + 248 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 249 + return -ENODEV; 250 + 251 + w_priv = devm_kzalloc(&client->dev, sizeof(*w_priv), GFP_KERNEL); 252 + if (!w_priv) 253 + return -ENOMEM; 254 + 255 + w_priv->wdd.info = &ziirave_wdt_info; 256 + w_priv->wdd.ops = &ziirave_wdt_ops; 257 + w_priv->wdd.min_timeout = ZIIRAVE_TIMEOUT_MIN; 258 + w_priv->wdd.max_timeout = ZIIRAVE_TIMEOUT_MAX; 259 + w_priv->wdd.parent = &client->dev; 260 + w_priv->wdd.groups = ziirave_wdt_groups; 261 + 262 + ret = watchdog_init_timeout(&w_priv->wdd, wdt_timeout, &client->dev); 263 + if (ret) { 264 + dev_info(&client->dev, 265 + "Unable to select timeout value, using default\n"); 266 + } 267 + 268 + /* 269 + * The default value set in the watchdog should be perfectly valid, so 270 + * pass that in if we haven't provided one via the module parameter or 271 + * of property. 272 + */ 273 + if (w_priv->wdd.timeout == 0) { 274 + val = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_TIMEOUT); 275 + if (val < 0) 276 + return val; 277 + 278 + if (val < ZIIRAVE_TIMEOUT_MIN) 279 + return -ENODEV; 280 + 281 + w_priv->wdd.timeout = val; 282 + } else { 283 + ret = ziirave_wdt_set_timeout(&w_priv->wdd, 284 + w_priv->wdd.timeout); 285 + if (ret) 286 + return ret; 287 + 288 + dev_info(&client->dev, "Timeout set to %ds.", 289 + w_priv->wdd.timeout); 290 + } 291 + 292 + watchdog_set_nowayout(&w_priv->wdd, nowayout); 293 + 294 + i2c_set_clientdata(client, w_priv); 295 + 296 + /* If in unconfigured state, set to stopped */ 297 + val = i2c_smbus_read_byte_data(client, ZIIRAVE_WDT_STATE); 298 + if (val < 0) 299 + return val; 300 + 301 + if (val == ZIIRAVE_STATE_INITIAL) 302 + ziirave_wdt_stop(&w_priv->wdd); 303 + 304 + ret = ziirave_wdt_init_duration(client); 305 + if (ret) 306 + return ret; 307 + 308 + ret = ziirave_wdt_revision(client, &w_priv->firmware_rev, 309 + ZIIRAVE_WDT_FIRM_VER_MAJOR); 310 + if (ret) 311 + return ret; 312 + 313 + ret = ziirave_wdt_revision(client, &w_priv->bootloader_rev, 314 + ZIIRAVE_WDT_BOOT_VER_MAJOR); 315 + if (ret) 316 + return ret; 317 + 318 + w_priv->reset_reason = i2c_smbus_read_byte_data(client, 319 + ZIIRAVE_WDT_RESET_REASON); 320 + if (w_priv->reset_reason < 0) 321 + return w_priv->reset_reason; 322 + 323 + if (w_priv->reset_reason >= ARRAY_SIZE(ziirave_reasons) || 324 + !ziirave_reasons[w_priv->reset_reason]) 325 + return -ENODEV; 326 + 327 + ret = watchdog_register_device(&w_priv->wdd); 328 + 329 + return ret; 330 + } 331 + 332 + static int ziirave_wdt_remove(struct i2c_client *client) 333 + { 334 + struct ziirave_wdt_data *w_priv = i2c_get_clientdata(client); 335 + 336 + watchdog_unregister_device(&w_priv->wdd); 337 + 338 + return 0; 339 + } 340 + 341 + static struct i2c_device_id ziirave_wdt_id[] = { 342 + { "ziirave-wdt", 0 }, 343 + { } 344 + }; 345 + MODULE_DEVICE_TABLE(i2c, ziirave_wdt_id); 346 + 347 + static const struct of_device_id zrv_wdt_of_match[] = { 348 + { .compatible = "zii,rave-wdt", }, 349 + { }, 350 + }; 351 + MODULE_DEVICE_TABLE(of, zrv_wdt_of_match); 352 + 353 + static struct i2c_driver ziirave_wdt_driver = { 354 + .driver = { 355 + .name = "ziirave_wdt", 356 + .of_match_table = zrv_wdt_of_match, 357 + }, 358 + .probe = ziirave_wdt_probe, 359 + .remove = ziirave_wdt_remove, 360 + .id_table = ziirave_wdt_id, 361 + }; 362 + 363 + module_i2c_driver(ziirave_wdt_driver); 364 + 365 + MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk"); 366 + MODULE_DESCRIPTION("Zodiac Aerospace RAVE Switch Watchdog Processor Driver"); 367 + MODULE_LICENSE("GPL");
-3
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 4 #include <linux/timer.h> 6 5 #include <linux/types.h> 7 6 #include <linux/watchdog.h> ··· 14 15 void *driver_data; 15 16 16 17 struct watchdog_device wdd; 17 - struct notifier_block notifier; 18 - struct notifier_block restart_handler; 19 18 20 19 struct timer_list soft_timer; 21 20 atomic_t soft_ticks;
+23 -15
include/linux/watchdog.h
··· 12 12 #include <linux/bitops.h> 13 13 #include <linux/device.h> 14 14 #include <linux/cdev.h> 15 + #include <linux/notifier.h> 15 16 #include <uapi/linux/watchdog.h> 16 17 17 18 struct watchdog_ops; 18 19 struct watchdog_device; 20 + struct watchdog_core_data; 19 21 20 22 /** struct watchdog_ops - The watchdog-devices operations 21 23 * ··· 28 26 * @status: The routine that shows the status of the watchdog device. 29 27 * @set_timeout:The routine for setting the watchdog devices timeout value (in seconds). 30 28 * @get_timeleft:The routine that gets the time left before a reset (in seconds). 31 - * @ref: The ref operation for dyn. allocated watchdog_device structs 32 - * @unref: The unref operation for dyn. allocated watchdog_device structs 29 + * @restart: The routine for restarting the machine. 33 30 * @ioctl: The routines that handles extra ioctl calls. 34 31 * 35 32 * The watchdog_ops structure contains a list of low-level operations ··· 46 45 unsigned int (*status)(struct watchdog_device *); 47 46 int (*set_timeout)(struct watchdog_device *, unsigned int); 48 47 unsigned int (*get_timeleft)(struct watchdog_device *); 49 - void (*ref)(struct watchdog_device *); 50 - void (*unref)(struct watchdog_device *); 48 + int (*restart)(struct watchdog_device *); 51 49 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long); 52 50 }; 53 51 54 52 /** struct watchdog_device - The structure that defines a watchdog device 55 53 * 56 54 * @id: The watchdog's ID. (Allocated by watchdog_register_device) 57 - * @cdev: The watchdog's Character device. 58 - * @dev: The device for our watchdog 59 55 * @parent: The parent bus device 56 + * @groups: List of sysfs attribute groups to create when creating the 57 + * watchdog device. 60 58 * @info: Pointer to a watchdog_info structure. 61 59 * @ops: Pointer to the list of watchdog operations. 62 60 * @bootstatus: Status of the watchdog device at boot. 63 61 * @timeout: The watchdog devices timeout value (in seconds). 64 62 * @min_timeout:The watchdog devices minimum timeout value (in seconds). 65 63 * @max_timeout:The watchdog devices maximum timeout value (in seconds). 66 - * @driver-data:Pointer to the drivers private data. 67 - * @lock: Lock for watchdog core internal use only. 64 + * @reboot_nb: The notifier block to stop watchdog on reboot. 65 + * @restart_nb: The notifier block to register a restart function. 66 + * @driver_data:Pointer to the drivers private data. 67 + * @wd_data: Pointer to watchdog core internal data. 68 68 * @status: Field that contains the devices internal status bits. 69 69 * @deferred: entry in wtd_deferred_reg_list which is used to 70 70 * register early initialized watchdogs. ··· 81 79 */ 82 80 struct watchdog_device { 83 81 int id; 84 - struct cdev cdev; 85 - struct device *dev; 86 82 struct device *parent; 83 + const struct attribute_group **groups; 87 84 const struct watchdog_info *info; 88 85 const struct watchdog_ops *ops; 89 86 unsigned int bootstatus; 90 87 unsigned int timeout; 91 88 unsigned int min_timeout; 92 89 unsigned int max_timeout; 90 + struct notifier_block reboot_nb; 91 + struct notifier_block restart_nb; 93 92 void *driver_data; 94 - struct mutex lock; 93 + struct watchdog_core_data *wd_data; 95 94 unsigned long status; 96 95 /* Bit numbers for status flags */ 97 96 #define WDOG_ACTIVE 0 /* Is the watchdog running/active */ 98 - #define WDOG_DEV_OPEN 1 /* Opened via /dev/watchdog ? */ 99 - #define WDOG_ALLOW_RELEASE 2 /* Did we receive the magic char ? */ 100 - #define WDOG_NO_WAY_OUT 3 /* Is 'nowayout' feature set ? */ 101 - #define WDOG_UNREGISTERED 4 /* Has the device been unregistered */ 97 + #define WDOG_NO_WAY_OUT 1 /* Is 'nowayout' feature set ? */ 98 + #define WDOG_STOP_ON_REBOOT 2 /* Should be stopped on reboot */ 102 99 struct list_head deferred; 103 100 }; 104 101 ··· 115 114 { 116 115 if (nowayout) 117 116 set_bit(WDOG_NO_WAY_OUT, &wdd->status); 117 + } 118 + 119 + /* Use the following function to stop the watchdog on reboot */ 120 + static inline void watchdog_stop_on_reboot(struct watchdog_device *wdd) 121 + { 122 + set_bit(WDOG_STOP_ON_REBOOT, &wdd->status); 118 123 } 119 124 120 125 /* Use the following function to check if a timeout value is invalid */ ··· 149 142 } 150 143 151 144 /* drivers/watchdog/watchdog_core.c */ 145 + void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority); 152 146 extern int watchdog_init_timeout(struct watchdog_device *wdd, 153 147 unsigned int timeout_parm, struct device *dev); 154 148 extern int watchdog_register_device(struct watchdog_device *);