From a45b408a020ba53e0a2b2214e1371ef6d42ad5c4 Mon Sep 17 00:00:00 2001 From: Rex-BC Chen Date: Tue, 1 Mar 2022 13:37:31 +0800 Subject: [PATCH 01/38] dt-bindings: watchdog: Add compatible for MediaTek MT8186 Add dt-binding documentation of watchdog for MediaTek MT8186 SoC. Signed-off-by: Rex-BC Chen Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220301054405.25021-2-rex-bc.chen@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/mtk-wdt.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt index a97418c74f6bc..762c62e428ef2 100644 --- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt @@ -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 From 1d6866e8f15c978e82ef16ce6d21ee96b2eca7ee Mon Sep 17 00:00:00 2001 From: Runyang Chen Date: Tue, 1 Mar 2022 13:37:32 +0800 Subject: [PATCH 02/38] dt-bindings: reset: mt8186: add reset-controller header file 1. Add toprgu reset-controller header file for MT8186. 2. Add DSI software reset bit which is controlled in MMSYS for MT8186. Signed-off-by: Runyang Chen Signed-off-by: Rex-BC Chen Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220301054405.25021-3-rex-bc.chen@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- include/dt-bindings/reset/mt8186-resets.h | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 include/dt-bindings/reset/mt8186-resets.h diff --git a/include/dt-bindings/reset/mt8186-resets.h b/include/dt-bindings/reset/mt8186-resets.h new file mode 100644 index 0000000000000..5f850370c42c9 --- /dev/null +++ b/include/dt-bindings/reset/mt8186-resets.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Runyang Chen + */ + +#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 */ From 4dbabc4d9e8cc6d8267a9883d6694c8925235e1a Mon Sep 17 00:00:00 2001 From: Runyang Chen Date: Tue, 1 Mar 2022 13:37:33 +0800 Subject: [PATCH 03/38] watchdog: mediatek: mt8186: add wdt support Support MT8186 watchdog device. Signed-off-by: Runyang Chen Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220301054405.25021-4-rex-bc.chen@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtk_wdt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 4577a76dd464f..fe5a2ecba97a6 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -80,6 +81,10 @@ 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, }; @@ -419,6 +424,7 @@ static const struct of_device_id mtk_wdt_dt_ids[] = { { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data }, { .compatible = "mediatek,mt6589-wdt" }, { .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 */ } From 100ad27e9537aa1187b86c249b1b48e451ded4cb Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 15 Feb 2022 16:12:02 +0800 Subject: [PATCH 04/38] dt-bindings: watchdog: imx7ulp-wdt: Add imx93 compatible string The wdog on i.MX93 is modified from i.MX8ULP with some changes, it uses one compatible string, so add i.MX93 support. Signed-off-by: Peng Fan Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220215081202.787853-1-peng.fan@oss.nxp.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml index 4ca8a31359a55..8562978aa0c8b 100644 --- a/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/fsl-imx7ulp-wdt.yaml @@ -19,6 +19,7 @@ properties: - items: - const: fsl,imx8ulp-wdt - const: fsl,imx7ulp-wdt + - const: fsl,imx93-wdt reg: maxItems: 1 From 2dd441f16d6ad6104d85c4e5dfeb6dde4df26869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Wed, 16 Feb 2022 07:34:08 +0100 Subject: [PATCH 05/38] watchdog: bcm7038_wdt: Support BCM6345 compatible string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new "compatible" value has been added in the commit 17fffe91ba36 ("dt-bindings: watchdog: Add BCM6345 compatible to BCM7038 binding"). It's meant to be used for BCM63xx SoCs family but hardware block can be programmed just like the 7038 one. Cc: Florian Fainelli Signed-off-by: Rafał Miłecki Acked-by: Florian Fainelli Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220216063408.23168-1-zajec5@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/bcm7038_wdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c index 8656a137e9a4a..1ffcf6aca6aee 100644 --- a/drivers/watchdog/bcm7038_wdt.c +++ b/drivers/watchdog/bcm7038_wdt.c @@ -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" }, {}, }; From 711a5b25bac95dcd1111521ed71693330e74a926 Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Wed, 5 Jan 2022 18:04:56 +0800 Subject: [PATCH 06/38] watchdog: mtk_wdt: mt7986: Add toprgu reset controller support Besides watchdog, the mt7986 toprgu module also provides software reset functionality for various peripheral subsystems (eg, ethernet, pcie, and connectivity) Signed-off-by: Sam Shih Reviewed-by: Matthias Brugger Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220105100456.7126-3-sam.shih@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtk_wdt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index fe5a2ecba97a6..f0d4e3cc74590 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -77,6 +78,10 @@ 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, }; @@ -423,6 +428,7 @@ 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 }, From a03f70cfb283c48a5f0925fe868b479bc9b66fd4 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Tue, 11 Jan 2022 22:23:10 +0100 Subject: [PATCH 07/38] dt-bindings: watchdog: improve QCOM compatible parsing for modern chips Parse compatible as expected for modern QCOMs. Fixes warnings as: arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dt.yaml: watchdog@17980000: compatible: ['qcom,apss-wdt-sdm845', 'qcom,kpss-wdt'] is too long From schema: Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml arch/arm64/boot/dts/qcom/sdm845-oneplus-fajita.dt.yaml: watchdog@17980000: compatible: Additional items are not allowed ('qcom,kpss-wdt' was unexpected) From schema: Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml Signed-off-by: David Heidelberg Reviewed-by: Bjorn Andersson Reviewed-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220111212310.97566-1-david@ixit.cz Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/qcom-wdt.yaml | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index 16c6f82a13ca2..4ff8c59c59ab7 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -14,22 +14,27 @@ 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-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 From 289660a4af0e1e38873b7a5cc772114d3b911427 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Fri, 11 Feb 2022 11:55:28 +0000 Subject: [PATCH 08/38] dt-bindings: watchdog: convert faraday,ftwdt010 to yaml Converts watchdog/faraday,ftwdt010.txt to yaml. This permits to detect missing properties like clocks and resets or compatible like moxa,moxart-watchdog. Signed-off-by: Corentin Labbe Reviewed-by: Linus Walleij Reviewed-by: Krzysztof Kozlowski Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220211115528.3382374-1-clabbe@baylibre.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/faraday,ftwdt010.txt | 22 ------ .../bindings/watchdog/faraday,ftwdt010.yaml | 67 +++++++++++++++++++ 2 files changed, 67 insertions(+), 22 deletions(-) delete mode 100644 Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt create mode 100644 Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml diff --git a/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt b/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt deleted file mode 100644 index 9ecdb502e6059..0000000000000 --- a/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.txt +++ /dev/null @@ -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>; -}; diff --git a/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml b/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml new file mode 100644 index 0000000000000..ca9e1beff76b6 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/faraday,ftwdt010.yaml @@ -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 + - Corentin Labbe + +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 + 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"; + }; +... From ea2949df22a533cdf75e4583c00b1ce94cd5a83b Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 25 Feb 2022 17:53:14 +0000 Subject: [PATCH 09/38] watchdog: rzg2l_wdt: Fix 32bit overflow issue The value of timer_cycle_us can be 0 due to 32bit overflow. For eg:- If we assign the counter value "0xfff" for computing maxval. This patch fixes this issue by appending ULL to 1024, so that it is promoted to 64bit. This patch also fixes the warning message, 'watchdog: Invalid min and max timeout values, resetting to 0!'. Fixes: 2cbc5cd0b55fa2 ("watchdog: Add Watchdog Timer driver for RZ/G2L") Signed-off-by: Biju Das Reviewed-by: Guenter Roeck Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20220225175320.11041-2-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 6b426df34fd6f..96f2a018ab626 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -53,7 +53,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); } From 95abafe76297fa057de6c3486ef844bd446bdf18 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 25 Feb 2022 17:53:15 +0000 Subject: [PATCH 10/38] watchdog: rzg2l_wdt: Fix Runtime PM usage Both rzg2l_wdt_probe() and rzg2l_wdt_start() calls pm_runtime_get() which results in a usage counter imbalance. This patch fixes this issue by removing pm_runtime_get() call from probe. Fixes: 2cbc5cd0b55fa2 ("watchdog: Add Watchdog Timer driver for RZ/G2L") Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220225175320.11041-3-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 96f2a018ab626..0fc73b8a9567e 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -151,12 +151,11 @@ static const struct watchdog_ops rzg2l_wdt_ops = { .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); } @@ -206,11 +205,6 @@ static int rzg2l_wdt_probe(struct platform_device *pdev) reset_control_deassert(priv->rstc); 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 +216,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 +229,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[] = { From e4cf89596c1f1e33309556699f910ced4abbaf44 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 25 Feb 2022 17:53:16 +0000 Subject: [PATCH 11/38] watchdog: rzg2l_wdt: Fix 'BUG: Invalid wait context' This patch fixes the issue 'BUG: Invalid wait context' during restart() callback by using clk_prepare_enable() instead of pm_runtime_get_sync() for turning on the clocks during restart. This issue is noticed when testing with renesas_defconfig. [ 42.213802] reboot: Restarting system [ 42.217860] [ 42.219364] ============================= [ 42.223368] [ BUG: Invalid wait context ] [ 42.227372] 5.17.0-rc5-arm64-renesas-00002-g10393723e35e #522 Not tainted [ 42.234153] ----------------------------- [ 42.238155] systemd-shutdow/1 is trying to lock: [ 42.242766] ffff00000a650828 (&genpd->mlock){+.+.}-{3:3}, at: genpd_lock_mtx+0x14/0x20 [ 42.250709] other info that might help us debug this: [ 42.255753] context-{4:4} [ 42.258368] 2 locks held by systemd-shutdow/1: [ 42.262806] #0: ffff80000944e1c8 (system_transition_mutex#2){+.+.}-{3:3}, at: __do_sys_reboot+0xd0/0x250 [ 42.272388] #1: ffff8000094c4e40 (rcu_read_lock){....}-{1:2}, at: atomic_notifier_call_chain+0x0/0x150 [ 42.281795] stack backtrace: [ 42.284672] CPU: 0 PID: 1 Comm: systemd-shutdow Not tainted 5.17.0-rc5-arm64-renesas-00002-g10393723e35e #522 [ 42.294577] Hardware name: Renesas SMARC EVK based on r9a07g044c2 (DT) [ 42.301096] Call trace: [ 42.303538] dump_backtrace+0xcc/0xd8 [ 42.307203] show_stack+0x14/0x30 [ 42.310517] dump_stack_lvl+0x88/0xb0 [ 42.314180] dump_stack+0x14/0x2c [ 42.317492] __lock_acquire+0x1b24/0x1b50 [ 42.321502] lock_acquire+0x120/0x3a8 [ 42.325162] __mutex_lock+0x84/0x8f8 [ 42.328737] mutex_lock_nested+0x30/0x58 [ 42.332658] genpd_lock_mtx+0x14/0x20 [ 42.336319] genpd_runtime_resume+0xc4/0x228 [ 42.340587] __rpm_callback+0x44/0x170 [ 42.344337] rpm_callback+0x64/0x70 [ 42.347824] rpm_resume+0x4e0/0x6b8 [ 42.351310] __pm_runtime_resume+0x50/0x78 [ 42.355404] rzg2l_wdt_restart+0x28/0x68 [ 42.359329] watchdog_restart_notifier+0x1c/0x30 [ 42.363943] atomic_notifier_call_chain+0x94/0x150 [ 42.368732] do_kernel_restart+0x24/0x30 [ 42.372652] machine_restart+0x44/0x70 [ 42.376399] kernel_restart+0x3c/0x60 [ 42.380058] __do_sys_reboot+0x228/0x250 [ 42.383977] __arm64_sys_reboot+0x20/0x28 [ 42.387983] invoke_syscall+0x40/0xf8 Fixes: 2cbc5cd0b55fa2 ("watchdog: Add Watchdog Timer driver for RZ/G2L") Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220225175320.11041-4-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 0fc73b8a9567e..48dfe6e5e64f3 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -43,6 +43,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) @@ -118,7 +120,9 @@ static int rzg2l_wdt_restart(struct watchdog_device *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); @@ -165,7 +169,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); @@ -177,22 +180,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"); From 33d04d0fdba9fae18c7d58364643d2c606a43dba Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 25 Feb 2022 17:53:17 +0000 Subject: [PATCH 12/38] watchdog: rzg2l_wdt: Fix reset control imbalance Both rzg2l_wdt_probe() and rzg2l_wdt_start() calls reset_control_ deassert() which results in a reset control imbalance. This patch fixes reset control imbalance by removing reset_control_ deassert() from rzg2l_wdt_start() and replaces reset_control_assert with reset_control_reset in rzg2l_wdt_stop() as watchdog module can be stopped only by a module reset. This change will allow us to restart WDT after stop() by configuring WDT timeout and enable registers. Fixes: 2cbc5cd0b55fa2 ("watchdog: Add Watchdog Timer driver for RZ/G2L") Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220225175320.11041-5-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 48dfe6e5e64f3..88274704b260d 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -88,7 +88,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 */ @@ -108,7 +107,7 @@ 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; } From baf1aace9ad15401f08e048a7f1fdec79821bc61 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 25 Feb 2022 17:53:18 +0000 Subject: [PATCH 13/38] watchdog: rzg2l_wdt: Add error check for reset_control_deassert If reset_control_deassert() fails, then we won't be able to access the device registers. Therefore check the return code of reset_control_deassert() and bailout in case of error. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220225175320.11041-6-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 88274704b260d..73b667ed3e995 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -203,7 +203,10 @@ 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); priv->wdev.info = &rzg2l_wdt_ident; From f43e6ddbd7d7b63b9e71927a1f50860f8d55f9cc Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 25 Feb 2022 17:53:19 +0000 Subject: [PATCH 14/38] watchdog: rzg2l_wdt: Use force reset for WDT reset This patch uses the force reset(WDTRSTB) for triggering WDT reset for restart callback. This method(ie, Generate Reset (WDTRSTB) Signal on parity error)is faster compared to the overflow method for triggering watchdog reset. Overflow method: reboot: Restarting system Reboot failed -- System halted NOTICE: BL2: v2.5(release):v2.5/rzg2l-1.00-27-gf48f1440c Parity error method: reboot: Restarting system NOTICE: BL2: v2.5(release):v2.5/rzg2l-1.00-27-gf48f1440c Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220225175320.11041-7-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 73b667ed3e995..4e7107655cc22 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -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 @@ -117,17 +120,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); - 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; } From 4055ee81009e606e830af1acd9e2e35a36249713 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Fri, 25 Feb 2022 17:53:20 +0000 Subject: [PATCH 15/38] watchdog: rzg2l_wdt: Add set_timeout callback This patch adds support for set_timeout callback. Once WDT is started, the WDT cycle setting register(WDTSET) can be updated only after issuing a module reset. Otherwise, it will ignore the writes and will hold the previous value. This patch updates the WDTSET register if it is active. Signed-off-by: Biju Das Reviewed-by: Geert Uytterhoeven Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220225175320.11041-8-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 4e7107655cc22..6eea0ee4af49e 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -115,6 +115,25 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev) 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; +} + static int rzg2l_wdt_restart(struct watchdog_device *wdev, unsigned long action, void *data) { @@ -151,6 +170,7 @@ 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, }; From 83999b61d583cd07492600ea7b5cde3fbfd863fb Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Tue, 1 Mar 2022 12:23:32 +0000 Subject: [PATCH 16/38] dt-bindings: watchdog: renesas,wdt: Document RZ/V2L SoC Document RZ/V2L WDT bindings. RZ/V2L WDT is identical to one found on the RZ/G2L SoC. No driver changes are required as generic compatible string "renesas,rzg2l-wdt" will be used as a fallback. While at it, drop the comment "# RZ/G2L" for "renesas,rzg2l-wdt" compatible string as this will avoid changing the line for every new SoC addition. Signed-off-by: Lad Prabhakar Reviewed-by: Biju Das Acked-by: Krzysztof Kozlowski Reviewed-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220301122332.14796-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml index d060438e1402d..59a48387e72da 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml @@ -22,7 +22,8 @@ properties: - items: - enum: - renesas,r9a07g044-wdt # RZ/G2{L,LC} - - const: renesas,rzg2l-wdt # RZ/G2L + - renesas,r9a07g054-wdt # RZ/V2L + - const: renesas,rzg2l-wdt - items: - enum: From 5794dda109fc870fce48a8cdf580750b40bf9d15 Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Wed, 5 Jan 2022 18:04:55 +0800 Subject: [PATCH 17/38] dt-bindings: reset: mt7986: Add reset-controller header file Add infracfg, toprgu, and ethsys reset-controller header file for MT7986 platform. Signed-off-by: Sam Shih Acked-by: Rob Herring Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/20220105100456.7126-2-sam.shih@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- include/dt-bindings/reset/mt7986-resets.h | 55 +++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 include/dt-bindings/reset/mt7986-resets.h diff --git a/include/dt-bindings/reset/mt7986-resets.h b/include/dt-bindings/reset/mt7986-resets.h new file mode 100644 index 0000000000000..af3d16c81192f --- /dev/null +++ b/include/dt-bindings/reset/mt7986-resets.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (c) 2022 MediaTek Inc. + * Author: Sam Shih + */ + +#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 */ From 94e4a7d5f87668e43f6939c6418d64f884e0bdab Mon Sep 17 00:00:00 2001 From: Xiantao Hu Date: Thu, 24 Mar 2022 11:18:04 +0800 Subject: [PATCH 18/38] dt-bindings: watchdog: Add watchdog yaml file for Sunplus SP7021 This adds the documentation for the devicetree bindings of the Sunplus SP7021 watchdog driver, found from SP7021 SoCs and newer. Signed-off-by: Xiantao Hu Reviewed-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220324031805.61316-2-xt.hu@cqplus1.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/sunplus,sp7021-wdt.yaml | 47 +++++++++++++++++++ MAINTAINERS | 6 +++ 2 files changed, 53 insertions(+) create mode 100644 Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml diff --git a/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml b/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml new file mode 100644 index 0000000000000..d902710131910 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml @@ -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 + +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>; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index edc96cdb85e85..fade1e499addb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18902,6 +18902,12 @@ S: Maintained F: Documentation/devicetree/bindings/serial/sunplus,sp7021-uart.yaml F: drivers/tty/serial/sunplus-uart.c +SUNPLUS WATCHDOG DRIVER +M: Xiantao Hu +L: linux-watchdog@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/watchdog/sunplus,sp7021-wdt.yaml + SUPERH M: Yoshinori Sato M: Rich Felker From daf42866960ce69d48c94c4fc1aa997638b4c2e9 Mon Sep 17 00:00:00 2001 From: Xiantao Hu Date: Thu, 24 Mar 2022 11:18:05 +0800 Subject: [PATCH 19/38] watchdog: Add watchdog driver for Sunplus SP7021 Sunplus SP7021 requires watchdog timer support. Add watchdog driver to enable this. Signed-off-by: Xiantao Hu Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220324031805.61316-3-xt.hu@cqplus1.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- MAINTAINERS | 1 + drivers/watchdog/Kconfig | 11 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/sunplus_wdt.c | 220 +++++++++++++++++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 drivers/watchdog/sunplus_wdt.c diff --git a/MAINTAINERS b/MAINTAINERS index fade1e499addb..d02286f5084c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18907,6 +18907,7 @@ M: Xiantao Hu 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 diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c4e82a8d863f8..a7cd3ef5b3d8a 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1011,6 +1011,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 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f7da867e8782e..71c933a5964a5 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -95,6 +95,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 diff --git a/drivers/watchdog/sunplus_wdt.c b/drivers/watchdog/sunplus_wdt.c new file mode 100644 index 0000000000000..e2d8c532bcb1a --- /dev/null +++ b/drivers/watchdog/sunplus_wdt.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * sunplus Watchdog Driver + * + * Copyright (C) 2021 Sunplus Technology Co., Ltd. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_DESCRIPTION("Sunplus Watchdog Timer Driver"); +MODULE_LICENSE("GPL"); From 70fabe207135194a48313bf56305f1ead32cea1f Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 17 Mar 2022 16:23:38 +0000 Subject: [PATCH 20/38] dt-bindings: watchdog: sunxi: fix F1C100s compatible The F1C100 series actually features a newer generation watchdog IP, so the compatible string was wrong. Signed-off-by: Andre Przywara Acked-by: Rob Herring Reviewed-by: Samuel Holland Link: https://lore.kernel.org/r/20220317162349.739636-2-andre.przywara@arm.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml index 43afa24513b98..7a26cde0afddf 100644 --- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml @@ -26,10 +26,8 @@ properties: - allwinner,sun50i-h616-wdt - allwinner,sun50i-r329-wdt - allwinner,sun50i-r329-wdt-reset + - allwinner,suniv-f1c100s-wdt - const: allwinner,sun6i-a31-wdt - - items: - - const: allwinner,suniv-f1c100s-wdt - - const: allwinner,sun4i-a10-wdt - const: allwinner,sun20i-d1-wdt - items: - const: allwinner,sun20i-d1-wdt-reset From 5b38db0ed51e17ab1135f8e354951aeb46aa57d3 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 17 Mar 2022 16:23:39 +0000 Subject: [PATCH 21/38] dt-bindings: watchdog: sunxi: clarify clock support Most Allwinner SoCs have just one input clock to drive the watchdog peripheral. So far this is the 24 MHz "HOSC" oscillator, divided down internally to 32 KHz. The F1C100 series watchdog however uses the unchanged 32 KHz "LOSC" as its only clock input, which has the same effect, but let's the binding description mismatch. Change the binding description to name the clocks more loosely, so both the LOSC and divided HOSC match the description. As the fixed clock names now make less sense, drop them from SoCs supporting just one clock input, they were not used by any DT anyway. For the newer SoCs, supporting a choice of two input clocks, we keep both the description and clock-names requirement. Signed-off-by: Andre Przywara Reviewed-by: Rob Herring Reviewed-by: Samuel Holland Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220317162349.739636-3-andre.przywara@arm.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../watchdog/allwinner,sun4i-a10-wdt.yaml | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml index 7a26cde0afddf..cbcf19f514114 100644 --- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml @@ -39,14 +39,8 @@ properties: clocks: minItems: 1 items: - - description: High-frequency oscillator input, divided internally - - description: Low-frequency oscillator input, only found on some variants - - clock-names: - minItems: 1 - items: - - const: hosc - - const: losc + - description: 32 KHz input clock + - description: secondary clock source interrupts: maxItems: 1 @@ -71,9 +65,14 @@ then: properties: clocks: minItems: 2 + items: + - description: High-frequency oscillator input, divided internally + - description: Low-frequency oscillator input clock-names: - minItems: 2 + items: + - const: hosc + - const: losc required: - clock-names @@ -83,9 +82,6 @@ else: clocks: maxItems: 1 - clock-names: - maxItems: 1 - unevaluatedProperties: false examples: From b1912875a548cf32eebc77eec85034052909bba8 Mon Sep 17 00:00:00 2001 From: Primoz Fiser Date: Fri, 22 Apr 2022 09:27:11 +0200 Subject: [PATCH 22/38] dt-bindings: mfd: da9063: watchdog: add suspend disable option Document the watchdog disable option which can be used if the hardware automatic suspend option is broken. Based on commit c514430c51ee8 ("dt-bindings: watchdog: da9062: add suspend disable option"). Signed-off-by: Primoz Fiser Reviewed-by: Rob Herring Reviewed-by: Adam Thomson Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220422072713.3172345-1-primoz.fiser@norik.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/mfd/da9063.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/da9063.txt b/Documentation/devicetree/bindings/mfd/da9063.txt index 91b79a21d4039..aa8b800cc4ad8 100644 --- a/Documentation/devicetree/bindings/mfd/da9063.txt +++ b/Documentation/devicetree/bindings/mfd/da9063.txt @@ -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: From a7ceca4398bc835c6ad29d10e1106de4cf0332e1 Mon Sep 17 00:00:00 2001 From: Primoz Fiser Date: Fri, 22 Apr 2022 09:27:12 +0200 Subject: [PATCH 23/38] watchdog: da9063: optionally disable watchdog during suspend Optionally disable watchdog during suspend (if enabled) and re-enable it upon resume. This enables boards to sleep without being interrupted by the watchdog. This patch is based on commit f6c98b08381c ("watchdog: da9062: add power management ops") and commit 8541673d2a5f ("watchdog: da9062: fix power management ops") and brings the same functionality to DA9063. Signed-off-by: Primoz Fiser Reviewed-by: Adam Thomson Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220422072713.3172345-2-primoz.fiser@norik.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/da9063_wdt.c | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c index 9adad1862bbdb..09a4af4c58fc8 100644 --- a/drivers/watchdog/da9063_wdt.c +++ b/drivers/watchdog/da9063_wdt.c @@ -18,6 +18,7 @@ #include #include #include +#include #include /* @@ -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); From ac97c9374d3cdfa42611a32a653ac75db423cac4 Mon Sep 17 00:00:00 2001 From: Eliav Farber Date: Thu, 14 Apr 2022 05:42:33 +0000 Subject: [PATCH 24/38] watchdog: sp805: disable watchdog on remove Disable the watchdog if it is active while removing the module. It is necessary in order to prevent a reset in case watchdog hw was running before the removal. Signed-off-by: Eliav Farber Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220414054233.1357-2-farbere@amazon.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sp805_wdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index dbeb2146c9681..f9479a3fe2a69 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -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. From 95d0eee9718a21ed35fb80a68d3a71759b136f77 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Thu, 7 Apr 2022 16:46:46 +0900 Subject: [PATCH 25/38] dt-bindings: watchdog: uniphier: Use unevaluatedProperties This refers common bindings, so this is preferred for unevaluatedProperties instead of additionalProperties. Signed-off-by: Kunihiko Hayashi Reviewed-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1649317606-21267-1-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../devicetree/bindings/watchdog/socionext,uniphier-wdt.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/watchdog/socionext,uniphier-wdt.yaml b/Documentation/devicetree/bindings/watchdog/socionext,uniphier-wdt.yaml index a059d16cb4f2e..90698cfa8f945 100644 --- a/Documentation/devicetree/bindings/watchdog/socionext,uniphier-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/socionext,uniphier-wdt.yaml @@ -19,7 +19,7 @@ properties: required: - compatible -additionalProperties: false +unevaluatedProperties: false examples: - | From c83f643878388d468e0a674ac9502d4080499646 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 21 Feb 2022 17:22:38 +0100 Subject: [PATCH 26/38] watchdog: rti_wdt: Fix calculation and evaluation of preset heartbeat This ensures that the same value is read back as was eventually programmed when using seconds as accuracy. Even then, comparing the more precise heartbeat_ms against heartbeat in seconds will almost never provide a match and will needlessly raise a warning. Fix by comparing apples to apples. Tested in combination with U-Boot as watchdog starter. Signed-off-by: Jan Kiszka Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/6a4b54ac-9588-e172-c4c7-b91d524a851e@siemens.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rti_wdt.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index db843f8258602..35f3c396a2ff3 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -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); From 26d14b9fc341893e862f17ab7db4543d5a530327 Mon Sep 17 00:00:00 2001 From: Bjorn Andersson Date: Fri, 8 Apr 2022 14:28:54 -0700 Subject: [PATCH 27/38] dt-bindings: watchdog: Add SC8180X and SC8280XP compatibles Add compatibles for the SC8180X and SC8280XP platforms to the Qualcomm watchdog binding. Signed-off-by: Bjorn Andersson Acked-by: Krzysztof Kozlowski Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220408212854.581481-1-bjorn.andersson@linaro.org [groeck: Rebased and resolved conflicts] Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index 4ff8c59c59ab7..2bd6b4a526372 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -20,6 +20,8 @@ properties: - 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 From b3ac0c58fa8934926360268f3d89ec7680644d7b Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Tue, 12 Apr 2022 07:08:23 +0000 Subject: [PATCH 28/38] watchdog: rti-wdt: Fix pm_runtime_get_sync() error checking If the device is already in a runtime PM enabled state pm_runtime_get_sync() will return 1, so a test for negative value should be used to check for errors. Fixes: 2d63908bdbfb ("watchdog: Add K3 RTI watchdog support") Signed-off-by: Miaoqian Lin Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220412070824.23708-1-linmq006@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rti_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c index 35f3c396a2ff3..053ef3bde12d4 100644 --- a/drivers/watchdog/rti_wdt.c +++ b/drivers/watchdog/rti_wdt.c @@ -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"); From 9ef958929fc288a85146d18368f4d2aaac80cdbc Mon Sep 17 00:00:00 2001 From: Liu Xinpeng Date: Tue, 26 Apr 2022 18:11:45 +0800 Subject: [PATCH 29/38] watchdog: iTCO_wdt: Using existing macro define covers more scenarios For power management, SET_NOIRQ_SYSTEM_SLEEP_PM_OPS defined for CONFIG_PM_SLEEP, will point ->suspend_noirq, ->freeze_noirq and ->poweroff_noirq to the same function. Vice versa happens for ->resume_noirq, ->thaw_noirq and ->restore_noirq. Signed-off-by: Liu Xinpeng Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1650967905-3199-1-git-send-email-liuxp11@chinatelecom.cn Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 3f2f4343644f5..34693f11385f6 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -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, }, }; From af84a5a75344871c44ddbf4ab901c3427909f893 Mon Sep 17 00:00:00 2001 From: Biju Das Date: Sun, 24 Apr 2022 08:13:23 +0100 Subject: [PATCH 30/38] dt-bindings: watchdog: renesas,wdt: Document RZ/G2UL SoC Document RZ/G2UL WDT bindings. RZ/G2UL WDT is similar to one found on the RZ/G2L SoC. No driver changes are required as generic compatible string "renesas,rzg2l-wdt" will be used as a fallback. Signed-off-by: Biju Das Acked-by: Krzysztof Kozlowski Reviewed-by: Geert Uytterhoeven Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220424071323.151757-1-biju.das.jz@bp.renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml index 59a48387e72da..84c008d956e47 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml @@ -21,6 +21,7 @@ properties: - items: - enum: + - renesas,r9a07g043-wdt # RZ/G2UL - renesas,r9a07g044-wdt # RZ/G2{L,LC} - renesas,r9a07g054-wdt # RZ/V2L - const: renesas,rzg2l-wdt From 382256b219fbc901a69481e5b60812556f53152e Mon Sep 17 00:00:00 2001 From: Andrej Picej Date: Mon, 6 Dec 2021 07:47:31 +0100 Subject: [PATCH 31/38] dt-bindings: watchdog: da9062: add watchdog timeout mode Document the watchdog timeout mode property. If this property is used the user can select what happens on watchdog timeout. Set this property to 1 to enable SHUTDOWN (the device resets), set it to 0 and the device will go to POWERDOWN on watchdog timeout. If this property is not set, don't touch the WATCHDOG_SD bit and leave the configuration to OTP. This way backward compatibility is not broken. Signed-off-by: Andrej Picej Reviewed-by: Adam Thomson Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20211206064732.280375-4-andrej.picej@norik.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/da9062-wdt.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/watchdog/da9062-wdt.txt b/Documentation/devicetree/bindings/watchdog/da9062-wdt.txt index 950e4fba8dbc7..354314d854ef7 100644 --- a/Documentation/devicetree/bindings/watchdog/da9062-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/da9062-wdt.txt @@ -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 From 6d72c7ac9fbe26a77800676507da980436b40b2f Mon Sep 17 00:00:00 2001 From: Liu Xinpeng Date: Tue, 26 Apr 2022 22:53:28 +0800 Subject: [PATCH 32/38] watchdog: wdat_wdt: Using the existing function to check parameter timeout If max_hw_heartbeat_ms is provided, the configured maximum timeout is not limited by it. The limit check in this driver therefore doesn't make much sense. Similar, the watchdog core ensures that minimum timeout limits are met if min_hw_heartbeat_ms is set. Using watchdog_timeout_invalid() makes more sense because it takes this into account. Signed-off-by: Liu Xinpeng Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1650984810-6247-2-git-send-email-liuxp11@chinatelecom.cn Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wdat_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index 195c8c004b69d..df0865a61a702 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -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; From 27fdf84510a1374748904db43f6755f912736d92 Mon Sep 17 00:00:00 2001 From: Liu Xinpeng Date: Tue, 26 Apr 2022 22:53:29 +0800 Subject: [PATCH 33/38] watchdog: wdat_wdt: Stop watchdog when rebooting the system Executing reboot command several times on the machine "Dell PowerEdge R740", UEFI security detection stopped machine with the following prompt: UEFI0082: The system was reset due to a timeout from the watchdog timer. Check the System Event Log (SEL) or crash dumps from Operating Sysstem to identify the source that triggered the watchdog timer reset. Update the firmware or driver for the identified device. iDRAC has warning event: "The watchdog timer reset the system". This patch fixes this issue by adding the reboot notifier. Signed-off-by: Liu Xinpeng Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1650984810-6247-3-git-send-email-liuxp11@chinatelecom.cn Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wdat_wdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index df0865a61a702..6f36a653767b3 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -462,6 +462,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) return ret; watchdog_set_nowayout(&wdat->wdd, nowayout); + watchdog_stop_on_reboot(&wdat->wdd); return devm_watchdog_register_device(dev, &wdat->wdd); } From 330415ebea81b65842e4cc6d2fd985c1b369e650 Mon Sep 17 00:00:00 2001 From: Liu Xinpeng Date: Tue, 26 Apr 2022 22:53:30 +0800 Subject: [PATCH 34/38] watchdog: wdat_wdt: Stop watchdog when uninstalling module Test shows that wachdog still reboots machine after the module is removed. Use watchdog_stop_on_unregister to stop the watchdog on removing. Signed-off-by: Liu Xinpeng eviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1650984810-6247-4-git-send-email-liuxp11@chinatelecom.cn Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wdat_wdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index 6f36a653767b3..e6f95e99156db 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -463,6 +463,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) 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); } From 9dc731bbb455eeaff6e90abef7a8d05dfa6ccc9a Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Wed, 27 Apr 2022 15:55:30 +0200 Subject: [PATCH 35/38] dt-bindings: watchdog: renesas,wdt: Add support for RZ/N1 Describe the WDT hardware in the RZ/N1 series. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Link: https://lore.kernel.org/r/20220427135531.708279-2-jjhiblot@traphandler.com [groeck: Rebased, fixed conflicts] Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml index 84c008d956e47..514d400c7a364 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml @@ -19,6 +19,11 @@ properties: - renesas,r7s9210-wdt # RZ/A2 - const: renesas,rza-wdt # RZ/A + - items: + - enum: + - renesas,r9a06g032-wdt # RZ/N1D + - const: renesas,rzn1-wdt # RZ/N1 + - items: - enum: - renesas,r9a07g043-wdt # RZ/G2UL @@ -96,6 +101,7 @@ allOf: contains: enum: - renesas,rza-wdt + - renesas,rzn1-wdt then: required: - power-domains From d65112f58464fd0ab62b8e4fb6c66cbf29b24b43 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Wed, 27 Apr 2022 15:55:31 +0200 Subject: [PATCH 36/38] watchdog: Add Renesas RZ/N1 Watchdog driver This is a driver for the standard WDT on the RZ/N1 devices. This WDT has very limited timeout capabilities. However, it can reset the device. To do so, the corresponding bits in the SysCtrl RSTEN register need to be enabled. This is not done by this driver. Signed-off-by: Phil Edworthy Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Tzung-Bi Shih Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220427135531.708279-3-jjhiblot@traphandler.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 8 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/rzn1_wdt.c | 203 ++++++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 drivers/watchdog/rzn1_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a7cd3ef5b3d8a..001ae1be9b61c 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -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 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 71c933a5964a5..5f88a6237f7c4 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -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 diff --git a/drivers/watchdog/rzn1_wdt.c b/drivers/watchdog/rzn1_wdt.c new file mode 100644 index 0000000000000..55ab384b99657 --- /dev/null +++ b/drivers/watchdog/rzn1_wdt.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "); +MODULE_LICENSE("GPL"); From 9215a90dd56e008999dbaa228c8eb2c7df98a418 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 May 2022 15:34:59 +0200 Subject: [PATCH 37/38] dt-bindings: watchdog: renesas,wdt: R-Car V3U is R-Car Gen4 Despite the name, R-Car V3U is the first member of the R-Car Gen4 family. Hence move its compatible value to the R-Car Gen4 section. Signed-off-by: Geert Uytterhoeven Acked-by: Krzysztof Kozlowski Reviewed-by: Wolfram Sang Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/2882a6de3905a57ae62d91060d27521af43c4068.1651497024.git.geert+renesas@glider.be Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml index 514d400c7a364..a8d7dde5271b8 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml @@ -59,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 From 5d24df3d690809952528e7a19a43d84bc5b99d44 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Wed, 11 May 2022 15:42:03 +0400 Subject: [PATCH 38/38] watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe of_parse_phandle() returns a node pointer with refcount incremented, we should use of_node_put() on it when done. Add missing of_node_put() in some error paths. Fixes: bf9006399939 ("watchdog: ts4800: add driver for TS-4800 watchdog") Signed-off-by: Miaoqian Lin Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20220511114203.47420-1-linmq006@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/ts4800_wdt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/ts4800_wdt.c b/drivers/watchdog/ts4800_wdt.c index c137ad2bd5c31..0ea554c7cda57 100644 --- a/drivers/watchdog/ts4800_wdt.c +++ b/drivers/watchdog/ts4800_wdt.c @@ -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;