aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-18 19:16:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-18 19:16:57 -0400
commit6eaac34ff30e189fda28110298ca9fbfb2f51e28 (patch)
treef2c2d70b12f3e745cfa2e3e6406d9ea6e843e8c0
parent13bf2cf9e2d1e0e56088ec6342c2726704100647 (diff)
parent12aea518a202bc7c947553840f1d93f8129b41b2 (diff)
Merge tag 'linux-watchdog-4.19-rc1' of git://www.linux-watchdog.org/linux-watchdog
Pull watchdog updates from Wim Van Sebroeck: - add MEN 16z069 IP-Core driver - renesas-wdt: add support for the R8A77990 wdt - stm32_iwdg: Add stm32mp1 support and pclk feature - sp805_wdt, orion_wdt, sprd_wdt: several improvements - imx2_wdt, stmp3xxx: switch to SPDX identifier * tag 'linux-watchdog-4.19-rc1' of git://www.linux-watchdog.org/linux-watchdog: watchdog: fix dependencies of menz69_wdt.o watchdog: sp805: Add clock-frequency property watchdog: add driver for the MEN 16z069 IP-Core watchdog: sprd_wdt: Remove redundant dev_err call in sprd_wdt_probe() watchdog: stmp3xxx: Switch to SPDX identifier watchdog: imx2_wdt: Switch to SPDX identifier watchdog: sp805: set WDOG_HW_RUNNING when appropriate watchdog: sp805: add 'timeout-sec' DT property support dt-bindings: watchdog: Add optional 'timeout-sec' property for sp805 dt-bindings: watchdog: Consolidate SP805 binding docs watchdog: orion_wdt: Mark watchdog as active when running at probe watchdog: stm32: add pclk feature for stm32mp1 dt-bindings: watchdog: add stm32mp1 support dt-bindings: watchdog: renesas-wdt: Add support for the R8A77990 wdt
-rw-r--r--Documentation/devicetree/bindings/watchdog/arm,sp805.txt29
-rw-r--r--Documentation/devicetree/bindings/watchdog/renesas-wdt.txt1
-rw-r--r--Documentation/devicetree/bindings/watchdog/sp805-wdt.txt31
-rw-r--r--Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt13
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/watchdog/Kconfig10
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/imx2_wdt.c5
-rw-r--r--drivers/watchdog/menz69_wdt.c170
-rw-r--r--drivers/watchdog/orion_wdt.c2
-rw-r--r--drivers/watchdog/sp805_wdt.c63
-rw-r--r--drivers/watchdog/sprd_wdt.c4
-rw-r--r--drivers/watchdog/stm32_iwdg.c116
-rw-r--r--drivers/watchdog/stmp3xxx_rtc_wdt.c5
14 files changed, 351 insertions, 105 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/arm,sp805.txt b/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
index ca99d64e6211..bee6f1f0e41b 100644
--- a/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
+++ b/Documentation/devicetree/bindings/watchdog/arm,sp805.txt
@@ -1,17 +1,32 @@
1ARM AMBA Primecell SP805 Watchdog 1ARM AMBA Primecell SP805 Watchdog
2 2
3SP805 WDT is a ARM Primecell Peripheral and has a standard-id register that
4can be used to identify the peripheral type, vendor, and revision.
5This value can be used for driver matching.
6
7As SP805 WDT is a primecell IP, it follows the base bindings specified in
8'arm/primecell.txt'
9
3Required properties: 10Required properties:
4- compatible: Should be "arm,sp805" & "arm,primecell" 11- compatible: Should be "arm,sp805" & "arm,primecell"
5- reg: Should contain location and length for watchdog timer register. 12- reg: Should contain location and length for watchdog timer register
6- interrupts: Should contain the list of watchdog timer interrupts. 13- clocks: Clocks driving the watchdog timer hardware. This list should be
7- clocks: clocks driving the watchdog timer hardware. This list should be 2 14 2 clocks. With 2 clocks, the order is wdog_clk, apb_pclk
8 clocks. With 2 clocks, the order is wdogclk clock, apb_pclk. 15 wdog_clk can be equal to or be a sub-multiple of the apb_pclk
16 frequency
17- clock-names: Shall be "wdog_clk" for first clock and "apb_pclk" for the
18 second one
19
20Optional properties:
21- interrupts: Should specify WDT interrupt number
22- timeout-sec: Should specify default WDT timeout in seconds. If unset, the
23 default timeout is determined by the driver
9 24
10Example: 25Example:
11 watchdog@66090000 { 26 watchdog@66090000 {
12 compatible = "arm,sp805", "arm,primecell"; 27 compatible = "arm,sp805", "arm,primecell";
13 reg = <0x66090000 0x1000>; 28 reg = <0x66090000 0x1000>;
14 interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>; 29 interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>;
15 clocks = <&apb_pclk>,<&apb_pclk>; 30 clocks = <&wdt_clk>, <&apb_pclk>;
16 clock-names = "wdogclk", "apb_pclk"; 31 clock-names = "wdog_clk", "apb_pclk";
17 }; 32 };
diff --git a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
index f24d802b8056..5d47a262474c 100644
--- a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
@@ -16,6 +16,7 @@ Required properties:
16 - "renesas,r8a7796-wdt" (R-Car M3-W) 16 - "renesas,r8a7796-wdt" (R-Car M3-W)
17 - "renesas,r8a77965-wdt" (R-Car M3-N) 17 - "renesas,r8a77965-wdt" (R-Car M3-N)
18 - "renesas,r8a77970-wdt" (R-Car V3M) 18 - "renesas,r8a77970-wdt" (R-Car V3M)
19 - "renesas,r8a77990-wdt" (R-Car E3)
19 - "renesas,r8a77995-wdt" (R-Car D3) 20 - "renesas,r8a77995-wdt" (R-Car D3)
20 - "renesas,r7s72100-wdt" (RZ/A1) 21 - "renesas,r7s72100-wdt" (RZ/A1)
21 The generic compatible string must be: 22 The generic compatible string must be:
diff --git a/Documentation/devicetree/bindings/watchdog/sp805-wdt.txt b/Documentation/devicetree/bindings/watchdog/sp805-wdt.txt
deleted file mode 100644
index edc4f0ea54a3..000000000000
--- a/Documentation/devicetree/bindings/watchdog/sp805-wdt.txt
+++ /dev/null
@@ -1,31 +0,0 @@
1* ARM SP805 Watchdog Timer (WDT) Controller
2
3SP805 WDT is a ARM Primecell Peripheral and has a standard-id register that
4can be used to identify the peripheral type, vendor, and revision.
5This value can be used for driver matching.
6
7As SP805 WDT is a primecell IP, it follows the base bindings specified in
8'arm/primecell.txt'
9
10Required properties:
11- compatible : Should be "arm,sp805-wdt", "arm,primecell"
12- reg : Base address and size of the watchdog timer registers.
13- clocks : From common clock binding.
14 First clock is PCLK and the second is WDOGCLK.
15 WDOGCLK can be equal to or be a sub-multiple of the PCLK frequency.
16- clock-names : From common clock binding.
17 Shall be "apb_pclk" for first clock and "wdog_clk" for the
18 second one.
19
20Optional properties:
21- interrupts : Should specify WDT interrupt number.
22
23Examples:
24
25 cluster1_core0_watchdog: wdt@c000000 {
26 compatible = "arm,sp805-wdt", "arm,primecell";
27 reg = <0x0 0xc000000 0x0 0x1000>;
28 clocks = <&clockgen 4 3>, <&clockgen 4 3>;
29 clock-names = "apb_pclk", "wdog_clk";
30 };
31
diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
index cc13b10a3f82..d8f4430b0a13 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,9 +2,15 @@ STM32 Independent WatchDoG (IWDG)
2--------------------------------- 2---------------------------------
3 3
4Required properties: 4Required properties:
5- compatible: "st,stm32-iwdg" 5- compatible: Should be either:
6- reg: physical base address and length of the registers set for the device 6 - "st,stm32-iwdg"
7- clocks: must contain a single entry describing the clock input 7 - "st,stm32mp1-iwdg"
8- reg: Physical base address and length of the registers set for the device
9- clocks: Reference to the clock entry lsi. Additional pclk clock entry
10 is required only for st,stm32mp1-iwdg.
11- clock-names: Name of the clocks used.
12 "lsi" for st,stm32-iwdg
13 "lsi", "pclk" for st,stm32mp1-iwdg
8 14
9Optional Properties: 15Optional Properties:
10- timeout-sec: Watchdog timeout value in seconds. 16- timeout-sec: Watchdog timeout value in seconds.
@@ -15,5 +21,6 @@ iwdg: watchdog@40003000 {
15 compatible = "st,stm32-iwdg"; 21 compatible = "st,stm32-iwdg";
16 reg = <0x40003000 0x400>; 22 reg = <0x40003000 0x400>;
17 clocks = <&clk_lsi>; 23 clocks = <&clk_lsi>;
24 clock-names = "lsi";
18 timeout-sec = <32>; 25 timeout-sec = <32>;
19}; 26};
diff --git a/MAINTAINERS b/MAINTAINERS
index 42caef5c808d..71b8592a7264 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9427,6 +9427,12 @@ F: drivers/leds/leds-menf21bmc.c
9427F: drivers/hwmon/menf21bmc_hwmon.c 9427F: drivers/hwmon/menf21bmc_hwmon.c
9428F: Documentation/hwmon/menf21bmc 9428F: Documentation/hwmon/menf21bmc
9429 9429
9430MEN Z069 WATCHDOG DRIVER
9431M: Johannes Thumshirn <jth@kernel.org>
9432L: linux-watchdog@vger.kernel.org
9433S: Maintained
9434F: drivers/watchdog/menz069_wdt.c
9435
9430MESON AO CEC DRIVER FOR AMLOGIC SOCS 9436MESON AO CEC DRIVER FOR AMLOGIC SOCS
9431M: Neil Armstrong <narmstrong@baylibre.com> 9437M: Neil Armstrong <narmstrong@baylibre.com>
9432L: linux-media@lists.freedesktop.org 9438L: linux-media@lists.freedesktop.org
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9af07fd92763..5ea8909a41f9 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -161,6 +161,16 @@ config MENF21BMC_WATCHDOG
161 This driver can also be built as a module. If so the module 161 This driver can also be built as a module. If so the module
162 will be called menf21bmc_wdt. 162 will be called menf21bmc_wdt.
163 163
164config MENZ069_WATCHDOG
165 tristate "MEN 16Z069 Watchdog"
166 depends on MCB
167 select WATCHDOG_CORE
168 help
169 Say Y here to include support for the MEN 16Z069 Watchdog.
170
171 This driver can also be built as a module. If so the module
172 will be called menz069_wdt.
173
164config TANGOX_WATCHDOG 174config TANGOX_WATCHDOG
165 tristate "Sigma Designs SMP86xx/SMP87xx watchdog" 175 tristate "Sigma Designs SMP86xx/SMP87xx watchdog"
166 select WATCHDOG_CORE 176 select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 1d3c6b094fe5..bf92e7bf9ce0 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -215,4 +215,5 @@ obj-$(CONFIG_MAX77620_WATCHDOG) += max77620_wdt.o
215obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o 215obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o
216obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o 216obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
217obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o 217obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o
218obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o
218obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o 219obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index f07850d2c977..2b52514eaa86 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -1,3 +1,4 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Watchdog driver for IMX2 and later processors 3 * Watchdog driver for IMX2 and later processors
3 * 4 *
@@ -7,10 +8,6 @@
7 * some parts adapted by similar drivers from Darius Augulis and Vladimir 8 * some parts adapted by similar drivers from Darius Augulis and Vladimir
8 * Zapolskiy, additional improvements by Wim Van Sebroeck. 9 * Zapolskiy, additional improvements by Wim Van Sebroeck.
9 * 10 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * NOTE: MX1 has a slightly different Watchdog than MX2 and later: 11 * NOTE: MX1 has a slightly different Watchdog than MX2 and later:
15 * 12 *
16 * MX1: MX2+: 13 * MX1: MX2+:
diff --git a/drivers/watchdog/menz69_wdt.c b/drivers/watchdog/menz69_wdt.c
new file mode 100644
index 000000000000..ed18238c5407
--- /dev/null
+++ b/drivers/watchdog/menz69_wdt.c
@@ -0,0 +1,170 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Watchdog driver for the MEN z069 IP-Core
4 *
5 * Copyright (C) 2018 Johannes Thumshirn <jth@kernel.org>
6 */
7#include <linux/io.h>
8#include <linux/kernel.h>
9#include <linux/mcb.h>
10#include <linux/module.h>
11#include <linux/watchdog.h>
12
13struct men_z069_drv {
14 struct watchdog_device wdt;
15 void __iomem *base;
16 struct resource *mem;
17};
18
19#define MEN_Z069_WTR 0x10
20#define MEN_Z069_WTR_WDEN BIT(15)
21#define MEN_Z069_WTR_WDET_MASK 0x7fff
22#define MEN_Z069_WVR 0x14
23
24#define MEN_Z069_TIMER_FREQ 500 /* 500 Hz */
25#define MEN_Z069_WDT_COUNTER_MIN 1
26#define MEN_Z069_WDT_COUNTER_MAX 0x7fff
27#define MEN_Z069_DEFAULT_TIMEOUT 30
28
29static bool nowayout = WATCHDOG_NOWAYOUT;
30module_param(nowayout, bool, 0);
31MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
32 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
33
34static int men_z069_wdt_start(struct watchdog_device *wdt)
35{
36 struct men_z069_drv *drv = watchdog_get_drvdata(wdt);
37 u16 val;
38
39 val = readw(drv->base + MEN_Z069_WTR);
40 val |= MEN_Z069_WTR_WDEN;
41 writew(val, drv->base + MEN_Z069_WTR);
42
43 return 0;
44}
45
46static int men_z069_wdt_stop(struct watchdog_device *wdt)
47{
48 struct men_z069_drv *drv = watchdog_get_drvdata(wdt);
49 u16 val;
50
51 val = readw(drv->base + MEN_Z069_WTR);
52 val &= ~MEN_Z069_WTR_WDEN;
53 writew(val, drv->base + MEN_Z069_WTR);
54
55 return 0;
56}
57
58static int men_z069_wdt_ping(struct watchdog_device *wdt)
59{
60 struct men_z069_drv *drv = watchdog_get_drvdata(wdt);
61 u16 val;
62
63 /* The watchdog trigger value toggles between 0x5555 and 0xaaaa */
64 val = readw(drv->base + MEN_Z069_WVR);
65 val ^= 0xffff;
66 writew(val, drv->base + MEN_Z069_WVR);
67
68 return 0;
69}
70
71static int men_z069_wdt_set_timeout(struct watchdog_device *wdt,
72 unsigned int timeout)
73{
74 struct men_z069_drv *drv = watchdog_get_drvdata(wdt);
75 u16 reg, val, ena;
76
77 wdt->timeout = timeout;
78 val = timeout * MEN_Z069_TIMER_FREQ;
79
80 reg = readw(drv->base + MEN_Z069_WVR);
81 ena = reg & MEN_Z069_WTR_WDEN;
82 reg = ena | val;
83 writew(reg, drv->base + MEN_Z069_WTR);
84
85 return 0;
86}
87
88static const struct watchdog_info men_z069_info = {
89 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
90 .identity = "MEN z069 Watchdog",
91};
92
93static const struct watchdog_ops men_z069_ops = {
94 .owner = THIS_MODULE,
95 .start = men_z069_wdt_start,
96 .stop = men_z069_wdt_stop,
97 .ping = men_z069_wdt_ping,
98 .set_timeout = men_z069_wdt_set_timeout,
99};
100
101static struct watchdog_device men_z069_wdt = {
102 .info = &men_z069_info,
103 .ops = &men_z069_ops,
104 .timeout = MEN_Z069_DEFAULT_TIMEOUT,
105 .min_timeout = 1,
106 .max_timeout = MEN_Z069_WDT_COUNTER_MAX / MEN_Z069_TIMER_FREQ,
107};
108
109static int men_z069_probe(struct mcb_device *dev,
110 const struct mcb_device_id *id)
111{
112 struct men_z069_drv *drv;
113 struct resource *mem;
114
115 drv = devm_kzalloc(&dev->dev, sizeof(struct men_z069_drv), GFP_KERNEL);
116 if (!drv)
117 return -ENOMEM;
118
119 mem = mcb_request_mem(dev, "z069-wdt");
120 if (IS_ERR(mem))
121 return PTR_ERR(mem);
122
123 drv->base = devm_ioremap(&dev->dev, mem->start, resource_size(mem));
124 if (drv->base == NULL)
125 goto release_mem;
126
127 drv->mem = mem;
128
129 drv->wdt = men_z069_wdt;
130 watchdog_init_timeout(&drv->wdt, 0, &dev->dev);
131 watchdog_set_nowayout(&drv->wdt, nowayout);
132 watchdog_set_drvdata(&drv->wdt, drv);
133 drv->wdt.parent = &dev->dev;
134 mcb_set_drvdata(dev, drv);
135
136 return watchdog_register_device(&men_z069_wdt);
137
138release_mem:
139 mcb_release_mem(mem);
140 return -ENOMEM;
141}
142
143static void men_z069_remove(struct mcb_device *dev)
144{
145 struct men_z069_drv *drv = mcb_get_drvdata(dev);
146
147 watchdog_unregister_device(&drv->wdt);
148 mcb_release_mem(drv->mem);
149}
150
151static const struct mcb_device_id men_z069_ids[] = {
152 { .device = 0x45 },
153 { }
154};
155MODULE_DEVICE_TABLE(mcb, men_z069_ids);
156
157static struct mcb_driver men_z069_driver = {
158 .driver = {
159 .name = "z069-wdt",
160 .owner = THIS_MODULE,
161 },
162 .probe = men_z069_probe,
163 .remove = men_z069_remove,
164 .id_table = men_z069_ids,
165};
166module_mcb_driver(men_z069_driver);
167
168MODULE_AUTHOR("Johannes Thumshirn <jth@kernel.org>");
169MODULE_LICENSE("GPL v2");
170MODULE_ALIAS("mcb:16z069");
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index ea676d233e1e..9db3b09f7568 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -581,6 +581,8 @@ static int orion_wdt_probe(struct platform_device *pdev)
581 */ 581 */
582 if (!orion_wdt_enabled(&dev->wdt)) 582 if (!orion_wdt_enabled(&dev->wdt))
583 orion_wdt_stop(&dev->wdt); 583 orion_wdt_stop(&dev->wdt);
584 else
585 set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
584 586
585 /* Request the IRQ only after the watchdog is disabled */ 587 /* Request the IRQ only after the watchdog is disabled */
586 irq = platform_get_irq(pdev, 0); 588 irq = platform_get_irq(pdev, 0);
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 9849db0743a7..072986d461b7 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -11,6 +11,7 @@
11 * warranty of any kind, whether express or implied. 11 * warranty of any kind, whether express or implied.
12 */ 12 */
13 13
14#include <linux/acpi.h>
14#include <linux/device.h> 15#include <linux/device.h>
15#include <linux/resource.h> 16#include <linux/resource.h>
16#include <linux/amba/bus.h> 17#include <linux/amba/bus.h>
@@ -22,6 +23,7 @@
22#include <linux/math64.h> 23#include <linux/math64.h>
23#include <linux/module.h> 24#include <linux/module.h>
24#include <linux/moduleparam.h> 25#include <linux/moduleparam.h>
26#include <linux/of.h>
25#include <linux/pm.h> 27#include <linux/pm.h>
26#include <linux/slab.h> 28#include <linux/slab.h>
27#include <linux/spinlock.h> 29#include <linux/spinlock.h>
@@ -42,6 +44,7 @@
42 /* control register masks */ 44 /* control register masks */
43 #define INT_ENABLE (1 << 0) 45 #define INT_ENABLE (1 << 0)
44 #define RESET_ENABLE (1 << 1) 46 #define RESET_ENABLE (1 << 1)
47 #define ENABLE_MASK (INT_ENABLE | RESET_ENABLE)
45#define WDTINTCLR 0x00C 48#define WDTINTCLR 0x00C
46#define WDTRIS 0x010 49#define WDTRIS 0x010
47#define WDTMIS 0x014 50#define WDTMIS 0x014
@@ -65,6 +68,7 @@ struct sp805_wdt {
65 spinlock_t lock; 68 spinlock_t lock;
66 void __iomem *base; 69 void __iomem *base;
67 struct clk *clk; 70 struct clk *clk;
71 u64 rate;
68 struct amba_device *adev; 72 struct amba_device *adev;
69 unsigned int load_val; 73 unsigned int load_val;
70}; 74};
@@ -74,13 +78,22 @@ module_param(nowayout, bool, 0);
74MODULE_PARM_DESC(nowayout, 78MODULE_PARM_DESC(nowayout,
75 "Set to 1 to keep watchdog running after device release"); 79 "Set to 1 to keep watchdog running after device release");
76 80
81/* returns true if wdt is running; otherwise returns false */
82static bool wdt_is_running(struct watchdog_device *wdd)
83{
84 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
85 u32 wdtcontrol = readl_relaxed(wdt->base + WDTCONTROL);
86
87 return (wdtcontrol & ENABLE_MASK) == ENABLE_MASK;
88}
89
77/* This routine finds load value that will reset system in required timout */ 90/* This routine finds load value that will reset system in required timout */
78static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout) 91static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
79{ 92{
80 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); 93 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
81 u64 load, rate; 94 u64 load, rate;
82 95
83 rate = clk_get_rate(wdt->clk); 96 rate = wdt->rate;
84 97
85 /* 98 /*
86 * sp805 runs counter with given value twice, after the end of first 99 * sp805 runs counter with given value twice, after the end of first
@@ -106,9 +119,7 @@ static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout)
106static unsigned int wdt_timeleft(struct watchdog_device *wdd) 119static unsigned int wdt_timeleft(struct watchdog_device *wdd)
107{ 120{
108 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd); 121 struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
109 u64 load, rate; 122 u64 load;
110
111 rate = clk_get_rate(wdt->clk);
112 123
113 spin_lock(&wdt->lock); 124 spin_lock(&wdt->lock);
114 load = readl_relaxed(wdt->base + WDTVALUE); 125 load = readl_relaxed(wdt->base + WDTVALUE);
@@ -118,7 +129,7 @@ static unsigned int wdt_timeleft(struct watchdog_device *wdd)
118 load += wdt->load_val + 1; 129 load += wdt->load_val + 1;
119 spin_unlock(&wdt->lock); 130 spin_unlock(&wdt->lock);
120 131
121 return div_u64(load, rate); 132 return div_u64(load, wdt->rate);
122} 133}
123 134
124static int 135static int
@@ -228,11 +239,25 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
228 if (IS_ERR(wdt->base)) 239 if (IS_ERR(wdt->base))
229 return PTR_ERR(wdt->base); 240 return PTR_ERR(wdt->base);
230 241
231 wdt->clk = devm_clk_get(&adev->dev, NULL); 242 if (adev->dev.of_node) {
232 if (IS_ERR(wdt->clk)) { 243 wdt->clk = devm_clk_get(&adev->dev, NULL);
233 dev_warn(&adev->dev, "Clock not found\n"); 244 if (IS_ERR(wdt->clk)) {
234 ret = PTR_ERR(wdt->clk); 245 dev_err(&adev->dev, "Clock not found\n");
235 goto err; 246 return PTR_ERR(wdt->clk);
247 }
248 wdt->rate = clk_get_rate(wdt->clk);
249 } else if (has_acpi_companion(&adev->dev)) {
250 /*
251 * When Driver probe with ACPI device, clock devices
252 * are not available, so watchdog rate get from
253 * clock-frequency property given in _DSD object.
254 */
255 device_property_read_u64(&adev->dev, "clock-frequency",
256 &wdt->rate);
257 if (!wdt->rate) {
258 dev_err(&adev->dev, "no clock-frequency property\n");
259 return -ENODEV;
260 }
236 } 261 }
237 262
238 wdt->adev = adev; 263 wdt->adev = adev;
@@ -244,7 +269,23 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
244 watchdog_set_nowayout(&wdt->wdd, nowayout); 269 watchdog_set_nowayout(&wdt->wdd, nowayout);
245 watchdog_set_drvdata(&wdt->wdd, wdt); 270 watchdog_set_drvdata(&wdt->wdd, wdt);
246 watchdog_set_restart_priority(&wdt->wdd, 128); 271 watchdog_set_restart_priority(&wdt->wdd, 128);
247 wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT); 272
273 /*
274 * If 'timeout-sec' devicetree property is specified, use that.
275 * Otherwise, use DEFAULT_TIMEOUT
276 */
277 wdt->wdd.timeout = DEFAULT_TIMEOUT;
278 watchdog_init_timeout(&wdt->wdd, 0, &adev->dev);
279 wdt_setload(&wdt->wdd, wdt->wdd.timeout);
280
281 /*
282 * If HW is already running, enable/reset the wdt and set the running
283 * bit to tell the wdt subsystem
284 */
285 if (wdt_is_running(&wdt->wdd)) {
286 wdt_enable(&wdt->wdd);
287 set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
288 }
248 289
249 ret = watchdog_register_device(&wdt->wdd); 290 ret = watchdog_register_device(&wdt->wdd);
250 if (ret) { 291 if (ret) {
diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c
index b4d484a42b70..ff9397d9638a 100644
--- a/drivers/watchdog/sprd_wdt.c
+++ b/drivers/watchdog/sprd_wdt.c
@@ -279,10 +279,8 @@ static int sprd_wdt_probe(struct platform_device *pdev)
279 279
280 wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 280 wdt_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
281 wdt->base = devm_ioremap_resource(&pdev->dev, wdt_res); 281 wdt->base = devm_ioremap_resource(&pdev->dev, wdt_res);
282 if (IS_ERR(wdt->base)) { 282 if (IS_ERR(wdt->base))
283 dev_err(&pdev->dev, "failed to map memory resource\n");
284 return PTR_ERR(wdt->base); 283 return PTR_ERR(wdt->base);
285 }
286 284
287 wdt->enable = devm_clk_get(&pdev->dev, "enable"); 285 wdt->enable = devm_clk_get(&pdev->dev, "enable");
288 if (IS_ERR(wdt->enable)) { 286 if (IS_ERR(wdt->enable)) {
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index c97ad5619cb0..e00e3b3526c6 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
11 11
12#include <linux/clk.h> 12#include <linux/clk.h>
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/interrupt.h> 14#include <linux/interrupt.h>
17#include <linux/io.h> 15#include <linux/io.h>
18#include <linux/iopoll.h> 16#include <linux/iopoll.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/of.h> 19#include <linux/of.h>
20#include <linux/of_device.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/watchdog.h> 22#include <linux/watchdog.h>
22 23
@@ -54,11 +55,15 @@
54#define TIMEOUT_US 100000 55#define TIMEOUT_US 100000
55#define SLEEP_US 1000 56#define SLEEP_US 1000
56 57
58#define HAS_PCLK true
59
57struct stm32_iwdg { 60struct stm32_iwdg {
58 struct watchdog_device wdd; 61 struct watchdog_device wdd;
59 void __iomem *regs; 62 void __iomem *regs;
60 struct clk *clk; 63 struct clk *clk_lsi;
64 struct clk *clk_pclk;
61 unsigned int rate; 65 unsigned int rate;
66 bool has_pclk;
62}; 67};
63 68
64static inline u32 reg_read(void __iomem *base, u32 reg) 69static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -133,6 +138,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device *wdd,
133 return 0; 138 return 0;
134} 139}
135 140
141static int stm32_iwdg_clk_init(struct platform_device *pdev,
142 struct stm32_iwdg *wdt)
143{
144 u32 ret;
145
146 wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
147 if (IS_ERR(wdt->clk_lsi)) {
148 dev_err(&pdev->dev, "Unable to get lsi clock\n");
149 return PTR_ERR(wdt->clk_lsi);
150 }
151
152 /* optional peripheral clock */
153 if (wdt->has_pclk) {
154 wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
155 if (IS_ERR(wdt->clk_pclk)) {
156 dev_err(&pdev->dev, "Unable to get pclk clock\n");
157 return PTR_ERR(wdt->clk_pclk);
158 }
159
160 ret = clk_prepare_enable(wdt->clk_pclk);
161 if (ret) {
162 dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
163 return ret;
164 }
165 }
166
167 ret = clk_prepare_enable(wdt->clk_lsi);
168 if (ret) {
169 dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
170 clk_disable_unprepare(wdt->clk_pclk);
171 return ret;
172 }
173
174 wdt->rate = clk_get_rate(wdt->clk_lsi);
175
176 return 0;
177}
178
136static const struct watchdog_info stm32_iwdg_info = { 179static const struct watchdog_info stm32_iwdg_info = {
137 .options = WDIOF_SETTIMEOUT | 180 .options = WDIOF_SETTIMEOUT |
138 WDIOF_MAGICCLOSE | 181 WDIOF_MAGICCLOSE |
@@ -147,49 +190,42 @@ static const struct watchdog_ops stm32_iwdg_ops = {
147 .set_timeout = stm32_iwdg_set_timeout, 190 .set_timeout = stm32_iwdg_set_timeout,
148}; 191};
149 192
193static const struct of_device_id stm32_iwdg_of_match[] = {
194 { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK },
195 { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK },
196 { /* end node */ }
197};
198MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
199
150static int stm32_iwdg_probe(struct platform_device *pdev) 200static int stm32_iwdg_probe(struct platform_device *pdev)
151{ 201{
152 struct watchdog_device *wdd; 202 struct watchdog_device *wdd;
203 const struct of_device_id *match;
153 struct stm32_iwdg *wdt; 204 struct stm32_iwdg *wdt;
154 struct resource *res; 205 struct resource *res;
155 void __iomem *regs;
156 struct clk *clk;
157 int ret; 206 int ret;
158 207
208 match = of_match_device(stm32_iwdg_of_match, &pdev->dev);
209 if (!match)
210 return -ENODEV;
211
212 wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
213 if (!wdt)
214 return -ENOMEM;
215
216 wdt->has_pclk = match->data;
217
159 /* This is the timer base. */ 218 /* This is the timer base. */
160 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 219 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
161 regs = devm_ioremap_resource(&pdev->dev, res); 220 wdt->regs = devm_ioremap_resource(&pdev->dev, res);
162 if (IS_ERR(regs)) { 221 if (IS_ERR(wdt->regs)) {
163 dev_err(&pdev->dev, "Could not get resource\n"); 222 dev_err(&pdev->dev, "Could not get resource\n");
164 return PTR_ERR(regs); 223 return PTR_ERR(wdt->regs);
165 } 224 }
166 225
167 clk = devm_clk_get(&pdev->dev, NULL); 226 ret = stm32_iwdg_clk_init(pdev, wdt);
168 if (IS_ERR(clk)) { 227 if (ret)
169 dev_err(&pdev->dev, "Unable to get clock\n");
170 return PTR_ERR(clk);
171 }
172
173 ret = clk_prepare_enable(clk);
174 if (ret) {
175 dev_err(&pdev->dev, "Unable to prepare clock %p\n", clk);
176 return ret; 228 return ret;
177 }
178
179 /*
180 * Allocate our watchdog driver data, which has the
181 * struct watchdog_device nested within it.
182 */
183 wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
184 if (!wdt) {
185 ret = -ENOMEM;
186 goto err;
187 }
188
189 /* Initialize struct stm32_iwdg. */
190 wdt->regs = regs;
191 wdt->clk = clk;
192 wdt->rate = clk_get_rate(clk);
193 229
194 /* Initialize struct watchdog_device. */ 230 /* Initialize struct watchdog_device. */
195 wdd = &wdt->wdd; 231 wdd = &wdt->wdd;
@@ -217,7 +253,8 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
217 253
218 return 0; 254 return 0;
219err: 255err:
220 clk_disable_unprepare(clk); 256 clk_disable_unprepare(wdt->clk_lsi);
257 clk_disable_unprepare(wdt->clk_pclk);
221 258
222 return ret; 259 return ret;
223} 260}
@@ -227,23 +264,18 @@ static int stm32_iwdg_remove(struct platform_device *pdev)
227 struct stm32_iwdg *wdt = platform_get_drvdata(pdev); 264 struct stm32_iwdg *wdt = platform_get_drvdata(pdev);
228 265
229 watchdog_unregister_device(&wdt->wdd); 266 watchdog_unregister_device(&wdt->wdd);
230 clk_disable_unprepare(wdt->clk); 267 clk_disable_unprepare(wdt->clk_lsi);
268 clk_disable_unprepare(wdt->clk_pclk);
231 269
232 return 0; 270 return 0;
233} 271}
234 272
235static const struct of_device_id stm32_iwdg_of_match[] = {
236 { .compatible = "st,stm32-iwdg" },
237 { /* end node */ }
238};
239MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
240
241static struct platform_driver stm32_iwdg_driver = { 273static struct platform_driver stm32_iwdg_driver = {
242 .probe = stm32_iwdg_probe, 274 .probe = stm32_iwdg_probe,
243 .remove = stm32_iwdg_remove, 275 .remove = stm32_iwdg_remove,
244 .driver = { 276 .driver = {
245 .name = "iwdg", 277 .name = "iwdg",
246 .of_match_table = stm32_iwdg_of_match, 278 .of_match_table = of_match_ptr(stm32_iwdg_of_match),
247 }, 279 },
248}; 280};
249module_platform_driver(stm32_iwdg_driver); 281module_platform_driver(stm32_iwdg_driver);
diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c
index d8b11eb269ad..994c54cc68e9 100644
--- a/drivers/watchdog/stmp3xxx_rtc_wdt.c
+++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c
@@ -1,13 +1,10 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28 3 * Watchdog driver for the RTC based watchdog in STMP3xxx and i.MX23/28
3 * 4 *
4 * Author: Wolfram Sang <kernel@pengutronix.de> 5 * Author: Wolfram Sang <kernel@pengutronix.de>
5 * 6 *
6 * Copyright (C) 2011-12 Wolfram Sang, Pengutronix 7 * 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 */ 8 */
12#include <linux/kernel.h> 9#include <linux/kernel.h>
13#include <linux/module.h> 10#include <linux/module.h>