diff --git a/Documentation/devicetree/bindings/watchdog/arm,sp805.yaml b/Documentation/devicetree/bindings/watchdog/arm,sp805.yaml index 7aea255b301be555d4721bfa83c9d99b7ae0e8e3..bd7c09ed1938550b031a64001cf5d498cb34b368 100644 --- a/Documentation/devicetree/bindings/watchdog/arm,sp805.yaml +++ b/Documentation/devicetree/bindings/watchdog/arm,sp805.yaml @@ -50,6 +50,10 @@ properties: - const: wdog_clk - const: apb_pclk + resets: + maxItems: 1 + description: WDOGRESn input reset signal for sp805 module. + required: - compatible - reg @@ -67,4 +71,5 @@ examples: interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>; clocks = <&wdt_clk>, <&apb_pclk>; clock-names = "wdog_clk", "apb_pclk"; + resets = <&wdt_rst>; }; diff --git a/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml b/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml index 816f85ee2c772220fb1f0ed36ea7c2f771a3f4df..cdf87db361837e1a9764e7a00b75523dec3a9964 100644 --- a/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml @@ -14,10 +14,14 @@ allOf: properties: compatible: - enum: - - atmel,sama5d4-wdt - - microchip,sam9x60-wdt - - microchip,sama7g5-wdt + oneOf: + - enum: + - atmel,sama5d4-wdt + - microchip,sam9x60-wdt + - microchip,sama7g5-wdt + - items: + - const: microchip,sam9x7-wdt + - const: microchip,sam9x60-wdt reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml index 951a7d54135a684939ba940e112c1736bbfbbcf3..ffb17add491af98b703ac67a2c45830bec9e962b 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml @@ -71,6 +71,7 @@ properties: - renesas,r8a779a0-wdt # R-Car V3U - renesas,r8a779f0-wdt # R-Car S4-8 - renesas,r8a779g0-wdt # R-Car V4H + - renesas,r8a779h0-wdt # R-Car V4M - const: renesas,rcar-gen4-wdt # R-Car Gen4 reg: diff --git a/Documentation/devicetree/bindings/watchdog/sprd,sp9860-wdt.yaml b/Documentation/devicetree/bindings/watchdog/sprd,sp9860-wdt.yaml new file mode 100644 index 0000000000000000000000000000000000000000..730d9a3a3cc55b7e28fcc182338243939ee0e69e --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/sprd,sp9860-wdt.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/sprd,sp9860-wdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Spreadtrum SP9860 watchdog timer + +maintainers: + - Orson Zhai <orsonzhai@gmail.com> + - Baolin Wang <baolin.wang7@gmail.com> + - Chunyan Zhang <zhang.lyra@gmail.com> + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + const: sprd,sp9860-wdt + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 2 + + clock-names: + items: + - const: enable + - const: rtc_enable + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - timeout-sec + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/sprd,sc9860-clk.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/interrupt-controller/irq.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + watchdog@40310000 { + compatible = "sprd,sp9860-wdt"; + reg = <0 0x40310000 0 0x1000>; + interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&aon_gate CLK_APCPU_WDG_EB>, <&aon_gate CLK_AP_WDG_RTC_EB>; + clock-names = "enable", "rtc_enable"; + timeout-sec = <12>; + }; + }; +... diff --git a/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt b/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt deleted file mode 100644 index aeaf3e0caf47b2695fde0c7d1eb86f89a46108fa..0000000000000000000000000000000000000000 --- a/Documentation/devicetree/bindings/watchdog/sprd-wdt.txt +++ /dev/null @@ -1,19 +0,0 @@ -Spreadtrum SoCs Watchdog timer - -Required properties: -- compatible : Should be "sprd,sp9860-wdt". -- reg : Specifies base physical address and size of the registers. -- interrupts : Exactly one interrupt specifier. -- timeout-sec : Contain the default watchdog timeout in seconds. -- clock-names : Contain the input clock names. -- clocks : Phandles to input clocks. - -Example: - watchdog: watchdog@40310000 { - compatible = "sprd,sp9860-wdt"; - reg = <0 0x40310000 0 0x1000>; - interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; - timeout-sec = <12>; - clock-names = "enable", "rtc_enable"; - clocks = <&clk_aon_apb_gates1 8>, <&clk_aon_apb_rtc_gates 9>; - }; diff --git a/Documentation/devicetree/bindings/watchdog/starfive,jh7100-wdt.yaml b/Documentation/devicetree/bindings/watchdog/starfive,jh7100-wdt.yaml index 68f3f6fd08a628781752dc64b54e7f856d34157a..e21f807b0b69ff317ac978dd173b3f0cce4ada88 100644 --- a/Documentation/devicetree/bindings/watchdog/starfive,jh7100-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/starfive,jh7100-wdt.yaml @@ -19,14 +19,16 @@ description: isn't cleared, the watchdog will reset the system unless the watchdog reset is disabled. -allOf: - - $ref: watchdog.yaml# - properties: compatible: - enum: - - starfive,jh7100-wdt - - starfive,jh7110-wdt + oneOf: + - enum: + - starfive,jh7100-wdt + - starfive,jh7110-wdt + - items: + - enum: + - starfive,jh8100-wdt + - const: starfive,jh7110-wdt reg: maxItems: 1 @@ -45,9 +47,8 @@ properties: - const: core resets: - items: - - description: APB reset - - description: Core reset + minItems: 1 + maxItems: 2 required: - compatible @@ -56,6 +57,27 @@ required: - clock-names - resets +allOf: + - $ref: watchdog.yaml# + + - if: + properties: + compatible: + contains: + enum: + - starfive,jh8100-wdt + then: + properties: + resets: + items: + - description: Core reset + else: + properties: + resets: + items: + - description: APB reset + - description: Core reset + unevaluatedProperties: false examples: diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 138dc8d8ca3d8a6b4ae4114137a6bc28cb3f09a7..ae30e394d176e5714ee58b336843485f338db5a6 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -378,11 +378,36 @@ static void hpwdt_exit(struct pci_dev *dev) pci_disable_device(dev); } +static int hpwdt_suspend(struct device *dev) +{ + if (watchdog_active(&hpwdt_dev)) + hpwdt_stop(); + + return 0; +} + +static int hpwdt_resume(struct device *dev) +{ + if (watchdog_active(&hpwdt_dev)) + hpwdt_start(&hpwdt_dev); + + return 0; +} + +static const struct dev_pm_ops hpwdt_pm_ops = { + LATE_SYSTEM_SLEEP_PM_OPS(hpwdt_suspend, hpwdt_resume) +}; + static struct pci_driver hpwdt_driver = { .name = "hpwdt", .id_table = hpwdt_devices, .probe = hpwdt_init_one, .remove = hpwdt_exit, + + .driver = { + .name = "hpwdt", + .pm = &hpwdt_pm_ops, + } }; MODULE_AUTHOR("Tom Mingarelli"); diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c index fb7fae750181bf3738299408241ee0db2f5f8e27..8d71f6a2236bfa7dfd864f17e32e11baa57e30ea 100644 --- a/drivers/watchdog/intel-mid_wdt.c +++ b/drivers/watchdog/intel-mid_wdt.c @@ -9,15 +9,20 @@ * Contact: David Cohen <david.a.cohen@linux.intel.com> */ +#include <linux/bitops.h> +#include <linux/device.h> +#include <linux/errno.h> #include <linux/interrupt.h> +#include <linux/math.h> #include <linux/module.h> -#include <linux/nmi.h> +#include <linux/panic.h> #include <linux/platform_device.h> +#include <linux/types.h> #include <linux/watchdog.h> + #include <linux/platform_data/intel-mid_wdt.h> #include <asm/intel_scu_ipc.h> -#include <asm/intel-mid.h> #define IPC_WATCHDOG 0xf8 @@ -122,7 +127,7 @@ static int mid_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct watchdog_device *wdt_dev; - struct intel_mid_wdt_pdata *pdata = dev->platform_data; + struct intel_mid_wdt_pdata *pdata = dev_get_platdata(dev); struct mid_wdt *mid; int ret; diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 9297a5891912748562f49921a7ff7dd925550304..3e8c15138eddadf5ff880788bad8dd1ebc3e483a 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -213,12 +213,16 @@ static int wdt_stop(struct watchdog_device *wdd) /** * wdt_set_timeout - set a new timeout value with watchdog ioctl + * @wdd: pointer to the watchdog_device structure * @t: timeout value in seconds * * The hardware device has a 8 or 16 bit watchdog timer (depends on * chip version) that can be configured to count seconds or minutes. * * Used within WDIOC_SETTIMEOUT watchdog device ioctl. + * + * Return: 0 if the timeout was set successfully, or a negative error code on + * failure. */ static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t) diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index 9e790f0c2096cdbd5ab349690b036670a0e17216..006f9c61aa64fd2b4ee9db493aeb54c8fafac818 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -41,6 +41,7 @@ static const u32 reg_offset_data_kpss[] = { struct qcom_wdt_match_data { const u32 *offset; bool pretimeout; + u32 max_tick_count; }; struct qcom_wdt { @@ -177,11 +178,13 @@ static const struct watchdog_info qcom_wdt_pt_info = { static const struct qcom_wdt_match_data match_data_apcs_tmr = { .offset = reg_offset_data_apcs_tmr, .pretimeout = false, + .max_tick_count = 0x10000000U, }; static const struct qcom_wdt_match_data match_data_kpss = { .offset = reg_offset_data_kpss, .pretimeout = true, + .max_tick_count = 0xFFFFFU, }; static int qcom_wdt_probe(struct platform_device *pdev) @@ -236,7 +239,7 @@ static int qcom_wdt_probe(struct platform_device *pdev) */ wdt->rate = clk_get_rate(clk); if (wdt->rate == 0 || - wdt->rate > 0x10000000U) { + wdt->rate > data->max_tick_count) { dev_err(dev, "invalid clock rate\n"); return -EINVAL; } @@ -260,7 +263,7 @@ static int qcom_wdt_probe(struct platform_device *pdev) wdt->wdd.ops = &qcom_wdt_ops; wdt->wdd.min_timeout = 1; - wdt->wdd.max_timeout = 0x10000000U / wdt->rate; + wdt->wdd.max_timeout = data->max_tick_count / wdt->rate; wdt->wdd.parent = dev; wdt->layout = data->offset; diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 2756ed54ca3d55c2d4d25b9b9828101d73244e86..109e2e37e8f09e6f8afd61375f52316664bc744d 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -25,6 +25,7 @@ #include <linux/moduleparam.h> #include <linux/pm.h> #include <linux/property.h> +#include <linux/reset.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/types.h> @@ -232,6 +233,7 @@ static int sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) { struct sp805_wdt *wdt; + struct reset_control *rst; u64 rate = 0; int ret = 0; @@ -264,6 +266,12 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) return -ENODEV; } + rst = devm_reset_control_get_optional_exclusive(&adev->dev, NULL); + if (IS_ERR(rst)) + return dev_err_probe(&adev->dev, PTR_ERR(rst), "Can not get reset\n"); + + reset_control_deassert(rst); + wdt->adev = adev; wdt->wdd.info = &wdt_info; wdt->wdd.ops = &wdt_ops; diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c index e28ead24c520e19a40dffc833d76757f3a8c9430..b4b059883618b94e8b8d77d9170b5f8cd71c7419 100644 --- a/drivers/watchdog/starfive-wdt.c +++ b/drivers/watchdog/starfive-wdt.c @@ -494,8 +494,13 @@ static int starfive_wdt_probe(struct platform_device *pdev) if (ret) goto err_exit; - if (!early_enable) - pm_runtime_put_sync(&pdev->dev); + if (!early_enable) { + if (pm_runtime_enabled(&pdev->dev)) { + ret = pm_runtime_put_sync(&pdev->dev); + if (ret) + goto err_exit; + } + } return 0; @@ -554,7 +559,10 @@ static int starfive_wdt_resume(struct device *dev) starfive_wdt_set_reload_count(wdt, wdt->reload); starfive_wdt_lock(wdt); - return starfive_wdt_start(wdt); + if (watchdog_active(&wdt->wdd)) + return starfive_wdt_start(wdt); + + return 0; } static int starfive_wdt_runtime_suspend(struct device *dev) diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c index d9fd50df9802ce036b9c49d249da043fc4cef232..5404e0387620218d38be644aa70a7e21f2d57edc 100644 --- a/drivers/watchdog/stm32_iwdg.c +++ b/drivers/watchdog/stm32_iwdg.c @@ -20,6 +20,8 @@ #include <linux/platform_device.h> #include <linux/watchdog.h> +#define DEFAULT_TIMEOUT 10 + /* IWDG registers */ #define IWDG_KR 0x00 /* Key register */ #define IWDG_PR 0x04 /* Prescaler Register */ @@ -248,6 +250,7 @@ static int stm32_iwdg_probe(struct platform_device *pdev) wdd->parent = dev; wdd->info = &stm32_iwdg_info; wdd->ops = &stm32_iwdg_ops; + wdd->timeout = DEFAULT_TIMEOUT; wdd->min_timeout = DIV_ROUND_UP((RLR_MIN + 1) * PR_MIN, wdt->rate); wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * wdt->data->max_prescaler * 1000) / wdt->rate; diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 5b55ccae06d4b02a32637c4cd4662d7f1917863b..aff2c3912ead69cae51fe8228b9f568ab2a61b41 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -260,12 +260,12 @@ static int __watchdog_register_device(struct watchdog_device *wdd) if (wdd->parent) { ret = of_alias_get_id(wdd->parent->of_node, "watchdog"); if (ret >= 0) - id = ida_simple_get(&watchdog_ida, ret, - ret + 1, GFP_KERNEL); + id = ida_alloc_range(&watchdog_ida, ret, ret, + GFP_KERNEL); } if (id < 0) - id = ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL); + id = ida_alloc_max(&watchdog_ida, MAX_DOGS - 1, GFP_KERNEL); if (id < 0) return id; @@ -273,19 +273,20 @@ static int __watchdog_register_device(struct watchdog_device *wdd) ret = watchdog_dev_register(wdd); if (ret) { - ida_simple_remove(&watchdog_ida, id); + ida_free(&watchdog_ida, id); if (!(id == 0 && ret == -EBUSY)) return ret; /* Retry in case a legacy watchdog module exists */ - id = ida_simple_get(&watchdog_ida, 1, MAX_DOGS, GFP_KERNEL); + id = ida_alloc_range(&watchdog_ida, 1, MAX_DOGS - 1, + GFP_KERNEL); if (id < 0) return id; wdd->id = id; ret = watchdog_dev_register(wdd); if (ret) { - ida_simple_remove(&watchdog_ida, id); + ida_free(&watchdog_ida, id); return ret; } } @@ -309,7 +310,7 @@ static int __watchdog_register_device(struct watchdog_device *wdd) pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", wdd->id, ret); watchdog_dev_unregister(wdd); - ida_simple_remove(&watchdog_ida, id); + ida_free(&watchdog_ida, id); return ret; } } @@ -382,7 +383,7 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd) unregister_reboot_notifier(&wdd->reboot_nb); watchdog_dev_unregister(wdd); - ida_simple_remove(&watchdog_ida, wdd->id); + ida_free(&watchdog_ida, wdd->id); } /**