linux-watchdog 5.19-rc1 tag
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iEYEABECAAYFAmKXhXYACgkQ+iyteGJfRsoTRQCgre6Jur9IDwegaxnbFpgZTde9 wf4AnAo5l8Vyz7EQLG1YSPjzr5kmK263 =Xdkg -----END PGP SIGNATURE----- Merge tag 'linux-watchdog-5.19-rc1' of git://www.linux-watchdog.org/linux-watchdog Pull watchdog updates from Wim Van Sebroeck: - Add MediaTek MT8186 support - Add Mediatek MT7986 reset-controller support - Add i.MX93 support - Add watchdog driver for Sunplus SP7021 - Add SC8180X and SC8280XP compatibles - Add Renesas RZ/N1 Watchdog driver and support for RZ/N1 - rzg2l_wdt improvements and fixes - Several other improvements and fixes * tag 'linux-watchdog-5.19-rc1' of git://www.linux-watchdog.org/linux-watchdog: (38 commits) watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe dt-bindings: watchdog: renesas,wdt: R-Car V3U is R-Car Gen4 watchdog: Add Renesas RZ/N1 Watchdog driver dt-bindings: watchdog: renesas,wdt: Add support for RZ/N1 watchdog: wdat_wdt: Stop watchdog when uninstalling module watchdog: wdat_wdt: Stop watchdog when rebooting the system watchdog: wdat_wdt: Using the existing function to check parameter timeout dt-bindings: watchdog: da9062: add watchdog timeout mode dt-bindings: watchdog: renesas,wdt: Document RZ/G2UL SoC watchdog: iTCO_wdt: Using existing macro define covers more scenarios watchdog: rti-wdt: Fix pm_runtime_get_sync() error checking dt-bindings: watchdog: Add SC8180X and SC8280XP compatibles watchdog: rti_wdt: Fix calculation and evaluation of preset heartbeat dt-bindings: watchdog: uniphier: Use unevaluatedProperties watchdog: sp805: disable watchdog on remove watchdog: da9063: optionally disable watchdog during suspend dt-bindings: mfd: da9063: watchdog: add suspend disable option dt-bindings: watchdog: sunxi: clarify clock support dt-bindings: watchdog: sunxi: fix F1C100s compatible watchdog: Add watchdog driver for Sunplus SP7021 ...
This commit is contained in:
commit
96752be4d7
|
@ -64,10 +64,13 @@ Sub-nodes:
|
|||
and KEY_SLEEP.
|
||||
|
||||
- watchdog : This node defines settings for the Watchdog timer associated
|
||||
with the DA9063 and DA9063L. There are currently no entries in this
|
||||
binding, however compatible = "dlg,da9063-watchdog" should be added
|
||||
if a node is created.
|
||||
with the DA9063 and DA9063L. The node should contain the compatible property
|
||||
with the value "dlg,da9063-watchdog".
|
||||
|
||||
Optional watchdog properties:
|
||||
- dlg,use-sw-pm: Add this property to disable the watchdog during suspend.
|
||||
Only use this option if you can't use the watchdog automatic suspend
|
||||
function during a suspend (see register CONTROL_B).
|
||||
|
||||
Example:
|
||||
|
||||
|
|
|
@ -10,6 +10,12 @@ Optional properties:
|
|||
- dlg,use-sw-pm: Add this property to disable the watchdog during suspend.
|
||||
Only use this option if you can't use the watchdog automatic suspend
|
||||
function during a suspend (see register CONTROL_B).
|
||||
- dlg,wdt-sd: Set what happens on watchdog timeout. If this bit is set the
|
||||
watchdog timeout triggers SHUTDOWN, if cleared the watchdog triggers
|
||||
POWERDOWN. Can be 0 or 1. Only use this option if you want to change the
|
||||
default chip's OTP setting for WATCHDOG_SD bit. If this property is NOT
|
||||
set the WATCHDOG_SD bit and on timeout watchdog behavior will match the
|
||||
chip's OTP settings.
|
||||
|
||||
Example: DA9062
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
Faraday Technology FTWDT010 watchdog
|
||||
|
||||
This is an IP part from Faraday Technology found in the Gemini
|
||||
SoCs and others.
|
||||
|
||||
Required properties:
|
||||
- compatible : must be one of
|
||||
"faraday,ftwdt010"
|
||||
"cortina,gemini-watchdog", "faraday,ftwdt010"
|
||||
- reg : shall contain base register location and length
|
||||
- interrupts : shall contain the interrupt for the watchdog
|
||||
|
||||
Optional properties:
|
||||
- timeout-sec : the default watchdog timeout in seconds.
|
||||
|
||||
Example:
|
||||
|
||||
watchdog@41000000 {
|
||||
compatible = "faraday,ftwdt010";
|
||||
reg = <0x41000000 0x1000>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
|
@ -0,0 +1,67 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/watchdog/faraday,ftwdt010.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Faraday Technology FTWDT010 watchdog
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
- Corentin Labbe <clabbe@baylibre.com>
|
||||
|
||||
description: |
|
||||
This is an IP part from Faraday Technology found in the Gemini
|
||||
SoCs and others.
|
||||
|
||||
allOf:
|
||||
- $ref: "watchdog.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: faraday,ftwdt010
|
||||
- items:
|
||||
- enum:
|
||||
- cortina,gemini-watchdog
|
||||
- moxa,moxart-watchdog
|
||||
- const: faraday,ftwdt010
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: PCLK
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
watchdog@41000000 {
|
||||
compatible = "faraday,ftwdt010";
|
||||
reg = <0x41000000 0x1000>;
|
||||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
timeout-secs = <5>;
|
||||
};
|
||||
- |
|
||||
watchdog: watchdog@98500000 {
|
||||
compatible = "moxa,moxart-watchdog", "faraday,ftwdt010";
|
||||
reg = <0x98500000 0x10>;
|
||||
clocks = <&clk_apb>;
|
||||
clock-names = "PCLK";
|
||||
};
|
||||
...
|
|
@ -19,6 +19,7 @@ properties:
|
|||
- items:
|
||||
- const: fsl,imx8ulp-wdt
|
||||
- const: fsl,imx7ulp-wdt
|
||||
- const: fsl,imx93-wdt
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -16,6 +16,7 @@ Required properties:
|
|||
"mediatek,mt7629-wdt", "mediatek,mt6589-wdt": for MT7629
|
||||
"mediatek,mt7986-wdt", "mediatek,mt6589-wdt": for MT7986
|
||||
"mediatek,mt8183-wdt": for MT8183
|
||||
"mediatek,mt8186-wdt", "mediatek,mt6589-wdt": for MT8186
|
||||
"mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516
|
||||
"mediatek,mt8192-wdt": for MT8192
|
||||
"mediatek,mt8195-wdt", "mediatek,mt6589-wdt": for MT8195
|
||||
|
|
|
@ -14,22 +14,29 @@ allOf:
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,apss-wdt-qcs404
|
||||
- qcom,apss-wdt-sc7180
|
||||
- qcom,apss-wdt-sc7280
|
||||
- qcom,apss-wdt-sdm845
|
||||
- qcom,apss-wdt-sdx55
|
||||
- qcom,apss-wdt-sm6350
|
||||
- qcom,apss-wdt-sm8150
|
||||
- qcom,apss-wdt-sm8250
|
||||
- qcom,kpss-timer
|
||||
- qcom,kpss-wdt
|
||||
- qcom,kpss-wdt-apq8064
|
||||
- qcom,kpss-wdt-ipq4019
|
||||
- qcom,kpss-wdt-ipq8064
|
||||
- qcom,kpss-wdt-msm8960
|
||||
- qcom,scss-timer
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,apss-wdt-qcs404
|
||||
- qcom,apss-wdt-sc7180
|
||||
- qcom,apss-wdt-sc7280
|
||||
- qcom,apss-wdt-sc8180x
|
||||
- qcom,apss-wdt-sc8280xp
|
||||
- qcom,apss-wdt-sdm845
|
||||
- qcom,apss-wdt-sdx55
|
||||
- qcom,apss-wdt-sm6350
|
||||
- qcom,apss-wdt-sm8150
|
||||
- qcom,apss-wdt-sm8250
|
||||
- const: qcom,kpss-wdt
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,kpss-wdt
|
||||
- qcom,kpss-timer
|
||||
- qcom,kpss-wdt-apq8064
|
||||
- qcom,kpss-wdt-ipq4019
|
||||
- qcom,kpss-wdt-ipq8064
|
||||
- qcom,kpss-wdt-msm8960
|
||||
- qcom,scss-timer
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -21,8 +21,15 @@ properties:
|
|||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r9a06g032-wdt # RZ/N1D
|
||||
- const: renesas,rzn1-wdt # RZ/N1
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r9a07g043-wdt # RZ/G2UL
|
||||
- renesas,r9a07g044-wdt # RZ/G2{L,LC}
|
||||
- const: renesas,rzg2l-wdt # RZ/G2L
|
||||
- renesas,r9a07g054-wdt # RZ/V2L
|
||||
- const: renesas,rzg2l-wdt
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
|
@ -52,11 +59,11 @@ properties:
|
|||
- renesas,r8a77980-wdt # R-Car V3H
|
||||
- renesas,r8a77990-wdt # R-Car E3
|
||||
- renesas,r8a77995-wdt # R-Car D3
|
||||
- renesas,r8a779a0-wdt # R-Car V3U
|
||||
- const: renesas,rcar-gen3-wdt # R-Car Gen3 and RZ/G2
|
||||
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,r8a779a0-wdt # R-Car V3U
|
||||
- renesas,r8a779f0-wdt # R-Car S4-8
|
||||
- const: renesas,rcar-gen4-wdt # R-Car Gen4
|
||||
|
||||
|
@ -94,6 +101,7 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- renesas,rza-wdt
|
||||
- renesas,rzn1-wdt
|
||||
then:
|
||||
required:
|
||||
- power-domains
|
||||
|
|
|
@ -19,7 +19,7 @@ properties:
|
|||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) Sunplus Co., Ltd. 2021
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/watchdog/sunplus,sp7021-wdt.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sunplus SoCs Watchdog
|
||||
|
||||
maintainers:
|
||||
- XianTao Hu <xt.hu@cqplus1.com>
|
||||
|
||||
allOf:
|
||||
- $ref: watchdog.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sunplus,sp7021-wdt
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: watchdog registers regions
|
||||
- description: miscellaneous control registers regions
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- resets
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
watchdog: watchdog@9c000630 {
|
||||
compatible = "sunplus,sp7021-wdt";
|
||||
reg = <0x9c000630 0x08>, <0x9c000274 0x04>;
|
||||
clocks = <&clkc 0x24>;
|
||||
resets = <&rstc 0x14>;
|
||||
};
|
||||
...
|
|
@ -19057,6 +19057,13 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/serial/sunplus,sp7021-uart.yaml
|
||||
F: drivers/tty/serial/sunplus-uart.c
|
||||
|
||||
SUNPLUS WATCHDOG DRIVER
|
||||
M: Xiantao Hu <xt.hu@cqplus1.com>
|
||||
L: linux-watchdog@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml
|
||||
F: drivers/watchdog/sunplus_wdt.c
|
||||
|
||||
SUPERH
|
||||
M: Yoshinori Sato <ysato@users.sourceforge.jp>
|
||||
M: Rich Felker <dalias@libc.org>
|
||||
|
|
|
@ -883,6 +883,14 @@ config RENESAS_RZAWDT
|
|||
This driver adds watchdog support for the integrated watchdogs in the
|
||||
Renesas RZ/A SoCs. These watchdogs can be used to reset a system.
|
||||
|
||||
config RENESAS_RZN1WDT
|
||||
tristate "Renesas RZ/N1 watchdog"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
This driver adds watchdog support for the integrated watchdogs in the
|
||||
Renesas RZ/N1 SoCs. These watchdogs can be used to reset a system.
|
||||
|
||||
config RENESAS_RZG2LWDT
|
||||
tristate "Renesas RZ/G2L WDT Watchdog"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
|
@ -1011,6 +1019,17 @@ config APPLE_WATCHDOG
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called apple_wdt.
|
||||
|
||||
config SUNPLUS_WATCHDOG
|
||||
tristate "Sunplus watchdog support"
|
||||
depends on ARCH_SUNPLUS || COMPILE_TEST
|
||||
select WATCHDOG_CORE
|
||||
help
|
||||
Say Y here to include support for the watchdog timer
|
||||
in Sunplus SoCs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sunplus_wdt.
|
||||
|
||||
# X86 (i386 + ia64 + x86_64) Architecture
|
||||
|
||||
config ACQUIRE_WDT
|
||||
|
|
|
@ -84,6 +84,7 @@ obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
|
|||
obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
|
||||
obj-$(CONFIG_RENESAS_WDT) += renesas_wdt.o
|
||||
obj-$(CONFIG_RENESAS_RZAWDT) += rza_wdt.o
|
||||
obj-$(CONFIG_RENESAS_RZN1WDT) += rzn1_wdt.o
|
||||
obj-$(CONFIG_RENESAS_RZG2LWDT) += rzg2l_wdt.o
|
||||
obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o
|
||||
obj-$(CONFIG_STM32_WATCHDOG) += stm32_iwdg.o
|
||||
|
@ -95,6 +96,7 @@ obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o
|
|||
obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o
|
||||
obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o
|
||||
obj-$(CONFIG_APPLE_WATCHDOG) += apple_wdt.o
|
||||
obj-$(CONFIG_SUNPLUS_WATCHDOG) += sunplus_wdt.o
|
||||
|
||||
# X86 (i386 + ia64 + x86_64) Architecture
|
||||
obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
|
||||
|
|
|
@ -218,6 +218,7 @@ static SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops, bcm7038_wdt_suspend,
|
|||
bcm7038_wdt_resume);
|
||||
|
||||
static const struct of_device_id bcm7038_wdt_match[] = {
|
||||
{ .compatible = "brcm,bcm6345-wdt" },
|
||||
{ .compatible = "brcm,bcm7038-wdt" },
|
||||
{},
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/mfd/da9063/registers.h>
|
||||
#include <linux/mfd/da9063/core.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/*
|
||||
|
@ -26,6 +27,8 @@
|
|||
* others: timeout = 2048 ms * 2^(TWDSCALE-1).
|
||||
*/
|
||||
static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
|
||||
static bool use_sw_pm;
|
||||
|
||||
#define DA9063_TWDSCALE_DISABLE 0
|
||||
#define DA9063_TWDSCALE_MIN 1
|
||||
#define DA9063_TWDSCALE_MAX (ARRAY_SIZE(wdt_timeout) - 1)
|
||||
|
@ -218,6 +221,8 @@ static int da9063_wdt_probe(struct platform_device *pdev)
|
|||
if (!wdd)
|
||||
return -ENOMEM;
|
||||
|
||||
use_sw_pm = device_property_present(dev, "dlg,use-sw-pm");
|
||||
|
||||
wdd->info = &da9063_watchdog_info;
|
||||
wdd->ops = &da9063_watchdog_ops;
|
||||
wdd->min_timeout = DA9063_WDT_MIN_TIMEOUT;
|
||||
|
@ -228,6 +233,7 @@ static int da9063_wdt_probe(struct platform_device *pdev)
|
|||
|
||||
watchdog_set_restart_priority(wdd, 128);
|
||||
watchdog_set_drvdata(wdd, da9063);
|
||||
dev_set_drvdata(dev, wdd);
|
||||
|
||||
wdd->timeout = DA9063_WDG_TIMEOUT;
|
||||
|
||||
|
@ -249,10 +255,40 @@ static int da9063_wdt_probe(struct platform_device *pdev)
|
|||
return devm_watchdog_register_device(dev, wdd);
|
||||
}
|
||||
|
||||
static int __maybe_unused da9063_wdt_suspend(struct device *dev)
|
||||
{
|
||||
struct watchdog_device *wdd = dev_get_drvdata(dev);
|
||||
|
||||
if (!use_sw_pm)
|
||||
return 0;
|
||||
|
||||
if (watchdog_active(wdd))
|
||||
return da9063_wdt_stop(wdd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused da9063_wdt_resume(struct device *dev)
|
||||
{
|
||||
struct watchdog_device *wdd = dev_get_drvdata(dev);
|
||||
|
||||
if (!use_sw_pm)
|
||||
return 0;
|
||||
|
||||
if (watchdog_active(wdd))
|
||||
return da9063_wdt_start(wdd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(da9063_wdt_pm_ops,
|
||||
da9063_wdt_suspend, da9063_wdt_resume);
|
||||
|
||||
static struct platform_driver da9063_wdt_driver = {
|
||||
.probe = da9063_wdt_probe,
|
||||
.driver = {
|
||||
.name = DA9063_DRVNAME_WATCHDOG,
|
||||
.pm = &da9063_wdt_pm_ops,
|
||||
},
|
||||
};
|
||||
module_platform_driver(da9063_wdt_driver);
|
||||
|
|
|
@ -596,7 +596,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/*
|
||||
* Suspend-to-idle requires this, because it stops the ticks and timekeeping, so
|
||||
* the watchdog cannot be pinged while in that state. In ACPI sleep states the
|
||||
|
@ -604,15 +603,15 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
|
|||
*/
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static inline bool need_suspend(void)
|
||||
static inline bool __maybe_unused need_suspend(void)
|
||||
{
|
||||
return acpi_target_system_state() == ACPI_STATE_S0;
|
||||
}
|
||||
#else
|
||||
static inline bool need_suspend(void) { return true; }
|
||||
static inline bool __maybe_unused need_suspend(void) { return true; }
|
||||
#endif
|
||||
|
||||
static int iTCO_wdt_suspend_noirq(struct device *dev)
|
||||
static int __maybe_unused iTCO_wdt_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct iTCO_wdt_private *p = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
@ -626,7 +625,7 @@ static int iTCO_wdt_suspend_noirq(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int iTCO_wdt_resume_noirq(struct device *dev)
|
||||
static int __maybe_unused iTCO_wdt_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct iTCO_wdt_private *p = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -637,20 +636,15 @@ static int iTCO_wdt_resume_noirq(struct device *dev)
|
|||
}
|
||||
|
||||
static const struct dev_pm_ops iTCO_wdt_pm = {
|
||||
.suspend_noirq = iTCO_wdt_suspend_noirq,
|
||||
.resume_noirq = iTCO_wdt_resume_noirq,
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(iTCO_wdt_suspend_noirq,
|
||||
iTCO_wdt_resume_noirq)
|
||||
};
|
||||
|
||||
#define ITCO_WDT_PM_OPS (&iTCO_wdt_pm)
|
||||
#else
|
||||
#define ITCO_WDT_PM_OPS NULL
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static struct platform_driver iTCO_wdt_driver = {
|
||||
.probe = iTCO_wdt_probe,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = ITCO_WDT_PM_OPS,
|
||||
.pm = &iTCO_wdt_pm,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
*/
|
||||
|
||||
#include <dt-bindings/reset/mt2712-resets.h>
|
||||
#include <dt-bindings/reset/mt7986-resets.h>
|
||||
#include <dt-bindings/reset/mt8183-resets.h>
|
||||
#include <dt-bindings/reset/mt8186-resets.h>
|
||||
#include <dt-bindings/reset/mt8192-resets.h>
|
||||
#include <dt-bindings/reset/mt8195-resets.h>
|
||||
#include <linux/delay.h>
|
||||
|
@ -76,10 +78,18 @@ static const struct mtk_wdt_data mt2712_data = {
|
|||
.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt7986_data = {
|
||||
.toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt8183_data = {
|
||||
.toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt8186_data = {
|
||||
.toprgu_sw_rst_num = MT8186_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
||||
static const struct mtk_wdt_data mt8192_data = {
|
||||
.toprgu_sw_rst_num = MT8192_TOPRGU_SW_RST_NUM,
|
||||
};
|
||||
|
@ -418,7 +428,9 @@ static int mtk_wdt_resume(struct device *dev)
|
|||
static const struct of_device_id mtk_wdt_dt_ids[] = {
|
||||
{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
|
||||
{ .compatible = "mediatek,mt6589-wdt" },
|
||||
{ .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
|
||||
{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
|
||||
{ .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data },
|
||||
{ .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data },
|
||||
{ .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data },
|
||||
{ /* sentinel */ }
|
||||
|
|
|
@ -226,7 +226,7 @@ static int rti_wdt_probe(struct platform_device *pdev)
|
|||
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return dev_err_probe(dev, ret, "runtime pm failed\n");
|
||||
|
@ -253,6 +253,7 @@ static int rti_wdt_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (readl(wdt->base + RTIDWDCTRL) == WDENABLE_KEY) {
|
||||
int preset_heartbeat;
|
||||
u32 time_left_ms;
|
||||
u64 heartbeat_ms;
|
||||
u32 wsize;
|
||||
|
@ -263,11 +264,12 @@ static int rti_wdt_probe(struct platform_device *pdev)
|
|||
heartbeat_ms <<= WDT_PRELOAD_SHIFT;
|
||||
heartbeat_ms *= 1000;
|
||||
do_div(heartbeat_ms, wdt->freq);
|
||||
if (heartbeat_ms != heartbeat * 1000)
|
||||
preset_heartbeat = heartbeat_ms + 500;
|
||||
preset_heartbeat /= 1000;
|
||||
if (preset_heartbeat != heartbeat)
|
||||
dev_warn(dev, "watchdog already running, ignoring heartbeat config!\n");
|
||||
|
||||
heartbeat = heartbeat_ms;
|
||||
heartbeat /= 1000;
|
||||
heartbeat = preset_heartbeat;
|
||||
|
||||
wsize = readl(wdt->base + RTIWWDSIZECTRL);
|
||||
ret = rti_wdt_setup_hw_hb(wdd, wsize);
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
#define WDTSET 0x04
|
||||
#define WDTTIM 0x08
|
||||
#define WDTINT 0x0C
|
||||
#define PECR 0x10
|
||||
#define PEEN 0x14
|
||||
#define WDTCNT_WDTEN BIT(0)
|
||||
#define WDTINT_INTDISP BIT(0)
|
||||
#define PEEN_FORCE BIT(0)
|
||||
|
||||
#define WDT_DEFAULT_TIMEOUT 60U
|
||||
|
||||
|
@ -43,6 +46,8 @@ struct rzg2l_wdt_priv {
|
|||
struct reset_control *rstc;
|
||||
unsigned long osc_clk_rate;
|
||||
unsigned long delay;
|
||||
struct clk *pclk;
|
||||
struct clk *osc_clk;
|
||||
};
|
||||
|
||||
static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
|
||||
|
@ -53,7 +58,7 @@ static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv)
|
|||
|
||||
static u32 rzg2l_wdt_get_cycle_usec(unsigned long cycle, u32 wdttime)
|
||||
{
|
||||
u64 timer_cycle_us = 1024 * 1024 * (wdttime + 1) * MICRO;
|
||||
u64 timer_cycle_us = 1024 * 1024ULL * (wdttime + 1) * MICRO;
|
||||
|
||||
return div64_ul(timer_cycle_us, cycle);
|
||||
}
|
||||
|
@ -86,7 +91,6 @@ static int rzg2l_wdt_start(struct watchdog_device *wdev)
|
|||
{
|
||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
|
||||
reset_control_deassert(priv->rstc);
|
||||
pm_runtime_get_sync(wdev->parent);
|
||||
|
||||
/* Initialize time out */
|
||||
|
@ -106,7 +110,26 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev)
|
|||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
|
||||
pm_runtime_put(wdev->parent);
|
||||
reset_control_assert(priv->rstc);
|
||||
reset_control_reset(priv->rstc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzg2l_wdt_set_timeout(struct watchdog_device *wdev, unsigned int timeout)
|
||||
{
|
||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
|
||||
wdev->timeout = timeout;
|
||||
|
||||
/*
|
||||
* If the watchdog is active, reset the module for updating the WDTSET
|
||||
* register so that it is updated with new timeout values.
|
||||
*/
|
||||
if (watchdog_active(wdev)) {
|
||||
pm_runtime_put(wdev->parent);
|
||||
reset_control_reset(priv->rstc);
|
||||
rzg2l_wdt_start(wdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -116,15 +139,14 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
|
|||
{
|
||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
|
||||
/* Reset the module before we modify any register */
|
||||
reset_control_reset(priv->rstc);
|
||||
pm_runtime_get_sync(wdev->parent);
|
||||
clk_prepare_enable(priv->pclk);
|
||||
clk_prepare_enable(priv->osc_clk);
|
||||
|
||||
/* smallest counter value to reboot soon */
|
||||
rzg2l_wdt_write(priv, WDTSET_COUNTER_VAL(1), WDTSET);
|
||||
/* Generate Reset (WDTRSTB) Signal on parity error */
|
||||
rzg2l_wdt_write(priv, 0, PECR);
|
||||
|
||||
/* Enable watchdog timer*/
|
||||
rzg2l_wdt_write(priv, WDTCNT_WDTEN, WDTCNT);
|
||||
/* Force parity error */
|
||||
rzg2l_wdt_write(priv, PEEN_FORCE, PEEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -148,15 +170,15 @@ static const struct watchdog_ops rzg2l_wdt_ops = {
|
|||
.start = rzg2l_wdt_start,
|
||||
.stop = rzg2l_wdt_stop,
|
||||
.ping = rzg2l_wdt_ping,
|
||||
.set_timeout = rzg2l_wdt_set_timeout,
|
||||
.restart = rzg2l_wdt_restart,
|
||||
};
|
||||
|
||||
static void rzg2l_wdt_reset_assert_pm_disable_put(void *data)
|
||||
static void rzg2l_wdt_reset_assert_pm_disable(void *data)
|
||||
{
|
||||
struct watchdog_device *wdev = data;
|
||||
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
|
||||
pm_runtime_put(wdev->parent);
|
||||
pm_runtime_disable(wdev->parent);
|
||||
reset_control_assert(priv->rstc);
|
||||
}
|
||||
|
@ -166,7 +188,6 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|||
struct device *dev = &pdev->dev;
|
||||
struct rzg2l_wdt_priv *priv;
|
||||
unsigned long pclk_rate;
|
||||
struct clk *wdt_clk;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
|
@ -178,22 +199,20 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(priv->base);
|
||||
|
||||
/* Get watchdog main clock */
|
||||
wdt_clk = clk_get(&pdev->dev, "oscclk");
|
||||
if (IS_ERR(wdt_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(wdt_clk), "no oscclk");
|
||||
priv->osc_clk = devm_clk_get(&pdev->dev, "oscclk");
|
||||
if (IS_ERR(priv->osc_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->osc_clk), "no oscclk");
|
||||
|
||||
priv->osc_clk_rate = clk_get_rate(wdt_clk);
|
||||
clk_put(wdt_clk);
|
||||
priv->osc_clk_rate = clk_get_rate(priv->osc_clk);
|
||||
if (!priv->osc_clk_rate)
|
||||
return dev_err_probe(&pdev->dev, -EINVAL, "oscclk rate is 0");
|
||||
|
||||
/* Get Peripheral clock */
|
||||
wdt_clk = clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(wdt_clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(wdt_clk), "no pclk");
|
||||
priv->pclk = devm_clk_get(&pdev->dev, "pclk");
|
||||
if (IS_ERR(priv->pclk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk), "no pclk");
|
||||
|
||||
pclk_rate = clk_get_rate(wdt_clk);
|
||||
clk_put(wdt_clk);
|
||||
pclk_rate = clk_get_rate(priv->pclk);
|
||||
if (!pclk_rate)
|
||||
return dev_err_probe(&pdev->dev, -EINVAL, "pclk rate is 0");
|
||||
|
||||
|
@ -204,13 +223,11 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(&pdev->dev, PTR_ERR(priv->rstc),
|
||||
"failed to get cpg reset");
|
||||
|
||||
reset_control_deassert(priv->rstc);
|
||||
ret = reset_control_deassert(priv->rstc);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to deassert");
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
ret = pm_runtime_resume_and_get(&pdev->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "pm_runtime_resume_and_get failed ret=%pe", ERR_PTR(ret));
|
||||
goto out_pm_get;
|
||||
}
|
||||
|
||||
priv->wdev.info = &rzg2l_wdt_ident;
|
||||
priv->wdev.ops = &rzg2l_wdt_ops;
|
||||
|
@ -222,7 +239,7 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|||
|
||||
watchdog_set_drvdata(&priv->wdev, priv);
|
||||
ret = devm_add_action_or_reset(&pdev->dev,
|
||||
rzg2l_wdt_reset_assert_pm_disable_put,
|
||||
rzg2l_wdt_reset_assert_pm_disable,
|
||||
&priv->wdev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -235,12 +252,6 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
|
|||
dev_warn(dev, "Specified timeout invalid, using default");
|
||||
|
||||
return devm_watchdog_register_device(&pdev->dev, &priv->wdev);
|
||||
|
||||
out_pm_get:
|
||||
pm_runtime_disable(dev);
|
||||
reset_control_assert(priv->rstc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id rzg2l_wdt_ids[] = {
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Renesas RZ/N1 Watchdog timer.
|
||||
* This is a 12-bit timer driver from a (62.5/16384) MHz clock. It can't even
|
||||
* cope with 2 seconds.
|
||||
*
|
||||
* Copyright 2018 Renesas Electronics Europe Ltd.
|
||||
*
|
||||
* Derived from Ralink RT288x watchdog timer.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
#define DEFAULT_TIMEOUT 60
|
||||
|
||||
#define RZN1_WDT_RETRIGGER 0x0
|
||||
#define RZN1_WDT_RETRIGGER_RELOAD_VAL 0
|
||||
#define RZN1_WDT_RETRIGGER_RELOAD_VAL_MASK 0xfff
|
||||
#define RZN1_WDT_RETRIGGER_PRESCALE BIT(12)
|
||||
#define RZN1_WDT_RETRIGGER_ENABLE BIT(13)
|
||||
#define RZN1_WDT_RETRIGGER_WDSI (0x2 << 14)
|
||||
|
||||
#define RZN1_WDT_PRESCALER 16384
|
||||
#define RZN1_WDT_MAX 4095
|
||||
|
||||
struct rzn1_watchdog {
|
||||
struct watchdog_device wdtdev;
|
||||
void __iomem *base;
|
||||
unsigned long clk_rate_khz;
|
||||
};
|
||||
|
||||
static inline uint32_t max_heart_beat_ms(unsigned long clk_rate_khz)
|
||||
{
|
||||
return (RZN1_WDT_MAX * RZN1_WDT_PRESCALER) / clk_rate_khz;
|
||||
}
|
||||
|
||||
static inline uint32_t compute_reload_value(uint32_t tick_ms,
|
||||
unsigned long clk_rate_khz)
|
||||
{
|
||||
return (tick_ms * clk_rate_khz) / RZN1_WDT_PRESCALER;
|
||||
}
|
||||
|
||||
static int rzn1_wdt_ping(struct watchdog_device *w)
|
||||
{
|
||||
struct rzn1_watchdog *wdt = watchdog_get_drvdata(w);
|
||||
|
||||
/* Any value retrigggers the watchdog */
|
||||
writel(0, wdt->base + RZN1_WDT_RETRIGGER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzn1_wdt_start(struct watchdog_device *w)
|
||||
{
|
||||
struct rzn1_watchdog *wdt = watchdog_get_drvdata(w);
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* The hardware allows you to write to this reg only once.
|
||||
* Since this includes the reload value, there is no way to change the
|
||||
* timeout once started. Also note that the WDT clock is half the bus
|
||||
* fabric clock rate, so if the bus fabric clock rate is changed after
|
||||
* the WDT is started, the WDT interval will be wrong.
|
||||
*/
|
||||
val = RZN1_WDT_RETRIGGER_WDSI;
|
||||
val |= RZN1_WDT_RETRIGGER_ENABLE;
|
||||
val |= RZN1_WDT_RETRIGGER_PRESCALE;
|
||||
val |= compute_reload_value(w->max_hw_heartbeat_ms, wdt->clk_rate_khz);
|
||||
writel(val, wdt->base + RZN1_WDT_RETRIGGER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rzn1_wdt_irq(int irq, void *_wdt)
|
||||
{
|
||||
pr_crit("RZN1 Watchdog. Initiating system reboot\n");
|
||||
emergency_restart();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct watchdog_info rzn1_wdt_info = {
|
||||
.identity = "RZ/N1 Watchdog",
|
||||
.options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
|
||||
};
|
||||
|
||||
static const struct watchdog_ops rzn1_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = rzn1_wdt_start,
|
||||
.ping = rzn1_wdt_ping,
|
||||
};
|
||||
|
||||
static void rzn1_wdt_clk_disable_unprepare(void *data)
|
||||
{
|
||||
clk_disable_unprepare(data);
|
||||
}
|
||||
|
||||
static int rzn1_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rzn1_watchdog *wdt;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct clk *clk;
|
||||
unsigned long clk_rate;
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
|
||||
if (!wdt)
|
||||
return -ENOMEM;
|
||||
|
||||
wdt->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(wdt->base))
|
||||
return PTR_ERR(wdt->base);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_irq(dev, irq, rzn1_wdt_irq, 0,
|
||||
np->name, wdt);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request irq %d\n", irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "failed to get the clock\n");
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to prepare/enable the clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_add_action_or_reset(dev, rzn1_wdt_clk_disable_unprepare,
|
||||
clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_rate = clk_get_rate(clk);
|
||||
if (!clk_rate) {
|
||||
dev_err(dev, "failed to get the clock rate\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wdt->clk_rate_khz = clk_rate / 1000;
|
||||
wdt->wdtdev.info = &rzn1_wdt_info,
|
||||
wdt->wdtdev.ops = &rzn1_wdt_ops,
|
||||
wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS,
|
||||
wdt->wdtdev.parent = dev;
|
||||
/*
|
||||
* The period of the watchdog cannot be changed once set
|
||||
* and is limited to a very short period.
|
||||
* Configure it for a 1s period once and for all, and
|
||||
* rely on the heart-beat provided by the watchdog core
|
||||
* to make this usable by the user-space.
|
||||
*/
|
||||
wdt->wdtdev.max_hw_heartbeat_ms = max_heart_beat_ms(wdt->clk_rate_khz);
|
||||
if (wdt->wdtdev.max_hw_heartbeat_ms > 1000)
|
||||
wdt->wdtdev.max_hw_heartbeat_ms = 1000;
|
||||
|
||||
wdt->wdtdev.timeout = DEFAULT_TIMEOUT;
|
||||
ret = watchdog_init_timeout(&wdt->wdtdev, 0, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
watchdog_set_drvdata(&wdt->wdtdev, wdt);
|
||||
|
||||
return devm_watchdog_register_device(dev, &wdt->wdtdev);
|
||||
}
|
||||
|
||||
|
||||
static const struct of_device_id rzn1_wdt_match[] = {
|
||||
{ .compatible = "renesas,rzn1-wdt" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rzn1_wdt_match);
|
||||
|
||||
static struct platform_driver rzn1_wdt_driver = {
|
||||
.probe = rzn1_wdt_probe,
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.of_match_table = rzn1_wdt_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(rzn1_wdt_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Renesas RZ/N1 hardware watchdog");
|
||||
MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -272,6 +272,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
watchdog_set_nowayout(&wdt->wdd, nowayout);
|
||||
watchdog_set_drvdata(&wdt->wdd, wdt);
|
||||
watchdog_set_restart_priority(&wdt->wdd, 128);
|
||||
watchdog_stop_on_unregister(&wdt->wdd);
|
||||
|
||||
/*
|
||||
* If 'timeout-sec' devicetree property is specified, use that.
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* sunplus Watchdog Driver
|
||||
*
|
||||
* Copyright (C) 2021 Sunplus Technology Co., Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
#include <linux/watchdog.h>
|
||||
|
||||
#define WDT_CTRL 0x00
|
||||
#define WDT_CNT 0x04
|
||||
|
||||
#define WDT_STOP 0x3877
|
||||
#define WDT_RESUME 0x4A4B
|
||||
#define WDT_CLRIRQ 0x7482
|
||||
#define WDT_UNLOCK 0xAB00
|
||||
#define WDT_LOCK 0xAB01
|
||||
#define WDT_CONMAX 0xDEAF
|
||||
|
||||
/* TIMEOUT_MAX = ffff0/90kHz =11.65, so longer than 11 seconds will time out. */
|
||||
#define SP_WDT_MAX_TIMEOUT 11U
|
||||
#define SP_WDT_DEFAULT_TIMEOUT 10
|
||||
|
||||
#define STC_CLK 90000
|
||||
|
||||
#define DEVICE_NAME "sunplus-wdt"
|
||||
|
||||
static unsigned int timeout;
|
||||
module_param(timeout, int, 0);
|
||||
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
|
||||
|
||||
static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
module_param(nowayout, bool, 0);
|
||||
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
struct sp_wdt_priv {
|
||||
struct watchdog_device wdev;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct reset_control *rstc;
|
||||
};
|
||||
|
||||
static int sp_wdt_restart(struct watchdog_device *wdev,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
void __iomem *base = priv->base;
|
||||
|
||||
writel(WDT_STOP, base + WDT_CTRL);
|
||||
writel(WDT_UNLOCK, base + WDT_CTRL);
|
||||
writel(0x0001, base + WDT_CNT);
|
||||
writel(WDT_LOCK, base + WDT_CTRL);
|
||||
writel(WDT_RESUME, base + WDT_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_wdt_ping(struct watchdog_device *wdev)
|
||||
{
|
||||
struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
void __iomem *base = priv->base;
|
||||
u32 count;
|
||||
|
||||
if (wdev->timeout > SP_WDT_MAX_TIMEOUT) {
|
||||
/* WDT_CONMAX sets the count to the maximum (down-counting). */
|
||||
writel(WDT_CONMAX, base + WDT_CTRL);
|
||||
} else {
|
||||
writel(WDT_UNLOCK, base + WDT_CTRL);
|
||||
/*
|
||||
* Watchdog timer is a 20-bit down-counting based on STC_CLK.
|
||||
* This register bits[16:0] is from bit[19:4] of the watchdog
|
||||
* timer counter.
|
||||
*/
|
||||
count = (wdev->timeout * STC_CLK) >> 4;
|
||||
writel(count, base + WDT_CNT);
|
||||
writel(WDT_LOCK, base + WDT_CTRL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_wdt_stop(struct watchdog_device *wdev)
|
||||
{
|
||||
struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
void __iomem *base = priv->base;
|
||||
|
||||
writel(WDT_STOP, base + WDT_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_wdt_start(struct watchdog_device *wdev)
|
||||
{
|
||||
struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
void __iomem *base = priv->base;
|
||||
|
||||
writel(WDT_RESUME, base + WDT_CTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int sp_wdt_get_timeleft(struct watchdog_device *wdev)
|
||||
{
|
||||
struct sp_wdt_priv *priv = watchdog_get_drvdata(wdev);
|
||||
void __iomem *base = priv->base;
|
||||
u32 val;
|
||||
|
||||
val = readl(base + WDT_CNT);
|
||||
val &= 0xffff;
|
||||
val = val << 4;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static const struct watchdog_info sp_wdt_info = {
|
||||
.identity = DEVICE_NAME,
|
||||
.options = WDIOF_SETTIMEOUT |
|
||||
WDIOF_MAGICCLOSE |
|
||||
WDIOF_KEEPALIVEPING,
|
||||
};
|
||||
|
||||
static const struct watchdog_ops sp_wdt_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.start = sp_wdt_start,
|
||||
.stop = sp_wdt_stop,
|
||||
.ping = sp_wdt_ping,
|
||||
.get_timeleft = sp_wdt_get_timeleft,
|
||||
.restart = sp_wdt_restart,
|
||||
};
|
||||
|
||||
static void sp_clk_disable_unprepare(void *data)
|
||||
{
|
||||
clk_disable_unprepare(data);
|
||||
}
|
||||
|
||||
static void sp_reset_control_assert(void *data)
|
||||
{
|
||||
reset_control_assert(data);
|
||||
}
|
||||
|
||||
static int sp_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct sp_wdt_priv *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(priv->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->clk), "Failed to get clock\n");
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to enable clock\n");
|
||||
|
||||
ret = devm_add_action_or_reset(dev, sp_clk_disable_unprepare, priv->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* The timer and watchdog shared the STC reset */
|
||||
priv->rstc = devm_reset_control_get_shared(dev, NULL);
|
||||
if (IS_ERR(priv->rstc))
|
||||
return dev_err_probe(dev, PTR_ERR(priv->rstc), "Failed to get reset\n");
|
||||
|
||||
reset_control_deassert(priv->rstc);
|
||||
|
||||
ret = devm_add_action_or_reset(dev, sp_reset_control_assert, priv->rstc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
priv->wdev.info = &sp_wdt_info;
|
||||
priv->wdev.ops = &sp_wdt_ops;
|
||||
priv->wdev.timeout = SP_WDT_DEFAULT_TIMEOUT;
|
||||
priv->wdev.max_hw_heartbeat_ms = SP_WDT_MAX_TIMEOUT * 1000;
|
||||
priv->wdev.min_timeout = 1;
|
||||
priv->wdev.parent = dev;
|
||||
|
||||
watchdog_set_drvdata(&priv->wdev, priv);
|
||||
watchdog_init_timeout(&priv->wdev, timeout, dev);
|
||||
watchdog_set_nowayout(&priv->wdev, nowayout);
|
||||
watchdog_stop_on_reboot(&priv->wdev);
|
||||
watchdog_set_restart_priority(&priv->wdev, 128);
|
||||
|
||||
return devm_watchdog_register_device(dev, &priv->wdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id sp_wdt_of_match[] = {
|
||||
{.compatible = "sunplus,sp7021-wdt", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sp_wdt_of_match);
|
||||
|
||||
static struct platform_driver sp_wdt_driver = {
|
||||
.probe = sp_wdt_probe,
|
||||
.driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.of_match_table = sp_wdt_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(sp_wdt_driver);
|
||||
|
||||
MODULE_AUTHOR("Xiantao Hu <xt.hu@cqplus1.com>");
|
||||
MODULE_DESCRIPTION("Sunplus Watchdog Timer Driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -125,13 +125,16 @@ static int ts4800_wdt_probe(struct platform_device *pdev)
|
|||
ret = of_property_read_u32_index(np, "syscon", 1, ®);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "no offset in syscon\n");
|
||||
of_node_put(syscon_np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* allocate memory for watchdog struct */
|
||||
wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
|
||||
if (!wdt)
|
||||
if (!wdt) {
|
||||
of_node_put(syscon_np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* set regmap and offset to know where to write */
|
||||
wdt->feed_offset = reg;
|
||||
|
|
|
@ -344,6 +344,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
|
|||
wdat->period = tbl->timer_period;
|
||||
wdat->wdd.min_hw_heartbeat_ms = wdat->period * tbl->min_count;
|
||||
wdat->wdd.max_hw_heartbeat_ms = wdat->period * tbl->max_count;
|
||||
wdat->wdd.min_timeout = 1;
|
||||
wdat->stopped_in_sleep = tbl->flags & ACPI_WDAT_STOPPED;
|
||||
wdat->wdd.info = &wdat_wdt_info;
|
||||
wdat->wdd.ops = &wdat_wdt_ops;
|
||||
|
@ -450,8 +451,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
|
|||
* watchdog properly after it has opened the device. In some cases
|
||||
* the BIOS default is too short and causes immediate reboot.
|
||||
*/
|
||||
if (timeout * 1000 < wdat->wdd.min_hw_heartbeat_ms ||
|
||||
timeout * 1000 > wdat->wdd.max_hw_heartbeat_ms) {
|
||||
if (watchdog_timeout_invalid(&wdat->wdd, timeout)) {
|
||||
dev_warn(dev, "Invalid timeout %d given, using %d\n",
|
||||
timeout, WDAT_DEFAULT_TIMEOUT);
|
||||
timeout = WDAT_DEFAULT_TIMEOUT;
|
||||
|
@ -462,6 +462,8 @@ static int wdat_wdt_probe(struct platform_device *pdev)
|
|||
return ret;
|
||||
|
||||
watchdog_set_nowayout(&wdat->wdd, nowayout);
|
||||
watchdog_stop_on_reboot(&wdat->wdd);
|
||||
watchdog_stop_on_unregister(&wdat->wdd);
|
||||
return devm_watchdog_register_device(dev, &wdat->wdd);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
|
||||
/*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Sam Shih <sam.shih@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT7986
|
||||
#define _DT_BINDINGS_RESET_CONTROLLER_MT7986
|
||||
|
||||
/* INFRACFG resets */
|
||||
#define MT7986_INFRACFG_PEXTP_MAC_SW_RST 6
|
||||
#define MT7986_INFRACFG_SSUSB_SW_RST 7
|
||||
#define MT7986_INFRACFG_EIP97_SW_RST 8
|
||||
#define MT7986_INFRACFG_AUDIO_SW_RST 13
|
||||
#define MT7986_INFRACFG_CQ_DMA_SW_RST 14
|
||||
|
||||
#define MT7986_INFRACFG_TRNG_SW_RST 17
|
||||
#define MT7986_INFRACFG_AP_DMA_SW_RST 32
|
||||
#define MT7986_INFRACFG_I2C_SW_RST 33
|
||||
#define MT7986_INFRACFG_NFI_SW_RST 34
|
||||
#define MT7986_INFRACFG_SPI0_SW_RST 35
|
||||
#define MT7986_INFRACFG_SPI1_SW_RST 36
|
||||
#define MT7986_INFRACFG_UART0_SW_RST 37
|
||||
#define MT7986_INFRACFG_UART1_SW_RST 38
|
||||
#define MT7986_INFRACFG_UART2_SW_RST 39
|
||||
#define MT7986_INFRACFG_AUXADC_SW_RST 43
|
||||
|
||||
#define MT7986_INFRACFG_APXGPT_SW_RST 66
|
||||
#define MT7986_INFRACFG_PWM_SW_RST 68
|
||||
|
||||
#define MT7986_INFRACFG_SW_RST_NUM 69
|
||||
|
||||
/* TOPRGU resets */
|
||||
#define MT7986_TOPRGU_APMIXEDSYS_SW_RST 0
|
||||
#define MT7986_TOPRGU_SGMII0_SW_RST 1
|
||||
#define MT7986_TOPRGU_SGMII1_SW_RST 2
|
||||
#define MT7986_TOPRGU_INFRA_SW_RST 3
|
||||
#define MT7986_TOPRGU_U2PHY_SW_RST 5
|
||||
#define MT7986_TOPRGU_PCIE_SW_RST 6
|
||||
#define MT7986_TOPRGU_SSUSB_SW_RST 7
|
||||
#define MT7986_TOPRGU_ETHDMA_SW_RST 20
|
||||
#define MT7986_TOPRGU_CONSYS_SW_RST 23
|
||||
|
||||
#define MT7986_TOPRGU_SW_RST_NUM 24
|
||||
|
||||
/* ETHSYS Subsystem resets */
|
||||
#define MT7986_ETHSYS_FE_SW_RST 6
|
||||
#define MT7986_ETHSYS_PMTR_SW_RST 8
|
||||
#define MT7986_ETHSYS_GMAC_SW_RST 23
|
||||
#define MT7986_ETHSYS_PPE0_SW_RST 30
|
||||
#define MT7986_ETHSYS_PPE1_SW_RST 31
|
||||
|
||||
#define MT7986_ETHSYS_SW_RST_NUM 32
|
||||
|
||||
#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT7986 */
|
|
@ -0,0 +1,36 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
|
||||
/*
|
||||
* Copyright (c) 2022 MediaTek Inc.
|
||||
* Author: Runyang Chen <runyang.chen@mediatek.com>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_RESET_CONTROLLER_MT8186
|
||||
#define _DT_BINDINGS_RESET_CONTROLLER_MT8186
|
||||
|
||||
#define MT8186_TOPRGU_INFRA_SW_RST 0
|
||||
#define MT8186_TOPRGU_MM_SW_RST 1
|
||||
#define MT8186_TOPRGU_MFG_SW_RST 2
|
||||
#define MT8186_TOPRGU_VENC_SW_RST 3
|
||||
#define MT8186_TOPRGU_VDEC_SW_RST 4
|
||||
#define MT8186_TOPRGU_IMG_SW_RST 5
|
||||
#define MT8186_TOPRGU_DDR_SW_RST 6
|
||||
#define MT8186_TOPRGU_INFRA_AO_SW_RST 8
|
||||
#define MT8186_TOPRGU_CONNSYS_SW_RST 9
|
||||
#define MT8186_TOPRGU_APMIXED_SW_RST 10
|
||||
#define MT8186_TOPRGU_PWRAP_SW_RST 11
|
||||
#define MT8186_TOPRGU_CONN_MCU_SW_RST 12
|
||||
#define MT8186_TOPRGU_IPNNA_SW_RST 13
|
||||
#define MT8186_TOPRGU_WPE_SW_RST 14
|
||||
#define MT8186_TOPRGU_ADSP_SW_RST 15
|
||||
#define MT8186_TOPRGU_AUDIO_SW_RST 17
|
||||
#define MT8186_TOPRGU_CAM_MAIN_SW_RST 18
|
||||
#define MT8186_TOPRGU_CAM_RAWA_SW_RST 19
|
||||
#define MT8186_TOPRGU_CAM_RAWB_SW_RST 20
|
||||
#define MT8186_TOPRGU_IPE_SW_RST 21
|
||||
#define MT8186_TOPRGU_IMG2_SW_RST 22
|
||||
#define MT8186_TOPRGU_SW_RST_NUM 23
|
||||
|
||||
/* MMSYS resets */
|
||||
#define MT8186_MMSYS_SW0_RST_B_DISP_DSI0 19
|
||||
|
||||
#endif /* _DT_BINDINGS_RESET_CONTROLLER_MT8186 */
|
Loading…
Reference in New Issue