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

Merge tag 'linux-watchdog-5.15-rc1' of git://www.linux-watchdog.org/linux-watchdog

Pull watchdog updates from Wim Van Sebroeck:

- add Mediatek MT7986 & MT8195 wdt support

- add Maxim MAX63xx

- drop bd70528 support

- rewrite ixp4xx to watchdog framework

- constify static struct watchdog_ops for sl28cpld_wdt, mpc8xxx_wdt and
tqmx86

- introduce watchdog_dev_suspend/resume

- several fixes and improvements

* tag 'linux-watchdog-5.15-rc1' of git://www.linux-watchdog.org/linux-watchdog:
dt-bindings: watchdog: Add compatible for Mediatek MT7986
watchdog: ixp4xx: Rewrite driver to use core
watchdog: Start watchdog in watchdog_set_last_hw_keepalive only if appropriate
watchdog: max63xx_wdt: Add device tree probing
dt-bindings: watchdog: Add Maxim MAX63xx bindings
watchdog: mediatek: mt8195: add wdt support
dt-bindings: reset: mt8195: add toprgu reset-controller header file
watchdog: tqmx86: Constify static struct watchdog_ops
watchdog: mpc8xxx_wdt: Constify static struct watchdog_ops
watchdog: sl28cpld_wdt: Constify static struct watchdog_ops
watchdog: iTCO_wdt: Fix detection of SMI-off case
watchdog: bcm2835_wdt: consider system-power-controller property
watchdog: imx2_wdg: notify wdog core to stop ping worker on suspend
watchdog: introduce watchdog_dev_suspend/resume
watchdog: Fix NULL pointer dereference when releasing cdev
watchdog: only run driver set_pretimeout op if device supports it
watchdog: bd70528 drop bd70528 support

