diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-18 19:16:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-18 19:16:57 -0400 |
commit | 6eaac34ff30e189fda28110298ca9fbfb2f51e28 (patch) | |
tree | f2c2d70b12f3e745cfa2e3e6406d9ea6e843e8c0 | |
parent | 13bf2cf9e2d1e0e56088ec6342c2726704100647 (diff) | |
parent | 12aea518a202bc7c947553840f1d93f8129b41b2 (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.txt | 29 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/watchdog/renesas-wdt.txt | 1 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/watchdog/sp805-wdt.txt | 31 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt | 13 | ||||
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 10 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/imx2_wdt.c | 5 | ||||
-rw-r--r-- | drivers/watchdog/menz69_wdt.c | 170 | ||||
-rw-r--r-- | drivers/watchdog/orion_wdt.c | 2 | ||||
-rw-r--r-- | drivers/watchdog/sp805_wdt.c | 63 | ||||
-rw-r--r-- | drivers/watchdog/sprd_wdt.c | 4 | ||||
-rw-r--r-- | drivers/watchdog/stm32_iwdg.c | 116 | ||||
-rw-r--r-- | drivers/watchdog/stmp3xxx_rtc_wdt.c | 5 |
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 @@ | |||
1 | ARM AMBA Primecell SP805 Watchdog | 1 | ARM AMBA Primecell SP805 Watchdog |
2 | 2 | ||
3 | SP805 WDT is a ARM Primecell Peripheral and has a standard-id register that | ||
4 | can be used to identify the peripheral type, vendor, and revision. | ||
5 | This value can be used for driver matching. | ||
6 | |||
7 | As SP805 WDT is a primecell IP, it follows the base bindings specified in | ||
8 | 'arm/primecell.txt' | ||
9 | |||
3 | Required properties: | 10 | Required 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 | |||
20 | Optional 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 | ||
10 | Example: | 25 | Example: |
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 | |||
3 | SP805 WDT is a ARM Primecell Peripheral and has a standard-id register that | ||
4 | can be used to identify the peripheral type, vendor, and revision. | ||
5 | This value can be used for driver matching. | ||
6 | |||
7 | As SP805 WDT is a primecell IP, it follows the base bindings specified in | ||
8 | 'arm/primecell.txt' | ||
9 | |||
10 | Required 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 | |||
20 | Optional properties: | ||
21 | - interrupts : Should specify WDT interrupt number. | ||
22 | |||
23 | Examples: | ||
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 | ||
4 | Required properties: | 4 | Required 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 | ||
9 | Optional Properties: | 15 | Optional 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 | |||
9427 | F: drivers/hwmon/menf21bmc_hwmon.c | 9427 | F: drivers/hwmon/menf21bmc_hwmon.c |
9428 | F: Documentation/hwmon/menf21bmc | 9428 | F: Documentation/hwmon/menf21bmc |
9429 | 9429 | ||
9430 | MEN Z069 WATCHDOG DRIVER | ||
9431 | M: Johannes Thumshirn <jth@kernel.org> | ||
9432 | L: linux-watchdog@vger.kernel.org | ||
9433 | S: Maintained | ||
9434 | F: drivers/watchdog/menz069_wdt.c | ||
9435 | |||
9430 | MESON AO CEC DRIVER FOR AMLOGIC SOCS | 9436 | MESON AO CEC DRIVER FOR AMLOGIC SOCS |
9431 | M: Neil Armstrong <narmstrong@baylibre.com> | 9437 | M: Neil Armstrong <narmstrong@baylibre.com> |
9432 | L: linux-media@lists.freedesktop.org | 9438 | L: 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 | ||
164 | config 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 | |||
164 | config TANGOX_WATCHDOG | 174 | config 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 | |||
215 | obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o | 215 | obj-$(CONFIG_ZIIRAVE_WATCHDOG) += ziirave_wdt.o |
216 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o | 216 | obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o |
217 | obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o | 217 | obj-$(CONFIG_MENF21BMC_WATCHDOG) += menf21bmc_wdt.o |
218 | obj-$(CONFIG_MENZ069_WATCHDOG) += menz69_wdt.o | ||
218 | obj-$(CONFIG_RAVE_SP_WATCHDOG) += rave-sp-wdt.o | 219 | obj-$(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 | |||
13 | struct 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 | |||
29 | static bool nowayout = WATCHDOG_NOWAYOUT; | ||
30 | module_param(nowayout, bool, 0); | ||
31 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | ||
32 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
33 | |||
34 | static 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 | |||
46 | static 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 | |||
58 | static 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 | |||
71 | static 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 | |||
88 | static const struct watchdog_info men_z069_info = { | ||
89 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | ||
90 | .identity = "MEN z069 Watchdog", | ||
91 | }; | ||
92 | |||
93 | static 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 | |||
101 | static 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 | |||
109 | static 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 | |||
138 | release_mem: | ||
139 | mcb_release_mem(mem); | ||
140 | return -ENOMEM; | ||
141 | } | ||
142 | |||
143 | static 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 | |||
151 | static const struct mcb_device_id men_z069_ids[] = { | ||
152 | { .device = 0x45 }, | ||
153 | { } | ||
154 | }; | ||
155 | MODULE_DEVICE_TABLE(mcb, men_z069_ids); | ||
156 | |||
157 | static 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 | }; | ||
166 | module_mcb_driver(men_z069_driver); | ||
167 | |||
168 | MODULE_AUTHOR("Johannes Thumshirn <jth@kernel.org>"); | ||
169 | MODULE_LICENSE("GPL v2"); | ||
170 | MODULE_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); | |||
74 | MODULE_PARM_DESC(nowayout, | 78 | MODULE_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 */ | ||
82 | static 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 */ |
78 | static int wdt_setload(struct watchdog_device *wdd, unsigned int timeout) | 91 | static 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) | |||
106 | static unsigned int wdt_timeleft(struct watchdog_device *wdd) | 119 | static 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 | ||
124 | static int | 135 | static 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 | |||
57 | struct stm32_iwdg { | 60 | struct 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 | ||
64 | static inline u32 reg_read(void __iomem *base, u32 reg) | 69 | static 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 | ||
141 | static 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 | |||
136 | static const struct watchdog_info stm32_iwdg_info = { | 179 | static 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 | ||
193 | static 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 | }; | ||
198 | MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match); | ||
199 | |||
150 | static int stm32_iwdg_probe(struct platform_device *pdev) | 200 | static 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; |
219 | err: | 255 | err: |
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 | ||
235 | static const struct of_device_id stm32_iwdg_of_match[] = { | ||
236 | { .compatible = "st,stm32-iwdg" }, | ||
237 | { /* end node */ } | ||
238 | }; | ||
239 | MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match); | ||
240 | |||
241 | static struct platform_driver stm32_iwdg_driver = { | 273 | static 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 | }; |
249 | module_platform_driver(stm32_iwdg_driver); | 281 | module_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> |