History

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

Pull watchdog updates from Wim Van Sebroeck: "This contains: - fixes and improvements - devicetree bindings - conversion to watchdog generic framework of the following drivers: - booke_wdt - bcm47xx_wdt.c - at91sam9_wdt - Removal of old STMP3xxx driver - Addition of following new drivers: - new driver for STMP3xxx and i.MX23/28 - Retu watchdog driver" * git://www.linux-watchdog.org/linux-watchdog: (30 commits) watchdog: sp805_wdt depends on ARM watchdog: davinci_wdt: update to devm_* API watchdog: davinci_wdt: use devm managed clk get watchdog: at91rm9200: add DT support watchdog: add timeout-sec property binding watchdog: at91sam9_wdt: Convert to use the watchdog framework watchdog: omap_wdt: Add option nowayout watchdog: core: dt: add support for the timeout-sec dt property watchdog: bcm47xx_wdt.c: add hard timer watchdog: bcm47xx_wdt.c: rename wdt_time to timeout watchdog: bcm47xx_wdt.c: rename ops methods watchdog: bcm47xx_wdt.c: use platform device watchdog: bcm47xx_wdt.c: convert to watchdog core api watchdog: Convert BookE watchdog driver to watchdog infrastructure watchdog: s3c2410_wdt: Use devm_* functions watchdog: remove old STMP3xxx driver watchdog: add new driver for STMP3xxx and i.MX23/28 rtc: stmp3xxx: add wdt-accessor function watchdog: introduce retu_wdt driver watchdog: intel_scu_watchdog: fix Kconfig dependency ...

Linus Torvalds committed 13 years ago

Commit 68b86a22 parents 527c680 41e9f3f31 files · +888 −856Browse files

Unified · Split

31 files
  1. Documentation/devicetree/bindings/watchdog/atmel-at91rm9200-wdt.txt +9 −0
  2. Documentation/devicetree/bindings/watchdog/atmel-wdt.txt +4 −0
  3. Documentation/devicetree/bindings/watchdog/marvel.txt +5 −0
  4. Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt +4 −0
  5. Documentation/devicetree/bindings/watchdog/qca-ar7130-wdt.txt +13 −0
  6. Documentation/devicetree/bindings/watchdog/samsung-wdt.txt +3 −0
  7. Documentation/watchdog/watchdog-kernel-api.txt +13 −1
  8. arch/mips/ath79/dev-common.c +9 −6
  9. drivers/rtc/rtc-stmp3xxx.c +64 −0
  10. drivers/watchdog/Kconfig +26 −9
  11. drivers/watchdog/Makefile +2 −1
  12. drivers/watchdog/at91rm9200_wdt.c +9 −0
  13. drivers/watchdog/at91sam9_wdt.c +46 −122
  14. drivers/watchdog/ath79_wdt.c +51 −15
  15. drivers/watchdog/bcm47xx_wdt.c +144 −195
  16. drivers/watchdog/booke_wdt.c +65 −120
  17. drivers/watchdog/davinci_wdt.c +6 −23
  18. drivers/watchdog/gef_wdt.c +1 −0
  19. drivers/watchdog/omap_wdt.c +5 −1
  20. drivers/watchdog/orion_wdt.c +5 −6
  21. drivers/watchdog/pnx4008_wdt.c +3 −4
  22. drivers/watchdog/retu_wdt.c +178 −0
  23. drivers/watchdog/s3c2410_wdt.c +13 −35
  24. drivers/watchdog/sp5100_tco.c +8 −19
  25. drivers/watchdog/stmp3xxx_rtc_wdt.c +111 −0
  26. drivers/watchdog/stmp3xxx_wdt.c +0 −288
  27. drivers/watchdog/watchdog_core.c +57 −9
  28. drivers/watchdog/watchdog_dev.c +1 −2
  29. include/linux/bcm47xx_wdt.h +9 −0
  30. include/linux/stmp3xxx_rtc_wdt.h +15 −0
  31. include/linux/watchdog.h +9 −0