+213 -318
+44
Documentation/devicetree/bindings/watchdog/maxim,max63xx.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/watchdog/maxim,max63xx.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Maxim 63xx Watchdog Timers 8 + 9 + allOf: 10 + - $ref: "watchdog.yaml#" 11 + 12 + maintainers: 13 + - Marc Zyngier <maz@kernel.org> 14 + - Linus Walleij <linus.walleij@linaro.org> 15 + 16 + properties: 17 + compatible: 18 + oneOf: 19 + - const: maxim,max6369 20 + - const: maxim,max6370 21 + - const: maxim,max6371 22 + - const: maxim,max6372 23 + - const: maxim,max6373 24 + - const: maxim,max6374 25 + 26 + reg: 27 + description: This is a 1-byte memory-mapped address 28 + maxItems: 1 29 + 30 + required: 31 + - compatible 32 + - reg 33 + 34 + unevaluatedProperties: false 35 + 36 + examples: 37 + - | 38 + wdt: watchdog@50000000 { 39 + compatible = "maxim,max6369"; 40 + reg = <0x50000000 0x1>; 41 + timeout-sec = <10>; 42 + }; 43 + 44 + ...
+1
Documentation/devicetree/bindings/watchdog/mtk-wdt.txt
··· 13 13 "mediatek,mt7622-wdt", "mediatek,mt6589-wdt": for MT7622 14 14 "mediatek,mt7623-wdt", "mediatek,mt6589-wdt": for MT7623 15 15 "mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629 16 + "mediatek,mt7986-wdt", "mediatek,mt6589-wdt": for MT7986 16 17 "mediatek,mt8183-wdt": for MT8183 17 18 "mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516 18 19 "mediatek,mt8192-wdt": for MT8192
-12
drivers/watchdog/Kconfig
··· 168 168 watchdog. Be aware that governors might affect the watchdog because it 169 169 is purely software, e.g. the panic governor will stall it! 170 170 171 - config BD70528_WATCHDOG 172 - tristate "ROHM BD70528 PMIC Watchdog" 173 - depends on MFD_ROHM_BD70528 174 - select WATCHDOG_CORE 175 - help 176 - Support for the watchdog in the ROHM BD70528 PMIC. Watchdog trigger 177 - cause system reset. 178 - 179 - Say Y here to include support for the ROHM BD70528 watchdog. 180 - Alternatively say M to compile the driver as a module, 181 - which will be called bd70528_wdt. 182 - 183 171 config BD957XMUF_WATCHDOG 184 172 tristate "ROHM BD9576MUF and BD9573MUF PMIC Watchdog" 185 173 depends on MFD_ROHM_BD957XMUF
-1
drivers/watchdog/Makefile
··· 204 204 obj-$(CONFIG_XEN_WDT) += xen_wdt.o 205 205 206 206 # Architecture Independent 207 - obj-$(CONFIG_BD70528_WATCHDOG) += bd70528_wdt.o 208 207 obj-$(CONFIG_BD957XMUF_WATCHDOG) += bd9576_wdt.o 209 208 obj-$(CONFIG_DA9052_WATCHDOG) += da9052_wdt.o 210 209 obj-$(CONFIG_DA9055_WATCHDOG) += da9055_wdt.o
+7 -3
drivers/watchdog/bcm2835_wdt.c
··· 205 205 if (err) 206 206 return err; 207 207 208 - if (pm_power_off == NULL) { 209 - pm_power_off = bcm2835_power_off; 210 - bcm2835_power_off_wdt = wdt; 208 + if (of_device_is_system_power_controller(pdev->dev.parent->of_node)) { 209 + if (!pm_power_off) { 210 + pm_power_off = bcm2835_power_off; 211 + bcm2835_power_off_wdt = wdt; 212 + } else { 213 + dev_info(dev, "Poweroff handler already present!\n"); 214 + } 211 215 } 212 216 213 217 dev_info(dev, "Broadcom BCM2835 watchdog timer");
-291
drivers/watchdog/bd70528_wdt.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - // Copyright (C) 2018 ROHM Semiconductors 3 - // ROHM BD70528MWV watchdog driver 4 - 5 - #include <linux/bcd.h> 6 - #include <linux/kernel.h> 7 - #include <linux/mfd/rohm-bd70528.h> 8 - #include <linux/module.h> 9 - #include <linux/of.h> 10 - #include <linux/platform_device.h> 11 - #include <linux/regmap.h> 12 - #include <linux/watchdog.h> 13 - 14 - /* 15 - * Max time we can set is 1 hour, 59 minutes and 59 seconds 16 - * and Minimum time is 1 second 17 - */ 18 - #define WDT_MAX_MS ((2 * 60 * 60 - 1) * 1000) 19 - #define WDT_MIN_MS 1000 20 - #define DEFAULT_TIMEOUT 60 21 - 22 - #define WD_CTRL_MAGIC1 0x55 23 - #define WD_CTRL_MAGIC2 0xAA 24 - 25 - struct wdtbd70528 { 26 - struct device *dev; 27 - struct regmap *regmap; 28 - struct rohm_regmap_dev *mfd; 29 - struct watchdog_device wdt; 30 - }; 31 - 32 - /** 33 - * bd70528_wdt_set - arm or disarm watchdog timer 34 - * 35 - * @data: device data for the PMIC instance we want to operate on 36 - * @enable: new state of WDT. zero to disable, non zero to enable 37 - * @old_state: previous state of WDT will be filled here 38 - * 39 - * Arm or disarm WDT on BD70528 PMIC. Expected to be called only by 40 - * BD70528 RTC and BD70528 WDT drivers. The rtc_timer_lock must be taken 41 - * by calling bd70528_wdt_lock before calling bd70528_wdt_set. 42 - */ 43 - int bd70528_wdt_set(struct rohm_regmap_dev *data, int enable, int *old_state) 44 - { 45 - int ret, i; 46 - unsigned int tmp; 47 - struct bd70528_data *bd70528 = container_of(data, struct bd70528_data, 48 - chip); 49 - u8 wd_ctrl_arr[3] = { WD_CTRL_MAGIC1, WD_CTRL_MAGIC2, 0 }; 50 - u8 *wd_ctrl = &wd_ctrl_arr[2]; 51 - 52 - ret = regmap_read(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, &tmp); 53 - if (ret) 54 - return ret; 55 - 56 - *wd_ctrl = (u8)tmp; 57 - 58 - if (old_state) { 59 - if (*wd_ctrl & BD70528_MASK_WDT_EN) 60 - *old_state |= BD70528_WDT_STATE_BIT; 61 - else 62 - *old_state &= ~BD70528_WDT_STATE_BIT; 63 - if ((!enable) == (!(*old_state & BD70528_WDT_STATE_BIT))) 64 - return 0; 65 - } 66 - 67 - if (enable) { 68 - if (*wd_ctrl & BD70528_MASK_WDT_EN) 69 - return 0; 70 - *wd_ctrl |= BD70528_MASK_WDT_EN; 71 - } else { 72 - if (*wd_ctrl & BD70528_MASK_WDT_EN) 73 - *wd_ctrl &= ~BD70528_MASK_WDT_EN; 74 - else 75 - return 0; 76 - } 77 - 78 - for (i = 0; i < 3; i++) { 79 - ret = regmap_write(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, 80 - wd_ctrl_arr[i]); 81 - if (ret) 82 - return ret; 83 - } 84 - 85 - ret = regmap_read(bd70528->chip.regmap, BD70528_REG_WDT_CTRL, &tmp); 86 - if ((tmp & BD70528_MASK_WDT_EN) != (*wd_ctrl & BD70528_MASK_WDT_EN)) { 87 - dev_err(bd70528->chip.dev, 88 - "Watchdog ctrl mismatch (hw) 0x%x (set) 0x%x\n", 89 - tmp, *wd_ctrl); 90 - ret = -EIO; 91 - } 92 - 93 - return ret; 94 - } 95 - EXPORT_SYMBOL(bd70528_wdt_set); 96 - 97 - /** 98 - * bd70528_wdt_lock - take WDT lock 99 - * 100 - * @data: device data for the PMIC instance we want to operate on 101 - * 102 - * Lock WDT for arming/disarming in order to avoid race condition caused 103 - * by WDT state changes initiated by WDT and RTC drivers. 104 - */ 105 - void bd70528_wdt_lock(struct rohm_regmap_dev *data) 106 - { 107 - struct bd70528_data *bd70528 = container_of(data, struct bd70528_data, 108 - chip); 109 - 110 - mutex_lock(&bd70528->rtc_timer_lock); 111 - } 112 - EXPORT_SYMBOL(bd70528_wdt_lock); 113 - 114 - /** 115 - * bd70528_wdt_unlock - unlock WDT lock 116 - * 117 - * @data: device data for the PMIC instance we want to operate on 118 - * 119 - * Unlock WDT lock which has previously been taken by call to 120 - * bd70528_wdt_lock. 121 - */ 122 - void bd70528_wdt_unlock(struct rohm_regmap_dev *data) 123 - { 124 - struct bd70528_data *bd70528 = container_of(data, struct bd70528_data, 125 - chip); 126 - 127 - mutex_unlock(&bd70528->rtc_timer_lock); 128 - } 129 - EXPORT_SYMBOL(bd70528_wdt_unlock); 130 - 131 - static int bd70528_wdt_set_locked(struct wdtbd70528 *w, int enable) 132 - { 133 - return bd70528_wdt_set(w->mfd, enable, NULL); 134 - } 135 - 136 - static int bd70528_wdt_change(struct wdtbd70528 *w, int enable) 137 - { 138 - int ret; 139 - 140 - bd70528_wdt_lock(w->mfd); 141 - ret = bd70528_wdt_set_locked(w, enable); 142 - bd70528_wdt_unlock(w->mfd); 143 - 144 - return ret; 145 - } 146 - 147 - static int bd70528_wdt_start(struct watchdog_device *wdt) 148 - { 149 - struct wdtbd70528 *w = watchdog_get_drvdata(wdt); 150 - 151 - dev_dbg(w->dev, "WDT ping...\n"); 152 - return bd70528_wdt_change(w, 1); 153 - } 154 - 155 - static int bd70528_wdt_stop(struct watchdog_device *wdt) 156 - { 157 - struct wdtbd70528 *w = watchdog_get_drvdata(wdt); 158 - 159 - dev_dbg(w->dev, "WDT stopping...\n"); 160 - return bd70528_wdt_change(w, 0); 161 - } 162 - 163 - static int bd70528_wdt_set_timeout(struct watchdog_device *wdt, 164 - unsigned int timeout) 165 - { 166 - unsigned int hours; 167 - unsigned int minutes; 168 - unsigned int seconds; 169 - int ret; 170 - struct wdtbd70528 *w = watchdog_get_drvdata(wdt); 171 - 172 - seconds = timeout; 173 - hours = timeout / (60 * 60); 174 - /* Maximum timeout is 1h 59m 59s => hours is 1 or 0 */ 175 - if (hours) 176 - seconds -= (60 * 60); 177 - minutes = seconds / 60; 178 - seconds = seconds % 60; 179 - 180 - bd70528_wdt_lock(w->mfd); 181 - 182 - ret = bd70528_wdt_set_locked(w, 0); 183 - if (ret) 184 - goto out_unlock; 185 - 186 - ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_HOUR, 187 - BD70528_MASK_WDT_HOUR, hours); 188 - if (ret) { 189 - dev_err(w->dev, "Failed to set WDT hours\n"); 190 - goto out_en_unlock; 191 - } 192 - ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_MINUTE, 193 - BD70528_MASK_WDT_MINUTE, bin2bcd(minutes)); 194 - if (ret) { 195 - dev_err(w->dev, "Failed to set WDT minutes\n"); 196 - goto out_en_unlock; 197 - } 198 - ret = regmap_update_bits(w->regmap, BD70528_REG_WDT_SEC, 199 - BD70528_MASK_WDT_SEC, bin2bcd(seconds)); 200 - if (ret) 201 - dev_err(w->dev, "Failed to set WDT seconds\n"); 202 - else 203 - dev_dbg(w->dev, "WDT tmo set to %u\n", timeout); 204 - 205 - out_en_unlock: 206 - ret = bd70528_wdt_set_locked(w, 1); 207 - out_unlock: 208 - bd70528_wdt_unlock(w->mfd); 209 - 210 - return ret; 211 - } 212 - 213 - static const struct watchdog_info bd70528_wdt_info = { 214 - .identity = "bd70528-wdt", 215 - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 216 - }; 217 - 218 - static const struct watchdog_ops bd70528_wdt_ops = { 219 - .start = bd70528_wdt_start, 220 - .stop = bd70528_wdt_stop, 221 - .set_timeout = bd70528_wdt_set_timeout, 222 - }; 223 - 224 - static int bd70528_wdt_probe(struct platform_device *pdev) 225 - { 226 - struct rohm_regmap_dev *bd70528; 227 - struct wdtbd70528 *w; 228 - int ret; 229 - unsigned int reg; 230 - 231 - bd70528 = dev_get_drvdata(pdev->dev.parent); 232 - if (!bd70528) { 233 - dev_err(&pdev->dev, "No MFD driver data\n"); 234 - return -EINVAL; 235 - } 236 - w = devm_kzalloc(&pdev->dev, sizeof(*w), GFP_KERNEL); 237 - if (!w) 238 - return -ENOMEM; 239 - 240 - w->regmap = bd70528->regmap; 241 - w->mfd = bd70528; 242 - w->dev = &pdev->dev; 243 - 244 - w->wdt.info = &bd70528_wdt_info; 245 - w->wdt.ops = &bd70528_wdt_ops; 246 - w->wdt.min_hw_heartbeat_ms = WDT_MIN_MS; 247 - w->wdt.max_hw_heartbeat_ms = WDT_MAX_MS; 248 - w->wdt.parent = pdev->dev.parent; 249 - w->wdt.timeout = DEFAULT_TIMEOUT; 250 - watchdog_set_drvdata(&w->wdt, w); 251 - watchdog_init_timeout(&w->wdt, 0, pdev->dev.parent); 252 - 253 - ret = bd70528_wdt_set_timeout(&w->wdt, w->wdt.timeout); 254 - if (ret) { 255 - dev_err(&pdev->dev, "Failed to set the watchdog timeout\n"); 256 - return ret; 257 - } 258 - 259 - bd70528_wdt_lock(w->mfd); 260 - ret = regmap_read(w->regmap, BD70528_REG_WDT_CTRL, &reg); 261 - bd70528_wdt_unlock(w->mfd); 262 - 263 - if (ret) { 264 - dev_err(&pdev->dev, "Failed to get the watchdog state\n"); 265 - return ret; 266 - } 267 - if (reg & BD70528_MASK_WDT_EN) { 268 - dev_dbg(&pdev->dev, "watchdog was running during probe\n"); 269 - set_bit(WDOG_HW_RUNNING, &w->wdt.status); 270 - } 271 - 272 - ret = devm_watchdog_register_device(&pdev->dev, &w->wdt); 273 - if (ret < 0) 274 - dev_err(&pdev->dev, "watchdog registration failed: %d\n", ret); 275 - 276 - return ret; 277 - } 278 - 279 - static struct platform_driver bd70528_wdt = { 280 - .driver = { 281 - .name = "bd70528-wdt" 282 - }, 283 - .probe = bd70528_wdt_probe, 284 - }; 285 - 286 - module_platform_driver(bd70528_wdt); 287 - 288 - MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 289 - MODULE_DESCRIPTION("BD70528 watchdog driver"); 290 - MODULE_LICENSE("GPL"); 291 - MODULE_ALIAS("platform:bd70528-wdt");
+1 -1
drivers/watchdog/iTCO_wdt.c
··· 362 362 * Otherwise, the BIOS generally reboots when the SMI triggers. 363 363 */ 364 364 if (p->smi_res && 365 - (SMI_EN(p) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN)) 365 + (inl(SMI_EN(p)) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN)) 366 366 tmrval /= 2; 367 367 368 368 /* from the specs: */
+1
drivers/watchdog/imx2_wdt.c
··· 317 317 watchdog_set_nowayout(wdog, nowayout); 318 318 watchdog_set_restart_priority(wdog, 128); 319 319 watchdog_init_timeout(wdog, timeout, dev); 320 + watchdog_stop_ping_on_suspend(wdog); 320 321 321 322 if (imx2_wdt_is_running(wdev)) { 322 323 imx2_wdt_set_timeout(wdog, wdog->timeout);
+20 -4
drivers/watchdog/max63xx_wdt.c
··· 26 26 #include <linux/spinlock.h> 27 27 #include <linux/io.h> 28 28 #include <linux/slab.h> 29 + #include <linux/property.h> 29 30 30 31 #define DEFAULT_HEARTBEAT 60 31 32 #define MAX_HEARTBEAT 60 ··· 100 99 { }, 101 100 }; 102 101 103 - static struct max63xx_timeout * 104 - max63xx_select_timeout(struct max63xx_timeout *table, int value) 102 + static const struct max63xx_timeout * 103 + max63xx_select_timeout(const struct max63xx_timeout *table, int value) 105 104 { 106 105 while (table->twd) { 107 106 if (value <= table->twd) { ··· 203 202 { 204 203 struct device *dev = &pdev->dev; 205 204 struct max63xx_wdt *wdt; 206 - struct max63xx_timeout *table; 205 + const struct max63xx_timeout *table; 207 206 int err; 208 207 209 208 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); 210 209 if (!wdt) 211 210 return -ENOMEM; 212 211 213 - table = (struct max63xx_timeout *)pdev->id_entry->driver_data; 212 + /* Attempt to use fwnode first */ 213 + table = device_get_match_data(dev); 214 + if (!table) 215 + table = (struct max63xx_timeout *)pdev->id_entry->driver_data; 214 216 215 217 if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT) 216 218 heartbeat = DEFAULT_HEARTBEAT; ··· 259 255 }; 260 256 MODULE_DEVICE_TABLE(platform, max63xx_id_table); 261 257 258 + static const struct of_device_id max63xx_dt_id_table[] = { 259 + { .compatible = "maxim,max6369", .data = max6369_table, }, 260 + { .compatible = "maxim,max6370", .data = max6369_table, }, 261 + { .compatible = "maxim,max6371", .data = max6371_table, }, 262 + { .compatible = "maxim,max6372", .data = max6371_table, }, 263 + { .compatible = "maxim,max6373", .data = max6373_table, }, 264 + { .compatible = "maxim,max6374", .data = max6373_table, }, 265 + { } 266 + }; 267 + MODULE_DEVICE_TABLE(of, max63xx_dt_id_table); 268 + 262 269 static struct platform_driver max63xx_wdt_driver = { 263 270 .probe = max63xx_wdt_probe, 264 271 .id_table = max63xx_id_table, 265 272 .driver = { 266 273 .name = "max63xx_wdt", 274 + .of_match_table = max63xx_dt_id_table, 267 275 }, 268 276 }; 269 277
+1 -1
drivers/watchdog/mpc8xxx_wdt.c
··· 118 118 .identity = "MPC8xxx", 119 119 }; 120 120 121 - static struct watchdog_ops mpc8xxx_wdt_ops = { 121 + static const struct watchdog_ops mpc8xxx_wdt_ops = { 122 122 .owner = THIS_MODULE, 123 123 .start = mpc8xxx_wdt_start, 124 124 .ping = mpc8xxx_wdt_ping,
+6
drivers/watchdog/mtk_wdt.c
··· 12 12 #include <dt-bindings/reset-controller/mt2712-resets.h> 13 13 #include <dt-bindings/reset-controller/mt8183-resets.h> 14 14 #include <dt-bindings/reset-controller/mt8192-resets.h> 15 + #include <dt-bindings/reset/mt8195-resets.h> 15 16 #include <linux/delay.h> 16 17 #include <linux/err.h> 17 18 #include <linux/init.h> ··· 81 80 82 81 static const struct mtk_wdt_data mt8192_data = { 83 82 .toprgu_sw_rst_num = MT8192_TOPRGU_SW_RST_NUM, 83 + }; 84 + 85 + static const struct mtk_wdt_data mt8195_data = { 86 + .toprgu_sw_rst_num = MT8195_TOPRGU_SW_RST_NUM, 84 87 }; 85 88 86 89 static int toprgu_reset_update(struct reset_controller_dev *rcdev, ··· 413 408 { .compatible = "mediatek,mt6589-wdt" }, 414 409 { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data }, 415 410 { .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data }, 411 + { .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data }, 416 412 { /* sentinel */ } 417 413 }; 418 414 MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
+1 -1
drivers/watchdog/sl28cpld_wdt.c
··· 108 108 .identity = "sl28cpld watchdog", 109 109 }; 110 110 111 - static struct watchdog_ops sl28cpld_wdt_ops = { 111 + static const struct watchdog_ops sl28cpld_wdt_ops = { 112 112 .owner = THIS_MODULE, 113 113 .start = sl28cpld_wdt_start, 114 114 .stop = sl28cpld_wdt_stop,
+1 -1
drivers/watchdog/tqmx86_wdt.c
··· 62 62 .identity = "TQMx86 Watchdog", 63 63 }; 64 64 65 - static struct watchdog_ops tqmx86_wdt_ops = { 65 + static const struct watchdog_ops tqmx86_wdt_ops = { 66 66 .owner = THIS_MODULE, 67 67 .start = tqmx86_wdt_start, 68 68 .set_timeout = tqmx86_wdt_set_timeout,
+37
drivers/watchdog/watchdog_core.c
··· 34 34 #include <linux/idr.h> /* For ida_* macros */ 35 35 #include <linux/err.h> /* For IS_ERR macros */ 36 36 #include <linux/of.h> /* For of_get_timeout_sec */ 37 + #include <linux/suspend.h> 37 38 38 39 #include "watchdog_core.h" /* For watchdog_dev_register/... */ 39 40 ··· 186 185 return NOTIFY_DONE; 187 186 } 188 187 188 + static int watchdog_pm_notifier(struct notifier_block *nb, unsigned long mode, 189 + void *data) 190 + { 191 + struct watchdog_device *wdd; 192 + int ret = 0; 193 + 194 + wdd = container_of(nb, struct watchdog_device, pm_nb); 195 + 196 + switch (mode) { 197 + case PM_HIBERNATION_PREPARE: 198 + case PM_RESTORE_PREPARE: 199 + case PM_SUSPEND_PREPARE: 200 + ret = watchdog_dev_suspend(wdd); 201 + break; 202 + case PM_POST_HIBERNATION: 203 + case PM_POST_RESTORE: 204 + case PM_POST_SUSPEND: 205 + ret = watchdog_dev_resume(wdd); 206 + break; 207 + } 208 + 209 + if (ret) 210 + return NOTIFY_BAD; 211 + 212 + return NOTIFY_DONE; 213 + } 214 + 189 215 /** 190 216 * watchdog_set_restart_priority - Change priority of restart handler 191 217 * @wdd: watchdog device ··· 317 289 ret = register_restart_handler(&wdd->restart_nb); 318 290 if (ret) 319 291 pr_warn("watchdog%d: Cannot register restart handler (%d)\n", 292 + wdd->id, ret); 293 + } 294 + 295 + if (test_bit(WDOG_NO_PING_ON_SUSPEND, &wdd->status)) { 296 + wdd->pm_nb.notifier_call = watchdog_pm_notifier; 297 + 298 + ret = register_pm_notifier(&wdd->pm_nb); 299 + if (ret) 300 + pr_warn("watchdog%d: Cannot register pm handler (%d)\n", 320 301 wdd->id, ret); 321 302 } 322 303
+54 -3
drivers/watchdog/watchdog_dev.c
··· 401 401 if (watchdog_pretimeout_invalid(wdd, timeout)) 402 402 return -EINVAL; 403 403 404 - if (wdd->ops->set_pretimeout) 404 + if (wdd->ops->set_pretimeout && (wdd->info->options & WDIOF_PRETIMEOUT)) 405 405 err = wdd->ops->set_pretimeout(wdd, timeout); 406 406 else 407 407 wdd->pretimeout = timeout; ··· 1096 1096 watchdog_stop(wdd); 1097 1097 } 1098 1098 1099 + watchdog_hrtimer_pretimeout_stop(wdd); 1100 + 1099 1101 mutex_lock(&wd_data->lock); 1100 1102 wd_data->wdd = NULL; 1101 1103 wdd->wd_data = NULL; ··· 1105 1103 1106 1104 hrtimer_cancel(&wd_data->timer); 1107 1105 kthread_cancel_work_sync(&wd_data->work); 1108 - watchdog_hrtimer_pretimeout_stop(wdd); 1109 1106 1110 1107 put_device(&wd_data->dev); 1111 1108 } ··· 1173 1172 1174 1173 wd_data->last_hw_keepalive = ktime_sub(now, ms_to_ktime(last_ping_ms)); 1175 1174 1176 - return __watchdog_ping(wdd); 1175 + if (watchdog_hw_running(wdd) && handle_boot_enabled) 1176 + return __watchdog_ping(wdd); 1177 + 1178 + return 0; 1177 1179 } 1178 1180 EXPORT_SYMBOL_GPL(watchdog_set_last_hw_keepalive); 1179 1181 ··· 1229 1225 unregister_chrdev_region(watchdog_devt, MAX_DOGS); 1230 1226 class_unregister(&watchdog_class); 1231 1227 kthread_destroy_worker(watchdog_kworker); 1228 + } 1229 + 1230 + int watchdog_dev_suspend(struct watchdog_device *wdd) 1231 + { 1232 + struct watchdog_core_data *wd_data = wdd->wd_data; 1233 + int ret = 0; 1234 + 1235 + if (!wdd->wd_data) 1236 + return -ENODEV; 1237 + 1238 + /* ping for the last time before suspend */ 1239 + mutex_lock(&wd_data->lock); 1240 + if (watchdog_worker_should_ping(wd_data)) 1241 + ret = __watchdog_ping(wd_data->wdd); 1242 + mutex_unlock(&wd_data->lock); 1243 + 1244 + if (ret) 1245 + return ret; 1246 + 1247 + /* 1248 + * make sure that watchdog worker will not kick in when the wdog is 1249 + * suspended 1250 + */ 1251 + hrtimer_cancel(&wd_data->timer); 1252 + kthread_cancel_work_sync(&wd_data->work); 1253 + 1254 + return 0; 1255 + } 1256 + 1257 + int watchdog_dev_resume(struct watchdog_device *wdd) 1258 + { 1259 + struct watchdog_core_data *wd_data = wdd->wd_data; 1260 + int ret = 0; 1261 + 1262 + if (!wdd->wd_data) 1263 + return -ENODEV; 1264 + 1265 + /* 1266 + * __watchdog_ping will also retrigger hrtimer and therefore restore the 1267 + * ping worker if needed. 1268 + */ 1269 + mutex_lock(&wd_data->lock); 1270 + if (watchdog_worker_should_ping(wd_data)) 1271 + ret = __watchdog_ping(wd_data->wdd); 1272 + mutex_unlock(&wd_data->lock); 1273 + 1274 + return ret; 1232 1275 } 1233 1276 1234 1277 module_param(handle_boot_enabled, bool, 0444);
+29
include/dt-bindings/reset/mt8195-resets.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)*/ 2 + /* 3 + * Copyright (c) 2021 MediaTek Inc. 4 + * Author: Christine Zhu <christine.zhu@mediatek.com> 5 + */ 6 + 7 + #ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8195 8 + #define _DT_BINDINGS_RESET_CONTROLLER_MT8195 9 + 10 + #define MT8195_TOPRGU_CONN_MCU_SW_RST 0 11 + #define MT8195_TOPRGU_INFRA_GRST_SW_RST 1 12 + #define MT8195_TOPRGU_APU_SW_RST 2 13 + #define MT8195_TOPRGU_INFRA_AO_GRST_SW_RST 6 14 + #define MT8195_TOPRGU_MMSYS_SW_RST 7 15 + #define MT8195_TOPRGU_MFG_SW_RST 8 16 + #define MT8195_TOPRGU_VENC_SW_RST 9 17 + #define MT8195_TOPRGU_VDEC_SW_RST 10 18 + #define MT8195_TOPRGU_IMG_SW_RST 11 19 + #define MT8195_TOPRGU_APMIXEDSYS_SW_RST 13 20 + #define MT8195_TOPRGU_AUDIO_SW_RST 14 21 + #define MT8195_TOPRGU_CAMSYS_SW_RST 15 22 + #define MT8195_TOPRGU_EDPTX_SW_RST 16 23 + #define MT8195_TOPRGU_ADSPSYS_SW_RST 21 24 + #define MT8195_TOPRGU_DPTX_SW_RST 22 25 + #define MT8195_TOPRGU_SPMI_MST_SW_RST 23 26 + 27 + #define MT8195_TOPRGU_SW_RST_NUM 16 28 + 29 + #endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8195 */
+10
include/linux/watchdog.h
··· 107 107 unsigned int max_hw_heartbeat_ms; 108 108 struct notifier_block reboot_nb; 109 109 struct notifier_block restart_nb; 110 + struct notifier_block pm_nb; 110 111 void *driver_data; 111 112 struct watchdog_core_data *wd_data; 112 113 unsigned long status; ··· 117 116 #define WDOG_STOP_ON_REBOOT 2 /* Should be stopped on reboot */ 118 117 #define WDOG_HW_RUNNING 3 /* True if HW watchdog running */ 119 118 #define WDOG_STOP_ON_UNREGISTER 4 /* Should be stopped on unregister */ 119 + #define WDOG_NO_PING_ON_SUSPEND 5 /* Ping worker should be stopped on suspend */ 120 120 struct list_head deferred; 121 121 }; 122 122 ··· 156 154 static inline void watchdog_stop_on_unregister(struct watchdog_device *wdd) 157 155 { 158 156 set_bit(WDOG_STOP_ON_UNREGISTER, &wdd->status); 157 + } 158 + 159 + /* Use the following function to stop the wdog ping worker when suspending */ 160 + static inline void watchdog_stop_ping_on_suspend(struct watchdog_device *wdd) 161 + { 162 + set_bit(WDOG_NO_PING_ON_SUSPEND, &wdd->status); 159 163 } 160 164 161 165 /* Use the following function to check if a timeout value is invalid */ ··· 217 209 unsigned int timeout_parm, struct device *dev); 218 210 extern int watchdog_register_device(struct watchdog_device *); 219 211 extern void watchdog_unregister_device(struct watchdog_device *); 212 + int watchdog_dev_suspend(struct watchdog_device *wdd); 213 + int watchdog_dev_resume(struct watchdog_device *wdd); 220 214 221 215 int watchdog_set_last_hw_keepalive(struct watchdog_device *, unsigned int); 222 216