mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
linux-watchdog 6.4-rc1 tag
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iEYEABECAAYFAmRTZSoACgkQ+iyteGJfRspyfACgojeDzj400vg0/ZfMrqvwGWiW rroAn13l3UIJI6dI8J89jjp2q5Xo0RSq =ECpF -----END PGP SIGNATURE----- Merge tag 'linux-watchdog-6.4-rc1' of git://www.linux-watchdog.org/linux-watchdog Pull watchdog updates from Wim Van Sebroeck: - Add watchdog driver for StarFive JH7100 and JH7110 Soc - Add Rockchip RK3588 devices - Add Qualcom IPQ5332 APSS, QCM2290 KPSS and SM6115 SoC devices - Add Mediatke MT8365 and MT6735 devices - Watchdog-core: Always set WDOG_HW_RUNNING when starting watchdog - Convert watchdog platform drivers to return void on the remove callback - Convert to devm_clk_get_enabled() helpers - ... and other small fixes and improvements * tag 'linux-watchdog-6.4-rc1' of git://www.linux-watchdog.org/linux-watchdog: (72 commits) watchdog: dw_wdt: Simplify clk management watchdog: dw_wdt: Fix the error handling path of dw_wdt_drv_probe() watchdog: starfive: Fix the warning of starfive_wdt_match watchdog: starfive: Fix the probe return error if PM and early_enable are both disabled MAINTAINERS: Add fragment for Xilinx watchdog driver watchdog: menz069_wdt: fix timeout setting watchdog: menz069_wdt: fix watchdog initialisation dt-bindings: watchdog: alphascale-asm9260: convert to DT schema watchdog: loongson1_wdt: Implement restart handler dt-bindings: watchdog: Document Qualcomm SM6115 watchdog dt-bindings: watchdog: realtek,otto-wdt: simplify requiring interrupt-names dt-bindings: watchdog: toshiba,visconti-wdt: simplify with unevaluatedProperties dt-bindings: watchdog: fsl-imx7ulp-wdt: simplify with unevaluatedProperties dt-bindings: watchdog: arm,sp805: drop unneeded minItems dt-bindings: watchdog: drop duplicated GPIO watchdog bindings dt-bindings: reset: Add binding for MediaTek MT6735 TOPRGU/WDT drivers: watchdog: Add StarFive Watchdog driver dt-bindings: watchdog: Add watchdog for StarFive JH7100 and JH7110 dt-bindings: watchdog: indentation, quotes and white-space cleanup watchdog: ebc-c384_wdt: Mark status as orphaned ...
This commit is contained in:
commit
78b421b6a7
@ -0,0 +1,70 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/watchdog/alphascale,asm9260-wdt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Alphascale asm9260 Watchdog timer
|
||||
|
||||
allOf:
|
||||
- $ref: watchdog.yaml#
|
||||
|
||||
maintainers:
|
||||
- Oleksij Rempel <linux@rempel-privat.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: alphascale,asm9260-wdt
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: source clock, used for tick counter
|
||||
- description: ahb gate
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mod
|
||||
- const: ahb
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: wdt_rst
|
||||
|
||||
alphascale,mode:
|
||||
description: |
|
||||
Specifies the reset mode of operation. If set to sw, then reset is handled
|
||||
via interrupt request, if set to debug, then it does nothing and logs.
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum: [hw, sw, debug]
|
||||
default: hw
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/alphascale,asm9260.h>
|
||||
watchdog0: watchdog@80048000 {
|
||||
compatible = "alphascale,asm9260-wdt";
|
||||
reg = <0x80048000 0x10>;
|
||||
clocks = <&acc CLKID_SYS_WDT>, <&acc CLKID_AHB_WDT>;
|
||||
clock-names = "mod", "ahb";
|
||||
interrupts = <55>;
|
||||
timeout-sec = <30>;
|
||||
alphascale,mode = "hw";
|
||||
};
|
@ -1,35 +0,0 @@
|
||||
Alphascale asm9260 Watchdog timer
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "alphascale,asm9260-wdt".
|
||||
- reg : Specifies base physical address and size of the registers.
|
||||
- clocks : the clocks feeding the watchdog timer. See clock-bindings.txt
|
||||
- clock-names : should be set to
|
||||
"mod" - source for tick counter.
|
||||
"ahb" - ahb gate.
|
||||
- resets : phandle pointing to the system reset controller with
|
||||
line index for the watchdog.
|
||||
- reset-names : should be set to "wdt_rst".
|
||||
|
||||
Optional properties:
|
||||
- timeout-sec : shall contain the default watchdog timeout in seconds,
|
||||
if unset, the default timeout is 30 seconds.
|
||||
- alphascale,mode : three modes are supported
|
||||
"hw" - hw reset (default).
|
||||
"sw" - sw reset.
|
||||
"debug" - no action is taken.
|
||||
|
||||
Example:
|
||||
|
||||
watchdog0: watchdog@80048000 {
|
||||
compatible = "alphascale,asm9260-wdt";
|
||||
reg = <0x80048000 0x10>;
|
||||
clocks = <&acc CLKID_SYS_WDT>, <&acc CLKID_AHB_WDT>;
|
||||
clock-names = "mod", "ahb";
|
||||
interrupts = <55>;
|
||||
resets = <&rst WDT_RESET>;
|
||||
reset-names = "wdt_rst";
|
||||
timeout-sec = <30>;
|
||||
alphascale,mode = "hw";
|
||||
};
|
@ -2,8 +2,8 @@
|
||||
# Copyright 2019 BayLibre, SAS
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/watchdog/amlogic,meson-gxbb-wdt.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
$id: http://devicetree.org/schemas/watchdog/amlogic,meson-gxbb-wdt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Meson GXBB SoCs Watchdog timer
|
||||
|
||||
@ -36,7 +36,7 @@ unevaluatedProperties: false
|
||||
examples:
|
||||
- |
|
||||
watchdog@98d0 {
|
||||
compatible = "amlogic,meson-gxbb-wdt";
|
||||
reg = <0x98d0 0x10>;
|
||||
clocks = <&xtal>;
|
||||
compatible = "amlogic,meson-gxbb-wdt";
|
||||
reg = <0x98d0 0x10>;
|
||||
clocks = <&xtal>;
|
||||
};
|
||||
|
@ -40,7 +40,6 @@ unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
watchdog@2a440000 {
|
||||
compatible = "arm,sbsa-gwdt";
|
||||
reg = <0x2a440000 0x1000>,
|
||||
|
@ -43,7 +43,6 @@ properties:
|
||||
Clocks driving the watchdog timer hardware. The first clock is used
|
||||
for the actual watchdog counter. The second clock drives the register
|
||||
interface.
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
|
@ -44,7 +44,7 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
watchdog@2c000620 {
|
||||
compatible = "arm,arm11mp-twd-wdt";
|
||||
reg = <0x2c000620 0x20>;
|
||||
interrupts = <GIC_PPI 14 0xf01>;
|
||||
compatible = "arm,arm11mp-twd-wdt";
|
||||
reg = <0x2c000620 0x20>;
|
||||
interrupts = <GIC_PPI 14 0xf01>;
|
||||
};
|
||||
|
@ -16,6 +16,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- arm,smc-wdt
|
||||
|
||||
arm,smc-id:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
@ -30,9 +31,9 @@ unevaluatedProperties: false
|
||||
examples:
|
||||
- |
|
||||
watchdog {
|
||||
compatible = "arm,smc-wdt";
|
||||
arm,smc-id = <0x82003D06>;
|
||||
timeout-sec = <15>;
|
||||
compatible = "arm,smc-wdt";
|
||||
arm,smc-id = <0x82003D06>;
|
||||
timeout-sec = <15>;
|
||||
};
|
||||
|
||||
...
|
||||
|
@ -65,13 +65,13 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
watchdog@fc068640 {
|
||||
compatible = "atmel,sama5d4-wdt";
|
||||
reg = <0xfc068640 0x10>;
|
||||
interrupts = <4 IRQ_TYPE_LEVEL_HIGH 5>;
|
||||
timeout-sec = <10>;
|
||||
atmel,watchdog-type = "hardware";
|
||||
atmel,dbg-halt;
|
||||
atmel,idle-halt;
|
||||
compatible = "atmel,sama5d4-wdt";
|
||||
reg = <0xfc068640 0x10>;
|
||||
interrupts = <4 IRQ_TYPE_LEVEL_HIGH 5>;
|
||||
timeout-sec = <10>;
|
||||
atmel,watchdog-type = "hardware";
|
||||
atmel,dbg-halt;
|
||||
atmel,idle-halt;
|
||||
};
|
||||
|
||||
...
|
||||
|
@ -37,7 +37,7 @@ required:
|
||||
examples:
|
||||
- |
|
||||
watchdog@f040a7e8 {
|
||||
compatible = "brcm,bcm7038-wdt";
|
||||
reg = <0xf040a7e8 0x16>;
|
||||
clocks = <&upg_fixed>;
|
||||
compatible = "brcm,bcm7038-wdt";
|
||||
reg = <0xf040a7e8 0x16>;
|
||||
clocks = <&upg_fixed>;
|
||||
};
|
||||
|
@ -52,16 +52,16 @@ examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
watchdog@41000000 {
|
||||
compatible = "faraday,ftwdt010";
|
||||
reg = <0x41000000 0x1000>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
timeout-sec = <5>;
|
||||
compatible = "faraday,ftwdt010";
|
||||
reg = <0x41000000 0x1000>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
timeout-sec = <5>;
|
||||
};
|
||||
- |
|
||||
watchdog: watchdog@98500000 {
|
||||
compatible = "moxa,moxart-watchdog", "faraday,ftwdt010";
|
||||
reg = <0x98500000 0x10>;
|
||||
clocks = <&clk_apb>;
|
||||
clock-names = "PCLK";
|
||||
compatible = "moxa,moxart-watchdog", "faraday,ftwdt010";
|
||||
reg = <0x98500000 0x10>;
|
||||
clocks = <&clk_apb>;
|
||||
clock-names = "PCLK";
|
||||
};
|
||||
...
|
||||
|
@ -30,15 +30,13 @@ properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
timeout-sec: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- reg
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -1,55 +0,0 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/watchdog/gpio-wdt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: GPIO controlled watchdog
|
||||
|
||||
maintainers:
|
||||
- Robert Marko <robert.marko@sartura.hr>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: linux,wdt-gpio
|
||||
|
||||
gpios:
|
||||
maxItems: 1
|
||||
description: GPIO connected to the WDT reset pin
|
||||
|
||||
hw_algo:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: Algorithm used by the driver
|
||||
oneOf:
|
||||
- description:
|
||||
Either a high-to-low or a low-to-high transition clears the WDT counter.
|
||||
The watchdog timer is disabled when GPIO is left floating or connected
|
||||
to a three-state buffer.
|
||||
const: toggle
|
||||
- description:
|
||||
Low or high level starts counting WDT timeout, the opposite level
|
||||
disables the WDT.
|
||||
Active level is determined by the GPIO flags.
|
||||
const: level
|
||||
|
||||
hw_margin_ms:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: Maximum time to reset watchdog circuit (in milliseconds)
|
||||
minimum: 2
|
||||
maximum: 65535
|
||||
|
||||
always-running:
|
||||
type: boolean
|
||||
description:
|
||||
If the watchdog timer cannot be disabled, add this flag to have the driver
|
||||
keep toggling the signal without a client.
|
||||
It will only cease to toggle the signal when the device is open and the
|
||||
timeout elapsed.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- gpios
|
||||
- hw_algo
|
||||
- hw_margin_ms
|
||||
|
||||
unevaluatedProperties: false
|
@ -8,6 +8,7 @@ title: GPIO-controlled Watchdog
|
||||
|
||||
maintainers:
|
||||
- Guenter Roeck <linux@roeck-us.net>
|
||||
- Robert Marko <robert.marko@sartura.hr>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@ -19,11 +20,23 @@ properties:
|
||||
|
||||
hw_algo:
|
||||
description: The algorithm used by the driver.
|
||||
enum: [ level, toggle ]
|
||||
oneOf:
|
||||
- description:
|
||||
Either a high-to-low or a low-to-high transition clears the WDT counter.
|
||||
The watchdog timer is disabled when GPIO is left floating or connected
|
||||
to a three-state buffer.
|
||||
const: toggle
|
||||
- description:
|
||||
Low or high level starts counting WDT timeout, the opposite level
|
||||
disables the WDT.
|
||||
Active level is determined by the GPIO flags.
|
||||
const: level
|
||||
|
||||
hw_margin_ms:
|
||||
description: Maximum time to reset watchdog circuit (milliseconds).
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 2
|
||||
maximum: 65535
|
||||
|
||||
always-running:
|
||||
type: boolean
|
||||
@ -42,7 +55,7 @@ required:
|
||||
allOf:
|
||||
- $ref: watchdog.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -34,7 +34,7 @@ additionalProperties: false
|
||||
examples:
|
||||
- |
|
||||
watchdog@100 {
|
||||
compatible = "mediatek,mt7621-wdt";
|
||||
reg = <0x100 0x100>;
|
||||
mediatek,sysctl = <&sysc>;
|
||||
compatible = "mediatek,mt7621-wdt";
|
||||
reg = <0x100 0x100>;
|
||||
mediatek,sysctl = <&sysc>;
|
||||
};
|
||||
|
@ -22,6 +22,7 @@ properties:
|
||||
- enum:
|
||||
- mediatek,mt2712-wdt
|
||||
- mediatek,mt6589-wdt
|
||||
- mediatek,mt6735-wdt
|
||||
- mediatek,mt6795-wdt
|
||||
- mediatek,mt7986-wdt
|
||||
- mediatek,mt8183-wdt
|
||||
@ -38,6 +39,7 @@ properties:
|
||||
- mediatek,mt7623-wdt
|
||||
- mediatek,mt7629-wdt
|
||||
- mediatek,mt8173-wdt
|
||||
- mediatek,mt8365-wdt
|
||||
- mediatek,mt8516-wdt
|
||||
- const: mediatek,mt6589-wdt
|
||||
|
||||
|
@ -18,7 +18,10 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,kpss-wdt-ipq4019
|
||||
- qcom,apss-wdt-ipq5332
|
||||
- qcom,apss-wdt-ipq9574
|
||||
- qcom,apss-wdt-msm8994
|
||||
- qcom,apss-wdt-qcm2290
|
||||
- qcom,apss-wdt-qcs404
|
||||
- qcom,apss-wdt-sa8775p
|
||||
- qcom,apss-wdt-sc7180
|
||||
@ -28,6 +31,7 @@ properties:
|
||||
- qcom,apss-wdt-sdm845
|
||||
- qcom,apss-wdt-sdx55
|
||||
- qcom,apss-wdt-sdx65
|
||||
- qcom,apss-wdt-sm6115
|
||||
- qcom,apss-wdt-sm6350
|
||||
- qcom,apss-wdt-sm8150
|
||||
- qcom,apss-wdt-sm8250
|
||||
@ -113,26 +117,26 @@ examples:
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
watchdog@17c10000 {
|
||||
compatible = "qcom,apss-wdt-sm8150", "qcom,kpss-wdt";
|
||||
reg = <0x17c10000 0x1000>;
|
||||
clocks = <&sleep_clk>;
|
||||
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
timeout-sec = <10>;
|
||||
compatible = "qcom,apss-wdt-sm8150", "qcom,kpss-wdt";
|
||||
reg = <0x17c10000 0x1000>;
|
||||
clocks = <&sleep_clk>;
|
||||
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
timeout-sec = <10>;
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
watchdog@200a000 {
|
||||
compatible = "qcom,kpss-wdt-ipq8064", "qcom,kpss-timer", "qcom,msm-timer";
|
||||
interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 5 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
|
||||
reg = <0x0200a000 0x100>;
|
||||
clock-frequency = <25000000>;
|
||||
clocks = <&sleep_clk>;
|
||||
clock-names = "sleep";
|
||||
cpu-offset = <0x80000>;
|
||||
compatible = "qcom,kpss-wdt-ipq8064", "qcom,kpss-timer", "qcom,msm-timer";
|
||||
interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>,
|
||||
<GIC_PPI 5 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
|
||||
reg = <0x0200a000 0x100>;
|
||||
clock-frequency = <25000000>;
|
||||
clocks = <&sleep_clk>;
|
||||
clock-names = "sleep";
|
||||
cpu-offset = <0x80000>;
|
||||
};
|
||||
|
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/watchdog/ralink,rt2880-wdt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Ralink Watchdog Timers
|
||||
|
||||
maintainers:
|
||||
- Sergio Paracuellos <sergio.paracuellos@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: watchdog.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ralink,rt2880-wdt
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
watchdog@100 {
|
||||
compatible = "ralink,rt2880-wdt";
|
||||
reg = <0x120 0x10>;
|
||||
clocks = <&clkref>;
|
||||
resets = <&rstctrl 8>;
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <1>;
|
||||
};
|
@ -67,12 +67,10 @@ required:
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
dependencies:
|
||||
interrupts: [ interrupt-names ]
|
||||
|
||||
examples:
|
||||
- |
|
||||
watchdog: watchdog@3150 {
|
||||
|
@ -177,11 +177,11 @@ examples:
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
wdt0: watchdog@e6020000 {
|
||||
compatible = "renesas,r8a7795-wdt", "renesas,rcar-gen3-wdt";
|
||||
reg = <0xe6020000 0x0c>;
|
||||
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 402>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 402>;
|
||||
timeout-sec = <60>;
|
||||
compatible = "renesas,r8a7795-wdt", "renesas,rcar-gen3-wdt";
|
||||
reg = <0xe6020000 0x0c>;
|
||||
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 402>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 402>;
|
||||
timeout-sec = <60>;
|
||||
};
|
||||
|
@ -1,18 +0,0 @@
|
||||
Ralink Watchdog Timers
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "ralink,rt2880-wdt"
|
||||
- reg: physical base address of the controller and length of the register range
|
||||
|
||||
Optional properties:
|
||||
- interrupts: Specify the INTC interrupt number
|
||||
|
||||
Example:
|
||||
|
||||
watchdog@120 {
|
||||
compatible = "ralink,rt2880-wdt";
|
||||
reg = <0x120 0x10>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <1>;
|
||||
};
|
@ -83,25 +83,25 @@ required:
|
||||
examples:
|
||||
- |
|
||||
watchdog@ffd02000 {
|
||||
compatible = "snps,dw-wdt";
|
||||
reg = <0xffd02000 0x1000>;
|
||||
interrupts = <0 171 4>;
|
||||
clocks = <&per_base_clk>;
|
||||
resets = <&wdt_rst>;
|
||||
compatible = "snps,dw-wdt";
|
||||
reg = <0xffd02000 0x1000>;
|
||||
interrupts = <0 171 4>;
|
||||
clocks = <&per_base_clk>;
|
||||
resets = <&wdt_rst>;
|
||||
};
|
||||
|
||||
- |
|
||||
watchdog@ffd02000 {
|
||||
compatible = "snps,dw-wdt";
|
||||
reg = <0xffd02000 0x1000>;
|
||||
interrupts = <0 171 4>;
|
||||
clocks = <&per_base_clk>;
|
||||
clock-names = "tclk";
|
||||
snps,watchdog-tops = <0x000000FF 0x000001FF 0x000003FF
|
||||
0x000007FF 0x0000FFFF 0x0001FFFF
|
||||
0x0003FFFF 0x0007FFFF 0x000FFFFF
|
||||
0x001FFFFF 0x003FFFFF 0x007FFFFF
|
||||
0x00FFFFFF 0x01FFFFFF 0x03FFFFFF
|
||||
0x07FFFFFF>;
|
||||
compatible = "snps,dw-wdt";
|
||||
reg = <0xffd02000 0x1000>;
|
||||
interrupts = <0 171 4>;
|
||||
clocks = <&per_base_clk>;
|
||||
clock-names = "tclk";
|
||||
snps,watchdog-tops = <0x000000FF 0x000001FF 0x000003FF
|
||||
0x000007FF 0x0000FFFF 0x0001FFFF
|
||||
0x0003FFFF 0x0007FFFF 0x000FFFFF
|
||||
0x001FFFFF 0x003FFFFF 0x007FFFFF
|
||||
0x00FFFFFF 0x01FFFFFF 0x03FFFFFF
|
||||
0x07FFFFFF>;
|
||||
};
|
||||
...
|
||||
|
@ -48,11 +48,11 @@ examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
watchdog@5a002000 {
|
||||
compatible = "st,stm32mp1-iwdg";
|
||||
reg = <0x5a002000 0x400>;
|
||||
clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
|
||||
clock-names = "pclk", "lsi";
|
||||
timeout-sec = <32>;
|
||||
compatible = "st,stm32mp1-iwdg";
|
||||
reg = <0x5a002000 0x400>;
|
||||
clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
|
||||
clock-names = "pclk", "lsi";
|
||||
timeout-sec = <32>;
|
||||
};
|
||||
|
||||
...
|
||||
|
@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/watchdog/starfive,jh7100-wdt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: StarFive Watchdog for JH7100 and JH7110 SoC
|
||||
|
||||
maintainers:
|
||||
- Xingyu Wu <xingyu.wu@starfivetech.com>
|
||||
- Samin Guo <samin.guo@starfivetech.com>
|
||||
|
||||
description:
|
||||
The JH7100 and JH7110 watchdog both are 32 bit counters. JH7100 watchdog
|
||||
has only one timeout phase and reboots. And JH7110 watchdog has two
|
||||
timeout phases. At the first phase, the signal of watchdog interrupt
|
||||
output(WDOGINT) will rise when counter is 0. The counter will reload
|
||||
the timeout value. And then, if counter decreases to 0 again and WDOGINT
|
||||
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
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: APB clock
|
||||
- description: Core clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
- const: core
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: APB reset
|
||||
- description: Core reset
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
watchdog@12480000 {
|
||||
compatible = "starfive,jh7100-wdt";
|
||||
reg = <0x12480000 0x10000>;
|
||||
clocks = <&clk 171>,
|
||||
<&clk 172>;
|
||||
clock-names = "apb", "core";
|
||||
resets = <&rst 99>,
|
||||
<&rst 100>;
|
||||
};
|
@ -24,14 +24,12 @@ properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
timeout-sec: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
@ -58,11 +58,11 @@ unevaluatedProperties: false
|
||||
examples:
|
||||
- |
|
||||
watchdog@40100000 {
|
||||
compatible = "xlnx,xps-timebase-wdt-1.00.a";
|
||||
reg = <0x40100000 0x1000>;
|
||||
clock-frequency = <50000000>;
|
||||
clocks = <&clkc 15>;
|
||||
xlnx,wdt-enable-once = <0x0>;
|
||||
xlnx,wdt-interval = <0x1b>;
|
||||
compatible = "xlnx,xps-timebase-wdt-1.00.a";
|
||||
reg = <0x40100000 0x1000>;
|
||||
clock-frequency = <50000000>;
|
||||
clocks = <&clkc 15>;
|
||||
xlnx,wdt-enable-once = <0x0>;
|
||||
xlnx,wdt-interval = <0x1b>;
|
||||
};
|
||||
...
|
||||
|
18
MAINTAINERS
18
MAINTAINERS
@ -20136,6 +20136,13 @@ S: Supported
|
||||
F: Documentation/devicetree/bindings/rng/starfive*
|
||||
F: drivers/char/hw_random/jh7110-trng.c
|
||||
|
||||
STARFIVE WATCHDOG DRIVER
|
||||
M: Xingyu Wu <xingyu.wu@starfivetech.com>
|
||||
M: Samin Guo <samin.guo@starfivetech.com>
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/watchdog/starfive*
|
||||
F: drivers/watchdog/starfive-wdt.c
|
||||
|
||||
STATIC BRANCH/CALL
|
||||
M: Peter Zijlstra <peterz@infradead.org>
|
||||
M: Josh Poimboeuf <jpoimboe@kernel.org>
|
||||
@ -22706,9 +22713,8 @@ S: Maintained
|
||||
F: drivers/media/rc/winbond-cir.c
|
||||
|
||||
WINSYSTEMS EBC-C384 WATCHDOG DRIVER
|
||||
M: William Breathitt Gray <william.gray@linaro.org>
|
||||
L: linux-watchdog@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/watchdog/ebc-c384_wdt.c
|
||||
|
||||
WINSYSTEMS WS16C48 GPIO DRIVER
|
||||
@ -23169,6 +23175,14 @@ F: Documentation/devicetree/bindings/media/xilinx/
|
||||
F: drivers/media/platform/xilinx/
|
||||
F: include/uapi/linux/xilinx-v4l2-controls.h
|
||||
|
||||
XILINX WATCHDOG DRIVER
|
||||
M: Srinivas Neeli <srinivas.neeli@amd.com>
|
||||
R: Shubhrajyoti Datta <shubhrajyoti.datta@amd.com>
|
||||
R: Michal Simek <michal.simek@amd.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/watchdog/xlnx,xps-timebase-wdt.yaml
|
||||
F: drivers/watchdog/of_xilinx_wdt.c
|
||||
|
||||
XILINX XDMA DRIVER
|
||||
M: Lizhi Hou <lizhi.hou@amd.com>
|
||||
M: Brian Xu <brian.xu@amd.com>
|
||||
|
@ -1999,6 +1999,17 @@ config WATCHDOG_RTAS
|
||||
To compile this driver as a module, choose M here. The module
|
||||
will be called wdrtas.
|
||||
|
||||
# RISC-V Architecture
|
||||
|
||||
config STARFIVE_WATCHDOG
|
||||
tristate "StarFive Watchdog support"
|
||||
depends on ARCH_STARFIVE || COMPILE_TEST
|
||||
select WATCHDOG_CORE
|
||||
default ARCH_STARFIVE
|
||||
help
|
||||
Say Y here to support the watchdog of StarFive JH7100 and JH7110
|
||||
SoC. This driver can also be built as a module if choose M.
|
||||
|
||||
# S390 Architecture
|
||||
|
||||
config DIAG288_WATCHDOG
|
||||
|
@ -192,6 +192,9 @@ obj-$(CONFIG_MEN_A21_WDT) += mena21_wdt.o
|
||||
obj-$(CONFIG_PSERIES_WDT) += pseries-wdt.o
|
||||
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
|
||||
|
||||
# RISC-V Architecture
|
||||
obj-$(CONFIG_STARFIVE_WATCHDOG) += starfive-wdt.o
|
||||
|
||||
# S390 Architecture
|
||||
obj-$(CONFIG_DIAG288_WATCHDOG) += diag288_wdt.o
|
||||
|
||||
|
@ -271,14 +271,12 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acq_remove(struct platform_device *dev)
|
||||
static void acq_remove(struct platform_device *dev)
|
||||
{
|
||||
misc_deregister(&acq_miscdev);
|
||||
release_region(wdt_start, 1);
|
||||
if (wdt_stop != wdt_start)
|
||||
release_region(wdt_stop, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acq_shutdown(struct platform_device *dev)
|
||||
@ -288,7 +286,7 @@ static void acq_shutdown(struct platform_device *dev)
|
||||
}
|
||||
|
||||
static struct platform_driver acquirewdt_driver = {
|
||||
.remove = acq_remove,
|
||||
.remove_new = acq_remove,
|
||||
.shutdown = acq_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
@ -279,14 +279,12 @@ unreg_stop:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int advwdt_remove(struct platform_device *dev)
|
||||
static void advwdt_remove(struct platform_device *dev)
|
||||
{
|
||||
misc_deregister(&advwdt_miscdev);
|
||||
release_region(wdt_start, 1);
|
||||
if (wdt_stop != wdt_start)
|
||||
release_region(wdt_stop, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void advwdt_shutdown(struct platform_device *dev)
|
||||
@ -296,7 +294,7 @@ static void advwdt_shutdown(struct platform_device *dev)
|
||||
}
|
||||
|
||||
static struct platform_driver advwdt_driver = {
|
||||
.remove = advwdt_remove,
|
||||
.remove_new = advwdt_remove,
|
||||
.shutdown = advwdt_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
@ -290,12 +290,11 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ar7_wdt_remove(struct platform_device *pdev)
|
||||
static void ar7_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
misc_deregister(&ar7_wdt_miscdev);
|
||||
clk_put(vbus_clk);
|
||||
vbus_clk = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar7_wdt_shutdown(struct platform_device *pdev)
|
||||
@ -306,7 +305,7 @@ static void ar7_wdt_shutdown(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver ar7_wdt_driver = {
|
||||
.probe = ar7_wdt_probe,
|
||||
.remove = ar7_wdt_remove,
|
||||
.remove_new = ar7_wdt_remove,
|
||||
.shutdown = ar7_wdt_shutdown,
|
||||
.driver = {
|
||||
.name = "ar7_wdt",
|
||||
|
@ -465,7 +465,7 @@ static struct platform_driver aspeed_watchdog_driver = {
|
||||
.probe = aspeed_wdt_probe,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = of_match_ptr(aspeed_wdt_of_table),
|
||||
.of_match_table = aspeed_wdt_of_table,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -258,7 +258,7 @@ static int at91wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int at91wdt_remove(struct platform_device *pdev)
|
||||
static void at91wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int res;
|
||||
@ -269,8 +269,6 @@ static int at91wdt_remove(struct platform_device *pdev)
|
||||
|
||||
misc_deregister(&at91wdt_miscdev);
|
||||
at91wdt_miscdev.parent = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void at91wdt_shutdown(struct platform_device *pdev)
|
||||
@ -299,7 +297,7 @@ MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
|
||||
|
||||
static struct platform_driver at91wdt_driver = {
|
||||
.probe = at91wdt_probe,
|
||||
.remove = at91wdt_remove,
|
||||
.remove_new = at91wdt_remove,
|
||||
.shutdown = at91wdt_shutdown,
|
||||
.suspend = pm_ptr(at91wdt_suspend),
|
||||
.resume = pm_ptr(at91wdt_resume),
|
||||
|
@ -296,11 +296,10 @@ err_clk_disable:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ath79_wdt_remove(struct platform_device *pdev)
|
||||
static void ath79_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
misc_deregister(&ath79_wdt_miscdev);
|
||||
clk_disable_unprepare(wdt_clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath79_wdt_shutdown(struct platform_device *pdev)
|
||||
@ -318,7 +317,7 @@ MODULE_DEVICE_TABLE(of, ath79_wdt_match);
|
||||
|
||||
static struct platform_driver ath79_wdt_driver = {
|
||||
.probe = ath79_wdt_probe,
|
||||
.remove = ath79_wdt_remove,
|
||||
.remove_new = ath79_wdt_remove,
|
||||
.shutdown = ath79_wdt_shutdown,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
|
@ -218,17 +218,15 @@ static int bcm2835_wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835_wdt_remove(struct platform_device *pdev)
|
||||
static void bcm2835_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (pm_power_off == bcm2835_power_off)
|
||||
pm_power_off = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver bcm2835_wdt_driver = {
|
||||
.probe = bcm2835_wdt_probe,
|
||||
.remove = bcm2835_wdt_remove,
|
||||
.remove_new = bcm2835_wdt_remove,
|
||||
.driver = {
|
||||
.name = "bcm2835-wdt",
|
||||
},
|
||||
|
@ -202,7 +202,7 @@ static int bcm47xx_wdt_probe(struct platform_device *pdev)
|
||||
watchdog_set_restart_priority(&wdt->wdd, 64);
|
||||
watchdog_stop_on_reboot(&wdt->wdd);
|
||||
|
||||
ret = watchdog_register_device(&wdt->wdd);
|
||||
ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdd);
|
||||
if (ret)
|
||||
goto err_timer;
|
||||
|
||||
@ -218,21 +218,11 @@ err_timer:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bcm47xx_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct bcm47xx_wdt *wdt = dev_get_platdata(&pdev->dev);
|
||||
|
||||
watchdog_unregister_device(&wdt->wdd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver bcm47xx_wdt_driver = {
|
||||
.driver = {
|
||||
.name = "bcm47xx-wdt",
|
||||
},
|
||||
.probe = bcm47xx_wdt_probe,
|
||||
.remove = bcm47xx_wdt_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(bcm47xx_wdt_driver);
|
||||
|
@ -310,12 +310,10 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm_kona_wdt_remove(struct platform_device *pdev)
|
||||
static void bcm_kona_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
bcm_kona_wdt_debug_exit(pdev);
|
||||
dev_dbg(&pdev->dev, "Watchdog driver disabled");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm_kona_wdt_of_match[] = {
|
||||
@ -330,7 +328,7 @@ static struct platform_driver bcm_kona_wdt_driver = {
|
||||
.of_match_table = bcm_kona_wdt_of_match,
|
||||
},
|
||||
.probe = bcm_kona_wdt_probe,
|
||||
.remove = bcm_kona_wdt_remove,
|
||||
.remove_new = bcm_kona_wdt_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(bcm_kona_wdt_driver);
|
||||
|
@ -614,7 +614,7 @@ out_iounmap:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cpwd_remove(struct platform_device *op)
|
||||
static void cpwd_remove(struct platform_device *op)
|
||||
{
|
||||
struct cpwd *p = platform_get_drvdata(op);
|
||||
int i;
|
||||
@ -638,8 +638,6 @@ static int cpwd_remove(struct platform_device *op)
|
||||
of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ);
|
||||
|
||||
cpwd_device = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id cpwd_match[] = {
|
||||
@ -656,7 +654,7 @@ static struct platform_driver cpwd_driver = {
|
||||
.of_match_table = cpwd_match,
|
||||
},
|
||||
.probe = cpwd_probe,
|
||||
.remove = cpwd_remove,
|
||||
.remove_new = cpwd_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(cpwd_driver);
|
||||
|
@ -566,22 +566,16 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
|
||||
* to the common timer/bus clocks configuration, in which the very
|
||||
* first found clock supply both timer and APB signals.
|
||||
*/
|
||||
dw_wdt->clk = devm_clk_get(dev, "tclk");
|
||||
dw_wdt->clk = devm_clk_get_enabled(dev, "tclk");
|
||||
if (IS_ERR(dw_wdt->clk)) {
|
||||
dw_wdt->clk = devm_clk_get(dev, NULL);
|
||||
dw_wdt->clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(dw_wdt->clk))
|
||||
return PTR_ERR(dw_wdt->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dw_wdt->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dw_wdt->rate = clk_get_rate(dw_wdt->clk);
|
||||
if (dw_wdt->rate == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_disable_clk;
|
||||
}
|
||||
if (dw_wdt->rate == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Request APB clock if device is configured with async clocks mode.
|
||||
@ -590,21 +584,13 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
|
||||
* so the pclk phandle reference is left optional. If it couldn't be
|
||||
* found we consider the device configured in synchronous clocks mode.
|
||||
*/
|
||||
dw_wdt->pclk = devm_clk_get_optional(dev, "pclk");
|
||||
if (IS_ERR(dw_wdt->pclk)) {
|
||||
ret = PTR_ERR(dw_wdt->pclk);
|
||||
goto out_disable_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dw_wdt->pclk);
|
||||
if (ret)
|
||||
goto out_disable_clk;
|
||||
dw_wdt->pclk = devm_clk_get_optional_enabled(dev, "pclk");
|
||||
if (IS_ERR(dw_wdt->pclk))
|
||||
return PTR_ERR(dw_wdt->pclk);
|
||||
|
||||
dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
|
||||
if (IS_ERR(dw_wdt->rst)) {
|
||||
ret = PTR_ERR(dw_wdt->rst);
|
||||
goto out_disable_pclk;
|
||||
}
|
||||
if (IS_ERR(dw_wdt->rst))
|
||||
return PTR_ERR(dw_wdt->rst);
|
||||
|
||||
/* Enable normal reset without pre-timeout by default. */
|
||||
dw_wdt_update_mode(dw_wdt, DW_WDT_RMOD_RESET);
|
||||
@ -621,12 +607,12 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
|
||||
IRQF_SHARED | IRQF_TRIGGER_RISING,
|
||||
pdev->name, dw_wdt);
|
||||
if (ret)
|
||||
goto out_disable_pclk;
|
||||
return ret;
|
||||
|
||||
dw_wdt->wdd.info = &dw_wdt_pt_ident;
|
||||
} else {
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto out_disable_pclk;
|
||||
return ret;
|
||||
|
||||
dw_wdt->wdd.info = &dw_wdt_ident;
|
||||
}
|
||||
@ -635,7 +621,7 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
|
||||
|
||||
ret = dw_wdt_init_timeouts(dw_wdt, dev);
|
||||
if (ret)
|
||||
goto out_disable_clk;
|
||||
goto out_assert_rst;
|
||||
|
||||
wdd = &dw_wdt->wdd;
|
||||
wdd->ops = &dw_wdt_ops;
|
||||
@ -667,21 +653,18 @@ static int dw_wdt_drv_probe(struct platform_device *pdev)
|
||||
|
||||
ret = watchdog_register_device(wdd);
|
||||
if (ret)
|
||||
goto out_disable_pclk;
|
||||
goto out_assert_rst;
|
||||
|
||||
dw_wdt_dbgfs_init(dw_wdt);
|
||||
|
||||
return 0;
|
||||
|
||||
out_disable_pclk:
|
||||
clk_disable_unprepare(dw_wdt->pclk);
|
||||
|
||||
out_disable_clk:
|
||||
clk_disable_unprepare(dw_wdt->clk);
|
||||
out_assert_rst:
|
||||
reset_control_assert(dw_wdt->rst);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dw_wdt_drv_remove(struct platform_device *pdev)
|
||||
static void dw_wdt_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dw_wdt *dw_wdt = platform_get_drvdata(pdev);
|
||||
|
||||
@ -689,10 +672,6 @@ static int dw_wdt_drv_remove(struct platform_device *pdev)
|
||||
|
||||
watchdog_unregister_device(&dw_wdt->wdd);
|
||||
reset_control_assert(dw_wdt->rst);
|
||||
clk_disable_unprepare(dw_wdt->pclk);
|
||||
clk_disable_unprepare(dw_wdt->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
@ -705,7 +684,7 @@ MODULE_DEVICE_TABLE(of, dw_wdt_of_match);
|
||||
|
||||
static struct platform_driver dw_wdt_driver = {
|
||||
.probe = dw_wdt_drv_probe,
|
||||
.remove = dw_wdt_drv_remove,
|
||||
.remove_new = dw_wdt_drv_remove,
|
||||
.driver = {
|
||||
.name = "dw_wdt",
|
||||
.of_match_table = of_match_ptr(dw_wdt_of_match),
|
||||
|
@ -283,15 +283,13 @@ static int gef_wdt_probe(struct platform_device *dev)
|
||||
return misc_register(&gef_wdt_miscdev);
|
||||
}
|
||||
|
||||
static int gef_wdt_remove(struct platform_device *dev)
|
||||
static void gef_wdt_remove(struct platform_device *dev)
|
||||
{
|
||||
misc_deregister(&gef_wdt_miscdev);
|
||||
|
||||
gef_wdt_handler_disable();
|
||||
|
||||
iounmap(gef_wdt_regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id gef_wdt_ids[] = {
|
||||
@ -308,7 +306,7 @@ static struct platform_driver gef_wdt_driver = {
|
||||
.of_match_table = gef_wdt_ids,
|
||||
},
|
||||
.probe = gef_wdt_probe,
|
||||
.remove = gef_wdt_remove,
|
||||
.remove_new = gef_wdt_remove,
|
||||
};
|
||||
|
||||
static int __init gef_wdt_init(void)
|
||||
|
@ -238,10 +238,9 @@ static int __init geodewdt_probe(struct platform_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int geodewdt_remove(struct platform_device *dev)
|
||||
static void geodewdt_remove(struct platform_device *dev)
|
||||
{
|
||||
misc_deregister(&geodewdt_miscdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void geodewdt_shutdown(struct platform_device *dev)
|
||||
@ -250,7 +249,7 @@ static void geodewdt_shutdown(struct platform_device *dev)
|
||||
}
|
||||
|
||||
static struct platform_driver geodewdt_driver = {
|
||||
.remove = geodewdt_remove,
|
||||
.remove_new = geodewdt_remove,
|
||||
.shutdown = geodewdt_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
@ -316,14 +316,13 @@ out_nostopreg:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ibwdt_remove(struct platform_device *dev)
|
||||
static void ibwdt_remove(struct platform_device *dev)
|
||||
{
|
||||
misc_deregister(&ibwdt_miscdev);
|
||||
release_region(WDT_START, 1);
|
||||
#if WDT_START != WDT_STOP
|
||||
release_region(WDT_STOP, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ibwdt_shutdown(struct platform_device *dev)
|
||||
@ -333,7 +332,7 @@ static void ibwdt_shutdown(struct platform_device *dev)
|
||||
}
|
||||
|
||||
static struct platform_driver ibwdt_driver = {
|
||||
.remove = ibwdt_remove,
|
||||
.remove_new = ibwdt_remove,
|
||||
.shutdown = ibwdt_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
@ -266,7 +266,7 @@ misc_register_error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ie6xx_wdt_remove(struct platform_device *pdev)
|
||||
static void ie6xx_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
|
||||
@ -276,13 +276,11 @@ static int ie6xx_wdt_remove(struct platform_device *pdev)
|
||||
ie6xx_wdt_debugfs_exit();
|
||||
release_region(res->start, resource_size(res));
|
||||
ie6xx_wdt_data.sch_wdtba = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ie6xx_wdt_driver = {
|
||||
.probe = ie6xx_wdt_probe,
|
||||
.remove = ie6xx_wdt_remove,
|
||||
.remove_new = ie6xx_wdt_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
},
|
||||
|
@ -439,11 +439,11 @@ static int __maybe_unused imx2_wdt_resume(struct device *dev)
|
||||
static SIMPLE_DEV_PM_OPS(imx2_wdt_pm_ops, imx2_wdt_suspend,
|
||||
imx2_wdt_resume);
|
||||
|
||||
struct imx2_wdt_data imx_wdt = {
|
||||
static struct imx2_wdt_data imx_wdt = {
|
||||
.wdw_supported = true,
|
||||
};
|
||||
|
||||
struct imx2_wdt_data imx_wdt_legacy = {
|
||||
static struct imx2_wdt_data imx_wdt_legacy = {
|
||||
.wdw_supported = false,
|
||||
};
|
||||
|
||||
|
@ -112,12 +112,6 @@ static const struct watchdog_info ixp4xx_wdt_info = {
|
||||
.identity = KBUILD_MODNAME,
|
||||
};
|
||||
|
||||
/* Devres-handled clock disablement */
|
||||
static void ixp4xx_clock_action(void *d)
|
||||
{
|
||||
clk_disable_unprepare(d);
|
||||
}
|
||||
|
||||
static int ixp4xx_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -139,16 +133,10 @@ static int ixp4xx_wdt_probe(struct platform_device *pdev)
|
||||
* Retrieve rate from a fixed clock from the device tree if
|
||||
* the parent has that, else use the default clock rate.
|
||||
*/
|
||||
clk = devm_clk_get(dev->parent, NULL);
|
||||
if (!IS_ERR(clk)) {
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = devm_add_action_or_reset(dev, ixp4xx_clock_action, clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
clk = devm_clk_get_enabled(dev->parent, NULL);
|
||||
if (!IS_ERR(clk))
|
||||
iwdt->rate = clk_get_rate(clk);
|
||||
}
|
||||
|
||||
if (!iwdt->rate)
|
||||
iwdt->rate = IXP4XX_TIMER_FREQ;
|
||||
|
||||
|
@ -7,7 +7,11 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include <loongson1.h>
|
||||
|
||||
/* Loongson 1 Watchdog Register Definitions */
|
||||
#define WDT_EN 0x0
|
||||
#define WDT_TIMER 0x4
|
||||
#define WDT_SET 0x8
|
||||
|
||||
#define DEFAULT_HEARTBEAT 30
|
||||
|
||||
@ -66,6 +70,18 @@ static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ls1x_wdt_restart(struct watchdog_device *wdt_dev,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
|
||||
|
||||
writel(0x1, drvdata->base + WDT_EN);
|
||||
writel(0x1, drvdata->base + WDT_TIMER);
|
||||
writel(0x1, drvdata->base + WDT_SET);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct watchdog_info ls1x_wdt_info = {
|
||||
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
|
||||
.identity = "Loongson1 Watchdog",
|
||||
@ -77,13 +93,9 @@ static const struct watchdog_ops ls1x_wdt_ops = {
|
||||
.stop = ls1x_wdt_stop,
|
||||
.ping = ls1x_wdt_ping,
|
||||
.set_timeout = ls1x_wdt_set_timeout,
|
||||
.restart = ls1x_wdt_restart,
|
||||
};
|
||||
|
||||
static void ls1x_clk_disable_unprepare(void *data)
|
||||
{
|
||||
clk_disable_unprepare(data);
|
||||
}
|
||||
|
||||
static int ls1x_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -100,20 +112,10 @@ static int ls1x_wdt_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(drvdata->base))
|
||||
return PTR_ERR(drvdata->base);
|
||||
|
||||
drvdata->clk = devm_clk_get(dev, pdev->name);
|
||||
drvdata->clk = devm_clk_get_enabled(dev, pdev->name);
|
||||
if (IS_ERR(drvdata->clk))
|
||||
return PTR_ERR(drvdata->clk);
|
||||
|
||||
err = clk_prepare_enable(drvdata->clk);
|
||||
if (err) {
|
||||
dev_err(dev, "clk enable failed\n");
|
||||
return err;
|
||||
}
|
||||
err = devm_add_action_or_reset(dev, ls1x_clk_disable_unprepare,
|
||||
drvdata->clk);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
clk_rate = clk_get_rate(drvdata->clk);
|
||||
if (!clk_rate)
|
||||
return -EINVAL;
|
||||
|
@ -261,14 +261,12 @@ static int lpc18xx_wdt_probe(struct platform_device *pdev)
|
||||
return devm_watchdog_register_device(dev, &lpc18xx_wdt->wdt_dev);
|
||||
}
|
||||
|
||||
static int lpc18xx_wdt_remove(struct platform_device *pdev)
|
||||
static void lpc18xx_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev);
|
||||
|
||||
dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n");
|
||||
del_timer_sync(&lpc18xx_wdt->timer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id lpc18xx_wdt_match[] = {
|
||||
@ -283,7 +281,7 @@ static struct platform_driver lpc18xx_wdt_driver = {
|
||||
.of_match_table = lpc18xx_wdt_match,
|
||||
},
|
||||
.probe = lpc18xx_wdt_probe,
|
||||
.remove = lpc18xx_wdt_remove,
|
||||
.remove_new = lpc18xx_wdt_remove,
|
||||
};
|
||||
module_platform_driver(lpc18xx_wdt_driver);
|
||||
|
||||
|
@ -77,7 +77,7 @@ static int men_z069_wdt_set_timeout(struct watchdog_device *wdt,
|
||||
wdt->timeout = timeout;
|
||||
val = timeout * MEN_Z069_TIMER_FREQ;
|
||||
|
||||
reg = readw(drv->base + MEN_Z069_WVR);
|
||||
reg = readw(drv->base + MEN_Z069_WTR);
|
||||
ena = reg & MEN_Z069_WTR_WDEN;
|
||||
reg = ena | val;
|
||||
writew(reg, drv->base + MEN_Z069_WTR);
|
||||
@ -98,14 +98,6 @@ static const struct watchdog_ops men_z069_ops = {
|
||||
.set_timeout = men_z069_wdt_set_timeout,
|
||||
};
|
||||
|
||||
static struct watchdog_device men_z069_wdt = {
|
||||
.info = &men_z069_info,
|
||||
.ops = &men_z069_ops,
|
||||
.timeout = MEN_Z069_DEFAULT_TIMEOUT,
|
||||
.min_timeout = 1,
|
||||
.max_timeout = MEN_Z069_WDT_COUNTER_MAX / MEN_Z069_TIMER_FREQ,
|
||||
};
|
||||
|
||||
static int men_z069_probe(struct mcb_device *dev,
|
||||
const struct mcb_device_id *id)
|
||||
{
|
||||
@ -125,15 +117,19 @@ static int men_z069_probe(struct mcb_device *dev,
|
||||
goto release_mem;
|
||||
|
||||
drv->mem = mem;
|
||||
drv->wdt.info = &men_z069_info;
|
||||
drv->wdt.ops = &men_z069_ops;
|
||||
drv->wdt.timeout = MEN_Z069_DEFAULT_TIMEOUT;
|
||||
drv->wdt.min_timeout = 1;
|
||||
drv->wdt.max_timeout = MEN_Z069_WDT_COUNTER_MAX / MEN_Z069_TIMER_FREQ;
|
||||
|
||||
drv->wdt = men_z069_wdt;
|
||||
watchdog_init_timeout(&drv->wdt, 0, &dev->dev);
|
||||
watchdog_set_nowayout(&drv->wdt, nowayout);
|
||||
watchdog_set_drvdata(&drv->wdt, drv);
|
||||
drv->wdt.parent = &dev->dev;
|
||||
mcb_set_drvdata(dev, drv);
|
||||
|
||||
return watchdog_register_device(&men_z069_wdt);
|
||||
return watchdog_register_device(&drv->wdt);
|
||||
|
||||
release_mem:
|
||||
mcb_release_mem(mem);
|
||||
|
@ -221,7 +221,7 @@ static int mtx1_wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtx1_wdt_remove(struct platform_device *pdev)
|
||||
static void mtx1_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
/* FIXME: do we need to lock this test ? */
|
||||
if (mtx1_wdt_device.queue) {
|
||||
@ -230,12 +230,11 @@ static int mtx1_wdt_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
misc_deregister(&mtx1_wdt_misc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mtx1_wdt_driver = {
|
||||
.probe = mtx1_wdt_probe,
|
||||
.remove = mtx1_wdt_remove,
|
||||
.remove_new = mtx1_wdt_remove,
|
||||
.driver.name = "mtx1-wdt",
|
||||
.driver.owner = THIS_MODULE,
|
||||
};
|
||||
|
@ -218,7 +218,7 @@ static int nic7018_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nic7018_remove(struct platform_device *pdev)
|
||||
static void nic7018_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct nic7018_wdt *wdt = platform_get_drvdata(pdev);
|
||||
|
||||
@ -226,8 +226,6 @@ static int nic7018_remove(struct platform_device *pdev)
|
||||
|
||||
/* Lock WDT register */
|
||||
outb(LOCK, wdt->io_base + WDT_REG_LOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct acpi_device_id nic7018_device_ids[] = {
|
||||
@ -238,7 +236,7 @@ MODULE_DEVICE_TABLE(acpi, nic7018_device_ids);
|
||||
|
||||
static struct platform_driver watchdog_driver = {
|
||||
.probe = nic7018_probe,
|
||||
.remove = nic7018_remove,
|
||||
.remove_new = nic7018_remove,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.acpi_match_table = ACPI_PTR(nic7018_device_ids),
|
||||
|
@ -446,12 +446,10 @@ static void nv_tco_cleanup(void)
|
||||
release_region(tcobase, 0x10);
|
||||
}
|
||||
|
||||
static int nv_tco_remove(struct platform_device *dev)
|
||||
static void nv_tco_remove(struct platform_device *dev)
|
||||
{
|
||||
if (tcobase)
|
||||
nv_tco_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nv_tco_shutdown(struct platform_device *dev)
|
||||
@ -469,7 +467,7 @@ static void nv_tco_shutdown(struct platform_device *dev)
|
||||
|
||||
static struct platform_driver nv_tco_driver = {
|
||||
.probe = nv_tco_init,
|
||||
.remove = nv_tco_remove,
|
||||
.remove_new = nv_tco_remove,
|
||||
.shutdown = nv_tco_shutdown,
|
||||
.driver = {
|
||||
.name = TCO_MODULE_NAME,
|
||||
|
@ -306,14 +306,12 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
|
||||
mutex_unlock(&wdev->lock);
|
||||
}
|
||||
|
||||
static int omap_wdt_remove(struct platform_device *pdev)
|
||||
static void omap_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(wdev->dev);
|
||||
watchdog_unregister_device(&wdev->wdog);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* REVISIT ... not clear this is the best way to handle system suspend; and
|
||||
@ -359,7 +357,7 @@ MODULE_DEVICE_TABLE(of, omap_wdt_of_match);
|
||||
|
||||
static struct platform_driver omap_wdt_driver = {
|
||||
.probe = omap_wdt_probe,
|
||||
.remove = omap_wdt_remove,
|
||||
.remove_new = omap_wdt_remove,
|
||||
.shutdown = omap_wdt_shutdown,
|
||||
.suspend = pm_ptr(omap_wdt_suspend),
|
||||
.resume = pm_ptr(omap_wdt_resume),
|
||||
|
@ -649,7 +649,7 @@ disable_clk:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int orion_wdt_remove(struct platform_device *pdev)
|
||||
static void orion_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct watchdog_device *wdt_dev = platform_get_drvdata(pdev);
|
||||
struct orion_watchdog *dev = watchdog_get_drvdata(wdt_dev);
|
||||
@ -657,7 +657,6 @@ static int orion_wdt_remove(struct platform_device *pdev)
|
||||
watchdog_unregister_device(wdt_dev);
|
||||
clk_disable_unprepare(dev->clk);
|
||||
clk_put(dev->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void orion_wdt_shutdown(struct platform_device *pdev)
|
||||
@ -668,7 +667,7 @@ static void orion_wdt_shutdown(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver orion_wdt_driver = {
|
||||
.probe = orion_wdt_probe,
|
||||
.remove = orion_wdt_remove,
|
||||
.remove_new = orion_wdt_remove,
|
||||
.shutdown = orion_wdt_shutdown,
|
||||
.driver = {
|
||||
.name = "orion_wdt",
|
||||
|
@ -298,10 +298,9 @@ static int rc32434_wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rc32434_wdt_remove(struct platform_device *pdev)
|
||||
static void rc32434_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
misc_deregister(&rc32434_wdt_miscdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rc32434_wdt_shutdown(struct platform_device *pdev)
|
||||
@ -311,7 +310,7 @@ static void rc32434_wdt_shutdown(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver rc32434_wdt_driver = {
|
||||
.probe = rc32434_wdt_probe,
|
||||
.remove = rc32434_wdt_remove,
|
||||
.remove_new = rc32434_wdt_remove,
|
||||
.shutdown = rc32434_wdt_shutdown,
|
||||
.driver = {
|
||||
.name = "rc32434_wdt",
|
||||
|
@ -257,7 +257,7 @@ static int rdc321x_wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdc321x_wdt_remove(struct platform_device *pdev)
|
||||
static void rdc321x_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (rdc321x_wdt_device.queue) {
|
||||
rdc321x_wdt_device.queue = 0;
|
||||
@ -265,13 +265,11 @@ static int rdc321x_wdt_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
misc_deregister(&rdc321x_wdt_misc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver rdc321x_wdt_driver = {
|
||||
.probe = rdc321x_wdt_probe,
|
||||
.remove = rdc321x_wdt_remove,
|
||||
.remove_new = rdc321x_wdt_remove,
|
||||
.driver = {
|
||||
.name = "rdc321x-wdt",
|
||||
},
|
||||
|
@ -292,14 +292,12 @@ static int rwdt_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rwdt_remove(struct platform_device *pdev)
|
||||
static void rwdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rwdt_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
watchdog_unregister_device(&priv->wdev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rwdt_suspend(struct device *dev)
|
||||
@ -339,7 +337,7 @@ static struct platform_driver rwdt_driver = {
|
||||
.pm = &rwdt_pm_ops,
|
||||
},
|
||||
.probe = rwdt_probe,
|
||||
.remove = rwdt_remove,
|
||||
.remove_new = rwdt_remove,
|
||||
};
|
||||
module_platform_driver(rwdt_driver);
|
||||
|
||||
|
@ -217,14 +217,12 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int riowd_remove(struct platform_device *op)
|
||||
static void riowd_remove(struct platform_device *op)
|
||||
{
|
||||
struct riowd *p = platform_get_drvdata(op);
|
||||
|
||||
misc_deregister(&riowd_miscdev);
|
||||
of_iounmap(&op->resource[0], p->regs, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id riowd_match[] = {
|
||||
@ -241,7 +239,7 @@ static struct platform_driver riowd_driver = {
|
||||
.of_match_table = riowd_match,
|
||||
},
|
||||
.probe = riowd_probe,
|
||||
.remove = riowd_remove,
|
||||
.remove_new = riowd_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(riowd_driver);
|
||||
|
@ -178,21 +178,11 @@ static int rn5t618_wdt_probe(struct platform_device *pdev)
|
||||
|
||||
platform_set_drvdata(pdev, wdt);
|
||||
|
||||
return watchdog_register_device(&wdt->wdt_dev);
|
||||
}
|
||||
|
||||
static int rn5t618_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rn5t618_wdt *wdt = platform_get_drvdata(pdev);
|
||||
|
||||
watchdog_unregister_device(&wdt->wdt_dev);
|
||||
|
||||
return 0;
|
||||
return devm_watchdog_register_device(dev, &wdt->wdt_dev);
|
||||
}
|
||||
|
||||
static struct platform_driver rn5t618_wdt_driver = {
|
||||
.probe = rn5t618_wdt_probe,
|
||||
.remove = rn5t618_wdt_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
},
|
||||
|
@ -40,10 +40,13 @@
|
||||
#define TMR1CTL_PRESCALE_MASK 0xf
|
||||
#define TMR1CTL_PRESCALE_65536 0xf
|
||||
|
||||
static struct clk *rt288x_wdt_clk;
|
||||
static unsigned long rt288x_wdt_freq;
|
||||
static void __iomem *rt288x_wdt_base;
|
||||
static struct reset_control *rt288x_wdt_reset;
|
||||
struct rt2880_wdt_data {
|
||||
void __iomem *base;
|
||||
unsigned long freq;
|
||||
struct clk *clk;
|
||||
struct reset_control *rst;
|
||||
struct watchdog_device wdt;
|
||||
};
|
||||
|
||||
static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
module_param(nowayout, bool, 0);
|
||||
@ -51,52 +54,56 @@ MODULE_PARM_DESC(nowayout,
|
||||
"Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
static inline void rt_wdt_w32(unsigned reg, u32 val)
|
||||
static inline void rt_wdt_w32(void __iomem *base, unsigned int reg, u32 val)
|
||||
{
|
||||
iowrite32(val, rt288x_wdt_base + reg);
|
||||
iowrite32(val, base + reg);
|
||||
}
|
||||
|
||||
static inline u32 rt_wdt_r32(unsigned reg)
|
||||
static inline u32 rt_wdt_r32(void __iomem *base, unsigned int reg)
|
||||
{
|
||||
return ioread32(rt288x_wdt_base + reg);
|
||||
return ioread32(base + reg);
|
||||
}
|
||||
|
||||
static int rt288x_wdt_ping(struct watchdog_device *w)
|
||||
{
|
||||
rt_wdt_w32(TIMER_REG_TMR1LOAD, w->timeout * rt288x_wdt_freq);
|
||||
struct rt2880_wdt_data *drvdata = watchdog_get_drvdata(w);
|
||||
|
||||
rt_wdt_w32(drvdata->base, TIMER_REG_TMR1LOAD, w->timeout * drvdata->freq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt288x_wdt_start(struct watchdog_device *w)
|
||||
{
|
||||
struct rt2880_wdt_data *drvdata = watchdog_get_drvdata(w);
|
||||
u32 t;
|
||||
|
||||
t = rt_wdt_r32(TIMER_REG_TMR1CTL);
|
||||
t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL);
|
||||
t &= ~(TMR1CTL_MODE_MASK << TMR1CTL_MODE_SHIFT |
|
||||
TMR1CTL_PRESCALE_MASK);
|
||||
t |= (TMR1CTL_MODE_WDT << TMR1CTL_MODE_SHIFT |
|
||||
TMR1CTL_PRESCALE_65536);
|
||||
rt_wdt_w32(TIMER_REG_TMR1CTL, t);
|
||||
rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t);
|
||||
|
||||
rt288x_wdt_ping(w);
|
||||
|
||||
t = rt_wdt_r32(TIMER_REG_TMR1CTL);
|
||||
t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL);
|
||||
t |= TMR1CTL_ENABLE;
|
||||
rt_wdt_w32(TIMER_REG_TMR1CTL, t);
|
||||
rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt288x_wdt_stop(struct watchdog_device *w)
|
||||
{
|
||||
struct rt2880_wdt_data *drvdata = watchdog_get_drvdata(w);
|
||||
u32 t;
|
||||
|
||||
rt288x_wdt_ping(w);
|
||||
|
||||
t = rt_wdt_r32(TIMER_REG_TMR1CTL);
|
||||
t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL);
|
||||
t &= ~TMR1CTL_ENABLE;
|
||||
rt_wdt_w32(TIMER_REG_TMR1CTL, t);
|
||||
rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -130,41 +137,45 @@ static const struct watchdog_ops rt288x_wdt_ops = {
|
||||
.set_timeout = rt288x_wdt_set_timeout,
|
||||
};
|
||||
|
||||
static struct watchdog_device rt288x_wdt_dev = {
|
||||
.info = &rt288x_wdt_info,
|
||||
.ops = &rt288x_wdt_ops,
|
||||
.min_timeout = 1,
|
||||
};
|
||||
|
||||
static int rt288x_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct watchdog_device *wdt;
|
||||
struct rt2880_wdt_data *drvdata;
|
||||
int ret;
|
||||
|
||||
rt288x_wdt_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(rt288x_wdt_base))
|
||||
return PTR_ERR(rt288x_wdt_base);
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
rt288x_wdt_clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(rt288x_wdt_clk))
|
||||
return PTR_ERR(rt288x_wdt_clk);
|
||||
drvdata->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(drvdata->base))
|
||||
return PTR_ERR(drvdata->base);
|
||||
|
||||
rt288x_wdt_reset = devm_reset_control_get_exclusive(dev, NULL);
|
||||
if (!IS_ERR(rt288x_wdt_reset))
|
||||
reset_control_deassert(rt288x_wdt_reset);
|
||||
drvdata->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(drvdata->clk))
|
||||
return PTR_ERR(drvdata->clk);
|
||||
|
||||
rt288x_wdt_freq = clk_get_rate(rt288x_wdt_clk) / RALINK_WDT_PRESCALE;
|
||||
drvdata->rst = devm_reset_control_get_exclusive(dev, NULL);
|
||||
if (!IS_ERR(drvdata->rst))
|
||||
reset_control_deassert(drvdata->rst);
|
||||
|
||||
rt288x_wdt_dev.bootstatus = rt288x_wdt_bootcause();
|
||||
rt288x_wdt_dev.max_timeout = (0xfffful / rt288x_wdt_freq);
|
||||
rt288x_wdt_dev.parent = dev;
|
||||
drvdata->freq = clk_get_rate(drvdata->clk) / RALINK_WDT_PRESCALE;
|
||||
|
||||
watchdog_init_timeout(&rt288x_wdt_dev, rt288x_wdt_dev.max_timeout,
|
||||
dev);
|
||||
watchdog_set_nowayout(&rt288x_wdt_dev, nowayout);
|
||||
wdt = &drvdata->wdt;
|
||||
wdt->info = &rt288x_wdt_info;
|
||||
wdt->ops = &rt288x_wdt_ops;
|
||||
wdt->min_timeout = 1;
|
||||
wdt->max_timeout = (0xfffful / drvdata->freq);
|
||||
wdt->parent = dev;
|
||||
wdt->bootstatus = rt288x_wdt_bootcause();
|
||||
|
||||
watchdog_stop_on_reboot(&rt288x_wdt_dev);
|
||||
ret = devm_watchdog_register_device(dev, &rt288x_wdt_dev);
|
||||
watchdog_init_timeout(wdt, wdt->max_timeout, dev);
|
||||
watchdog_set_nowayout(wdt, nowayout);
|
||||
watchdog_set_drvdata(wdt, drvdata);
|
||||
|
||||
watchdog_stop_on_reboot(wdt);
|
||||
ret = devm_watchdog_register_device(dev, &drvdata->wdt);
|
||||
if (!ret)
|
||||
dev_info(dev, "Initialized\n");
|
||||
|
||||
|
@ -304,15 +304,13 @@ err_iomap:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rti_wdt_remove(struct platform_device *pdev)
|
||||
static void rti_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rti_wdt_device *wdt = platform_get_drvdata(pdev);
|
||||
|
||||
watchdog_unregister_device(&wdt->wdd);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rti_wdt_of_match[] = {
|
||||
@ -327,7 +325,7 @@ static struct platform_driver rti_wdt_driver = {
|
||||
.of_match_table = rti_wdt_of_match,
|
||||
},
|
||||
.probe = rti_wdt_probe,
|
||||
.remove = rti_wdt_remove,
|
||||
.remove_new = rti_wdt_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(rti_wdt_driver);
|
||||
|
@ -308,11 +308,6 @@ static inline unsigned int s3c2410wdt_max_timeout(struct s3c2410_wdt *wdt)
|
||||
/ S3C2410_WTCON_MAXDIV);
|
||||
}
|
||||
|
||||
static inline struct s3c2410_wdt *freq_to_wdt(struct notifier_block *nb)
|
||||
{
|
||||
return container_of(nb, struct s3c2410_wdt, freq_transition);
|
||||
}
|
||||
|
||||
static int s3c2410wdt_disable_wdt_reset(struct s3c2410_wdt *wdt, bool mask)
|
||||
{
|
||||
const u32 mask_val = BIT(wdt->drv_data->mask_bit);
|
||||
@ -443,11 +438,6 @@ static int s3c2410wdt_start(struct watchdog_device *wdd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int s3c2410wdt_is_running(struct s3c2410_wdt *wdt)
|
||||
{
|
||||
return readl(wdt->reg_base + S3C2410_WTCON) & S3C2410_WTCON_ENABLE;
|
||||
}
|
||||
|
||||
static int s3c2410wdt_set_heartbeat(struct watchdog_device *wdd,
|
||||
unsigned int timeout)
|
||||
{
|
||||
@ -579,8 +569,8 @@ static inline unsigned int s3c2410wdt_get_bootstatus(struct s3c2410_wdt *wdt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline const struct s3c2410_wdt_variant *
|
||||
s3c2410_get_wdt_drv_data(struct platform_device *pdev)
|
||||
static inline int
|
||||
s3c2410_get_wdt_drv_data(struct platform_device *pdev, struct s3c2410_wdt *wdt)
|
||||
{
|
||||
const struct s3c2410_wdt_variant *variant;
|
||||
struct device *dev = &pdev->dev;
|
||||
@ -601,26 +591,30 @@ s3c2410_get_wdt_drv_data(struct platform_device *pdev)
|
||||
|
||||
err = of_property_read_u32(dev->of_node,
|
||||
"samsung,cluster-index", &index);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to get cluster index\n");
|
||||
return NULL;
|
||||
}
|
||||
if (err)
|
||||
return dev_err_probe(dev, -EINVAL, "failed to get cluster index\n");
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
return variant;
|
||||
break;
|
||||
case 1:
|
||||
return (variant == &drv_data_exynos850_cl0) ?
|
||||
variant = (variant == &drv_data_exynos850_cl0) ?
|
||||
&drv_data_exynos850_cl1 :
|
||||
&drv_data_exynosautov9_cl1;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "wrong cluster index: %u\n", index);
|
||||
return NULL;
|
||||
return dev_err_probe(dev, -EINVAL, "wrong cluster index: %u\n", index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return variant;
|
||||
wdt->drv_data = variant;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s3c2410wdt_wdt_disable_action(void *data)
|
||||
{
|
||||
s3c2410wdt_enable(data, false);
|
||||
}
|
||||
|
||||
static int s3c2410wdt_probe(struct platform_device *pdev)
|
||||
@ -639,17 +633,16 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
|
||||
spin_lock_init(&wdt->lock);
|
||||
wdt->wdt_device = s3c2410_wdd;
|
||||
|
||||
wdt->drv_data = s3c2410_get_wdt_drv_data(pdev);
|
||||
if (!wdt->drv_data)
|
||||
return -EINVAL;
|
||||
ret = s3c2410_get_wdt_drv_data(pdev, wdt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (wdt->drv_data->quirks & QUIRKS_HAVE_PMUREG) {
|
||||
wdt->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||
"samsung,syscon-phandle");
|
||||
if (IS_ERR(wdt->pmureg)) {
|
||||
dev_err(dev, "syscon regmap lookup failed.\n");
|
||||
return PTR_ERR(wdt->pmureg);
|
||||
}
|
||||
if (IS_ERR(wdt->pmureg))
|
||||
return dev_err_probe(dev, PTR_ERR(wdt->pmureg),
|
||||
"syscon regmap lookup failed.\n");
|
||||
}
|
||||
|
||||
wdt_irq = platform_get_irq(pdev, 0);
|
||||
@ -661,35 +654,17 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(wdt->reg_base))
|
||||
return PTR_ERR(wdt->reg_base);
|
||||
|
||||
wdt->bus_clk = devm_clk_get(dev, "watchdog");
|
||||
if (IS_ERR(wdt->bus_clk)) {
|
||||
dev_err(dev, "failed to find bus clock\n");
|
||||
return PTR_ERR(wdt->bus_clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(wdt->bus_clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to enable bus clock\n");
|
||||
return ret;
|
||||
}
|
||||
wdt->bus_clk = devm_clk_get_enabled(dev, "watchdog");
|
||||
if (IS_ERR(wdt->bus_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(wdt->bus_clk), "failed to get bus clock\n");
|
||||
|
||||
/*
|
||||
* "watchdog_src" clock is optional; if it's not present -- just skip it
|
||||
* and use "watchdog" clock as both bus and source clock.
|
||||
*/
|
||||
wdt->src_clk = devm_clk_get_optional(dev, "watchdog_src");
|
||||
if (IS_ERR(wdt->src_clk)) {
|
||||
dev_err_probe(dev, PTR_ERR(wdt->src_clk),
|
||||
"failed to get source clock\n");
|
||||
ret = PTR_ERR(wdt->src_clk);
|
||||
goto err_bus_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(wdt->src_clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable source clock\n");
|
||||
goto err_bus_clk;
|
||||
}
|
||||
wdt->src_clk = devm_clk_get_optional_enabled(dev, "watchdog_src");
|
||||
if (IS_ERR(wdt->src_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(wdt->src_clk), "failed to get source clock\n");
|
||||
|
||||
wdt->wdt_device.min_timeout = 1;
|
||||
wdt->wdt_device.max_timeout = s3c2410wdt_max_timeout(wdt);
|
||||
@ -705,21 +680,17 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
|
||||
if (ret) {
|
||||
ret = s3c2410wdt_set_heartbeat(&wdt->wdt_device,
|
||||
S3C2410_WATCHDOG_DEFAULT_TIME);
|
||||
if (ret == 0) {
|
||||
if (ret == 0)
|
||||
dev_warn(dev, "tmr_margin value out of range, default %d used\n",
|
||||
S3C2410_WATCHDOG_DEFAULT_TIME);
|
||||
} else {
|
||||
dev_err(dev, "failed to use default timeout\n");
|
||||
goto err_src_clk;
|
||||
}
|
||||
else
|
||||
return dev_err_probe(dev, ret, "failed to use default timeout\n");
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, wdt_irq, s3c2410wdt_irq, 0,
|
||||
pdev->name, pdev);
|
||||
if (ret != 0) {
|
||||
dev_err(dev, "failed to install irq (%d)\n", ret);
|
||||
goto err_src_clk;
|
||||
}
|
||||
if (ret != 0)
|
||||
return dev_err_probe(dev, ret, "failed to install irq (%d)\n", ret);
|
||||
|
||||
watchdog_set_nowayout(&wdt->wdt_device, nowayout);
|
||||
watchdog_set_restart_priority(&wdt->wdt_device, 128);
|
||||
@ -742,13 +713,17 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
|
||||
s3c2410wdt_stop(&wdt->wdt_device);
|
||||
}
|
||||
|
||||
ret = watchdog_register_device(&wdt->wdt_device);
|
||||
ret = devm_watchdog_register_device(dev, &wdt->wdt_device);
|
||||
if (ret)
|
||||
goto err_src_clk;
|
||||
return ret;
|
||||
|
||||
ret = s3c2410wdt_enable(wdt, true);
|
||||
if (ret < 0)
|
||||
goto err_unregister;
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, s3c2410wdt_wdt_disable_action, wdt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, wdt);
|
||||
|
||||
@ -762,34 +737,6 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
|
||||
(wtcon & S3C2410_WTCON_INTEN) ? "en" : "dis");
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister:
|
||||
watchdog_unregister_device(&wdt->wdt_device);
|
||||
|
||||
err_src_clk:
|
||||
clk_disable_unprepare(wdt->src_clk);
|
||||
|
||||
err_bus_clk:
|
||||
clk_disable_unprepare(wdt->bus_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int s3c2410wdt_remove(struct platform_device *dev)
|
||||
{
|
||||
int ret;
|
||||
struct s3c2410_wdt *wdt = platform_get_drvdata(dev);
|
||||
|
||||
ret = s3c2410wdt_enable(wdt, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
watchdog_unregister_device(&wdt->wdt_device);
|
||||
|
||||
clk_disable_unprepare(wdt->src_clk);
|
||||
clk_disable_unprepare(wdt->bus_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void s3c2410wdt_shutdown(struct platform_device *dev)
|
||||
@ -844,7 +791,6 @@ static DEFINE_SIMPLE_DEV_PM_OPS(s3c2410wdt_pm_ops,
|
||||
|
||||
static struct platform_driver s3c2410wdt_driver = {
|
||||
.probe = s3c2410wdt_probe,
|
||||
.remove = s3c2410wdt_remove,
|
||||
.shutdown = s3c2410wdt_shutdown,
|
||||
.id_table = s3c2410_wdt_ids,
|
||||
.driver = {
|
||||
|
@ -229,19 +229,17 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sa1100dog_remove(struct platform_device *pdev)
|
||||
static void sa1100dog_remove(struct platform_device *pdev)
|
||||
{
|
||||
misc_deregister(&sa1100dog_miscdev);
|
||||
clk_disable_unprepare(clk);
|
||||
clk_put(clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver sa1100dog_driver = {
|
||||
.driver.name = "sa1100_wdt",
|
||||
.probe = sa1100dog_probe,
|
||||
.remove = sa1100dog_remove,
|
||||
.remove_new = sa1100dog_remove,
|
||||
};
|
||||
module_platform_driver(sa1100dog_driver);
|
||||
|
||||
|
@ -361,7 +361,7 @@ static int __maybe_unused sbsa_gwdt_suspend(struct device *dev)
|
||||
{
|
||||
struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
|
||||
|
||||
if (watchdog_active(&gwdt->wdd))
|
||||
if (watchdog_hw_running(&gwdt->wdd))
|
||||
sbsa_gwdt_stop(&gwdt->wdd);
|
||||
|
||||
return 0;
|
||||
@ -372,7 +372,7 @@ static int __maybe_unused sbsa_gwdt_resume(struct device *dev)
|
||||
{
|
||||
struct sbsa_gwdt *gwdt = dev_get_drvdata(dev);
|
||||
|
||||
if (watchdog_active(&gwdt->wdd))
|
||||
if (watchdog_hw_running(&gwdt->wdd))
|
||||
sbsa_gwdt_start(&gwdt->wdd);
|
||||
|
||||
return 0;
|
||||
|
@ -425,7 +425,7 @@ exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sch311x_wdt_remove(struct platform_device *pdev)
|
||||
static void sch311x_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
/* Stop the timer before we leave */
|
||||
if (!nowayout)
|
||||
@ -436,7 +436,6 @@ static int sch311x_wdt_remove(struct platform_device *pdev)
|
||||
release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
|
||||
release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
|
||||
sch311x_wdt_data.runtime_reg = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sch311x_wdt_shutdown(struct platform_device *dev)
|
||||
@ -447,7 +446,7 @@ static void sch311x_wdt_shutdown(struct platform_device *dev)
|
||||
|
||||
static struct platform_driver sch311x_wdt_driver = {
|
||||
.probe = sch311x_wdt_probe,
|
||||
.remove = sch311x_wdt_remove,
|
||||
.remove_new = sch311x_wdt_remove,
|
||||
.shutdown = sch311x_wdt_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
@ -279,13 +279,11 @@ static int sh_wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sh_wdt_remove(struct platform_device *pdev)
|
||||
static void sh_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
watchdog_unregister_device(&sh_wdt_dev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sh_wdt_shutdown(struct platform_device *pdev)
|
||||
@ -299,7 +297,7 @@ static struct platform_driver sh_wdt_driver = {
|
||||
},
|
||||
|
||||
.probe = sh_wdt_probe,
|
||||
.remove = sh_wdt_remove,
|
||||
.remove_new = sh_wdt_remove,
|
||||
.shutdown = sh_wdt_shutdown,
|
||||
};
|
||||
|
||||
|
@ -115,6 +115,10 @@ static int tco_timer_start(struct watchdog_device *wdd)
|
||||
val |= SP5100_WDT_START_STOP_BIT;
|
||||
writel(val, SP5100_WDT_CONTROL(tco->tcobase));
|
||||
|
||||
/* This must be a distinct write. */
|
||||
val |= SP5100_WDT_TRIGGER_BIT;
|
||||
writel(val, SP5100_WDT_CONTROL(tco->tcobase));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -239,13 +239,11 @@ static int st_wdog_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int st_wdog_remove(struct platform_device *pdev)
|
||||
static void st_wdog_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct st_wdog *st_wdog = watchdog_get_drvdata(&st_wdog_dev);
|
||||
|
||||
st_wdog_setup(st_wdog, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int st_wdog_suspend(struct device *dev)
|
||||
@ -295,7 +293,7 @@ static struct platform_driver st_wdog_driver = {
|
||||
.of_match_table = st_wdog_match,
|
||||
},
|
||||
.probe = st_wdog_probe,
|
||||
.remove = st_wdog_remove,
|
||||
.remove_new = st_wdog_remove,
|
||||
};
|
||||
module_platform_driver(st_wdog_driver);
|
||||
|
||||
|
606
drivers/watchdog/starfive-wdt.c
Normal file
606
drivers/watchdog/starfive-wdt.c
Normal file
@ -0,0 +1,606 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Starfive Watchdog driver
|
||||
*
|
||||
* Copyright (C) 2022 StarFive Technology Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
/* JH7100 Watchdog register define */
|
||||
#define STARFIVE_WDT_JH7100_INTSTAUS 0x000
|
||||
#define STARFIVE_WDT_JH7100_CONTROL 0x104
|
||||
#define STARFIVE_WDT_JH7100_LOAD 0x108
|
||||
#define STARFIVE_WDT_JH7100_EN 0x110
|
||||
#define STARFIVE_WDT_JH7100_RELOAD 0x114 /* Write 0 or 1 to reload preset value */
|
||||
#define STARFIVE_WDT_JH7100_VALUE 0x118
|
||||
#define STARFIVE_WDT_JH7100_INTCLR 0x120 /*
|
||||
* [0]: Write 1 to clear interrupt
|
||||
* [1]: 1 mean clearing and 0 mean complete
|
||||
* [31:2]: reserved.
|
||||
*/
|
||||
#define STARFIVE_WDT_JH7100_LOCK 0x13c /* write 0x378f0765 to unlock */
|
||||
|
||||
/* JH7110 Watchdog register define */
|
||||
#define STARFIVE_WDT_JH7110_LOAD 0x000
|
||||
#define STARFIVE_WDT_JH7110_VALUE 0x004
|
||||
#define STARFIVE_WDT_JH7110_CONTROL 0x008 /*
|
||||
* [0]: reset enable;
|
||||
* [1]: interrupt enable && watchdog enable
|
||||
* [31:2]: reserved.
|
||||
*/
|
||||
#define STARFIVE_WDT_JH7110_INTCLR 0x00c /* clear intterupt and reload the counter */
|
||||
#define STARFIVE_WDT_JH7110_IMS 0x014
|
||||
#define STARFIVE_WDT_JH7110_LOCK 0xc00 /* write 0x1ACCE551 to unlock */
|
||||
|
||||
/* WDOGCONTROL */
|
||||
#define STARFIVE_WDT_ENABLE 0x1
|
||||
#define STARFIVE_WDT_EN_SHIFT 0
|
||||
#define STARFIVE_WDT_RESET_EN 0x1
|
||||
#define STARFIVE_WDT_JH7100_RST_EN_SHIFT 0
|
||||
#define STARFIVE_WDT_JH7110_RST_EN_SHIFT 1
|
||||
|
||||
/* WDOGLOCK */
|
||||
#define STARFIVE_WDT_JH7100_UNLOCK_KEY 0x378f0765
|
||||
#define STARFIVE_WDT_JH7110_UNLOCK_KEY 0x1acce551
|
||||
|
||||
/* WDOGINTCLR */
|
||||
#define STARFIVE_WDT_INTCLR 0x1
|
||||
#define STARFIVE_WDT_JH7100_INTCLR_AVA_SHIFT 1 /* Watchdog can clear interrupt when 0 */
|
||||
|
||||
#define STARFIVE_WDT_MAXCNT 0xffffffff
|
||||
#define STARFIVE_WDT_DEFAULT_TIME (15)
|
||||
#define STARFIVE_WDT_DELAY_US 0
|
||||
#define STARFIVE_WDT_TIMEOUT_US 10000
|
||||
|
||||
/* module parameter */
|
||||
#define STARFIVE_WDT_EARLY_ENA 0
|
||||
|
||||
static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
static int heartbeat;
|
||||
static bool early_enable = STARFIVE_WDT_EARLY_ENA;
|
||||
|
||||
module_param(heartbeat, int, 0);
|
||||
module_param(early_enable, bool, 0);
|
||||
module_param(nowayout, bool, 0);
|
||||
|
||||
MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
|
||||
__MODULE_STRING(STARFIVE_WDT_DEFAULT_TIME) ")");
|
||||
MODULE_PARM_DESC(early_enable,
|
||||
"Watchdog is started at boot time if set to 1, default="
|
||||
__MODULE_STRING(STARFIVE_WDT_EARLY_ENA));
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
struct starfive_wdt_variant {
|
||||
unsigned int control; /* Watchdog Control Resgister for reset enable */
|
||||
unsigned int load; /* Watchdog Load register */
|
||||
unsigned int reload; /* Watchdog Reload Control register */
|
||||
unsigned int enable; /* Watchdog Enable Register */
|
||||
unsigned int value; /* Watchdog Counter Value Register */
|
||||
unsigned int int_clr; /* Watchdog Interrupt Clear Register */
|
||||
unsigned int unlock; /* Watchdog Lock Register */
|
||||
unsigned int int_status; /* Watchdog Interrupt Status Register */
|
||||
|
||||
u32 unlock_key;
|
||||
char enrst_shift;
|
||||
char en_shift;
|
||||
bool intclr_check; /* whether need to check it before clearing interrupt */
|
||||
char intclr_ava_shift;
|
||||
bool double_timeout; /* The watchdog need twice timeout to reboot */
|
||||
};
|
||||
|
||||
struct starfive_wdt {
|
||||
struct watchdog_device wdd;
|
||||
spinlock_t lock; /* spinlock for register handling */
|
||||
void __iomem *base;
|
||||
struct clk *core_clk;
|
||||
struct clk *apb_clk;
|
||||
const struct starfive_wdt_variant *variant;
|
||||
unsigned long freq;
|
||||
u32 count; /* count of timeout */
|
||||
u32 reload; /* restore the count */
|
||||
};
|
||||
|
||||
/* Register layout and configuration for the JH7100 */
|
||||
static const struct starfive_wdt_variant starfive_wdt_jh7100_variant = {
|
||||
.control = STARFIVE_WDT_JH7100_CONTROL,
|
||||
.load = STARFIVE_WDT_JH7100_LOAD,
|
||||
.reload = STARFIVE_WDT_JH7100_RELOAD,
|
||||
.enable = STARFIVE_WDT_JH7100_EN,
|
||||
.value = STARFIVE_WDT_JH7100_VALUE,
|
||||
.int_clr = STARFIVE_WDT_JH7100_INTCLR,
|
||||
.unlock = STARFIVE_WDT_JH7100_LOCK,
|
||||
.unlock_key = STARFIVE_WDT_JH7100_UNLOCK_KEY,
|
||||
.int_status = STARFIVE_WDT_JH7100_INTSTAUS,
|
||||
.enrst_shift = STARFIVE_WDT_JH7100_RST_EN_SHIFT,
|
||||
.en_shift = STARFIVE_WDT_EN_SHIFT,
|
||||
.intclr_check = true,
|
||||
.intclr_ava_shift = STARFIVE_WDT_JH7100_INTCLR_AVA_SHIFT,
|
||||
.double_timeout = false,
|
||||
};
|
||||
|
||||
/* Register layout and configuration for the JH7110 */
|
||||
static const struct starfive_wdt_variant starfive_wdt_jh7110_variant = {
|
||||
.control = STARFIVE_WDT_JH7110_CONTROL,
|
||||
.load = STARFIVE_WDT_JH7110_LOAD,
|
||||
.enable = STARFIVE_WDT_JH7110_CONTROL,
|
||||
.value = STARFIVE_WDT_JH7110_VALUE,
|
||||
.int_clr = STARFIVE_WDT_JH7110_INTCLR,
|
||||
.unlock = STARFIVE_WDT_JH7110_LOCK,
|
||||
.unlock_key = STARFIVE_WDT_JH7110_UNLOCK_KEY,
|
||||
.int_status = STARFIVE_WDT_JH7110_IMS,
|
||||
.enrst_shift = STARFIVE_WDT_JH7110_RST_EN_SHIFT,
|
||||
.en_shift = STARFIVE_WDT_EN_SHIFT,
|
||||
.intclr_check = false,
|
||||
.double_timeout = true,
|
||||
};
|
||||
|
||||
static int starfive_wdt_enable_clock(struct starfive_wdt *wdt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(wdt->apb_clk);
|
||||
if (ret)
|
||||
return dev_err_probe(wdt->wdd.parent, ret, "failed to enable apb clock\n");
|
||||
|
||||
ret = clk_prepare_enable(wdt->core_clk);
|
||||
if (ret)
|
||||
return dev_err_probe(wdt->wdd.parent, ret, "failed to enable core clock\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void starfive_wdt_disable_clock(struct starfive_wdt *wdt)
|
||||
{
|
||||
clk_disable_unprepare(wdt->core_clk);
|
||||
clk_disable_unprepare(wdt->apb_clk);
|
||||
}
|
||||
|
||||
static inline int starfive_wdt_get_clock(struct starfive_wdt *wdt)
|
||||
{
|
||||
struct device *dev = wdt->wdd.parent;
|
||||
|
||||
wdt->apb_clk = devm_clk_get(dev, "apb");
|
||||
if (IS_ERR(wdt->apb_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(wdt->apb_clk), "failed to get apb clock\n");
|
||||
|
||||
wdt->core_clk = devm_clk_get(dev, "core");
|
||||
if (IS_ERR(wdt->core_clk))
|
||||
return dev_err_probe(dev, PTR_ERR(wdt->core_clk), "failed to get core clock\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int starfive_wdt_reset_init(struct device *dev)
|
||||
{
|
||||
struct reset_control *rsts;
|
||||
int ret;
|
||||
|
||||
rsts = devm_reset_control_array_get_exclusive(dev);
|
||||
if (IS_ERR(rsts))
|
||||
return dev_err_probe(dev, PTR_ERR(rsts), "failed to get resets\n");
|
||||
|
||||
ret = reset_control_deassert(rsts);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to deassert resets\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 starfive_wdt_ticks_to_sec(struct starfive_wdt *wdt, u32 ticks)
|
||||
{
|
||||
return DIV_ROUND_CLOSEST(ticks, wdt->freq);
|
||||
}
|
||||
|
||||
/* Write unlock-key to unlock. Write other value to lock. */
|
||||
static void starfive_wdt_unlock(struct starfive_wdt *wdt)
|
||||
{
|
||||
spin_lock(&wdt->lock);
|
||||
writel(wdt->variant->unlock_key, wdt->base + wdt->variant->unlock);
|
||||
}
|
||||
|
||||
static void starfive_wdt_lock(struct starfive_wdt *wdt)
|
||||
{
|
||||
writel(~wdt->variant->unlock_key, wdt->base + wdt->variant->unlock);
|
||||
spin_unlock(&wdt->lock);
|
||||
}
|
||||
|
||||
/* enable watchdog interrupt to reset/reboot */
|
||||
static void starfive_wdt_enable_reset(struct starfive_wdt *wdt)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(wdt->base + wdt->variant->control);
|
||||
val |= STARFIVE_WDT_RESET_EN << wdt->variant->enrst_shift;
|
||||
writel(val, wdt->base + wdt->variant->control);
|
||||
}
|
||||
|
||||
/* interrupt status whether has been raised from the counter */
|
||||
static bool starfive_wdt_raise_irq_status(struct starfive_wdt *wdt)
|
||||
{
|
||||
return !!readl(wdt->base + wdt->variant->int_status);
|
||||
}
|
||||
|
||||
/* waiting interrupt can be free to clear */
|
||||
static int starfive_wdt_wait_int_free(struct starfive_wdt *wdt)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
return readl_poll_timeout_atomic(wdt->base + wdt->variant->int_clr, value,
|
||||
!(value & BIT(wdt->variant->intclr_ava_shift)),
|
||||
STARFIVE_WDT_DELAY_US, STARFIVE_WDT_TIMEOUT_US);
|
||||
}
|
||||
|
||||
/* clear interrupt signal before initialization or reload */
|
||||
static int starfive_wdt_int_clr(struct starfive_wdt *wdt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (wdt->variant->intclr_check) {
|
||||
ret = starfive_wdt_wait_int_free(wdt);
|
||||
if (ret)
|
||||
return dev_err_probe(wdt->wdd.parent, ret,
|
||||
"watchdog is not ready to clear interrupt.\n");
|
||||
}
|
||||
writel(STARFIVE_WDT_INTCLR, wdt->base + wdt->variant->int_clr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void starfive_wdt_set_count(struct starfive_wdt *wdt, u32 val)
|
||||
{
|
||||
writel(val, wdt->base + wdt->variant->load);
|
||||
}
|
||||
|
||||
static inline u32 starfive_wdt_get_count(struct starfive_wdt *wdt)
|
||||
{
|
||||
return readl(wdt->base + wdt->variant->value);
|
||||
}
|
||||
|
||||
/* enable watchdog */
|
||||
static inline void starfive_wdt_enable(struct starfive_wdt *wdt)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(wdt->base + wdt->variant->enable);
|
||||
val |= STARFIVE_WDT_ENABLE << wdt->variant->en_shift;
|
||||
writel(val, wdt->base + wdt->variant->enable);
|
||||
}
|
||||
|
||||
/* disable watchdog */
|
||||
static inline void starfive_wdt_disable(struct starfive_wdt *wdt)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(wdt->base + wdt->variant->enable);
|
||||
val &= ~(STARFIVE_WDT_ENABLE << wdt->variant->en_shift);
|
||||
writel(val, wdt->base + wdt->variant->enable);
|
||||
}
|
||||
|
||||
static inline void starfive_wdt_set_reload_count(struct starfive_wdt *wdt, u32 count)
|
||||
{
|
||||
starfive_wdt_set_count(wdt, count);
|
||||
|
||||
/* 7100 need set any value to reload register and could reload value to counter */
|
||||
if (wdt->variant->reload)
|
||||
writel(0x1, wdt->base + wdt->variant->reload);
|
||||
}
|
||||
|
||||
static unsigned int starfive_wdt_max_timeout(struct starfive_wdt *wdt)
|
||||
{
|
||||
if (wdt->variant->double_timeout)
|
||||
return DIV_ROUND_UP(STARFIVE_WDT_MAXCNT, (wdt->freq / 2)) - 1;
|
||||
|
||||
return DIV_ROUND_UP(STARFIVE_WDT_MAXCNT, wdt->freq) - 1;
|
||||
}
|
||||
|
||||
static unsigned int starfive_wdt_get_timeleft(struct watchdog_device *wdd)
|
||||
{
|
||||
struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
u32 count;
|
||||
|
||||
/*
|
||||
* If the watchdog takes twice timeout and set half count value,
|
||||
* timeleft value should add the count value before first timeout.
|
||||
*/
|
||||
count = starfive_wdt_get_count(wdt);
|
||||
if (wdt->variant->double_timeout && !starfive_wdt_raise_irq_status(wdt))
|
||||
count += wdt->count;
|
||||
|
||||
return starfive_wdt_ticks_to_sec(wdt, count);
|
||||
}
|
||||
|
||||
static int starfive_wdt_keepalive(struct watchdog_device *wdd)
|
||||
{
|
||||
struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
int ret;
|
||||
|
||||
starfive_wdt_unlock(wdt);
|
||||
ret = starfive_wdt_int_clr(wdt);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
starfive_wdt_set_reload_count(wdt, wdt->count);
|
||||
|
||||
exit:
|
||||
/* exit with releasing spinlock and locking registers */
|
||||
starfive_wdt_lock(wdt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int starfive_wdt_start(struct starfive_wdt *wdt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
starfive_wdt_unlock(wdt);
|
||||
/* disable watchdog, to be safe */
|
||||
starfive_wdt_disable(wdt);
|
||||
|
||||
starfive_wdt_enable_reset(wdt);
|
||||
ret = starfive_wdt_int_clr(wdt);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
starfive_wdt_set_count(wdt, wdt->count);
|
||||
starfive_wdt_enable(wdt);
|
||||
|
||||
exit:
|
||||
starfive_wdt_lock(wdt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void starfive_wdt_stop(struct starfive_wdt *wdt)
|
||||
{
|
||||
starfive_wdt_unlock(wdt);
|
||||
starfive_wdt_disable(wdt);
|
||||
starfive_wdt_lock(wdt);
|
||||
}
|
||||
|
||||
static int starfive_wdt_pm_start(struct watchdog_device *wdd)
|
||||
{
|
||||
struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
int ret = pm_runtime_get_sync(wdd->parent);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return starfive_wdt_start(wdt);
|
||||
}
|
||||
|
||||
static int starfive_wdt_pm_stop(struct watchdog_device *wdd)
|
||||
{
|
||||
struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
|
||||
starfive_wdt_stop(wdt);
|
||||
return pm_runtime_put_sync(wdd->parent);
|
||||
}
|
||||
|
||||
static int starfive_wdt_set_timeout(struct watchdog_device *wdd,
|
||||
unsigned int timeout)
|
||||
{
|
||||
struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
|
||||
unsigned long count = timeout * wdt->freq;
|
||||
|
||||
/* some watchdogs take two timeouts to reset */
|
||||
if (wdt->variant->double_timeout)
|
||||
count /= 2;
|
||||
|
||||
wdt->count = count;
|
||||
wdd->timeout = timeout;
|
||||
|
||||
starfive_wdt_unlock(wdt);
|
||||
starfive_wdt_disable(wdt);
|
||||
starfive_wdt_set_reload_count(wdt, wdt->count);
|
||||
starfive_wdt_enable(wdt);
|
||||
starfive_wdt_lock(wdt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define STARFIVE_WDT_OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)
|
||||
|
||||
static const struct watchdog_info starfive_wdt_info = {
|
||||
.options = STARFIVE_WDT_OPTIONS,
|
||||
.identity = "StarFive Watchdog",
|
||||
};
|
||||
|
||||
static const struct watchdog_ops starfive_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = starfive_wdt_pm_start,
|
||||
.stop = starfive_wdt_pm_stop,
|
||||
.ping = starfive_wdt_keepalive,
|
||||
.set_timeout = starfive_wdt_set_timeout,
|
||||
.get_timeleft = starfive_wdt_get_timeleft,
|
||||
};
|
||||
|
||||
static int starfive_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct starfive_wdt *wdt;
|
||||
int ret;
|
||||
|
||||
wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
|
||||
if (!wdt)
|
||||
return -ENOMEM;
|
||||
|
||||
wdt->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(wdt->base))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(wdt->base), "error mapping registers\n");
|
||||
|
||||
wdt->wdd.parent = &pdev->dev;
|
||||
ret = starfive_wdt_get_clock(wdt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, wdt);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
if (pm_runtime_enabled(&pdev->dev)) {
|
||||
ret = pm_runtime_get_sync(&pdev->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
/* runtime PM is disabled but clocks need to be enabled */
|
||||
ret = starfive_wdt_enable_clock(wdt);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = starfive_wdt_reset_init(&pdev->dev);
|
||||
if (ret)
|
||||
goto err_exit;
|
||||
|
||||
watchdog_set_drvdata(&wdt->wdd, wdt);
|
||||
wdt->wdd.info = &starfive_wdt_info;
|
||||
wdt->wdd.ops = &starfive_wdt_ops;
|
||||
wdt->variant = of_device_get_match_data(&pdev->dev);
|
||||
spin_lock_init(&wdt->lock);
|
||||
|
||||
wdt->freq = clk_get_rate(wdt->core_clk);
|
||||
if (!wdt->freq) {
|
||||
dev_err(&pdev->dev, "get clock rate failed.\n");
|
||||
ret = -EINVAL;
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
wdt->wdd.min_timeout = 1;
|
||||
wdt->wdd.max_timeout = starfive_wdt_max_timeout(wdt);
|
||||
wdt->wdd.timeout = STARFIVE_WDT_DEFAULT_TIME;
|
||||
watchdog_init_timeout(&wdt->wdd, heartbeat, &pdev->dev);
|
||||
starfive_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout);
|
||||
|
||||
watchdog_set_nowayout(&wdt->wdd, nowayout);
|
||||
watchdog_stop_on_reboot(&wdt->wdd);
|
||||
watchdog_stop_on_unregister(&wdt->wdd);
|
||||
|
||||
if (early_enable) {
|
||||
ret = starfive_wdt_start(wdt);
|
||||
if (ret)
|
||||
goto err_exit;
|
||||
set_bit(WDOG_HW_RUNNING, &wdt->wdd.status);
|
||||
} else {
|
||||
starfive_wdt_stop(wdt);
|
||||
}
|
||||
|
||||
ret = watchdog_register_device(&wdt->wdd);
|
||||
if (ret)
|
||||
goto err_exit;
|
||||
|
||||
if (!early_enable)
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
starfive_wdt_disable_clock(wdt);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int starfive_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct starfive_wdt *wdt = platform_get_drvdata(pdev);
|
||||
|
||||
starfive_wdt_stop(wdt);
|
||||
watchdog_unregister_device(&wdt->wdd);
|
||||
|
||||
if (pm_runtime_enabled(&pdev->dev))
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
else
|
||||
/* disable clock without PM */
|
||||
starfive_wdt_disable_clock(wdt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void starfive_wdt_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct starfive_wdt *wdt = platform_get_drvdata(pdev);
|
||||
|
||||
starfive_wdt_pm_stop(&wdt->wdd);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int starfive_wdt_suspend(struct device *dev)
|
||||
{
|
||||
struct starfive_wdt *wdt = dev_get_drvdata(dev);
|
||||
|
||||
/* Save watchdog state, and turn it off. */
|
||||
wdt->reload = starfive_wdt_get_count(wdt);
|
||||
|
||||
/* Note that WTCNT doesn't need to be saved. */
|
||||
starfive_wdt_stop(wdt);
|
||||
|
||||
return pm_runtime_force_suspend(dev);
|
||||
}
|
||||
|
||||
static int starfive_wdt_resume(struct device *dev)
|
||||
{
|
||||
struct starfive_wdt *wdt = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
starfive_wdt_unlock(wdt);
|
||||
/* Restore watchdog state. */
|
||||
starfive_wdt_set_reload_count(wdt, wdt->reload);
|
||||
starfive_wdt_lock(wdt);
|
||||
|
||||
return starfive_wdt_start(wdt);
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int starfive_wdt_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct starfive_wdt *wdt = dev_get_drvdata(dev);
|
||||
|
||||
starfive_wdt_disable_clock(wdt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int starfive_wdt_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct starfive_wdt *wdt = dev_get_drvdata(dev);
|
||||
|
||||
return starfive_wdt_enable_clock(wdt);
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct dev_pm_ops starfive_wdt_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(starfive_wdt_runtime_suspend, starfive_wdt_runtime_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(starfive_wdt_suspend, starfive_wdt_resume)
|
||||
};
|
||||
|
||||
static const struct of_device_id starfive_wdt_match[] = {
|
||||
{ .compatible = "starfive,jh7100-wdt", .data = &starfive_wdt_jh7100_variant },
|
||||
{ .compatible = "starfive,jh7110-wdt", .data = &starfive_wdt_jh7110_variant },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, starfive_wdt_match);
|
||||
|
||||
static struct platform_driver starfive_wdt_driver = {
|
||||
.probe = starfive_wdt_probe,
|
||||
.remove = starfive_wdt_remove,
|
||||
.shutdown = starfive_wdt_shutdown,
|
||||
.driver = {
|
||||
.name = "starfive-wdt",
|
||||
.pm = &starfive_wdt_pm_ops,
|
||||
.of_match_table = starfive_wdt_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(starfive_wdt_driver);
|
||||
|
||||
MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
|
||||
MODULE_AUTHOR("Samin Guo <samin.guo@starfivetech.com>");
|
||||
MODULE_DESCRIPTION("StarFive Watchdog Device Driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -109,10 +109,9 @@ static int stmp3xxx_wdt_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stmp3xxx_wdt_remove(struct platform_device *pdev)
|
||||
static void stmp3xxx_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
unregister_reboot_notifier(&wdt_notifier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused stmp3xxx_wdt_suspend(struct device *dev)
|
||||
@ -144,7 +143,7 @@ static struct platform_driver stmp3xxx_wdt_driver = {
|
||||
.pm = &stmp3xxx_wdt_pm_ops,
|
||||
},
|
||||
.probe = stmp3xxx_wdt_probe,
|
||||
.remove = stmp3xxx_wdt_remove,
|
||||
.remove_new = stmp3xxx_wdt_remove,
|
||||
};
|
||||
module_platform_driver(stmp3xxx_wdt_driver);
|
||||
|
||||
|
@ -162,7 +162,7 @@ static int watchdog_reboot_notifier(struct notifier_block *nb,
|
||||
|
||||
wdd = container_of(nb, struct watchdog_device, reboot_nb);
|
||||
if (code == SYS_DOWN || code == SYS_HALT) {
|
||||
if (watchdog_active(wdd) || watchdog_hw_running(wdd)) {
|
||||
if (watchdog_hw_running(wdd)) {
|
||||
int ret;
|
||||
|
||||
ret = wdd->ops->stop(wdd);
|
||||
|
@ -192,7 +192,7 @@ static int watchdog_ping(struct watchdog_device *wdd)
|
||||
{
|
||||
struct watchdog_core_data *wd_data = wdd->wd_data;
|
||||
|
||||
if (!watchdog_active(wdd) && !watchdog_hw_running(wdd))
|
||||
if (!watchdog_hw_running(wdd))
|
||||
return 0;
|
||||
|
||||
set_bit(_WDOG_KEEPALIVE, &wd_data->status);
|
||||
@ -268,6 +268,7 @@ static int watchdog_start(struct watchdog_device *wdd)
|
||||
trace_watchdog_start(wdd, err);
|
||||
if (err == 0) {
|
||||
set_bit(WDOG_ACTIVE, &wdd->status);
|
||||
set_bit(WDOG_HW_RUNNING, &wdd->status);
|
||||
wd_data->last_keepalive = started_at;
|
||||
wd_data->last_hw_keepalive = started_at;
|
||||
watchdog_update_worker(wdd);
|
||||
|
@ -207,10 +207,9 @@ void watchdog_unregister_pretimeout(struct watchdog_device *wdd)
|
||||
list_for_each_entry_safe(p, t, &pretimeout_list, entry) {
|
||||
if (p->wdd == wdd) {
|
||||
list_del(&p->entry);
|
||||
kfree(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&pretimeout_lock);
|
||||
|
||||
kfree(p);
|
||||
}
|
||||
|
@ -153,18 +153,11 @@ static int wm8350_wdt_probe(struct platform_device *pdev)
|
||||
/* Default to 4s timeout */
|
||||
wm8350_wdt_set_timeout(&wm8350_wdt, 4);
|
||||
|
||||
return watchdog_register_device(&wm8350_wdt);
|
||||
}
|
||||
|
||||
static int wm8350_wdt_remove(struct platform_device *pdev)
|
||||
{
|
||||
watchdog_unregister_device(&wm8350_wdt);
|
||||
return 0;
|
||||
return devm_watchdog_register_device(&pdev->dev, &wm8350_wdt);
|
||||
}
|
||||
|
||||
static struct platform_driver wm8350_wdt_driver = {
|
||||
.probe = wm8350_wdt_probe,
|
||||
.remove = wm8350_wdt_remove,
|
||||
.driver = {
|
||||
.name = "wm8350-wdt",
|
||||
},
|
||||
|
17
include/dt-bindings/reset/mediatek,mt6735-wdt.h
Normal file
17
include/dt-bindings/reset/mediatek,mt6735-wdt.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_MEDIATEK_MT6735_WDT_H_
|
||||
#define _DT_BINDINGS_RESET_MEDIATEK_MT6735_WDT_H_
|
||||
|
||||
#define MT6735_TOPRGU_MM_RST 1
|
||||
#define MT6735_TOPRGU_MFG_RST 2
|
||||
#define MT6735_TOPRGU_VENC_RST 3
|
||||
#define MT6735_TOPRGU_VDEC_RST 4
|
||||
#define MT6735_TOPRGU_IMG_RST 5
|
||||
#define MT6735_TOPRGU_MD_RST 7
|
||||
#define MT6735_TOPRGU_CONN_RST 9
|
||||
#define MT6735_TOPRGU_C2K_SW_RST 14
|
||||
#define MT6735_TOPRGU_C2K_RST 15
|
||||
#define MT6735_TOPRGU_RST_NUM 9
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user