Documentation/devicetree/bindings/watchdog/atmel-at91rm9200-wdt.txt+9−0
@@ -0,0 +1,9 @@
1+Atmel AT91RM9200 System Timer Watchdog
2+
3+Required properties:
4+- compatible: must be "atmel,at91sam9260-wdt".
5+
6+Example:
7+ watchdog@fffffd00 {
8+ compatible = "atmel,at91rm9200-wdt";
9+ };
Documentation/devicetree/bindings/watchdog/atmel-wdt.txt+4−0
@@ -7,9 +7,13 @@ Required properties: · 6 unmodified lines
77 - reg: physical base address of the controller and length of memory mapped
88 region.
99
10+Optional properties:
11+- timeout-sec: contains the watchdog timeout in seconds.
12+
1013 Example:
1114
1215 watchdog@fffffd40 {
1316 compatible = "atmel,at91sam9260-wdt";
1417 reg = <0xfffffd40 0x10>;
18+ timeout-sec = <10>;
1519 };
Documentation/devicetree/bindings/watchdog/marvel.txt+5−0
@@ -5,10 +5,15 @@ Required Properties: · 4 unmodified lines
55 - Compatibility : "marvell,orion-wdt"
66 - reg : Address of the timer registers
77
8+Optional properties:
9+
10+- timeout-sec : Contains the watchdog timeout in seconds
11+
812 Example:
913
1014 wdt@20300 {
1115 compatible = "marvell,orion-wdt";
1216 reg = <0x20300 0x28>;
17+ timeout-sec = <10>;
1318 status = "okay";
1419 };
Documentation/devicetree/bindings/watchdog/pnx4008-wdt.txt+4−0
@@ -5,9 +5,13 @@ Required properties: · 4 unmodified lines
55 - reg: physical base address of the controller and length of memory mapped
66 region.
77
8+Optional properties:
9+- timeout-sec: contains the watchdog timeout in seconds.
10+
811 Example:
912
1013 watchdog@4003C000 {
1114 compatible = "nxp,pnx4008-wdt";
1215 reg = <0x4003C000 0x1000>;
16+ timeout-sec = <10>;
1317 };
Documentation/devicetree/bindings/watchdog/qca-ar7130-wdt.txt+13−0
@@ -0,0 +1,13 @@
1+* Qualcomm Atheros AR7130 Watchdog Timer (WDT) Controller
2+
3+Required properties:
4+- compatible: must be "qca,ar7130-wdt"
5+- reg: physical base address of the controller and length of memory mapped
6+ region.
7+
8+Example:
9+
10+wdt@18060008 {
11+ compatible = "qca,ar9330-wdt", "qca,ar7130-wdt";
12+ reg = <0x18060008 0x8>;
13+};
Documentation/devicetree/bindings/watchdog/samsung-wdt.txt+3−0
@@ -9,3 +9,6 @@ Required properties: · 8 unmodified lines
99 - reg : base physical address of the controller and length of memory mapped
1010 region.
1111 - interrupts : interrupt number to the cpu.
12+
13+Optional properties:
14+- timeout-sec : contains the watchdog timeout in seconds.
Documentation/watchdog/watchdog-kernel-api.txt+13−1
@@ -1,6 +1,6 @@
11 The Linux WatchDog Timer Driver Core kernel API.
22 ===============================================
3−Last reviewed: 22-May-2012
3+Last reviewed: 12-Feb-2013
44
55 Wim Van Sebroeck <wim@iguana.be>
66
@@ -212,3 +212,15 @@ driver specific data to and a pointer to the data itself. · 205 unmodified lines
212212 The watchdog_get_drvdata function allows you to retrieve driver specific data.
213213 The argument of this function is the watchdog device where you want to retrieve
214214 data from. The function returns the pointer to the driver specific data.
215+
216+To initialize the timeout field, the following function can be used:
217+
218+extern int watchdog_init_timeout(struct watchdog_device *wdd,
219+ unsigned int timeout_parm, struct device *dev);
220+
221+The watchdog_init_timeout function allows you to initialize the timeout field
222+using the module timeout parameter or by retrieving the timeout-sec property from
223+the device tree (if the module timeout parameter is invalid). Best practice is
224+to set the default timeout value as timeout value in the watchdog_device and
225+then use this function to set the user "preferred" timeout value.
226+This routine returns zero on success and a negative errno code for failure.
arch/mips/ath79/dev-common.c+9−6
@@ -102,12 +102,15 @@ void __init ath79_register_uart(void) · 101 unmodified lines
102102 }
103103 }
104104
105−static struct platform_device ath79_wdt_device = {
106− .name = "ath79-wdt",
107− .id = -1,
108−};
109−
110105 void __init ath79_register_wdt(void)
111106 {
112− platform_device_register(&ath79_wdt_device);
107+ struct resource res;
108+
109+ memset(&res, 0, sizeof(res));
110+
111+ res.flags = IORESOURCE_MEM;
112+ res.start = AR71XX_RESET_BASE + AR71XX_RESET_REG_WDOG_CTRL;
113+ res.end = res.start + 0x8 - 1;
114+
115+ platform_device_register_simple("ath79-wdt", -1, &res, 1);
113116 }
drivers/rtc/rtc-stmp3xxx.c+64−0
@@ -27,6 +27,8 @@ · 26 unmodified lines
2727 #include <linux/slab.h>
2828 #include <linux/of_device.h>
2929 #include <linux/of.h>
30+#include <linux/stmp_device.h>
31+#include <linux/stmp3xxx_rtc_wdt.h>
3032
3133 #include <mach/common.h>
3234
@@ -36,6 +38,7 @@ · 3 unmodified lines
3638 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN 0x00000001
3739 #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN 0x00000002
3840 #define STMP3XXX_RTC_CTRL_ALARM_IRQ 0x00000004
41+#define STMP3XXX_RTC_CTRL_WATCHDOGEN 0x00000010
3942
4043 #define STMP3XXX_RTC_STAT 0x10
4144 #define STMP3XXX_RTC_STAT_STALE_SHIFT 16
@@ -45,6 +48,8 @@ · 3 unmodified lines
4548
4649 #define STMP3XXX_RTC_ALARM 0x40
4750
51+#define STMP3XXX_RTC_WATCHDOG 0x50
52+
4853 #define STMP3XXX_RTC_PERSISTENT0 0x60
4954 #define STMP3XXX_RTC_PERSISTENT0_SET 0x64
5055 #define STMP3XXX_RTC_PERSISTENT0_CLR 0x68
@@ -52,12 +57,70 @@ · 1 unmodified line
5257 #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN 0x00000004
5358 #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE 0x00000080
5459
60+#define STMP3XXX_RTC_PERSISTENT1 0x70
61+/* missing bitmask in headers */
62+#define STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER 0x80000000
63+
5564 struct stmp3xxx_rtc_data {
5665 struct rtc_device *rtc;
5766 void __iomem *io;
5867 int irq_alarm;
5968 };
6069
70+#if IS_ENABLED(CONFIG_STMP3XXX_RTC_WATCHDOG)
71+/**
72+ * stmp3xxx_wdt_set_timeout - configure the watchdog inside the STMP3xxx RTC
73+ * @dev: the parent device of the watchdog (= the RTC)
74+ * @timeout: the desired value for the timeout register of the watchdog.
75+ * 0 disables the watchdog
76+ *
77+ * The watchdog needs one register and two bits which are in the RTC domain.
78+ * To handle the resource conflict, the RTC driver will create another
79+ * platform_device for the watchdog driver as a child of the RTC device.
80+ * The watchdog driver is passed the below accessor function via platform_data
81+ * to configure the watchdog. Locking is not needed because accessing SET/CLR
82+ * registers is atomic.
83+ */
84+
85+static void stmp3xxx_wdt_set_timeout(struct device *dev, u32 timeout)
86+{
87+ struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
88+
89+ if (timeout) {
90+ writel(timeout, rtc_data->io + STMP3XXX_RTC_WATCHDOG);
91+ writel(STMP3XXX_RTC_CTRL_WATCHDOGEN,
92+ rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
93+ writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER,
94+ rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_SET);
95+ } else {
96+ writel(STMP3XXX_RTC_CTRL_WATCHDOGEN,
97+ rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
98+ writel(STMP3XXX_RTC_PERSISTENT1_FORCE_UPDATER,
99+ rtc_data->io + STMP3XXX_RTC_PERSISTENT1 + STMP_OFFSET_REG_CLR);
100+ }
101+}
102+
103+static struct stmp3xxx_wdt_pdata wdt_pdata = {
104+ .wdt_set_timeout = stmp3xxx_wdt_set_timeout,
105+};
106+
107+static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
108+{
109+ struct platform_device *wdt_pdev =
110+ platform_device_alloc("stmp3xxx_rtc_wdt", rtc_pdev->id);
111+
112+ if (wdt_pdev) {
113+ wdt_pdev->dev.parent = &rtc_pdev->dev;
114+ wdt_pdev->dev.platform_data = &wdt_pdata;
115+ platform_device_add(wdt_pdev);
116+ }
117+}
118+#else
119+static void stmp3xxx_wdt_register(struct platform_device *rtc_pdev)
120+{
121+}
122+#endif /* CONFIG_STMP3XXX_RTC_WATCHDOG */
123+
61124 static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data)
62125 {
63126 /*
@@ -233,6 +296,7 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) · 169 unmodified lines
233296 goto out_irq_alarm;
234297 }
235298
299+ stmp3xxx_wdt_register(pdev);
236300 return 0;
237301
238302 out_irq_alarm:
drivers/watchdog/Kconfig+26−9
@@ -79,6 +79,7 @@ config DA9052_WATCHDOG · 78 unmodified lines
7979 config DA9055_WATCHDOG
8080 tristate "Dialog Semiconductor DA9055 Watchdog"
8181 depends on MFD_DA9055
82+ select WATCHDOG_CORE
8283 help
8384 If you say yes here you get support for watchdog on the Dialog
8485 Semiconductor DA9055 PMIC.
@@ -108,7 +109,7 @@ config WM8350_WATCHDOG · 23 unmodified lines
108109
109110 config ARM_SP805_WATCHDOG
110111 tristate "ARM SP805 Watchdog"
111− depends on ARM_AMBA
112+ depends on ARM && ARM_AMBA
112113 select WATCHDOG_CORE
113114 help
114115 ARM Primecell SP805 Watchdog timer. This will reboot your system when
@@ -116,7 +117,7 @@ config ARM_SP805_WATCHDOG · 1 unmodified line
116117
117118 config AT91RM9200_WATCHDOG
118119 tristate "AT91RM9200 watchdog"
119− depends on ARCH_AT91RM9200
120+ depends on ARCH_AT91
120121 help
121122 Watchdog timer embedded into AT91RM9200 chips. This will reboot your
122123 system when the timeout is reached.
@@ -124,6 +125,7 @@ config AT91RM9200_WATCHDOG · 1 unmodified line
124125 config AT91SAM9X_WATCHDOG
125126 tristate "AT91SAM9X / AT91CAP9 watchdog"
126127 depends on ARCH_AT91 && !ARCH_AT91RM9200
128+ select WATCHDOG_CORE
127129 help
128130 Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will
129131 reboot your system when the timeout is reached.
@@ -316,14 +318,15 @@ config TWL4030_WATCHDOG · 186 unmodified lines
316318 Support for TI TWL4030 watchdog. Say 'Y' here to enable the
317319 watchdog timer support for TWL4030 chips.
318320
319−config STMP3XXX_WATCHDOG
320− tristate "Freescale STMP3XXX watchdog"
321− depends on ARCH_STMP3XXX
321+config STMP3XXX_RTC_WATCHDOG
322+ tristate "Freescale STMP3XXX & i.MX23/28 watchdog"
323+ depends on RTC_DRV_STMP
324+ select WATCHDOG_CORE
322325 help
323− Say Y here if to include support for the watchdog timer
324− for the Sigmatel STMP37XX/378X SoC.
326+ Say Y here to include support for the watchdog timer inside
327+ the RTC for the STMP37XX/378X or i.MX23/28 SoC.
325328 To compile this driver as a module, choose M here: the
326− module will be called stmp3xxx_wdt.
329+ module will be called stmp3xxx_rtc_wdt.
327330
328331 config NUC900_WATCHDOG
329332 tristate "Nuvoton NUC900 watchdog"
@@ -376,6 +379,18 @@ config UX500_WATCHDOG · 46 unmodified lines
376379 To compile this driver as a module, choose M here: the
377380 module will be called ux500_wdt.
378381
382+config RETU_WATCHDOG
383+ tristate "Retu watchdog"
384+ depends on MFD_RETU
385+ select WATCHDOG_CORE
386+ help
387+ Retu watchdog driver for Nokia Internet Tablets (770, N800,
388+ N810). At least on N800 the watchdog cannot be disabled, so
389+ this driver is essential and you should enable it.
390+
391+ To compile this driver as a module, choose M here: the
392+ module will be called retu_wdt.
393+
379394 # AVR32 Architecture
380395
381396 config AT32AP700X_WDT
@@ -593,7 +608,7 @@ config IE6XX_WDT · 211 unmodified lines
593608
594609 config INTEL_SCU_WATCHDOG
595610 bool "Intel SCU Watchdog for Mobile Platforms"
596− depends on X86_MRST
611+ depends on X86_INTEL_MID
597612 ---help---
598613 Hardware driver for the watchdog time built into the Intel SCU
599614 for Intel Mobile Platforms.
@@ -983,6 +998,7 @@ config ATH79_WDT · 383 unmodified lines
983998 config BCM47XX_WDT
984999 tristate "Broadcom BCM47xx Watchdog Timer"
9851000 depends on BCM47XX
1001+ select WATCHDOG_CORE
9861002 help
9871003 Hardware driver for the Broadcom BCM47xx Watchdog Timer.
9881004
@@ -1131,6 +1147,7 @@ config PIKA_WDT · 142 unmodified lines
11311147 config BOOKE_WDT
11321148 tristate "PowerPC Book-E Watchdog Timer"
11331149 depends on BOOKE || 4xx
1150+ select WATCHDOG_CORE
11341151 ---help---
11351152 Watchdog driver for PowerPC Book-E chips, such as the Freescale
11361153 MPC85xx SOCs and the IBM PowerPC 440.
drivers/watchdog/Makefile+2−1
@@ -48,11 +48,12 @@ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o · 47 unmodified lines
4848 obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o
4949 obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
5050 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
51−obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
51+obj-$(CONFIG_STMP3XXX_RTC_WATCHDOG) += stmp3xxx_rtc_wdt.o
5252 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
5353 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
5454 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
5555 obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
56+obj-$(CONFIG_RETU_WATCHDOG) += retu_wdt.o
5657
5758 # AVR32 Architecture
5859 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
drivers/watchdog/at91rm9200_wdt.c+9−0
@@ -24,6 +24,8 @@ · 23 unmodified lines
2424 #include <linux/types.h>
2525 #include <linux/watchdog.h>
2626 #include <linux/uaccess.h>
27+#include <linux/of.h>
28+#include <linux/of_device.h>
2729 #include <mach/at91_st.h>
2830
2931 #define WDT_DEFAULT_TIME 5 /* seconds */
@@ -252,6 +254,12 @@ static int at91wdt_resume(struct platform_device *pdev) · 222 unmodified lines
252254 #define at91wdt_resume NULL
253255 #endif
254256
257+static const struct of_device_id at91_wdt_dt_ids[] = {
258+ { .compatible = "atmel,at91rm9200-wdt" },
259+ { /* sentinel */ }
260+};
261+MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
262+
255263 static struct platform_driver at91wdt_driver = {
256264 .probe = at91wdt_probe,
257265 .remove = at91wdt_remove,
@@ -261,6 +269,7 @@ static struct platform_driver at91wdt_driver = { · 3 unmodified lines
261269 .driver = {
262270 .name = "at91_wdt",
263271 .owner = THIS_MODULE,
272+ .of_match_table = of_match_ptr(at91_wdt_dt_ids),
264273 },
265274 };
266275
drivers/watchdog/at91sam9_wdt.c+46−122
@@ -18,11 +18,9 @@ · 17 unmodified lines
1818 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1919
2020 #include <linux/errno.h>
21−#include <linux/fs.h>
2221 #include <linux/init.h>
2322 #include <linux/io.h>
2423 #include <linux/kernel.h>
25−#include <linux/miscdevice.h>
2624 #include <linux/module.h>
2725 #include <linux/moduleparam.h>
2826 #include <linux/platform_device.h>
@@ -58,7 +56,7 @@ · 29 unmodified lines
5856
5957 /* User land timeout */
6058 #define WDT_HEARTBEAT 15
61−static int heartbeat = WDT_HEARTBEAT;
59+static int heartbeat;
6260 module_param(heartbeat, int, 0);
6361 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. "
6462 "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")");
@@ -68,19 +66,17 @@ module_param(nowayout, bool, 0); · 3 unmodified lines
6866 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
6967 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
7068
69+static struct watchdog_device at91_wdt_dev;
7170 static void at91_ping(unsigned long data);
7271
7372 static struct {
7473 void __iomem *base;
7574 unsigned long next_heartbeat; /* the next_heartbeat for the timer */
76− unsigned long open;
77− char expect_close;
7875 struct timer_list timer; /* The timer that pings the watchdog */
7976 } at91wdt_private;
8077
8178 /* ......................................................................... */
8279
83−
8480 /*
8581 * Reload the watchdog timer. (ie, pat the watchdog)
8682 */
@@ -95,39 +91,37 @@ static inline void at91_wdt_reset(void) · 8 unmodified lines
9591 static void at91_ping(unsigned long data)
9692 {
9793 if (time_before(jiffies, at91wdt_private.next_heartbeat) ||
98− (!nowayout && !at91wdt_private.open)) {
94+ (!watchdog_active(&at91_wdt_dev))) {
9995 at91_wdt_reset();
10096 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
10197 } else
10298 pr_crit("I will reset your machine !\n");
10399 }
104100
105−/*
106− * Watchdog device is opened, and watchdog starts running.
107− */
108−static int at91_wdt_open(struct inode *inode, struct file *file)
101+static int at91_wdt_ping(struct watchdog_device *wdd)
109102 {
110− if (test_and_set_bit(0, &at91wdt_private.open))
111− return -EBUSY;
103+ /* calculate when the next userspace timeout will be */
104+ at91wdt_private.next_heartbeat = jiffies + wdd->timeout * HZ;
105+ return 0;
106+}
112107
113− at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
108+static int at91_wdt_start(struct watchdog_device *wdd)
109+{
110+ /* calculate the next userspace timeout and modify the timer */
111+ at91_wdt_ping(wdd);
114112 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
115−
116− return nonseekable_open(inode, file);
113+ return 0;
117114 }
118115
119−/*
120− * Close the watchdog device.
121− */
122−static int at91_wdt_close(struct inode *inode, struct file *file)
116+static int at91_wdt_stop(struct watchdog_device *wdd)
123117 {
124− clear_bit(0, &at91wdt_private.open);
125−
126− /* stop internal ping */
127− if (!at91wdt_private.expect_close)
128− del_timer(&at91wdt_private.timer);
118+ /* The watchdog timer hardware can not be stopped... */
119+ return 0;
120+}
129121
130− at91wdt_private.expect_close = 0;
122+static int at91_wdt_set_timeout(struct watchdog_device *wdd, unsigned int new_timeout)
123+{
124+ wdd->timeout = new_timeout;
131125 return 0;
132126 }
133127
@@ -163,96 +157,28 @@ static int at91_wdt_settimeout(unsigned int timeout) · 29 unmodified lines
163157 return 0;
164158 }
165159
160+/* ......................................................................... */
161+
166162 static const struct watchdog_info at91_wdt_info = {
167163 .identity = DRV_NAME,
168164 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
169165 WDIOF_MAGICCLOSE,
170166 };
171167
172−/*
173− * Handle commands from user-space.
174− */
175−static long at91_wdt_ioctl(struct file *file,
176− unsigned int cmd, unsigned long arg)
177−{
178− void __user *argp = (void __user *)arg;
179− int __user *p = argp;
180− int new_value;
181−
182− switch (cmd) {
183− case WDIOC_GETSUPPORT:
184− return copy_to_user(argp, &at91_wdt_info,
185− sizeof(at91_wdt_info)) ? -EFAULT : 0;
186−
187− case WDIOC_GETSTATUS:
188− case WDIOC_GETBOOTSTATUS:
189− return put_user(0, p);
190−
191− case WDIOC_KEEPALIVE:
192− at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
193− return 0;
194−
195− case WDIOC_SETTIMEOUT:
196− if (get_user(new_value, p))
197− return -EFAULT;
198−
199− heartbeat = new_value;
200− at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
201−
202− return put_user(new_value, p); /* return current value */
203−
204− case WDIOC_GETTIMEOUT:
205− return put_user(heartbeat, p);
206− }
207− return -ENOTTY;
208−}
209−
210−/*
211− * Pat the watchdog whenever device is written to.
212− */
213−static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len,
214− loff_t *ppos)
215−{
216− if (!len)
217− return 0;
218−
219− /* Scan for magic character */
220− if (!nowayout) {
221− size_t i;
222−
223− at91wdt_private.expect_close = 0;
224−
225− for (i = 0; i < len; i++) {
226− char c;
227− if (get_user(c, data + i))
228− return -EFAULT;
229− if (c == 'V') {
230− at91wdt_private.expect_close = 42;
231− break;
232− }
233− }
234− }
235−
236− at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
237−
238− return len;
239−}
240−
241−/* ......................................................................... */
242−
243−static const struct file_operations at91wdt_fops = {
244− .owner = THIS_MODULE,
245− .llseek = no_llseek,
246− .unlocked_ioctl = at91_wdt_ioctl,
247− .open = at91_wdt_open,
248− .release = at91_wdt_close,
249− .write = at91_wdt_write,
168+static const struct watchdog_ops at91_wdt_ops = {
169+ .owner = THIS_MODULE,
170+ .start = at91_wdt_start,
171+ .stop = at91_wdt_stop,
172+ .ping = at91_wdt_ping,
173+ .set_timeout = at91_wdt_set_timeout,
250174 };
251175
252−static struct miscdevice at91wdt_miscdev = {
253− .minor = WATCHDOG_MINOR,
254− .name = "watchdog",
255− .fops = &at91wdt_fops,
176+static struct watchdog_device at91_wdt_dev = {
177+ .info = &at91_wdt_info,
178+ .ops = &at91_wdt_ops,
179+ .timeout = WDT_HEARTBEAT,
180+ .min_timeout = 1,
181+ .max_timeout = 0xFFFF,
256182 };
257183
258184 static int __init at91wdt_probe(struct platform_device *pdev)
@@ -260,10 +186,6 @@ static int __init at91wdt_probe(struct platform_device *pdev) · 1 unmodified line
260186 struct resource *r;
261187 int res;
262188
263− if (at91wdt_miscdev.parent)
264− return -EBUSY;
265− at91wdt_miscdev.parent = &pdev->dev;
266−
267189 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
268190 if (!r)
269191 return -ENODEV;
@@ -273,38 +195,41 @@ static int __init at91wdt_probe(struct platform_device *pdev) · 3 unmodified lines
273195 return -ENOMEM;
274196 }
275197
198+ at91_wdt_dev.parent = &pdev->dev;
199+ watchdog_init_timeout(&at91_wdt_dev, heartbeat, &pdev->dev);
200+ watchdog_set_nowayout(&at91_wdt_dev, nowayout);
201+
276202 /* Set watchdog */
277203 res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000));
278204 if (res)
279205 return res;
280206
281− res = misc_register(&at91wdt_miscdev);
207+ res = watchdog_register_device(&at91_wdt_dev);
282208 if (res)
283209 return res;
284210
285− at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ;
211+ at91wdt_private.next_heartbeat = jiffies + at91_wdt_dev.timeout * HZ;
286212 setup_timer(&at91wdt_private.timer, at91_ping, 0);
287213 mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT);
288214
289215 pr_info("enabled (heartbeat=%d sec, nowayout=%d)\n",
290− heartbeat, nowayout);
216+ at91_wdt_dev.timeout, nowayout);
291217
292218 return 0;
293219 }
294220
295221 static int __exit at91wdt_remove(struct platform_device *pdev)
296222 {
297− int res;
223+ watchdog_unregister_device(&at91_wdt_dev);
298224
299− res = misc_deregister(&at91wdt_miscdev);
300− if (!res)
301− at91wdt_miscdev.parent = NULL;
225+ pr_warn("I quit now, hardware will probably reboot!\n");
226+ del_timer(&at91wdt_private.timer);
302227
303− return res;
228+ return 0;
304229 }
305230
306231 #if defined(CONFIG_OF)
307−static const struct of_device_id at91_wdt_dt_ids[] __initconst = {
232+static const struct of_device_id at91_wdt_dt_ids[] = {
308233 { .compatible = "atmel,at91sam9260-wdt" },
309234 { /* sentinel */ }
310235 };
@@ -326,4 +251,3 @@ module_platform_driver_probe(at91wdt_driver, at91wdt_probe); · 15 unmodified lines
326251 MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>");
327252 MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors");
328253 MODULE_LICENSE("GPL");
329−MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
drivers/watchdog/ath79_wdt.c+51−15
@@ -23,6 +23,7 @@ · 22 unmodified lines
2323 #include <linux/errno.h>
2424 #include <linux/fs.h>
2525 #include <linux/init.h>
26+#include <linux/io.h>
2627 #include <linux/kernel.h>
2728 #include <linux/miscdevice.h>
2829 #include <linux/module.h>
@@ -32,14 +33,16 @@ · 3 unmodified lines
3233 #include <linux/watchdog.h>
3334 #include <linux/clk.h>
3435 #include <linux/err.h>
35−
36−#include <asm/mach-ath79/ath79.h>
37−#include <asm/mach-ath79/ar71xx_regs.h>
36+#include <linux/of.h>
37+#include <linux/of_platform.h>
3838
3939 #define DRIVER_NAME "ath79-wdt"
4040
4141 #define WDT_TIMEOUT 15 /* seconds */
4242
43+#define WDOG_REG_CTRL 0x00
44+#define WDOG_REG_TIMER 0x04
45+
4346 #define WDOG_CTRL_LAST_RESET BIT(31)
4447 #define WDOG_CTRL_ACTION_MASK 3
4548 #define WDOG_CTRL_ACTION_NONE 0 /* no action */
@@ -66,27 +69,38 @@ static struct clk *wdt_clk; · 20 unmodified lines
6669 static unsigned long wdt_freq;
6770 static int boot_status;
6871 static int max_timeout;
72+static void __iomem *wdt_base;
73+
74+static inline void ath79_wdt_wr(unsigned reg, u32 val)
75+{
76+ iowrite32(val, wdt_base + reg);
77+}
78+
79+static inline u32 ath79_wdt_rr(unsigned reg)
80+{
81+ return ioread32(wdt_base + reg);
82+}
6983
7084 static inline void ath79_wdt_keepalive(void)
7185 {
72− ath79_reset_wr(AR71XX_RESET_REG_WDOG, wdt_freq * timeout);
86+ ath79_wdt_wr(WDOG_REG_TIMER, wdt_freq * timeout);
7387 /* flush write */
74− ath79_reset_rr(AR71XX_RESET_REG_WDOG);
88+ ath79_wdt_rr(WDOG_REG_TIMER);
7589 }
7690
7791 static inline void ath79_wdt_enable(void)
7892 {
7993 ath79_wdt_keepalive();
80− ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR);
94+ ath79_wdt_wr(WDOG_REG_CTRL, WDOG_CTRL_ACTION_FCR);
8195 /* flush write */
82− ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
96+ ath79_wdt_rr(WDOG_REG_CTRL);
8397 }
8498
8599 static inline void ath79_wdt_disable(void)
86100 {
87− ath79_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE);
101+ ath79_wdt_wr(WDOG_REG_CTRL, WDOG_CTRL_ACTION_NONE);
88102 /* flush write */
89− ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
103+ ath79_wdt_rr(WDOG_REG_CTRL);
90104 }
91105
92106 static int ath79_wdt_set_timeout(int val)
@@ -226,16 +240,32 @@ static struct miscdevice ath79_wdt_miscdev = { · 133 unmodified lines
226240
227241 static int ath79_wdt_probe(struct platform_device *pdev)
228242 {
243+ struct resource *res;
229244 u32 ctrl;
230245 int err;
231246
232− wdt_clk = clk_get(&pdev->dev, "wdt");
247+ if (wdt_base)
248+ return -EBUSY;
249+
250+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
251+ if (!res) {
252+ dev_err(&pdev->dev, "no memory resource found\n");
253+ return -EINVAL;
254+ }
255+
256+ wdt_base = devm_request_and_ioremap(&pdev->dev, res);
257+ if (!wdt_base) {
258+ dev_err(&pdev->dev, "unable to remap memory region\n");
259+ return -ENOMEM;
260+ }
261+
262+ wdt_clk = devm_clk_get(&pdev->dev, "wdt");
233263 if (IS_ERR(wdt_clk))
234264 return PTR_ERR(wdt_clk);
235265
236266 err = clk_enable(wdt_clk);
237267 if (err)
238− goto err_clk_put;
268+ return err;
239269
240270 wdt_freq = clk_get_rate(wdt_clk);
241271 if (!wdt_freq) {
@@ -251,7 +281,7 @@ static int ath79_wdt_probe(struct platform_device *pdev) · 9 unmodified lines
251281 max_timeout, timeout);
252282 }
253283
254− ctrl = ath79_reset_rr(AR71XX_RESET_REG_WDOG_CTRL);
284+ ctrl = ath79_wdt_rr(WDOG_REG_CTRL);
255285 boot_status = (ctrl & WDOG_CTRL_LAST_RESET) ? WDIOF_CARDRESET : 0;
256286
257287 err = misc_register(&ath79_wdt_miscdev);
@@ -265,8 +295,6 @@ static int ath79_wdt_probe(struct platform_device *pdev) · 7 unmodified lines
265295
266296 err_clk_disable:
267297 clk_disable(wdt_clk);
268−err_clk_put:
269− clk_put(wdt_clk);
270298 return err;
271299 }
272300
@@ -274,7 +302,6 @@ static int ath79_wdt_remove(struct platform_device *pdev) · 1 unmodified line
274302 {
275303 misc_deregister(&ath79_wdt_miscdev);
276304 clk_disable(wdt_clk);
277− clk_put(wdt_clk);
278305 return 0;
279306 }
280307
@@ -283,6 +310,14 @@ static void ath97_wdt_shutdown(struct platform_device *pdev) · 2 unmodified lines
283310 ath79_wdt_disable();
284311 }
285312
313+#ifdef CONFIG_OF
314+static const struct of_device_id ath79_wdt_match[] = {
315+ { .compatible = "qca,ar7130-wdt" },
316+ {},
317+};
318+MODULE_DEVICE_TABLE(of, ath79_wdt_match);
319+#endif
320+
286321 static struct platform_driver ath79_wdt_driver = {
287322 .probe = ath79_wdt_probe,
288323 .remove = ath79_wdt_remove,
@@ -290,6 +325,7 @@ static struct platform_driver ath79_wdt_driver = { · 1 unmodified line
290325 .driver = {
291326 .name = DRIVER_NAME,
292327 .owner = THIS_MODULE,
328+ .of_match_table = of_match_ptr(ath79_wdt_match),
293329 },
294330 };
295331
drivers/watchdog/bcm47xx_wdt.c+144−195
@@ -3,6 +3,7 @@ · 2 unmodified lines
33 *
44 * Copyright (C) 2008 Aleksandar Radovanovic <biblbroks@sezampro.rs>
55 * Copyright (C) 2009 Matthieu CASTET <castet.matthieu@free.fr>
6+ * Copyright (C) 2012-2013 Hauke Mehrtens <hauke@hauke-m.de>
67 *
78 * This program is free software; you can redistribute it and/or
89 * modify it under the terms of the GNU General Public License
@@ -12,165 +13,143 @@ · 3 unmodified lines
1213
1314 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1415
16+#include <linux/bcm47xx_wdt.h>
1517 #include <linux/bitops.h>
1618 #include <linux/errno.h>
17−#include <linux/fs.h>
1819 #include <linux/init.h>
1920 #include <linux/kernel.h>
20−#include <linux/miscdevice.h>
2121 #include <linux/module.h>
2222 #include <linux/moduleparam.h>
23+#include <linux/platform_device.h>
2324 #include <linux/reboot.h>
2425 #include <linux/types.h>
25−#include <linux/uaccess.h>
2626 #include <linux/watchdog.h>
2727 #include <linux/timer.h>
2828 #include <linux/jiffies.h>
29−#include <linux/ssb/ssb_embedded.h>
30−#include <asm/mach-bcm47xx/bcm47xx.h>
3129
3230 #define DRV_NAME "bcm47xx_wdt"
3331
3432 #define WDT_DEFAULT_TIME 30 /* seconds */
35−#define WDT_MAX_TIME 255 /* seconds */
33+#define WDT_SOFTTIMER_MAX 255 /* seconds */
34+#define WDT_SOFTTIMER_THRESHOLD 60 /* seconds */
3635
37−static int wdt_time = WDT_DEFAULT_TIME;
36+static int timeout = WDT_DEFAULT_TIME;
3837 static bool nowayout = WATCHDOG_NOWAYOUT;
3938
40−module_param(wdt_time, int, 0);
41−MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
39+module_param(timeout, int, 0);
40+MODULE_PARM_DESC(timeout, "Watchdog time in seconds. (default="
4241 __MODULE_STRING(WDT_DEFAULT_TIME) ")");
4342
44−#ifdef CONFIG_WATCHDOG_NOWAYOUT
4543 module_param(nowayout, bool, 0);
4644 MODULE_PARM_DESC(nowayout,
4745 "Watchdog cannot be stopped once started (default="
4846 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
49−#endif
5047
51−static unsigned long bcm47xx_wdt_busy;
52−static char expect_release;
53−static struct timer_list wdt_timer;
54−static atomic_t ticks;
55−
56−static inline void bcm47xx_wdt_hw_start(void)
48+static inline struct bcm47xx_wdt *bcm47xx_wdt_get(struct watchdog_device *wdd)
5749 {
58− /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */
59− switch (bcm47xx_bus_type) {
60−#ifdef CONFIG_BCM47XX_SSB
61− case BCM47XX_BUS_TYPE_SSB:
62− ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0xfffffff);
63− break;
64−#endif
65−#ifdef CONFIG_BCM47XX_BCMA
66− case BCM47XX_BUS_TYPE_BCMA:
67− bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc,
68− 0xfffffff);
69− break;
70−#endif
71− }
50+ return container_of(wdd, struct bcm47xx_wdt, wdd);
7251 }
7352
74−static inline int bcm47xx_wdt_hw_stop(void)
53+static int bcm47xx_wdt_hard_keepalive(struct watchdog_device *wdd)
7554 {
76− switch (bcm47xx_bus_type) {
77−#ifdef CONFIG_BCM47XX_SSB
78− case BCM47XX_BUS_TYPE_SSB:
79− return ssb_watchdog_timer_set(&bcm47xx_bus.ssb, 0);
80−#endif
81−#ifdef CONFIG_BCM47XX_BCMA
82− case BCM47XX_BUS_TYPE_BCMA:
83− bcma_chipco_watchdog_timer_set(&bcm47xx_bus.bcma.bus.drv_cc, 0);
84− return 0;
85−#endif
86− }
87− return -EINVAL;
88−}
55+ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
8956
90−static void bcm47xx_timer_tick(unsigned long unused)
91−{
92− if (!atomic_dec_and_test(&ticks)) {
93− bcm47xx_wdt_hw_start();
94− mod_timer(&wdt_timer, jiffies + HZ);
95− } else {
96− pr_crit("Watchdog will fire soon!!!\n");
97− }
57+ wdt->timer_set_ms(wdt, wdd->timeout * 1000);
58+
59+ return 0;
9860 }
9961
100−static inline void bcm47xx_wdt_pet(void)
62+static int bcm47xx_wdt_hard_start(struct watchdog_device *wdd)
10163 {
102− atomic_set(&ticks, wdt_time);
64+ return 0;
10365 }
10466
105−static void bcm47xx_wdt_start(void)
67+static int bcm47xx_wdt_hard_stop(struct watchdog_device *wdd)
10668 {
107− bcm47xx_wdt_pet();
108− bcm47xx_timer_tick(0);
69+ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
70+
71+ wdt->timer_set(wdt, 0);
72+
73+ return 0;
10974 }
11075
111−static void bcm47xx_wdt_pause(void)
76+static int bcm47xx_wdt_hard_set_timeout(struct watchdog_device *wdd,
77+ unsigned int new_time)
11278 {
113− del_timer_sync(&wdt_timer);
114− bcm47xx_wdt_hw_stop();
79+ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
80+ u32 max_timer = wdt->max_timer_ms;
81+
82+ if (new_time < 1 || new_time > max_timer / 1000) {
83+ pr_warn("timeout value must be 1<=x<=%d, using %d\n",
84+ max_timer / 1000, new_time);
85+ return -EINVAL;
86+ }
87+
88+ wdd->timeout = new_time;
89+ return 0;
11590 }
11691
117−static void bcm47xx_wdt_stop(void)
92+static struct watchdog_ops bcm47xx_wdt_hard_ops = {
93+ .owner = THIS_MODULE,
94+ .start = bcm47xx_wdt_hard_start,
95+ .stop = bcm47xx_wdt_hard_stop,
96+ .ping = bcm47xx_wdt_hard_keepalive,
97+ .set_timeout = bcm47xx_wdt_hard_set_timeout,
98+};
99+
100+static void bcm47xx_wdt_soft_timer_tick(unsigned long data)
118101 {
119− bcm47xx_wdt_pause();
102+ struct bcm47xx_wdt *wdt = (struct bcm47xx_wdt *)data;
103+ u32 next_tick = min(wdt->wdd.timeout * 1000, wdt->max_timer_ms);
104+
105+ if (!atomic_dec_and_test(&wdt->soft_ticks)) {
106+ wdt->timer_set_ms(wdt, next_tick);
107+ mod_timer(&wdt->soft_timer, jiffies + HZ);
108+ } else {
109+ pr_crit("Watchdog will fire soon!!!\n");
110+ }
120111 }
121112
122−static int bcm47xx_wdt_settimeout(int new_time)
113+static int bcm47xx_wdt_soft_keepalive(struct watchdog_device *wdd)
123114 {
124− if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
125− return -EINVAL;
115+ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
116+
117+ atomic_set(&wdt->soft_ticks, wdd->timeout);
126118
127− wdt_time = new_time;
128119 return 0;
129120 }
130121
131−static int bcm47xx_wdt_open(struct inode *inode, struct file *file)
122+static int bcm47xx_wdt_soft_start(struct watchdog_device *wdd)
132123 {
133− if (test_and_set_bit(0, &bcm47xx_wdt_busy))
134− return -EBUSY;
124+ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
125+
126+ bcm47xx_wdt_soft_keepalive(wdd);
127+ bcm47xx_wdt_soft_timer_tick((unsigned long)wdt);
135128
136− bcm47xx_wdt_start();
137− return nonseekable_open(inode, file);
129+ return 0;
138130 }
139131
140−static int bcm47xx_wdt_release(struct inode *inode, struct file *file)
132+static int bcm47xx_wdt_soft_stop(struct watchdog_device *wdd)
141133 {
142− if (expect_release == 42) {
143− bcm47xx_wdt_stop();
144− } else {
145− pr_crit("Unexpected close, not stopping watchdog!\n");
146− bcm47xx_wdt_start();
147− }
134+ struct bcm47xx_wdt *wdt = bcm47xx_wdt_get(wdd);
135+
136+ del_timer_sync(&wdt->soft_timer);
137+ wdt->timer_set(wdt, 0);
148138
149− clear_bit(0, &bcm47xx_wdt_busy);
150− expect_release = 0;
151139 return 0;
152140 }
153141
154−static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data,
155− size_t len, loff_t *ppos)
142+static int bcm47xx_wdt_soft_set_timeout(struct watchdog_device *wdd,
143+ unsigned int new_time)
156144 {
157− if (len) {
158− if (!nowayout) {
159− size_t i;
160−
161− expect_release = 0;
162−
163− for (i = 0; i != len; i++) {
164− char c;
165− if (get_user(c, data + i))
166− return -EFAULT;
167− if (c == 'V')
168− expect_release = 42;
169− }
170− }
171− bcm47xx_wdt_pet();
145+ if (new_time < 1 || new_time > WDT_SOFTTIMER_MAX) {
146+ pr_warn("timeout value must be 1<=x<=%d, using %d\n",
147+ WDT_SOFTTIMER_MAX, new_time);
148+ return -EINVAL;
172149 }
173− return len;
150+
151+ wdd->timeout = new_time;
152+ return 0;
174153 }
175154
176155 static const struct watchdog_info bcm47xx_wdt_info = {
@@ -180,130 +159,100 @@ static const struct watchdog_info bcm47xx_wdt_info = { · 3 unmodified lines
180159 WDIOF_MAGICCLOSE,
181160 };
182161
183−static long bcm47xx_wdt_ioctl(struct file *file,
184− unsigned int cmd, unsigned long arg)
185−{
186− void __user *argp = (void __user *)arg;
187− int __user *p = argp;
188− int new_value, retval = -EINVAL;
189−
190− switch (cmd) {
191− case WDIOC_GETSUPPORT:
192− return copy_to_user(argp, &bcm47xx_wdt_info,
193− sizeof(bcm47xx_wdt_info)) ? -EFAULT : 0;
194−
195− case WDIOC_GETSTATUS:
196− case WDIOC_GETBOOTSTATUS:
197− return put_user(0, p);
198−
199− case WDIOC_SETOPTIONS:
200− if (get_user(new_value, p))
201− return -EFAULT;
202−
203− if (new_value & WDIOS_DISABLECARD) {
204− bcm47xx_wdt_stop();
205− retval = 0;
206− }
207−
208− if (new_value & WDIOS_ENABLECARD) {
209− bcm47xx_wdt_start();
210− retval = 0;
211− }
212−
213− return retval;
214−
215− case WDIOC_KEEPALIVE:
216− bcm47xx_wdt_pet();
217− return 0;
218−
219− case WDIOC_SETTIMEOUT:
220− if (get_user(new_value, p))
221− return -EFAULT;
222−
223− if (bcm47xx_wdt_settimeout(new_value))
224− return -EINVAL;
225−
226− bcm47xx_wdt_pet();
227−
228− case WDIOC_GETTIMEOUT:
229− return put_user(wdt_time, p);
230−
231− default:
232− return -ENOTTY;
233− }
234−}
235−
236162 static int bcm47xx_wdt_notify_sys(struct notifier_block *this,
237− unsigned long code, void *unused)
163+ unsigned long code, void *unused)
238164 {
165+ struct bcm47xx_wdt *wdt;
166+
167+ wdt = container_of(this, struct bcm47xx_wdt, notifier);
239168 if (code == SYS_DOWN || code == SYS_HALT)
240− bcm47xx_wdt_stop();
169+ wdt->wdd.ops->stop(&wdt->wdd);
241170 return NOTIFY_DONE;
242171 }
243172
244−static const struct file_operations bcm47xx_wdt_fops = {
173+static struct watchdog_ops bcm47xx_wdt_soft_ops = {
245174 .owner = THIS_MODULE,
246− .llseek = no_llseek,
247− .unlocked_ioctl = bcm47xx_wdt_ioctl,
248− .open = bcm47xx_wdt_open,
249− .release = bcm47xx_wdt_release,
250− .write = bcm47xx_wdt_write,
251−};
252−
253−static struct miscdevice bcm47xx_wdt_miscdev = {
254− .minor = WATCHDOG_MINOR,
255− .name = "watchdog",
256− .fops = &bcm47xx_wdt_fops,
257−};
258−
259−static struct notifier_block bcm47xx_wdt_notifier = {
260− .notifier_call = bcm47xx_wdt_notify_sys,
175+ .start = bcm47xx_wdt_soft_start,
176+ .stop = bcm47xx_wdt_soft_stop,
177+ .ping = bcm47xx_wdt_soft_keepalive,
178+ .set_timeout = bcm47xx_wdt_soft_set_timeout,
261179 };
262180
263−static int __init bcm47xx_wdt_init(void)
181+static int bcm47xx_wdt_probe(struct platform_device *pdev)
264182 {
265183 int ret;
184+ bool soft;
185+ struct bcm47xx_wdt *wdt = dev_get_platdata(&pdev->dev);
266186
267− if (bcm47xx_wdt_hw_stop() < 0)
268− return -ENODEV;
187+ if (!wdt)
188+ return -ENXIO;
269189
270− setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L);
190+ soft = wdt->max_timer_ms < WDT_SOFTTIMER_THRESHOLD * 1000;
271191
272− if (bcm47xx_wdt_settimeout(wdt_time)) {
273− bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME);
274− pr_info("wdt_time value must be 0 < wdt_time < %d, using %d\n",
275− (WDT_MAX_TIME + 1), wdt_time);
192+ if (soft) {
193+ wdt->wdd.ops = &bcm47xx_wdt_soft_ops;
194+ setup_timer(&wdt->soft_timer, bcm47xx_wdt_soft_timer_tick,
195+ (long unsigned int)wdt);
196+ } else {
197+ wdt->wdd.ops = &bcm47xx_wdt_hard_ops;
276198 }
277199
278− ret = register_reboot_notifier(&bcm47xx_wdt_notifier);
200+ wdt->wdd.info = &bcm47xx_wdt_info;
201+ wdt->wdd.timeout = WDT_DEFAULT_TIME;
202+ ret = wdt->wdd.ops->set_timeout(&wdt->wdd, timeout);
279203 if (ret)
280− return ret;
204+ goto err_timer;
205+ watchdog_set_nowayout(&wdt->wdd, nowayout);
281206
282− ret = misc_register(&bcm47xx_wdt_miscdev);
283− if (ret) {
284− unregister_reboot_notifier(&bcm47xx_wdt_notifier);
285− return ret;
286− }
207+ wdt->notifier.notifier_call = &bcm47xx_wdt_notify_sys;
208+
209+ ret = register_reboot_notifier(&wdt->notifier);
210+ if (ret)
211+ goto err_timer;
287212
288− pr_info("BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
289− wdt_time, nowayout ? ", nowayout" : "");
213+ ret = watchdog_register_device(&wdt->wdd);
214+ if (ret)
215+ goto err_notifier;
216+
217+ dev_info(&pdev->dev, "BCM47xx Watchdog Timer enabled (%d seconds%s%s)\n",
218+ timeout, nowayout ? ", nowayout" : "",
219+ soft ? ", Software Timer" : "");
290220 return 0;
221+
222+err_notifier:
223+ unregister_reboot_notifier(&wdt->notifier);
224+err_timer:
225+ if (soft)
226+ del_timer_sync(&wdt->soft_timer);
227+
228+ return ret;
291229 }
292230
293−static void __exit bcm47xx_wdt_exit(void)
231+static int bcm47xx_wdt_remove(struct platform_device *pdev)
294232 {
295− if (!nowayout)
296− bcm47xx_wdt_stop();
233+ struct bcm47xx_wdt *wdt = dev_get_platdata(&pdev->dev);
297234
298− misc_deregister(&bcm47xx_wdt_miscdev);
235+ if (!wdt)
236+ return -ENXIO;
299237
300− unregister_reboot_notifier(&bcm47xx_wdt_notifier);
238+ watchdog_unregister_device(&wdt->wdd);
239+ unregister_reboot_notifier(&wdt->notifier);
240+
241+ return 0;
301242 }
302243
303−module_init(bcm47xx_wdt_init);
304−module_exit(bcm47xx_wdt_exit);
244+static struct platform_driver bcm47xx_wdt_driver = {
245+ .driver = {
246+ .owner = THIS_MODULE,
247+ .name = "bcm47xx-wdt",
248+ },
249+ .probe = bcm47xx_wdt_probe,
250+ .remove = bcm47xx_wdt_remove,
251+};
252+
253+module_platform_driver(bcm47xx_wdt_driver);
305254
306255 MODULE_AUTHOR("Aleksandar Radovanovic");
256+MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
307257 MODULE_DESCRIPTION("Watchdog driver for Broadcom BCM47xx");
308258 MODULE_LICENSE("GPL");
309−MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
drivers/watchdog/booke_wdt.c+65−120
@@ -15,12 +15,8 @@ · 14 unmodified lines
1515 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1616
1717 #include <linux/module.h>
18−#include <linux/fs.h>
1918 #include <linux/smp.h>
20−#include <linux/miscdevice.h>
21−#include <linux/notifier.h>
2219 #include <linux/watchdog.h>
23−#include <linux/uaccess.h>
2420
2521 #include <asm/reg_booke.h>
2622 #include <asm/time.h>
@@ -45,7 +41,7 @@ u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT; · 18 unmodified lines
4541 #define WDTP_MASK (TCR_WP_MASK)
4642 #endif
4743
48−static DEFINE_SPINLOCK(booke_wdt_lock);
44+#ifdef CONFIG_PPC_FSL_BOOK3E
4945
5046 /* For the specified period, determine the number of seconds
5147 * corresponding to the reset time. There will be a watchdog
@@ -86,6 +82,24 @@ static unsigned int sec_to_period(unsigned int secs) · 34 unmodified lines
8682 return 0;
8783 }
8884
85+#define MAX_WDT_TIMEOUT period_to_sec(1)
86+
87+#else /* CONFIG_PPC_FSL_BOOK3E */
88+
89+static unsigned long long period_to_sec(unsigned int period)
90+{
91+ return period;
92+}
93+
94+static unsigned int sec_to_period(unsigned int secs)
95+{
96+ return secs;
97+}
98+
99+#define MAX_WDT_TIMEOUT 3 /* from Kconfig */
100+
101+#endif /* !CONFIG_PPC_FSL_BOOK3E */
102+
89103 static void __booke_wdt_set(void *data)
90104 {
91105 u32 val;
@@ -107,9 +121,11 @@ static void __booke_wdt_ping(void *data) · 15 unmodified lines
107121 mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
108122 }
109123
110−static void booke_wdt_ping(void)
124+static int booke_wdt_ping(struct watchdog_device *wdog)
111125 {
112126 on_each_cpu(__booke_wdt_ping, NULL, 0);
127+
128+ return 0;
113129 }
114130
115131 static void __booke_wdt_enable(void *data)
@@ -146,152 +162,81 @@ static void __booke_wdt_disable(void *data) · 30 unmodified lines
146162
147163 }
148164
149−static ssize_t booke_wdt_write(struct file *file, const char __user *buf,
150− size_t count, loff_t *ppos)
165+static void __booke_wdt_start(struct watchdog_device *wdog)
151166 {
152− booke_wdt_ping();
153− return count;
167+ on_each_cpu(__booke_wdt_enable, NULL, 0);
168+ pr_debug("watchdog enabled (timeout = %u sec)\n", wdog->timeout);
154169 }
155170
156−static struct watchdog_info ident = {
157− .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
158− .identity = "PowerPC Book-E Watchdog",
159−};
160−
161−static long booke_wdt_ioctl(struct file *file,
162− unsigned int cmd, unsigned long arg)
171+static int booke_wdt_start(struct watchdog_device *wdog)
163172 {
164− u32 tmp = 0;
165− u32 __user *p = (u32 __user *)arg;
166−
167− switch (cmd) {
168− case WDIOC_GETSUPPORT:
169− return copy_to_user(p, &ident, sizeof(ident)) ? -EFAULT : 0;
170− case WDIOC_GETSTATUS:
171− return put_user(0, p);
172− case WDIOC_GETBOOTSTATUS:
173− /* XXX: something is clearing TSR */
174− tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
175− /* returns CARDRESET if last reset was caused by the WDT */
176− return put_user((tmp ? WDIOF_CARDRESET : 0), p);
177− case WDIOC_SETOPTIONS:
178− if (get_user(tmp, p))
179− return -EFAULT;
180− if (tmp == WDIOS_ENABLECARD) {
181− booke_wdt_ping();
182− break;
183− } else
184− return -EINVAL;
185− return 0;
186− case WDIOC_KEEPALIVE:
187− booke_wdt_ping();
188− return 0;
189− case WDIOC_SETTIMEOUT:
190− if (get_user(tmp, p))
191− return -EFAULT;
192−#ifdef CONFIG_PPC_FSL_BOOK3E
193− /* period of 1 gives the largest possible timeout */
194− if (tmp > period_to_sec(1))
195− return -EINVAL;
196− booke_wdt_period = sec_to_period(tmp);
197−#else
198− booke_wdt_period = tmp;
199−#endif
200− booke_wdt_set();
201− /* Fall */
202− case WDIOC_GETTIMEOUT:
203−#ifdef CONFIG_FSL_BOOKE
204− return put_user(period_to_sec(booke_wdt_period), p);
205−#else
206− return put_user(booke_wdt_period, p);
207−#endif
208− default:
209− return -ENOTTY;
210− }
211−
212− return 0;
213−}
214−
215−/* wdt_is_active stores whether or not the /dev/watchdog device is opened */
216−static unsigned long wdt_is_active;
217−
218−static int booke_wdt_open(struct inode *inode, struct file *file)
219−{
220− /* /dev/watchdog can only be opened once */
221− if (test_and_set_bit(0, &wdt_is_active))
222− return -EBUSY;
223−
224− spin_lock(&booke_wdt_lock);
225173 if (booke_wdt_enabled == 0) {
226174 booke_wdt_enabled = 1;
227− on_each_cpu(__booke_wdt_enable, NULL, 0);
228− pr_debug("watchdog enabled (timeout = %llu sec)\n",
229− period_to_sec(booke_wdt_period));
175+ __booke_wdt_start(wdog);
230176 }
231− spin_unlock(&booke_wdt_lock);
232−
233− return nonseekable_open(inode, file);
177+ return 0;
234178 }
235179
236−static int booke_wdt_release(struct inode *inode, struct file *file)
180+static int booke_wdt_stop(struct watchdog_device *wdog)
237181 {
238−#ifndef CONFIG_WATCHDOG_NOWAYOUT
239− /* Normally, the watchdog is disabled when /dev/watchdog is closed, but
240− * if CONFIG_WATCHDOG_NOWAYOUT is defined, then it means that the
241− * watchdog should remain enabled. So we disable it only if
242− * CONFIG_WATCHDOG_NOWAYOUT is not defined.
243− */
244182 on_each_cpu(__booke_wdt_disable, NULL, 0);
245183 booke_wdt_enabled = 0;
246184 pr_debug("watchdog disabled\n");
247−#endif
248185
249− clear_bit(0, &wdt_is_active);
186+ return 0;
187+}
188+
189+static int booke_wdt_set_timeout(struct watchdog_device *wdt_dev,
190+ unsigned int timeout)
191+{
192+ if (timeout > MAX_WDT_TIMEOUT)
193+ return -EINVAL;
194+ booke_wdt_period = sec_to_period(timeout);
195+ wdt_dev->timeout = timeout;
196+ booke_wdt_set();
250197
251198 return 0;
252199 }
253200
254−static const struct file_operations booke_wdt_fops = {
201+static struct watchdog_info booke_wdt_info = {
202+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
203+ .identity = "PowerPC Book-E Watchdog",
204+};
205+
206+static struct watchdog_ops booke_wdt_ops = {
255207 .owner = THIS_MODULE,
256− .llseek = no_llseek,
257− .write = booke_wdt_write,
258− .unlocked_ioctl = booke_wdt_ioctl,
259− .open = booke_wdt_open,
260− .release = booke_wdt_release,
208+ .start = booke_wdt_start,
209+ .stop = booke_wdt_stop,
210+ .ping = booke_wdt_ping,
211+ .set_timeout = booke_wdt_set_timeout,
261212 };
262213
263−static struct miscdevice booke_wdt_miscdev = {
264− .minor = WATCHDOG_MINOR,
265− .name = "watchdog",
266− .fops = &booke_wdt_fops,
214+static struct watchdog_device booke_wdt_dev = {
215+ .info = &booke_wdt_info,
216+ .ops = &booke_wdt_ops,
217+ .min_timeout = 1,
218+ .max_timeout = 0xFFFF
267219 };
268220
269221 static void __exit booke_wdt_exit(void)
270222 {
271− misc_deregister(&booke_wdt_miscdev);
223+ watchdog_unregister_device(&booke_wdt_dev);
272224 }
273225
274226 static int __init booke_wdt_init(void)
275227 {
276228 int ret = 0;
229+ bool nowayout = WATCHDOG_NOWAYOUT;
277230
278231 pr_info("powerpc book-e watchdog driver loaded\n");
279− ident.firmware_version = cur_cpu_spec->pvr_value;
280−
281− ret = misc_register(&booke_wdt_miscdev);
282− if (ret) {
283− pr_err("cannot register device (minor=%u, ret=%i)\n",
284− WATCHDOG_MINOR, ret);
285− return ret;
286− }
287−
288− spin_lock(&booke_wdt_lock);
289− if (booke_wdt_enabled == 1) {
290− pr_info("watchdog enabled (timeout = %llu sec)\n",
291− period_to_sec(booke_wdt_period));
292− on_each_cpu(__booke_wdt_enable, NULL, 0);
293− }
294− spin_unlock(&booke_wdt_lock);
232+ booke_wdt_info.firmware_version = cur_cpu_spec->pvr_value;
233+ booke_wdt_set_timeout(&booke_wdt_dev,
234+ period_to_sec(CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT));
235+ watchdog_set_nowayout(&booke_wdt_dev, nowayout);
236+ if (booke_wdt_enabled)
237+ __booke_wdt_start(&booke_wdt_dev);
238+
239+ ret = watchdog_register_device(&booke_wdt_dev);
295240
296241 return ret;
297242 }
drivers/watchdog/davinci_wdt.c+6−23
@@ -69,7 +69,6 @@ static unsigned long wdt_status; · 68 unmodified lines
6969 #define WDT_REGION_INITED 2
7070 #define WDT_DEVICE_INITED 3
7171
72−static struct resource *wdt_mem;
7372 static void __iomem *wdt_base;
7473 struct clk *wdt_clk;
7574
@@ -201,10 +200,11 @@ static struct miscdevice davinci_wdt_miscdev = { · 125 unmodified lines
201200
202201 static int davinci_wdt_probe(struct platform_device *pdev)
203202 {
204− int ret = 0, size;
203+ int ret = 0;
205204 struct device *dev = &pdev->dev;
205+ struct resource *wdt_mem;
206206
207− wdt_clk = clk_get(dev, NULL);
207+ wdt_clk = devm_clk_get(dev, NULL);
208208 if (WARN_ON(IS_ERR(wdt_clk)))
209209 return PTR_ERR(wdt_clk);
210210
@@ -221,43 +221,26 @@ static int davinci_wdt_probe(struct platform_device *pdev) · 10 unmodified lines
221221 return -ENOENT;
222222 }
223223
224− size = resource_size(wdt_mem);
225− if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
226− dev_err(dev, "failed to get memory region\n");
227− return -ENOENT;
228− }
229−
230− wdt_base = ioremap(wdt_mem->start, size);
224+ wdt_base = devm_request_and_ioremap(dev, wdt_mem);
231225 if (!wdt_base) {
232− dev_err(dev, "failed to map memory region\n");
233− release_mem_region(wdt_mem->start, size);
234− wdt_mem = NULL;
235− return -ENOMEM;
226+ dev_err(dev, "ioremap failed\n");
227+ return -EADDRNOTAVAIL;
236228 }
237229
238230 ret = misc_register(&davinci_wdt_miscdev);
239231 if (ret < 0) {
240232 dev_err(dev, "cannot register misc device\n");
241− release_mem_region(wdt_mem->start, size);
242− wdt_mem = NULL;
243233 } else {
244234 set_bit(WDT_DEVICE_INITED, &wdt_status);
245235 }
246236
247− iounmap(wdt_base);
248237 return ret;
249238 }
250239
251240 static int davinci_wdt_remove(struct platform_device *pdev)
252241 {
253242 misc_deregister(&davinci_wdt_miscdev);
254− if (wdt_mem) {
255− release_mem_region(wdt_mem->start, resource_size(wdt_mem));
256− wdt_mem = NULL;
257− }
258−
259243 clk_disable_unprepare(wdt_clk);
260− clk_put(wdt_clk);
261244
262245 return 0;
263246 }
drivers/watchdog/gef_wdt.c+1−0
@@ -310,6 +310,7 @@ static struct platform_driver gef_wdt_driver = { · 309 unmodified lines
310310 .of_match_table = gef_wdt_ids,
311311 },
312312 .probe = gef_wdt_probe,
313+ .remove = gef_wdt_remove,
313314 };
314315
315316 static int __init gef_wdt_init(void)
drivers/watchdog/omap_wdt.c+5−1
@@ -45,6 +45,11 @@ · 44 unmodified lines
4545
4646 #include "omap_wdt.h"
4747
48+static bool nowayout = WATCHDOG_NOWAYOUT;
49+module_param(nowayout, bool, 0);
50+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
51+ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
52+
4853 static unsigned timer_margin;
4954 module_param(timer_margin, uint, 0);
5055 MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)");
@@ -201,7 +206,6 @@ static const struct watchdog_ops omap_wdt_ops = { · 150 unmodified lines
201206 static int omap_wdt_probe(struct platform_device *pdev)
202207 {
203208 struct omap_wd_timer_platform_data *pdata = pdev->dev.platform_data;
204− bool nowayout = WATCHDOG_NOWAYOUT;
205209 struct watchdog_device *omap_wdt;
206210 struct resource *res, *mem;
207211 struct omap_wdt_dev *wdev;
drivers/watchdog/orion_wdt.c+5−6
@@ -140,6 +140,7 @@ static const struct watchdog_ops orion_wdt_ops = { · 139 unmodified lines
140140 static struct watchdog_device orion_wdt = {
141141 .info = &orion_wdt_info,
142142 .ops = &orion_wdt_ops,
143+ .min_timeout = 1,
143144 };
144145
145146 static int orion_wdt_probe(struct platform_device *pdev)
@@ -164,12 +165,9 @@ static int orion_wdt_probe(struct platform_device *pdev) · 18 unmodified lines
164165
165166 wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk;
166167
167− if ((heartbeat < 1) || (heartbeat > wdt_max_duration))
168− heartbeat = wdt_max_duration;
169−
170− orion_wdt.timeout = heartbeat;
171− orion_wdt.min_timeout = 1;
168+ orion_wdt.timeout = wdt_max_duration;
172169 orion_wdt.max_timeout = wdt_max_duration;
170+ watchdog_init_timeout(&orion_wdt, heartbeat, &pdev->dev);
173171
174172 watchdog_set_nowayout(&orion_wdt, nowayout);
175173 ret = watchdog_register_device(&orion_wdt);
@@ -179,7 +177,7 @@ static int orion_wdt_probe(struct platform_device *pdev) · 3 unmodified lines
179177 }
180178
181179 pr_info("Initial timeout %d sec%s\n",
182− heartbeat, nowayout ? ", nowayout" : "");
180+ orion_wdt.timeout, nowayout ? ", nowayout" : "");
183181 return 0;
184182 }
185183
@@ -225,4 +223,5 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" · 39 unmodified lines
225223 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
226224
227225 MODULE_LICENSE("GPL");
226+MODULE_ALIAS("platform:orion_wdt");
228227 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
drivers/watchdog/pnx4008_wdt.c+3−4
@@ -142,6 +142,7 @@ static const struct watchdog_ops pnx4008_wdt_ops = { · 141 unmodified lines
142142 static struct watchdog_device pnx4008_wdd = {
143143 .info = &pnx4008_wdt_ident,
144144 .ops = &pnx4008_wdt_ops,
145+ .timeout = DEFAULT_HEARTBEAT,
145146 .min_timeout = 1,
146147 .max_timeout = MAX_HEARTBEAT,
147148 };
@@ -151,8 +152,7 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) · 3 unmodified lines
151152 struct resource *r;
152153 int ret = 0;
153154
154− if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
155− heartbeat = DEFAULT_HEARTBEAT;
155+ watchdog_init_timeout(&pnx4008_wdd, heartbeat, &pdev->dev);
156156
157157 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
158158 wdt_base = devm_ioremap_resource(&pdev->dev, r);
@@ -167,7 +167,6 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) · 8 unmodified lines
167167 if (ret)
168168 goto out;
169169
170− pnx4008_wdd.timeout = heartbeat;
171170 pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ?
172171 WDIOF_CARDRESET : 0;
173172 watchdog_set_nowayout(&pnx4008_wdd, nowayout);
@@ -181,7 +180,7 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) · 7 unmodified lines
181180 }
182181
183182 dev_info(&pdev->dev, "PNX4008 Watchdog Timer: heartbeat %d sec\n",
184− heartbeat);
183+ pnx4008_wdd.timeout);
185184
186185 return 0;
187186
drivers/watchdog/retu_wdt.c+178−0
@@ -0,0 +1,178 @@
1+/*
2+ * Retu watchdog driver
3+ *
4+ * Copyright (C) 2004, 2005 Nokia Corporation
5+ *
6+ * Based on code written by Amit Kucheria and Michael Buesch.
7+ * Rewritten by Aaro Koskinen.
8+ *
9+ * This file is subject to the terms and conditions of the GNU General
10+ * Public License. See the file "COPYING" in the main directory of this
11+ * archive for more details.
12+ *
13+ * This program is distributed in the hope that it will be useful,
14+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+ * GNU General Public License for more details.
17+ */
18+
19+#include <linux/init.h>
20+#include <linux/slab.h>
21+#include <linux/errno.h>
22+#include <linux/device.h>
23+#include <linux/kernel.h>
24+#include <linux/module.h>
25+#include <linux/mfd/retu.h>
26+#include <linux/watchdog.h>
27+#include <linux/platform_device.h>
28+
29+/* Watchdog timer values in seconds */
30+#define RETU_WDT_MAX_TIMER 63
31+
32+struct retu_wdt_dev {
33+ struct retu_dev *rdev;
34+ struct device *dev;
35+ struct delayed_work ping_work;
36+};
37+
38+/*
39+ * Since Retu watchdog cannot be disabled in hardware, we must kick it
40+ * with a timer until userspace watchdog software takes over. If
41+ * CONFIG_WATCHDOG_NOWAYOUT is set, we never start the feeding.
42+ */
43+static void retu_wdt_ping_enable(struct retu_wdt_dev *wdev)
44+{
45+ retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
46+ schedule_delayed_work(&wdev->ping_work,
47+ round_jiffies_relative(RETU_WDT_MAX_TIMER * HZ / 2));
48+}
49+
50+static void retu_wdt_ping_disable(struct retu_wdt_dev *wdev)
51+{
52+ retu_write(wdev->rdev, RETU_REG_WATCHDOG, RETU_WDT_MAX_TIMER);
53+ cancel_delayed_work_sync(&wdev->ping_work);
54+}
55+
56+static void retu_wdt_ping_work(struct work_struct *work)
57+{
58+ struct retu_wdt_dev *wdev = container_of(to_delayed_work(work),
59+ struct retu_wdt_dev, ping_work);
60+ retu_wdt_ping_enable(wdev);
61+}
62+
63+static int retu_wdt_start(struct watchdog_device *wdog)
64+{
65+ struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);
66+
67+ retu_wdt_ping_disable(wdev);
68+
69+ return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
70+}
71+
72+static int retu_wdt_stop(struct watchdog_device *wdog)
73+{
74+ struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);
75+
76+ retu_wdt_ping_enable(wdev);
77+
78+ return 0;
79+}
80+
81+static int retu_wdt_ping(struct watchdog_device *wdog)
82+{
83+ struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);
84+
85+ return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
86+}
87+
88+static int retu_wdt_set_timeout(struct watchdog_device *wdog,
89+ unsigned int timeout)
90+{
91+ struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);
92+
93+ wdog->timeout = timeout;
94+ return retu_write(wdev->rdev, RETU_REG_WATCHDOG, wdog->timeout);
95+}
96+
97+static const struct watchdog_info retu_wdt_info = {
98+ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
99+ .identity = "Retu watchdog",
100+};
101+
102+static const struct watchdog_ops retu_wdt_ops = {
103+ .owner = THIS_MODULE,
104+ .start = retu_wdt_start,
105+ .stop = retu_wdt_stop,
106+ .ping = retu_wdt_ping,
107+ .set_timeout = retu_wdt_set_timeout,
108+};
109+
110+static int retu_wdt_probe(struct platform_device *pdev)
111+{
112+ struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent);
113+ bool nowayout = WATCHDOG_NOWAYOUT;
114+ struct watchdog_device *retu_wdt;
115+ struct retu_wdt_dev *wdev;
116+ int ret;
117+
118+ retu_wdt = devm_kzalloc(&pdev->dev, sizeof(*retu_wdt), GFP_KERNEL);
119+ if (!retu_wdt)
120+ return -ENOMEM;
121+
122+ wdev = devm_kzalloc(&pdev->dev, sizeof(*wdev), GFP_KERNEL);
123+ if (!wdev)
124+ return -ENOMEM;
125+
126+ retu_wdt->info = &retu_wdt_info;
127+ retu_wdt->ops = &retu_wdt_ops;
128+ retu_wdt->timeout = RETU_WDT_MAX_TIMER;
129+ retu_wdt->min_timeout = 0;
130+ retu_wdt->max_timeout = RETU_WDT_MAX_TIMER;
131+
132+ watchdog_set_drvdata(retu_wdt, wdev);
133+ watchdog_set_nowayout(retu_wdt, nowayout);
134+
135+ wdev->rdev = rdev;
136+ wdev->dev = &pdev->dev;
137+
138+ INIT_DELAYED_WORK(&wdev->ping_work, retu_wdt_ping_work);
139+
140+ ret = watchdog_register_device(retu_wdt);
141+ if (ret < 0)
142+ return ret;
143+
144+ if (nowayout)
145+ retu_wdt_ping(retu_wdt);
146+ else
147+ retu_wdt_ping_enable(wdev);
148+
149+ platform_set_drvdata(pdev, retu_wdt);
150+
151+ return 0;
152+}
153+
154+static int retu_wdt_remove(struct platform_device *pdev)
155+{
156+ struct watchdog_device *wdog = platform_get_drvdata(pdev);
157+ struct retu_wdt_dev *wdev = watchdog_get_drvdata(wdog);
158+
159+ watchdog_unregister_device(wdog);
160+ cancel_delayed_work_sync(&wdev->ping_work);
161+
162+ return 0;
163+}
164+
165+static struct platform_driver retu_wdt_driver = {
166+ .probe = retu_wdt_probe,
167+ .remove = retu_wdt_remove,
168+ .driver = {
169+ .name = "retu-wdt",
170+ },
171+};
172+module_platform_driver(retu_wdt_driver);
173+
174+MODULE_ALIAS("platform:retu-wdt");
175+MODULE_DESCRIPTION("Retu watchdog");
176+MODULE_AUTHOR("Amit Kucheria");
177+MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
178+MODULE_LICENSE("GPL");
drivers/watchdog/s3c2410_wdt.c+13−35
@@ -53,7 +53,7 @@ · 52 unmodified lines
5353 #define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
5454
5555 static bool nowayout = WATCHDOG_NOWAYOUT;
56−static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
56+static int tmr_margin;
5757 static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT;
5858 static int soft_noboot;
5959 static int debug;
@@ -226,6 +226,7 @@ static struct watchdog_ops s3c2410wdt_ops = { · 166 unmodified lines
226226 static struct watchdog_device s3c2410_wdd = {
227227 .info = &s3c2410_wdt_ident,
228228 .ops = &s3c2410wdt_ops,
229+ .timeout = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME,
229230 };
230231
231232 /* interrupt handler code */
@@ -309,7 +310,6 @@ static int s3c2410wdt_probe(struct platform_device *pdev) · 77 unmodified lines
309310 unsigned int wtcon;
310311 int started = 0;
311312 int ret;
312− int size;
313313
314314 DBG("%s: probe=%p\n", __func__, pdev);
315315
@@ -330,28 +330,20 @@ static int s3c2410wdt_probe(struct platform_device *pdev) · 14 unmodified lines
330330 }
331331
332332 /* get the memory region for the watchdog timer */
333−
334− size = resource_size(wdt_mem);
335− if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
336− dev_err(dev, "failed to get memory region\n");
337− ret = -EBUSY;
338− goto err;
339− }
340−
341− wdt_base = ioremap(wdt_mem->start, size);
333+ wdt_base = devm_request_and_ioremap(dev, wdt_mem);
342334 if (wdt_base == NULL) {
343− dev_err(dev, "failed to ioremap() region\n");
344− ret = -EINVAL;
345− goto err_req;
335+ dev_err(dev, "failed to devm_request_and_ioremap() region\n");
336+ ret = -ENOMEM;
337+ goto err;
346338 }
347339
348340 DBG("probe: mapped wdt_base=%p\n", wdt_base);
349341
350− wdt_clock = clk_get(&pdev->dev, "watchdog");
342+ wdt_clock = devm_clk_get(dev, "watchdog");
351343 if (IS_ERR(wdt_clock)) {
352344 dev_err(dev, "failed to find watchdog clock source\n");
353345 ret = PTR_ERR(wdt_clock);
354− goto err_map;
346+ goto err;
355347 }
356348
357349 clk_prepare_enable(wdt_clock);
@@ -365,7 +357,8 @@ static int s3c2410wdt_probe(struct platform_device *pdev) · 7 unmodified lines
365357 /* see if we can actually set the requested timer margin, and if
366358 * not, try the default value */
367359
368− if (s3c2410wdt_set_heartbeat(&s3c2410_wdd, tmr_margin)) {
360+ watchdog_init_timeout(&s3c2410_wdd, tmr_margin, &pdev->dev);
361+ if (s3c2410wdt_set_heartbeat(&s3c2410_wdd, s3c2410_wdd.timeout)) {
369362 started = s3c2410wdt_set_heartbeat(&s3c2410_wdd,
370363 CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME);
371364
@@ -378,7 +371,8 @@ static int s3c2410wdt_probe(struct platform_device *pdev) · 6 unmodified lines
378371 "cannot start\n");
379372 }
380373
381− ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
374+ ret = devm_request_irq(dev, wdt_irq->start, s3c2410wdt_irq, 0,
375+ pdev->name, pdev);
382376 if (ret != 0) {
383377 dev_err(dev, "failed to install irq (%d)\n", ret);
384378 goto err_cpufreq;
@@ -389,7 +383,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) · 4 unmodified lines
389383 ret = watchdog_register_device(&s3c2410_wdd);
390384 if (ret) {
391385 dev_err(dev, "cannot register watchdog (%d)\n", ret);
392− goto err_irq;
386+ goto err_cpufreq;
393387 }
394388
395389 if (tmr_atboot && started == 0) {
@@ -414,23 +408,13 @@ static int s3c2410wdt_probe(struct platform_device *pdev) · 18 unmodified lines
414408
415409 return 0;
416410
417− err_irq:
418− free_irq(wdt_irq->start, pdev);
419−
420411 err_cpufreq:
421412 s3c2410wdt_cpufreq_deregister();
422413
423414 err_clk:
424415 clk_disable_unprepare(wdt_clock);
425− clk_put(wdt_clock);
426416 wdt_clock = NULL;
427417
428− err_map:
429− iounmap(wdt_base);
430−
431− err_req:
432− release_mem_region(wdt_mem->start, size);
433−
434418 err:
435419 wdt_irq = NULL;
436420 wdt_mem = NULL;
@@ -441,17 +425,11 @@ static int s3c2410wdt_remove(struct platform_device *dev) · 4 unmodified lines
441425 {
442426 watchdog_unregister_device(&s3c2410_wdd);
443427
444− free_irq(wdt_irq->start, dev);
445−
446428 s3c2410wdt_cpufreq_deregister();
447429
448430 clk_disable_unprepare(wdt_clock);
449− clk_put(wdt_clock);
450431 wdt_clock = NULL;
451432
452− iounmap(wdt_base);
453−
454− release_mem_region(wdt_mem->start, resource_size(wdt_mem));
455433 wdt_irq = NULL;
456434 wdt_mem = NULL;
457435 return 0;
drivers/watchdog/sp5100_tco.c+8−19
@@ -361,7 +361,7 @@ static unsigned char sp5100_tco_setupdevice(void) · 360 unmodified lines
361361 {
362362 struct pci_dev *dev = NULL;
363363 const char *dev_name = NULL;
364− u32 val;
364+ u32 val, tmp_val;
365365 u32 index_reg, data_reg, base_addr;
366366
367367 /* Match the PCI device */
@@ -497,30 +497,19 @@ static unsigned char sp5100_tco_setupdevice(void) · 129 unmodified lines
497497 pr_debug("Got 0x%04x from resource tree\n", val);
498498 }
499499
500− /* Restore to the low three bits, if chipset is SB8x0(or later) */
501− if (sp5100_tco_pci->revision >= 0x40) {
502− u8 reserved_bit;
503− reserved_bit = inb(base_addr) & 0x7;
504− val |= (u32)reserved_bit;
505− }
500+ /* Restore to the low three bits */
501+ outb(base_addr+0, index_reg);
502+ tmp_val = val | (inb(data_reg) & 0x7);
506503
507504 /* Re-programming the watchdog timer base address */
508505 outb(base_addr+0, index_reg);
509− /* Low three bits of BASE are reserved */
510− outb((val >> 0) & 0xf8, data_reg);
506+ outb((tmp_val >> 0) & 0xff, data_reg);
511507 outb(base_addr+1, index_reg);
512− outb((val >> 8) & 0xff, data_reg);
508+ outb((tmp_val >> 8) & 0xff, data_reg);
513509 outb(base_addr+2, index_reg);
514− outb((val >> 16) & 0xff, data_reg);
510+ outb((tmp_val >> 16) & 0xff, data_reg);
515511 outb(base_addr+3, index_reg);
516− outb((val >> 24) & 0xff, data_reg);
517−
518− /*
519− * Clear unnecessary the low three bits,
520− * if chipset is SB8x0(or later)
521− */
522− if (sp5100_tco_pci->revision >= 0x40)
523− val &= ~0x7;
512+ outb((tmp_val >> 24) & 0xff, data_reg);
524513
525514 if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
526515 dev_name)) {
drivers/watchdog/stmp3xxx_rtc_wdt.c+111−0
@@ -0,0 +1,111 @@
1+/*
2+ * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28
3+ *
4+ * Author: Wolfram Sang <w.sang@pengutronix.de>
5+ *
6+ * Copyright (C) 2011-12 Wolfram Sang, Pengutronix
7+ *
8+ * This program is free software; you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License version 2 as published by
10+ * the Free Software Foundation.
11+ */
12+#include <linux/init.h>
13+#include <linux/kernel.h>
14+#include <linux/module.h>
15+#include <linux/miscdevice.h>
16+#include <linux/watchdog.h>
17+#include <linux/platform_device.h>
18+#include <linux/stmp3xxx_rtc_wdt.h>
19+
20+#define WDOG_TICK_RATE 1000 /* 1 kHz clock */
21+#define STMP3XXX_DEFAULT_TIMEOUT 19
22+#define STMP3XXX_MAX_TIMEOUT (UINT_MAX / WDOG_TICK_RATE)
23+
24+static int heartbeat = STMP3XXX_DEFAULT_TIMEOUT;
25+module_param(heartbeat, uint, 0);
26+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat period in seconds from 1 to "
27+ __MODULE_STRING(STMP3XXX_MAX_TIMEOUT) ", default "
28+ __MODULE_STRING(STMP3XXX_DEFAULT_TIMEOUT));
29+
30+static int wdt_start(struct watchdog_device *wdd)
31+{
32+ struct device *dev = watchdog_get_drvdata(wdd);
33+ struct stmp3xxx_wdt_pdata *pdata = dev->platform_data;
34+
35+ pdata->wdt_set_timeout(dev->parent, wdd->timeout * WDOG_TICK_RATE);
36+ return 0;
37+}
38+
39+static int wdt_stop(struct watchdog_device *wdd)
40+{
41+ struct device *dev = watchdog_get_drvdata(wdd);
42+ struct stmp3xxx_wdt_pdata *pdata = dev->platform_data;
43+
44+ pdata->wdt_set_timeout(dev->parent, 0);
45+ return 0;
46+}
47+
48+static int wdt_set_timeout(struct watchdog_device *wdd, unsigned new_timeout)
49+{
50+ wdd->timeout = new_timeout;
51+ return wdt_start(wdd);
52+}
53+
54+static const struct watchdog_info stmp3xxx_wdt_ident = {
55+ .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
56+ .identity = "STMP3XXX RTC Watchdog",
57+};
58+
59+static const struct watchdog_ops stmp3xxx_wdt_ops = {
60+ .owner = THIS_MODULE,
61+ .start = wdt_start,
62+ .stop = wdt_stop,
63+ .set_timeout = wdt_set_timeout,
64+};
65+
66+static struct watchdog_device stmp3xxx_wdd = {
67+ .info = &stmp3xxx_wdt_ident,
68+ .ops = &stmp3xxx_wdt_ops,
69+ .min_timeout = 1,
70+ .max_timeout = STMP3XXX_MAX_TIMEOUT,
71+ .status = WATCHDOG_NOWAYOUT_INIT_STATUS,
72+};
73+
74+static int stmp3xxx_wdt_probe(struct platform_device *pdev)
75+{
76+ int ret;
77+
78+ watchdog_set_drvdata(&stmp3xxx_wdd, &pdev->dev);
79+
80+ stmp3xxx_wdd.timeout = clamp_t(unsigned, heartbeat, 1, STMP3XXX_MAX_TIMEOUT);
81+
82+ ret = watchdog_register_device(&stmp3xxx_wdd);
83+ if (ret < 0) {
84+ dev_err(&pdev->dev, "cannot register watchdog device\n");
85+ return ret;
86+ }
87+
88+ dev_info(&pdev->dev, "initialized watchdog with heartbeat %ds\n",
89+ stmp3xxx_wdd.timeout);
90+ return 0;
91+}
92+
93+static int stmp3xxx_wdt_remove(struct platform_device *pdev)
94+{
95+ watchdog_unregister_device(&stmp3xxx_wdd);
96+ return 0;
97+}
98+
99+static struct platform_driver stmp3xxx_wdt_driver = {
100+ .driver = {
101+ .name = "stmp3xxx_rtc_wdt",
102+ },
103+ .probe = stmp3xxx_wdt_probe,
104+ .remove = stmp3xxx_wdt_remove,
105+};
106+module_platform_driver(stmp3xxx_wdt_driver);
107+
108+MODULE_DESCRIPTION("STMP3XXX RTC Watchdog Driver");
109+MODULE_LICENSE("GPL v2");
110+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
111+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
drivers/watchdog/stmp3xxx_wdt.c+0−288
@@ -1,288 +0,0 @@
1−/*
2− * Watchdog driver for Freescale STMP37XX/STMP378X
3− *
4− * Author: Vitaly Wool <vital@embeddedalley.com>
5− *
6− * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
7− * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
8− */
9−
10−#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11−
12−#include <linux/init.h>
13−#include <linux/kernel.h>
14−#include <linux/fs.h>
15−#include <linux/miscdevice.h>
16−#include <linux/watchdog.h>
17−#include <linux/platform_device.h>
18−#include <linux/spinlock.h>
19−#include <linux/uaccess.h>
20−#include <linux/module.h>
21−
22−#include <mach/platform.h>
23−#include <mach/regs-rtc.h>
24−
25−#define DEFAULT_HEARTBEAT 19
26−#define MAX_HEARTBEAT (0x10000000 >> 6)
27−
28−/* missing bitmask in headers */
29−#define BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER 0x80000000
30−
31−#define WDT_IN_USE 0
32−#define WDT_OK_TO_CLOSE 1
33−
34−#define WDOG_COUNTER_RATE 1000 /* 1 kHz clock */
35−
36−static DEFINE_SPINLOCK(stmp3xxx_wdt_io_lock);
37−static unsigned long wdt_status;
38−static const bool nowayout = WATCHDOG_NOWAYOUT;
39−static int heartbeat = DEFAULT_HEARTBEAT;
40−static unsigned long boot_status;
41−
42−static void wdt_enable(u32 value)
43−{
44− spin_lock(&stmp3xxx_wdt_io_lock);
45− __raw_writel(value, REGS_RTC_BASE + HW_RTC_WATCHDOG);
46− stmp3xxx_setl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL);
47− stmp3xxx_setl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER,
48− REGS_RTC_BASE + HW_RTC_PERSISTENT1);
49− spin_unlock(&stmp3xxx_wdt_io_lock);
50−}
51−
52−static void wdt_disable(void)
53−{
54− spin_lock(&stmp3xxx_wdt_io_lock);
55− stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER,
56− REGS_RTC_BASE + HW_RTC_PERSISTENT1);
57− stmp3xxx_clearl(BM_RTC_CTRL_WATCHDOGEN, REGS_RTC_BASE + HW_RTC_CTRL);
58− spin_unlock(&stmp3xxx_wdt_io_lock);
59−}
60−
61−static void wdt_ping(void)
62−{
63− wdt_enable(heartbeat * WDOG_COUNTER_RATE);
64−}
65−
66−static int stmp3xxx_wdt_open(struct inode *inode, struct file *file)
67−{
68− if (test_and_set_bit(WDT_IN_USE, &wdt_status))
69− return -EBUSY;
70−
71− clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
72− wdt_ping();
73−
74− return nonseekable_open(inode, file);
75−}
76−
77−static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data,
78− size_t len, loff_t *ppos)
79−{
80− if (len) {
81− if (!nowayout) {
82− size_t i;
83−
84− clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
85−
86− for (i = 0; i != len; i++) {
87− char c;
88−
89− if (get_user(c, data + i))
90− return -EFAULT;
91− if (c == 'V')
92− set_bit(WDT_OK_TO_CLOSE, &wdt_status);
93− }
94− }
95− wdt_ping();
96− }
97−
98− return len;
99−}
100−
101−static const struct watchdog_info ident = {
102− .options = WDIOF_CARDRESET |
103− WDIOF_MAGICCLOSE |
104− WDIOF_SETTIMEOUT |
105− WDIOF_KEEPALIVEPING,
106− .identity = "STMP3XXX Watchdog",
107−};
108−
109−static long stmp3xxx_wdt_ioctl(struct file *file, unsigned int cmd,
110− unsigned long arg)
111−{
112− void __user *argp = (void __user *)arg;
113− int __user *p = argp;
114− int new_heartbeat, opts;
115− int ret = -ENOTTY;
116−
117− switch (cmd) {
118− case WDIOC_GETSUPPORT:
119− ret = copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
120− break;
121−
122− case WDIOC_GETSTATUS:
123− ret = put_user(0, p);
124− break;
125−
126− case WDIOC_GETBOOTSTATUS:
127− ret = put_user(boot_status, p);
128− break;
129−
130− case WDIOC_SETOPTIONS:
131− if (get_user(opts, p)) {
132− ret = -EFAULT;
133− break;
134− }
135− if (opts & WDIOS_DISABLECARD)
136− wdt_disable();
137− else if (opts & WDIOS_ENABLECARD)
138− wdt_ping();
139− else {
140− pr_debug("%s: unknown option 0x%x\n", __func__, opts);
141− ret = -EINVAL;
142− break;
143− }
144− ret = 0;
145− break;
146−
147− case WDIOC_KEEPALIVE:
148− wdt_ping();
149− ret = 0;
150− break;
151−
152− case WDIOC_SETTIMEOUT:
153− if (get_user(new_heartbeat, p)) {
154− ret = -EFAULT;
155− break;
156− }
157− if (new_heartbeat <= 0 || new_heartbeat > MAX_HEARTBEAT) {
158− ret = -EINVAL;
159− break;
160− }
161−
162− heartbeat = new_heartbeat;
163− wdt_ping();
164− /* Fall through */
165−
166− case WDIOC_GETTIMEOUT:
167− ret = put_user(heartbeat, p);
168− break;
169− }
170− return ret;
171−}
172−
173−static int stmp3xxx_wdt_release(struct inode *inode, struct file *file)
174−{
175− int ret = 0;
176−
177− if (!nowayout) {
178− if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
179− wdt_ping();
180− pr_debug("%s: Device closed unexpectedly\n", __func__);
181− ret = -EINVAL;
182− } else {
183− wdt_disable();
184− clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
185− }
186− }
187− clear_bit(WDT_IN_USE, &wdt_status);
188−
189− return ret;
190−}
191−
192−static const struct file_operations stmp3xxx_wdt_fops = {
193− .owner = THIS_MODULE,
194− .llseek = no_llseek,
195− .write = stmp3xxx_wdt_write,
196− .unlocked_ioctl = stmp3xxx_wdt_ioctl,
197− .open = stmp3xxx_wdt_open,
198− .release = stmp3xxx_wdt_release,
199−};
200−
201−static struct miscdevice stmp3xxx_wdt_miscdev = {
202− .minor = WATCHDOG_MINOR,
203− .name = "watchdog",
204− .fops = &stmp3xxx_wdt_fops,
205−};
206−
207−static int stmp3xxx_wdt_probe(struct platform_device *pdev)
208−{
209− int ret = 0;
210−
211− if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
212− heartbeat = DEFAULT_HEARTBEAT;
213−
214− boot_status = __raw_readl(REGS_RTC_BASE + HW_RTC_PERSISTENT1) &
215− BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER;
216− boot_status = !!boot_status;
217− stmp3xxx_clearl(BV_RTC_PERSISTENT1_GENERAL__RTC_FORCE_UPDATER,
218− REGS_RTC_BASE + HW_RTC_PERSISTENT1);
219− wdt_disable(); /* disable for now */
220−
221− ret = misc_register(&stmp3xxx_wdt_miscdev);
222− if (ret < 0) {
223− dev_err(&pdev->dev, "cannot register misc device\n");
224− return ret;
225− }
226−
227− pr_info("initialized, heartbeat %d sec\n", heartbeat);
228−
229− return ret;
230−}
231−
232−static int stmp3xxx_wdt_remove(struct platform_device *pdev)
233−{
234− misc_deregister(&stmp3xxx_wdt_miscdev);
235− return 0;
236−}
237−
238−#ifdef CONFIG_PM
239−static int wdt_suspended;
240−static u32 wdt_saved_time;
241−
242−static int stmp3xxx_wdt_suspend(struct platform_device *pdev,
243− pm_message_t state)
244−{
245− if (__raw_readl(REGS_RTC_BASE + HW_RTC_CTRL) &
246− BM_RTC_CTRL_WATCHDOGEN) {
247− wdt_suspended = 1;
248− wdt_saved_time = __raw_readl(REGS_RTC_BASE + HW_RTC_WATCHDOG);
249− wdt_disable();
250− }
251− return 0;
252−}
253−
254−static int stmp3xxx_wdt_resume(struct platform_device *pdev)
255−{
256− if (wdt_suspended) {
257− wdt_enable(wdt_saved_time);
258− wdt_suspended = 0;
259− }
260− return 0;
261−}
262−#else
263−#define stmp3xxx_wdt_suspend NULL
264−#define stmp3xxx_wdt_resume NULL
265−#endif
266−
267−static struct platform_driver platform_wdt_driver = {
268− .driver = {
269− .name = "stmp3xxx_wdt",
270− },
271− .probe = stmp3xxx_wdt_probe,
272− .remove = stmp3xxx_wdt_remove,
273− .suspend = stmp3xxx_wdt_suspend,
274− .resume = stmp3xxx_wdt_resume,
275−};
276−
277−module_platform_driver(platform_wdt_driver);
278−
279−MODULE_DESCRIPTION("STMP3XXX Watchdog Driver");
280−MODULE_LICENSE("GPL");
281−
282−module_param(heartbeat, int, 0);
283−MODULE_PARM_DESC(heartbeat,
284− "Watchdog heartbeat period in seconds from 1 to "
285− __MODULE_STRING(MAX_HEARTBEAT) ", default "
286− __MODULE_STRING(DEFAULT_HEARTBEAT));
287−
288−MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
drivers/watchdog/watchdog_core.c+57−9
@@ -36,12 +36,68 @@ · 35 unmodified lines
3636 #include <linux/init.h> /* For __init/__exit/... */
3737 #include <linux/idr.h> /* For ida_* macros */
3838 #include <linux/err.h> /* For IS_ERR macros */
39+#include <linux/of.h> /* For of_get_timeout_sec */
3940
4041 #include "watchdog_core.h" /* For watchdog_dev_register/... */
4142
4243 static DEFINE_IDA(watchdog_ida);
4344 static struct class *watchdog_class;
4445
46+static void watchdog_check_min_max_timeout(struct watchdog_device *wdd)
47+{
48+ /*
49+ * Check that we have valid min and max timeout values, if
50+ * not reset them both to 0 (=not used or unknown)
51+ */
52+ if (wdd->min_timeout > wdd->max_timeout) {
53+ pr_info("Invalid min and max timeout values, resetting to 0!\n");
54+ wdd->min_timeout = 0;
55+ wdd->max_timeout = 0;
56+ }
57+}
58+
59+/**
60+ * watchdog_init_timeout() - initialize the timeout field
61+ * @timeout_parm: timeout module parameter
62+ * @dev: Device that stores the timeout-sec property
63+ *
64+ * Initialize the timeout field of the watchdog_device struct with either the
65+ * timeout module parameter (if it is valid value) or the timeout-sec property
66+ * (only if it is a valid value and the timeout_parm is out of bounds).
67+ * If none of them are valid then we keep the old value (which should normally
68+ * be the default timeout value.
69+ *
70+ * A zero is returned on success and -EINVAL for failure.
71+ */
72+int watchdog_init_timeout(struct watchdog_device *wdd,
73+ unsigned int timeout_parm, struct device *dev)
74+{
75+ unsigned int t = 0;
76+ int ret = 0;
77+
78+ watchdog_check_min_max_timeout(wdd);
79+
80+ /* try to get the tiemout module parameter first */
81+ if (!watchdog_timeout_invalid(wdd, timeout_parm)) {
82+ wdd->timeout = timeout_parm;
83+ return ret;
84+ }
85+ if (timeout_parm)
86+ ret = -EINVAL;
87+
88+ /* try to get the timeout_sec property */
89+ if (dev == NULL || dev->of_node == NULL)
90+ return ret;
91+ of_property_read_u32(dev->of_node, "timeout-sec", &t);
92+ if (!watchdog_timeout_invalid(wdd, t))
93+ wdd->timeout = t;
94+ else
95+ ret = -EINVAL;
96+
97+ return ret;
98+}
99+EXPORT_SYMBOL_GPL(watchdog_init_timeout);
100+
45101 /**
46102 * watchdog_register_device() - register a watchdog device
47103 * @wdd: watchdog device
@@ -63,15 +119,7 @@ int watchdog_register_device(struct watchdog_device *wdd) · 15 unmodified lines
63119 if (wdd->ops->start == NULL || wdd->ops->stop == NULL)
64120 return -EINVAL;
65121
66− /*
67− * Check that we have valid min and max timeout values, if
68− * not reset them both to 0 (=not used or unknown)
69− */
70− if (wdd->min_timeout > wdd->max_timeout) {
71− pr_info("Invalid min and max timeout values, resetting to 0!\n");
72− wdd->min_timeout = 0;
73− wdd->max_timeout = 0;
74− }
122+ watchdog_check_min_max_timeout(wdd);
75123
76124 /*
77125 * Note: now that all watchdog_device data has been verified, we
drivers/watchdog/watchdog_dev.c+1−2
@@ -200,8 +200,7 @@ static int watchdog_set_timeout(struct watchdog_device *wddev, · 199 unmodified lines
200200 !(wddev->info->options & WDIOF_SETTIMEOUT))
201201 return -EOPNOTSUPP;
202202
203− if ((wddev->max_timeout != 0) &&
204− (timeout < wddev->min_timeout || timeout > wddev->max_timeout))
203+ if (watchdog_timeout_invalid(wddev, timeout))
205204 return -EINVAL;
206205
207206 mutex_lock(&wddev->lock);
include/linux/bcm47xx_wdt.h+9−0
@@ -1,7 +1,10 @@
11 #ifndef LINUX_BCM47XX_WDT_H_
22 #define LINUX_BCM47XX_WDT_H_
33
4+#include <linux/notifier.h>
5+#include <linux/timer.h>
46 #include <linux/types.h>
7+#include <linux/watchdog.h>
58
69
710 struct bcm47xx_wdt {
@@ -10,6 +13,12 @@ struct bcm47xx_wdt { · 2 unmodified lines
1013 u32 max_timer_ms;
1114
1215 void *driver_data;
16+
17+ struct watchdog_device wdd;
18+ struct notifier_block notifier;
19+
20+ struct timer_list soft_timer;
21+ atomic_t soft_ticks;
1322 };
1423
1524 static inline void *bcm47xx_wdt_get_drvdata(struct bcm47xx_wdt *wdt)
include/linux/stmp3xxx_rtc_wdt.h+15−0
@@ -0,0 +1,15 @@
1+/*
2+ * stmp3xxx_rtc_wdt.h
3+ *
4+ * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
5+ *
6+ * This file is released under the GPLv2.
7+ */
8+#ifndef __LINUX_STMP3XXX_RTC_WDT_H
9+#define __LINUX_STMP3XXX_RTC_WDT_H
10+
11+struct stmp3xxx_wdt_pdata {
12+ void (*wdt_set_timeout)(struct device *dev, u32 timeout);
13+};
14+
15+#endif /* __LINUX_STMP3XXX_RTC_WDT_H */
include/linux/watchdog.h+9−0
@@ -118,6 +118,13 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway · 117 unmodified lines
118118 set_bit(WDOG_NO_WAY_OUT, &wdd->status);
119119 }
120120
121+/* Use the following function to check if a timeout value is invalid */
122+static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
123+{
124+ return ((wdd->max_timeout != 0) &&
125+ (t < wdd->min_timeout || t > wdd->max_timeout));
126+}
127+
121128 /* Use the following functions to manipulate watchdog driver specific data */
122129 static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void *data)
123130 {
@@ -130,6 +137,8 @@ static inline void *watchdog_get_drvdata(struct watchdog_device *wdd) · 6 unmodified lines
130137 }
131138
132139 /* drivers/watchdog/watchdog_core.c */
140+extern int watchdog_init_timeout(struct watchdog_device *wdd,
141+ unsigned int timeout_parm, struct device *dev);
133142 extern int watchdog_register_device(struct watchdog_device *);
134143 extern void watchdog_unregister_device(struct watchdog_device *);
135144

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t