From 9b30eac1b35a448081165cd906daf939d8750bfb Mon Sep 17 00:00:00 2001 From: Allen-KH Cheng Date: Tue, 17 Jan 2023 09:40:22 +0800 Subject: [PATCH 01/52] dt-bindings: watchdog: mtk-wdt: Add reset-by-toprgu support In some applications, the mtk-wdt requires the TOPRGU (Top Reset Generation Unit) to reset timer after system resets. Add optional mediatek,reset-by-toprgu property to enable it. Signed-off-by: Allen-KH Cheng Reviewed-by: AngeloGioacchino Del Regno Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20230117014023.2993-2-allen-kh.cheng@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml b/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml index b3605608410c..55b34461df1b 100644 --- a/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/mediatek,mtk-wdt.yaml @@ -52,6 +52,12 @@ properties: description: Disable sending output reset signal type: boolean + mediatek,reset-by-toprgu: + description: The Top Reset Generation Unit (TOPRGU) generates reset signals + and distributes them to each IP. If present, the watchdog timer will be + reset by TOPRGU once system resets. + type: boolean + '#reset-cells': const: 1 From a224764f97d28f1132cab02b79ae4c08a6de471e Mon Sep 17 00:00:00 2001 From: Allen-KH Cheng Date: Tue, 17 Jan 2023 09:40:23 +0800 Subject: [PATCH 02/52] watchdog: mtk_wdt: Add reset_by_toprgu support In some cases, the MediaTek watchdog requires the TOPRGU to reset timer after system resets. Provide a reset_by_toprgu parameter for configuration. Signed-off-by: Allen-KH Cheng Reviewed-by: AngeloGioacchino Del Regno Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20230117014023.2993-3-allen-kh.cheng@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtk_wdt.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 3e6212591e69..a9c437598e7e 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -50,6 +50,7 @@ #define WDT_MODE_IRQ_EN (1 << 3) #define WDT_MODE_AUTO_START (1 << 4) #define WDT_MODE_DUAL_EN (1 << 6) +#define WDT_MODE_CNT_SEL (1 << 8) #define WDT_MODE_KEY 0x22000000 #define WDT_SWRST 0x14 @@ -70,6 +71,7 @@ struct mtk_wdt_dev { spinlock_t lock; /* protects WDT_SWSYSRST reg */ struct reset_controller_dev rcdev; bool disable_wdt_extrst; + bool reset_by_toprgu; }; struct mtk_wdt_data { @@ -279,6 +281,8 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); if (mtk_wdt->disable_wdt_extrst) reg &= ~WDT_MODE_EXRST_EN; + if (mtk_wdt->reset_by_toprgu) + reg |= WDT_MODE_CNT_SEL; reg |= (WDT_MODE_EN | WDT_MODE_KEY); iowrite32(reg, wdt_base + WDT_MODE); @@ -408,6 +412,9 @@ static int mtk_wdt_probe(struct platform_device *pdev) mtk_wdt->disable_wdt_extrst = of_property_read_bool(dev->of_node, "mediatek,disable-extrst"); + mtk_wdt->reset_by_toprgu = + of_property_read_bool(dev->of_node, "mediatek,reset-by-toprgu"); + return 0; } From 3c22939eb345952b5c814df9cc6f9b2d56982453 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 16:02:17 +0100 Subject: [PATCH 03/52] watchdog: realtek_otto: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Acked-by: Sander Vanheule Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/5e4255782fbb43d1b4b5cd03bd12d7a184497134.1672498920.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/realtek_otto_wdt.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/drivers/watchdog/realtek_otto_wdt.c b/drivers/watchdog/realtek_otto_wdt.c index 2a5298c5e8e4..2c30ddd574c5 100644 --- a/drivers/watchdog/realtek_otto_wdt.c +++ b/drivers/watchdog/realtek_otto_wdt.c @@ -235,27 +235,14 @@ static const struct watchdog_info otto_wdt_info = { WDIOF_PRETIMEOUT, }; -static void otto_wdt_clock_action(void *data) -{ - clk_disable_unprepare(data); -} - static int otto_wdt_probe_clk(struct otto_wdt_ctrl *ctrl) { - struct clk *clk = devm_clk_get(ctrl->dev, NULL); - int ret; + struct clk *clk; + clk = devm_clk_get_enabled(ctrl->dev, NULL); if (IS_ERR(clk)) return dev_err_probe(ctrl->dev, PTR_ERR(clk), "Failed to get clock\n"); - ret = clk_prepare_enable(clk); - if (ret) - return dev_err_probe(ctrl->dev, ret, "Failed to enable clock\n"); - - ret = devm_add_action_or_reset(ctrl->dev, otto_wdt_clock_action, clk); - if (ret) - return ret; - ctrl->clk_rate_khz = clk_get_rate(clk) / 1000; if (ctrl->clk_rate_khz == 0) return dev_err_probe(ctrl->dev, -ENXIO, "Failed to get clock rate\n"); From a8a9b98057458cfcbf145af647916ca9f1a63ccb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 15:25:31 +0100 Subject: [PATCH 04/52] watchdog: pnx4008: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/61f4e39db4c88408ee0149580e9aa925b784bc93.1672496714.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pnx4008_wdt.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index e0ea133c1690..87a44a5675a1 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -179,11 +179,6 @@ static struct watchdog_device pnx4008_wdd = { .max_timeout = MAX_HEARTBEAT, }; -static void pnx4008_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int pnx4008_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -195,18 +190,10 @@ static int pnx4008_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdt_base)) return PTR_ERR(wdt_base); - wdt_clk = devm_clk_get(dev, NULL); + wdt_clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(wdt_clk)) return PTR_ERR(wdt_clk); - ret = clk_prepare_enable(wdt_clk); - if (ret) - return ret; - ret = devm_add_action_or_reset(dev, pnx4008_clk_disable_unprepare, - wdt_clk); - if (ret) - return ret; - pnx4008_wdd.bootstatus = (readl(WDTIM_RES(wdt_base)) & WDOG_RESET) ? WDIOF_CARDRESET : 0; pnx4008_wdd.parent = dev; From 7f7f8ad0725cf31af68aaccccee6d24b8c886679 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 15:22:57 +0100 Subject: [PATCH 05/52] watchdog: pic32-wdt: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/4335b4201b535ebc749a98bad0b99e3cb5317c39.1672496563.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pic32-wdt.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/watchdog/pic32-wdt.c b/drivers/watchdog/pic32-wdt.c index 41715d68d9e9..6d1a00222991 100644 --- a/drivers/watchdog/pic32-wdt.c +++ b/drivers/watchdog/pic32-wdt.c @@ -162,11 +162,6 @@ static const struct of_device_id pic32_wdt_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, pic32_wdt_dt_ids); -static void pic32_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int pic32_wdt_drv_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -186,22 +181,12 @@ static int pic32_wdt_drv_probe(struct platform_device *pdev) if (!wdt->rst_base) return -ENOMEM; - wdt->clk = devm_clk_get(dev, NULL); + wdt->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(wdt->clk)) { dev_err(dev, "clk not found\n"); return PTR_ERR(wdt->clk); } - ret = clk_prepare_enable(wdt->clk); - if (ret) { - dev_err(dev, "clk enable failed\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, pic32_clk_disable_unprepare, - wdt->clk); - if (ret) - return ret; - if (pic32_wdt_is_win_enabled(wdt)) { dev_err(dev, "windowed-clear mode is not supported.\n"); return -ENODEV; From e0912ea8714deb598c7763ec60c9ba83b157acf7 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 15:20:29 +0100 Subject: [PATCH 06/52] watchdog: pic32-dmt: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/f9a4dcfc6d31bd9c1417e2d97a40cc2c1dbc6f30.1672496405.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pic32-dmt.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/watchdog/pic32-dmt.c b/drivers/watchdog/pic32-dmt.c index f43062b3c4c8..bc4ccddc75a3 100644 --- a/drivers/watchdog/pic32-dmt.c +++ b/drivers/watchdog/pic32-dmt.c @@ -164,11 +164,6 @@ static struct watchdog_device pic32_dmt_wdd = { .ops = &pic32_dmt_fops, }; -static void pic32_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int pic32_dmt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -184,20 +179,12 @@ static int pic32_dmt_probe(struct platform_device *pdev) if (IS_ERR(dmt->regs)) return PTR_ERR(dmt->regs); - dmt->clk = devm_clk_get(dev, NULL); + dmt->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(dmt->clk)) { dev_err(dev, "clk not found\n"); return PTR_ERR(dmt->clk); } - ret = clk_prepare_enable(dmt->clk); - if (ret) - return ret; - ret = devm_add_action_or_reset(dev, pic32_clk_disable_unprepare, - dmt->clk); - if (ret) - return ret; - wdd->timeout = pic32_dmt_get_timeout_secs(dmt); if (!wdd->timeout) { dev_err(dev, "failed to read watchdog register timeout\n"); From 5eb3fb95eab28a6dbcd2eab6898e03af6658ee0e Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 13:26:09 +0100 Subject: [PATCH 07/52] watchdog: lpc18xx: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/d4c675190d3ddfbba5c354edb4274757f9117304.1672489554.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/lpc18xx_wdt.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c index 60b6d74f267d..1b9b5f21a0df 100644 --- a/drivers/watchdog/lpc18xx_wdt.c +++ b/drivers/watchdog/lpc18xx_wdt.c @@ -197,16 +197,10 @@ static const struct watchdog_ops lpc18xx_wdt_ops = { .restart = lpc18xx_wdt_restart, }; -static void lpc18xx_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int lpc18xx_wdt_probe(struct platform_device *pdev) { struct lpc18xx_wdt_dev *lpc18xx_wdt; struct device *dev = &pdev->dev; - int ret; lpc18xx_wdt = devm_kzalloc(dev, sizeof(*lpc18xx_wdt), GFP_KERNEL); if (!lpc18xx_wdt) @@ -216,38 +210,18 @@ static int lpc18xx_wdt_probe(struct platform_device *pdev) if (IS_ERR(lpc18xx_wdt->base)) return PTR_ERR(lpc18xx_wdt->base); - lpc18xx_wdt->reg_clk = devm_clk_get(dev, "reg"); + lpc18xx_wdt->reg_clk = devm_clk_get_enabled(dev, "reg"); if (IS_ERR(lpc18xx_wdt->reg_clk)) { dev_err(dev, "failed to get the reg clock\n"); return PTR_ERR(lpc18xx_wdt->reg_clk); } - lpc18xx_wdt->wdt_clk = devm_clk_get(dev, "wdtclk"); + lpc18xx_wdt->wdt_clk = devm_clk_get_enabled(dev, "wdtclk"); if (IS_ERR(lpc18xx_wdt->wdt_clk)) { dev_err(dev, "failed to get the wdt clock\n"); return PTR_ERR(lpc18xx_wdt->wdt_clk); } - ret = clk_prepare_enable(lpc18xx_wdt->reg_clk); - if (ret) { - dev_err(dev, "could not prepare or enable sys clock\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, lpc18xx_clk_disable_unprepare, - lpc18xx_wdt->reg_clk); - if (ret) - return ret; - - ret = clk_prepare_enable(lpc18xx_wdt->wdt_clk); - if (ret) { - dev_err(dev, "could not prepare or enable wdt clock\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, lpc18xx_clk_disable_unprepare, - lpc18xx_wdt->wdt_clk); - if (ret) - return ret; - /* We use the clock rate to calculate timeouts */ lpc18xx_wdt->clk_rate = clk_get_rate(lpc18xx_wdt->wdt_clk); if (lpc18xx_wdt->clk_rate == 0) { From 4de0224c6fbebfa4018a640ec34e5c160dffb959 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 13:57:49 +0100 Subject: [PATCH 08/52] watchdog: of_xilinx_wdt: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Acked-by: Michal Simek Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/2b041dc8230a4ed255051bb2d323da8a51a8d0be.1672491445.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 3318544366b8..2a079ca04aa3 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -154,11 +154,6 @@ static u32 xwdt_selftest(struct xwdt_device *xdev) return XWT_TIMER_FAILED; } -static void xwdt_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int xwdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -193,7 +188,7 @@ static int xwdt_probe(struct platform_device *pdev) watchdog_set_nowayout(xilinx_wdt_wdd, enable_once); - xdev->clk = devm_clk_get(dev, NULL); + xdev->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(xdev->clk)) { if (PTR_ERR(xdev->clk) != -ENOENT) return PTR_ERR(xdev->clk); @@ -211,15 +206,6 @@ static int xwdt_probe(struct platform_device *pdev) "The watchdog clock freq cannot be obtained\n"); } else { pfreq = clk_get_rate(xdev->clk); - rc = clk_prepare_enable(xdev->clk); - if (rc) { - dev_err(dev, "unable to enable clock\n"); - return rc; - } - rc = devm_add_action_or_reset(dev, xwdt_clk_disable_unprepare, - xdev->clk); - if (rc) - return rc; } /* From c4b8e92bc1a8d860ca53a41c25cd84fa03efaf50 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 11:53:34 +0100 Subject: [PATCH 09/52] watchdog: imgpdc: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1f8d1ce1e6a63c507a291aea624b1337326cc563.1672483996.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/imgpdc_wdt.c | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/drivers/watchdog/imgpdc_wdt.c b/drivers/watchdog/imgpdc_wdt.c index b57ff3787052..a55f801895d4 100644 --- a/drivers/watchdog/imgpdc_wdt.c +++ b/drivers/watchdog/imgpdc_wdt.c @@ -175,16 +175,11 @@ static const struct watchdog_ops pdc_wdt_ops = { .restart = pdc_wdt_restart, }; -static void pdc_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int pdc_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; u64 div; - int ret, val; + int val; unsigned long clk_rate; struct pdc_wdt_dev *pdc_wdt; @@ -196,38 +191,18 @@ static int pdc_wdt_probe(struct platform_device *pdev) if (IS_ERR(pdc_wdt->base)) return PTR_ERR(pdc_wdt->base); - pdc_wdt->sys_clk = devm_clk_get(dev, "sys"); + pdc_wdt->sys_clk = devm_clk_get_enabled(dev, "sys"); if (IS_ERR(pdc_wdt->sys_clk)) { dev_err(dev, "failed to get the sys clock\n"); return PTR_ERR(pdc_wdt->sys_clk); } - pdc_wdt->wdt_clk = devm_clk_get(dev, "wdt"); + pdc_wdt->wdt_clk = devm_clk_get_enabled(dev, "wdt"); if (IS_ERR(pdc_wdt->wdt_clk)) { dev_err(dev, "failed to get the wdt clock\n"); return PTR_ERR(pdc_wdt->wdt_clk); } - ret = clk_prepare_enable(pdc_wdt->sys_clk); - if (ret) { - dev_err(dev, "could not prepare or enable sys clock\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, pdc_clk_disable_unprepare, - pdc_wdt->sys_clk); - if (ret) - return ret; - - ret = clk_prepare_enable(pdc_wdt->wdt_clk); - if (ret) { - dev_err(dev, "could not prepare or enable wdt clock\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, pdc_clk_disable_unprepare, - pdc_wdt->wdt_clk); - if (ret) - return ret; - /* We use the clock rate to calculate the max timeout */ clk_rate = clk_get_rate(pdc_wdt->wdt_clk); if (clk_rate == 0) { From 616a2fe3cda63d4e6eb3a29f925f14b3766c633e Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 09:12:28 +0100 Subject: [PATCH 10/52] watchdog: cadence: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/615c6c3c46c3ee8e3136725af0ab0b51e1298091.1672474336.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/cadence_wdt.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c index bc99e9164930..23d41043863f 100644 --- a/drivers/watchdog/cadence_wdt.c +++ b/drivers/watchdog/cadence_wdt.c @@ -274,11 +274,6 @@ static const struct watchdog_ops cdns_wdt_ops = { .set_timeout = cdns_wdt_settimeout, }; -static void cdns_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - /************************Platform Operations*****************************/ /** * cdns_wdt_probe - Probe call for the device. @@ -333,21 +328,11 @@ static int cdns_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(cdns_wdt_device); watchdog_set_drvdata(cdns_wdt_device, wdt); - wdt->clk = devm_clk_get(dev, NULL); + wdt->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(wdt->clk)) return dev_err_probe(dev, PTR_ERR(wdt->clk), "input clock not found\n"); - ret = clk_prepare_enable(wdt->clk); - if (ret) { - dev_err(dev, "unable to enable clock\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, cdns_clk_disable_unprepare, - wdt->clk); - if (ret) - return ret; - clock_f = clk_get_rate(wdt->clk); if (clock_f <= CDNS_WDT_CLK_75MHZ) { wdt->prescaler = CDNS_WDT_PRESCALE_512; From 2cf46c636f4010baf696bb6afa43bebb2aa30a7a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 13:34:44 +0100 Subject: [PATCH 11/52] watchdog: meson_gxbb: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Reviewed-by: Martin Blumenstingl Link: https://lore.kernel.org/r/6c5948373d309408095c1a098b7b4c491c5265f7.1672490071.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/meson_gxbb_wdt.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/watchdog/meson_gxbb_wdt.c b/drivers/watchdog/meson_gxbb_wdt.c index 981a2f7c3bec..35d80cb39856 100644 --- a/drivers/watchdog/meson_gxbb_wdt.c +++ b/drivers/watchdog/meson_gxbb_wdt.c @@ -146,16 +146,10 @@ static const struct of_device_id meson_gxbb_wdt_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, meson_gxbb_wdt_dt_ids); -static void meson_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int meson_gxbb_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct meson_gxbb_wdt *data; - int ret; u32 ctrl_reg; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); @@ -166,18 +160,10 @@ static int meson_gxbb_wdt_probe(struct platform_device *pdev) if (IS_ERR(data->reg_base)) return PTR_ERR(data->reg_base); - data->clk = devm_clk_get(dev, NULL); + data->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(data->clk)) return PTR_ERR(data->clk); - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - ret = devm_add_action_or_reset(dev, meson_clk_disable_unprepare, - data->clk); - if (ret) - return ret; - platform_set_drvdata(pdev, data); data->wdt_dev.parent = dev; From 0a03207205f95abd90c8e1abb00c158066560ed2 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 11:37:39 +0100 Subject: [PATCH 12/52] watchdog: davinci: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/6a4cf8e8b9d8f555c77395ba2ecadc205553774d.1672483046.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/davinci_wdt.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 584a56893b81..5f2184bda7b2 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -189,14 +189,8 @@ static const struct watchdog_ops davinci_wdt_ops = { .restart = davinci_wdt_restart, }; -static void davinci_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int davinci_wdt_probe(struct platform_device *pdev) { - int ret = 0; struct device *dev = &pdev->dev; struct watchdog_device *wdd; struct davinci_wdt_device *davinci_wdt; @@ -205,21 +199,11 @@ static int davinci_wdt_probe(struct platform_device *pdev) if (!davinci_wdt) return -ENOMEM; - davinci_wdt->clk = devm_clk_get(dev, NULL); + davinci_wdt->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(davinci_wdt->clk)) return dev_err_probe(dev, PTR_ERR(davinci_wdt->clk), "failed to get clock node\n"); - ret = clk_prepare_enable(davinci_wdt->clk); - if (ret) { - dev_err(dev, "failed to prepare clock\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, davinci_clk_disable_unprepare, - davinci_wdt->clk); - if (ret) - return ret; - platform_set_drvdata(pdev, davinci_wdt); wdd = &davinci_wdt->wdd; From f3a0dd648961f09936278752a8e9299a55f82bc5 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 11:59:57 +0100 Subject: [PATCH 13/52] watchdog: imx7ulp: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/f23a2cf84958adca255b82fd688e7cee0461760f.1672484376.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/imx7ulp_wdt.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/watchdog/imx7ulp_wdt.c b/drivers/watchdog/imx7ulp_wdt.c index 2897902090b3..7ca486794ba7 100644 --- a/drivers/watchdog/imx7ulp_wdt.c +++ b/drivers/watchdog/imx7ulp_wdt.c @@ -299,11 +299,6 @@ static int imx7ulp_wdt_init(struct imx7ulp_wdt_device *wdt, unsigned int timeout return ret; } -static void imx7ulp_wdt_action(void *data) -{ - clk_disable_unprepare(data); -} - static int imx7ulp_wdt_probe(struct platform_device *pdev) { struct imx7ulp_wdt_device *imx7ulp_wdt; @@ -321,7 +316,7 @@ static int imx7ulp_wdt_probe(struct platform_device *pdev) if (IS_ERR(imx7ulp_wdt->base)) return PTR_ERR(imx7ulp_wdt->base); - imx7ulp_wdt->clk = devm_clk_get(dev, NULL); + imx7ulp_wdt->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(imx7ulp_wdt->clk)) { dev_err(dev, "Failed to get watchdog clock\n"); return PTR_ERR(imx7ulp_wdt->clk); @@ -336,14 +331,6 @@ static int imx7ulp_wdt_probe(struct platform_device *pdev) dev_info(dev, "imx7ulp wdt probe\n"); } - ret = clk_prepare_enable(imx7ulp_wdt->clk); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, imx7ulp_wdt_action, imx7ulp_wdt->clk); - if (ret) - return ret; - wdog = &imx7ulp_wdt->wdd; wdog->info = &imx7ulp_wdt_info; wdog->ops = &imx7ulp_wdt_ops; From 6cc0768ba6f5293a4435612164a2cfbf2edbd025 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 30 Dec 2022 17:41:31 +0100 Subject: [PATCH 14/52] watchdog: rtd119x: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/14b521b821279bc5111dc80b55d0936c5767c737.1672418470.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rtd119x_wdt.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/watchdog/rtd119x_wdt.c b/drivers/watchdog/rtd119x_wdt.c index 834b94ff3f90..95c8d7abce42 100644 --- a/drivers/watchdog/rtd119x_wdt.c +++ b/drivers/watchdog/rtd119x_wdt.c @@ -94,16 +94,10 @@ static const struct of_device_id rtd119x_wdt_dt_ids[] = { { } }; -static void rtd119x_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int rtd119x_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rtd119x_watchdog_device *data; - int ret; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -113,18 +107,10 @@ static int rtd119x_wdt_probe(struct platform_device *pdev) if (IS_ERR(data->base)) return PTR_ERR(data->base); - data->clk = devm_clk_get(dev, NULL); + data->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(data->clk)) return PTR_ERR(data->clk); - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - ret = devm_add_action_or_reset(dev, rtd119x_clk_disable_unprepare, - data->clk); - if (ret) - return ret; - data->wdt_dev.info = &rtd119x_wdt_info; data->wdt_dev.ops = &rtd119x_wdt_ops; data->wdt_dev.timeout = 120; From be80ae3d799dab1b46c661158b2b5d6695258178 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 09:10:17 +0100 Subject: [PATCH 15/52] watchdog: bcm7038: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Acked-by: Florian Fainelli Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/9c055911e9f557b7239000c8e6cfa0cc393a19e9.1672474203.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/bcm7038_wdt.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c index 9388838899ac..e038dd66b819 100644 --- a/drivers/watchdog/bcm7038_wdt.c +++ b/drivers/watchdog/bcm7038_wdt.c @@ -127,11 +127,6 @@ static const struct watchdog_ops bcm7038_wdt_ops = { .get_timeleft = bcm7038_wdt_get_timeleft, }; -static void bcm7038_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int bcm7038_wdt_probe(struct platform_device *pdev) { struct bcm7038_wdt_platform_data *pdata = pdev->dev.platform_data; @@ -153,17 +148,9 @@ static int bcm7038_wdt_probe(struct platform_device *pdev) if (pdata && pdata->clk_name) clk_name = pdata->clk_name; - wdt->clk = devm_clk_get(dev, clk_name); + wdt->clk = devm_clk_get_enabled(dev, clk_name); /* If unable to get clock, use default frequency */ if (!IS_ERR(wdt->clk)) { - err = clk_prepare_enable(wdt->clk); - if (err) - return err; - err = devm_add_action_or_reset(dev, - bcm7038_clk_disable_unprepare, - wdt->clk); - if (err) - return err; wdt->rate = clk_get_rate(wdt->clk); /* Prevent divide-by-zero exception */ if (!wdt->rate) From cd9e5d04dc47264e1101ed134e383020ab45a272 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 09:00:31 +0100 Subject: [PATCH 16/52] watchdog: armada_37xx: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/ccb096879a1309b9918ae956d6bdb9668c69bcda.1672473617.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/armada_37xx_wdt.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c index ac9fed1ef681..e58652939f8a 100644 --- a/drivers/watchdog/armada_37xx_wdt.c +++ b/drivers/watchdog/armada_37xx_wdt.c @@ -246,11 +246,6 @@ static const struct watchdog_ops armada_37xx_wdt_ops = { .get_timeleft = armada_37xx_wdt_get_timeleft, }; -static void armada_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int armada_37xx_wdt_probe(struct platform_device *pdev) { struct armada_37xx_watchdog *dev; @@ -280,18 +275,10 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev) return -ENOMEM; /* init clock */ - dev->clk = devm_clk_get(&pdev->dev, NULL); + dev->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(dev->clk)) return PTR_ERR(dev->clk); - ret = clk_prepare_enable(dev->clk); - if (ret) - return ret; - ret = devm_add_action_or_reset(&pdev->dev, - armada_clk_disable_unprepare, dev->clk); - if (ret) - return ret; - dev->clk_rate = clk_get_rate(dev->clk); if (!dev->clk_rate) return -EINVAL; From 1a8d192bccb2fbbdcfcd13e89e86ab8a0945ea75 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 30 Dec 2022 17:49:47 +0100 Subject: [PATCH 17/52] watchdog: qcom: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/7c2d5f3815949faf6d3a0237a7b5f272f00a7ae9.1672418969.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/qcom-wdt.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index 0d2209c5eaca..d776474dcdf3 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -175,11 +175,6 @@ static const struct watchdog_info qcom_wdt_pt_info = { .identity = KBUILD_MODNAME, }; -static void qcom_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static const struct qcom_wdt_match_data match_data_apcs_tmr = { .offset = reg_offset_data_apcs_tmr, .pretimeout = false, @@ -226,21 +221,12 @@ static int qcom_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) { dev_err(dev, "failed to get input clock\n"); return PTR_ERR(clk); } - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "failed to setup clock\n"); - return ret; - } - ret = devm_add_action_or_reset(dev, qcom_clk_disable_unprepare, clk); - if (ret) - return ret; - /* * We use the clock rate to calculate the max timeout, so ensure it's * not zero to avoid a divide-by-zero exception. From a42912ac400fdc05cffb6bc1e263eff466bbf8b2 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 30 Dec 2022 17:36:20 +0100 Subject: [PATCH 18/52] watchdog: rzn1: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/b1f8b5453791035ad534bd5ed36b49798ff4d9b2.1672418166.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzn1_wdt.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/watchdog/rzn1_wdt.c b/drivers/watchdog/rzn1_wdt.c index 55ab384b9965..980c1717adb5 100644 --- a/drivers/watchdog/rzn1_wdt.c +++ b/drivers/watchdog/rzn1_wdt.c @@ -98,11 +98,6 @@ static const struct watchdog_ops rzn1_wdt_ops = { .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; @@ -132,23 +127,12 @@ static int rzn1_wdt_probe(struct platform_device *pdev) return ret; } - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_enabled(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"); From 8c5210dbdf7e924b435c892d979472191d9cec95 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Fri, 30 Dec 2022 17:32:42 +0100 Subject: [PATCH 19/52] watchdog: visconti: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/13e8cdf17556da111d1d98a8fe0b1dc1c78007e2.1672417940.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/visconti_wdt.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/watchdog/visconti_wdt.c b/drivers/watchdog/visconti_wdt.c index 83ef55e66ca8..cef0794708e7 100644 --- a/drivers/watchdog/visconti_wdt.c +++ b/drivers/watchdog/visconti_wdt.c @@ -112,11 +112,6 @@ static const struct watchdog_ops visconti_wdt_ops = { .set_timeout = visconti_wdt_set_timeout, }; -static void visconti_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static int visconti_wdt_probe(struct platform_device *pdev) { struct watchdog_device *wdev; @@ -134,20 +129,10 @@ static int visconti_wdt_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) return dev_err_probe(dev, PTR_ERR(clk), "Could not get clock\n"); - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "Could not enable clock\n"); - return ret; - } - - ret = devm_add_action_or_reset(dev, visconti_clk_disable_unprepare, clk); - if (ret) - return ret; - clk_freq = clk_get_rate(clk); if (!clk_freq) return -EINVAL; From 98b7a1613011d9d5ec76841a2a5a689c3010d1f3 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 31 Dec 2022 08:57:22 +0100 Subject: [PATCH 20/52] watchdog: apple: Use devm_clk_get_enabled() helper The devm_clk_get_enabled() helper: - calls devm_clk_get() - calls clk_prepare_enable() and registers what is needed in order to call clk_disable_unprepare() when needed, as a managed resource. This simplifies the code and avoids the need of a dedicated function used with devm_add_action_or_reset(). Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Reviewed-by: Sven Peter Link: https://lore.kernel.org/r/6f312af6160d1e10b616c9adbd1fd8f822db964d.1672473415.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/apple_wdt.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/watchdog/apple_wdt.c b/drivers/watchdog/apple_wdt.c index 16aca21f13d6..eddeb0fede89 100644 --- a/drivers/watchdog/apple_wdt.c +++ b/drivers/watchdog/apple_wdt.c @@ -136,11 +136,6 @@ static int apple_wdt_restart(struct watchdog_device *wdd, unsigned long mode, return 0; } -static void apple_wdt_clk_disable_unprepare(void *data) -{ - clk_disable_unprepare(data); -} - static struct watchdog_ops apple_wdt_ops = { .owner = THIS_MODULE, .start = apple_wdt_start, @@ -162,7 +157,6 @@ static int apple_wdt_probe(struct platform_device *pdev) struct apple_wdt *wdt; struct clk *clk; u32 wdt_ctrl; - int ret; wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); if (!wdt) @@ -172,19 +166,9 @@ static int apple_wdt_probe(struct platform_device *pdev) if (IS_ERR(wdt->regs)) return PTR_ERR(wdt->regs); - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - - ret = clk_prepare_enable(clk); - if (ret) - return ret; - - ret = devm_add_action_or_reset(dev, apple_wdt_clk_disable_unprepare, - clk); - if (ret) - return ret; - wdt->clk_rate = clk_get_rate(clk); if (!wdt->clk_rate) return -EINVAL; From 00bdbc9a860152cafc0bcfa4fc70f38401101ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Thu, 22 Dec 2022 23:43:31 +0000 Subject: [PATCH 21/52] watchdog: wdat_wdt: Avoid unimplemented get_timeleft MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per the specification the action QUERY_COUNTDOWN_PERIOD is optional. If the action is not implemented by the physical device the driver would always report "0" from get_timeleft(). Avoid confusing userspace by only providing get_timeleft() when implemented by the hardware. Signed-off-by: Thomas Weißschuh Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221221-wdat_wdt-timeleft-v1-1-8e8a314c36cc@weissschuh.net Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wdat_wdt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index ce7a4a9e4b03..0ba99bed59fc 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -301,13 +301,12 @@ static const struct watchdog_info wdat_wdt_info = { .identity = "wdat_wdt", }; -static const struct watchdog_ops wdat_wdt_ops = { +static struct watchdog_ops wdat_wdt_ops = { .owner = THIS_MODULE, .start = wdat_wdt_start, .stop = wdat_wdt_stop, .ping = wdat_wdt_ping, .set_timeout = wdat_wdt_set_timeout, - .get_timeleft = wdat_wdt_get_timeleft, }; static int wdat_wdt_probe(struct platform_device *pdev) @@ -436,6 +435,9 @@ static int wdat_wdt_probe(struct platform_device *pdev) list_add_tail(&instr->node, instructions); } + if (wdat->instructions[ACPI_WDAT_GET_CURRENT_COUNTDOWN]) + wdat_wdt_ops.get_timeleft = wdat_wdt_get_timeleft; + wdat_wdt_boot_status(wdat); wdat_wdt_set_running(wdat); From f8ee39b44b75ac955bb54f46d5370481727c47e7 Mon Sep 17 00:00:00 2001 From: Primoz Fiser Date: Fri, 16 Dec 2022 09:36:45 +0100 Subject: [PATCH 22/52] watchdog: da9062: da9063: use unlocked xfer function in restart Machine resets via da9062/da9063 PMICs are challenging since one needs to use special i2c atomic transfers due to the fact interrupts are disabled in such late system stages. This is the reason both PMICs don't use regmap and have instead opted for i2c_smbus_write_byte_data() in restart handlers. However extensive testing revealed that even using atomic safe function is not enough and occasional resets fail with error message "Failed to shutdown (err = -11)". This is due to the fact that function i2c_smbus_write_byte_data() in turn calls __i2c_lock_bus_helper() which might fail with -EAGAIN when bus lock is already taken and cannot be released anymore. Thus replace i2c_smbus_write_byte_data() with unlocked flavor of i2c_smbus_xfer() function to avoid above dead-lock scenario. At this system stage we don't care about proper locking anymore and only want proper machine reset to be carried out. Signed-off-by: Primoz Fiser Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221216083645.2574077-1-primoz.fiser@norik.com [groeck: Fixed continuation line alignment] Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/da9062_wdt.c | 15 ++++++++++++--- drivers/watchdog/da9063_wdt.c | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c index f02cbd530538..426962547df1 100644 --- a/drivers/watchdog/da9062_wdt.c +++ b/drivers/watchdog/da9062_wdt.c @@ -155,11 +155,20 @@ static int da9062_wdt_restart(struct watchdog_device *wdd, unsigned long action, { struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd); struct i2c_client *client = to_i2c_client(wdt->hw->dev); + union i2c_smbus_data msg; int ret; - /* Don't use regmap because it is not atomic safe */ - ret = i2c_smbus_write_byte_data(client, DA9062AA_CONTROL_F, - DA9062AA_SHUTDOWN_MASK); + /* + * Don't use regmap because it is not atomic safe. Additionally, use + * unlocked flavor of i2c_smbus_xfer to avoid scenario where i2c bus + * might be previously locked by some process unable to release the + * lock due to interrupts already being disabled at this late stage. + */ + msg.byte = DA9062AA_SHUTDOWN_MASK; + ret = __i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, DA9062AA_CONTROL_F, + I2C_SMBUS_BYTE_DATA, &msg); + if (ret < 0) dev_alert(wdt->hw->dev, "Failed to shutdown (err = %d)\n", ret); diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c index 09a4af4c58fc..684667469b10 100644 --- a/drivers/watchdog/da9063_wdt.c +++ b/drivers/watchdog/da9063_wdt.c @@ -174,11 +174,20 @@ static int da9063_wdt_restart(struct watchdog_device *wdd, unsigned long action, { struct da9063 *da9063 = watchdog_get_drvdata(wdd); struct i2c_client *client = to_i2c_client(da9063->dev); + union i2c_smbus_data msg; int ret; - /* Don't use regmap because it is not atomic safe */ - ret = i2c_smbus_write_byte_data(client, DA9063_REG_CONTROL_F, - DA9063_SHUTDOWN); + /* + * Don't use regmap because it is not atomic safe. Additionally, use + * unlocked flavor of i2c_smbus_xfer to avoid scenario where i2c bus + * might previously be locked by some process unable to release the + * lock due to interrupts already being disabled at this late stage. + */ + msg.byte = DA9063_SHUTDOWN; + ret = __i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_WRITE, DA9063_REG_CONTROL_F, + I2C_SMBUS_BYTE_DATA, &msg); + if (ret < 0) dev_alert(da9063->dev, "Failed to shutdown (err = %d)\n", ret); From e8b1cb537b8095e1bc528ce2aef56318195d8343 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 13 Jan 2023 11:33:46 +0100 Subject: [PATCH 23/52] dt-bindings: watchdog: allow "timer" as node name On some SoCs the watchdog device is actually mixed with timer, e.g. the qcom,msm-timer on older Qualcomm SoCs where this is actually one hardware block responsible for both system timer and watchdog. Allow calling such device nodes as "timer". Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221212174933.208900-1-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/watchdog.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/watchdog/watchdog.yaml b/Documentation/devicetree/bindings/watchdog/watchdog.yaml index fccae0d00110..519b48889eb1 100644 --- a/Documentation/devicetree/bindings/watchdog/watchdog.yaml +++ b/Documentation/devicetree/bindings/watchdog/watchdog.yaml @@ -14,9 +14,14 @@ description: | This document describes generic bindings which can be used to describe watchdog devices in a device tree. +select: + properties: + $nodename: + pattern: "^watchdog(@.*|-[0-9a-f])?$" + properties: $nodename: - pattern: "^watchdog(@.*|-[0-9a-f])?$" + pattern: "^(timer|watchdog)(@.*|-[0-9a-f])?$" timeout-sec: description: From 4ea6b986dfaff19e014ea634bdca669eebe73def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Fri, 25 Nov 2022 23:12:40 +0100 Subject: [PATCH 24/52] watchdog: iTCO_wdt: Report firmware_version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Synchronize the reported information in dmesg and the watchdog APIs. Signed-off-by: Thomas Weißschuh Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221125221240.2818-1-linux@weissschuh.net Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index e937b4dd28be..264857d314da 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -441,11 +441,10 @@ static bool iTCO_wdt_set_running(struct iTCO_wdt_private *p) * Kernel Interfaces */ -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, - .firmware_version = 0, .identity = DRV_NAME, }; @@ -563,6 +562,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) break; } + ident.firmware_version = p->iTCO_version; p->wddev.info = &ident, p->wddev.ops = &iTCO_wdt_ops, p->wddev.bootstatus = 0; From 0d9e42e3c8ccde51a9ff7c49684ed7a3805ebd52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 18 Nov 2022 23:45:30 +0100 Subject: [PATCH 25/52] watchdog: ziirave_wdt: Convert to i2c's .probe_new() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe function doesn't make use of the i2c_device_id * parameter so it can be trivially converted. Signed-off-by: Uwe Kleine-König Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221118224540.619276-597-uwe@kleine-koenig.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/ziirave_wdt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c index d0e88875443a..21ca08a694ee 100644 --- a/drivers/watchdog/ziirave_wdt.c +++ b/drivers/watchdog/ziirave_wdt.c @@ -593,8 +593,7 @@ static int ziirave_wdt_init_duration(struct i2c_client *client) reset_duration); } -static int ziirave_wdt_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int ziirave_wdt_probe(struct i2c_client *client) { int ret; struct ziirave_wdt_data *w_priv; @@ -732,7 +731,7 @@ static struct i2c_driver ziirave_wdt_driver = { .name = "ziirave_wdt", .of_match_table = zrv_wdt_of_match, }, - .probe = ziirave_wdt_probe, + .probe_new = ziirave_wdt_probe, .remove = ziirave_wdt_remove, .id_table = ziirave_wdt_id, }; From 7bfd2747d3ec2c400857084527448c172a720d2a Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Fri, 18 Nov 2022 17:08:09 +0200 Subject: [PATCH 26/52] watchdog: dw_wdt: stop on reboot HW running watchdogs are just watchdogs that are enabled before the Linux driver is probed, usually by the bootloader (eg. U-Boot). When the system is shutting down, the mechanism for keeping a HW running watchdog pinged is also stopped, but the watchdog itself is not stopped, causing a reset, and preventing the system from being shut down. Opt into stopping watchdogs on reboot. Signed-off-by: Cosmin Tanislav Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221118150809.102505-1-cosmin.tanislav@analog.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/dw_wdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 52962e8d11a6..462f15bd5ffa 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -663,6 +663,7 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dw_wdt); watchdog_set_restart_priority(wdd, 128); + watchdog_stop_on_reboot(wdd); ret = watchdog_register_device(wdd); if (ret) From 71708daa6f1446248de107e04cf28ffd322c800f Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Fri, 25 Nov 2022 12:29:04 +0100 Subject: [PATCH 27/52] dt-bindings: watchdog: Convert GPIO binding to json-schema Convert the DT binding for GPIO WDT to JSON schema. Cc: luka.perkov@sartura.hr Signed-off-by: Robert Marko Reviewed-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221125112904.48652-1-robert.marko@sartura.hr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/gpio-wdt.yaml | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Documentation/devicetree/bindings/watchdog/gpio-wdt.yaml diff --git a/Documentation/devicetree/bindings/watchdog/gpio-wdt.yaml b/Documentation/devicetree/bindings/watchdog/gpio-wdt.yaml new file mode 100644 index 000000000000..155dc7965e9b --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/gpio-wdt.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/gpio-wdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO controlled watchdog + +maintainers: + - Robert Marko + +properties: + compatible: + const: linux,wdt-gpio + + gpios: + maxItems: 1 + description: GPIO connected to the WDT reset pin + + hw_algo: + $ref: /schemas/types.yaml#/definitions/string + description: Algorithm used by the driver + oneOf: + - description: + Either a high-to-low or a low-to-high transition clears the WDT counter. + The watchdog timer is disabled when GPIO is left floating or connected + to a three-state buffer. + const: toggle + - description: + Low or high level starts counting WDT timeout, the opposite level + disables the WDT. + Active level is determined by the GPIO flags. + const: level + + hw_margin_ms: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Maximum time to reset watchdog circuit (in milliseconds) + minimum: 2 + maximum: 65535 + + always-running: + type: boolean + description: + If the watchdog timer cannot be disabled, add this flag to have the driver + keep toggling the signal without a client. + It will only cease to toggle the signal when the device is open and the + timeout elapsed. + +required: + - compatible + - gpios + - hw_algo + - hw_margin_ms + +unevaluatedProperties: false From 69197b43d9e3b164e847beede62d576ee01ee081 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 23 Jan 2023 11:10:00 +0100 Subject: [PATCH 28/52] dt-bindings: watchdog: convert meson-wdt.txt to dt-schema Convert the Amlogic Meson6 SoCs Watchdog timer bindings to dt-schema. Take in account the used interrupts property. The "amlogic,meson8-wdt" representation has been simplified since there's no users of this compatible used along the "amlogic,meson6-wdt". Reviewed-by: Krzysztof Kozlowski Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221117-b4-amlogic-bindings-convert-v3-3-e28dd31e3bed@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/amlogic,meson6-wdt.yaml | 50 +++++++++++++++++++ .../bindings/watchdog/meson-wdt.txt | 21 -------- 2 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 Documentation/devicetree/bindings/watchdog/amlogic,meson6-wdt.yaml delete mode 100644 Documentation/devicetree/bindings/watchdog/meson-wdt.txt diff --git a/Documentation/devicetree/bindings/watchdog/amlogic,meson6-wdt.yaml b/Documentation/devicetree/bindings/watchdog/amlogic,meson6-wdt.yaml new file mode 100644 index 000000000000..84732cb58ec4 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/amlogic,meson6-wdt.yaml @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/amlogic,meson6-wdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson6 SoCs Watchdog timer + +maintainers: + - Neil Armstrong + - Martin Blumenstingl + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + oneOf: + - enum: + - amlogic,meson6-wdt + - amlogic,meson8-wdt + - amlogic,meson8b-wdt + - items: + - const: amlogic,meson8m2-wdt + - const: amlogic,meson8b-wdt + + interrupts: + maxItems: 1 + + reg: + maxItems: 1 + +required: + - compatible + - interrupts + - reg + +unevaluatedProperties: false + +examples: + - | + #include + #include + + wdt: watchdog@c1109900 { + compatible = "amlogic,meson6-wdt"; + reg = <0xc1109900 0x8>; + interrupts = ; + timeout-sec = <10>; + }; diff --git a/Documentation/devicetree/bindings/watchdog/meson-wdt.txt b/Documentation/devicetree/bindings/watchdog/meson-wdt.txt deleted file mode 100644 index 7588cc3971bf..000000000000 --- a/Documentation/devicetree/bindings/watchdog/meson-wdt.txt +++ /dev/null @@ -1,21 +0,0 @@ -Meson SoCs Watchdog timer - -Required properties: - -- compatible : depending on the SoC this should be one of: - "amlogic,meson6-wdt" on Meson6 SoCs - "amlogic,meson8-wdt" and "amlogic,meson6-wdt" on Meson8 SoCs - "amlogic,meson8b-wdt" on Meson8b SoCs - "amlogic,meson8m2-wdt" and "amlogic,meson8b-wdt" on Meson8m2 SoCs -- reg : Specifies base physical address and size of the registers. - -Optional properties: -- timeout-sec: contains the watchdog timeout in seconds. - -Example: - -wdt: watchdog@c1109900 { - compatible = "amlogic,meson6-wdt"; - reg = <0xc1109900 0x8>; - timeout-sec = <10>; -}; From d237c8d06d5a08a2dacb07c0ab07af696a58516c Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Fri, 18 Nov 2022 13:38:29 +0000 Subject: [PATCH 29/52] dt-bindings: watchdog: renesas,wdt: Document RZ/Five SoC The WDT block on the RZ/Five SoC is identical to one found on the RZ/G2UL SoC. "renesas,r9a07g043-wdt" compatible string will be used on the RZ/Five SoC so to make this clear, update the comment to include RZ/Five SoC. No driver changes are required as generic compatible string "renesas,rzg2l-wdt" will be used as a fallback on RZ/Five SoC. Signed-off-by: Lad Prabhakar Acked-by: Krzysztof Kozlowski Reviewed-by: Guenter Roeck Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20221118133829.12855-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 | 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 26b1815a6753..e2c9bf1aec38 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/renesas,wdt.yaml @@ -26,7 +26,7 @@ properties: - items: - enum: - - renesas,r9a07g043-wdt # RZ/G2UL + - renesas,r9a07g043-wdt # RZ/G2UL and RZ/Five - renesas,r9a07g044-wdt # RZ/G2{L,LC} - renesas,r9a07g054-wdt # RZ/V2L - const: renesas,rzg2l-wdt From e9651838fe7727c1c8b193b0217307c4c2260777 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Thu, 17 Nov 2022 11:58:45 +0100 Subject: [PATCH 30/52] dt-bindings: watchdog: Add MSM8994 watchdog timer Document the MSM8994 watchdog timer which is already used in DT. Signed-off-by: Konrad Dybcio Acked-by: Krzysztof Kozlowski Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221117105845.13644-2-konrad.dybcio@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index d8ac0be36e6c..a1f17c9e02db 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -17,6 +17,7 @@ properties: oneOf: - items: - enum: + - qcom,apss-wdt-msm8994 - qcom,apss-wdt-qcs404 - qcom,apss-wdt-sc7180 - qcom,apss-wdt-sc7280 From 6ba6f0f5910d5916539268c0ad55657bb8940616 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Thu, 17 Nov 2022 11:49:06 +0000 Subject: [PATCH 31/52] watchdog: rzg2l_wdt: Issue a reset before we put the PM clocks On RZ/Five SoC it was observed that setting timeout (to say 1 sec) wouldn't reset the system. The procedure described in the HW manual (Procedure for Activating Modules) for activating the target module states we need to start supply of the clock module before applying the reset signal. This patch makes sure we follow the same procedure to clear the registers of the WDT module, fixing the issues seen on RZ/Five SoC. While at it re-used rzg2l_wdt_stop() in rzg2l_wdt_set_timeout() as it has the same function calls. Fixes: 4055ee81009e ("watchdog: rzg2l_wdt: Add set_timeout callback") Signed-off-by: Lad Prabhakar Reviewed-by: Guenter Roeck Reviewed-by: Geert Uytterhoeven Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20221117114907.138583-2-fabrizio.castro.jz@renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index 974a4194a8fd..ceca42db0837 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -115,25 +115,23 @@ 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_reset(priv->rstc); + pm_runtime_put(wdev->parent); 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. + * register by calling rzg2l_wdt_stop() (which internally calls reset_control_reset() + * to reset the module) 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_stop(wdev); rzg2l_wdt_start(wdev); } From f769f97917c1e756e12ff042a93f6e3167254b5b Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Thu, 17 Nov 2022 11:49:07 +0000 Subject: [PATCH 32/52] watchdog: rzg2l_wdt: Handle TYPE-B reset for RZ/V2M As per section 48.4 of the HW User Manual, IPs in the RZ/V2M SoC need either a TYPE-A reset sequence or a TYPE-B reset sequence. More specifically, the watchdog IP needs a TYPE-B reset sequence. If the proper reset sequence isn't implemented, then resetting IPs may lead to undesired behaviour. In the restart callback of the watchdog driver the reset has basically no effect on the desired funcionality, as the register writes following the reset happen before the IP manages to come out of reset. Implement the TYPE-B reset sequence in the watchdog driver to address the issues with the restart callback on RZ/V2M. Fixes: ec122fd94eeb ("watchdog: rzg2l_wdt: Add rzv2m support") Signed-off-by: Fabrizio Castro Reviewed-by: Guenter Roeck Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20221117114907.138583-3-fabrizio.castro.jz@renesas.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/rzg2l_wdt.c | 37 +++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c index ceca42db0837..d404953d0e0f 100644 --- a/drivers/watchdog/rzg2l_wdt.c +++ b/drivers/watchdog/rzg2l_wdt.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ #define F2CYCLE_NSEC(f) (1000000000 / (f)) +#define RZV2M_A_NSEC 730 + static bool nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, bool, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" @@ -51,11 +54,35 @@ struct rzg2l_wdt_priv { struct reset_control *rstc; unsigned long osc_clk_rate; unsigned long delay; + unsigned long minimum_assertion_period; struct clk *pclk; struct clk *osc_clk; enum rz_wdt_type devtype; }; +static int rzg2l_wdt_reset(struct rzg2l_wdt_priv *priv) +{ + int err, status; + + if (priv->devtype == WDT_RZV2M) { + /* WDT needs TYPE-B reset control */ + err = reset_control_assert(priv->rstc); + if (err) + return err; + ndelay(priv->minimum_assertion_period); + err = reset_control_deassert(priv->rstc); + if (err) + return err; + err = read_poll_timeout(reset_control_status, status, + status != 1, 0, 1000, false, + priv->rstc); + } else { + err = reset_control_reset(priv->rstc); + } + + return err; +} + static void rzg2l_wdt_wait_delay(struct rzg2l_wdt_priv *priv) { /* delay timer when change the setting register */ @@ -115,7 +142,7 @@ static int rzg2l_wdt_stop(struct watchdog_device *wdev) { struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev); - reset_control_reset(priv->rstc); + rzg2l_wdt_reset(priv); pm_runtime_put(wdev->parent); return 0; @@ -154,6 +181,7 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev, rzg2l_wdt_write(priv, PEEN_FORCE, PEEN); } else { /* RZ/V2M doesn't have parity error registers */ + rzg2l_wdt_reset(priv); wdev->timeout = 0; @@ -251,6 +279,13 @@ static int rzg2l_wdt_probe(struct platform_device *pdev) priv->devtype = (uintptr_t)of_device_get_match_data(dev); + if (priv->devtype == WDT_RZV2M) { + priv->minimum_assertion_period = RZV2M_A_NSEC + + 3 * F2CYCLE_NSEC(pclk_rate) + 5 * + max(F2CYCLE_NSEC(priv->osc_clk_rate), + F2CYCLE_NSEC(pclk_rate)); + } + pm_runtime_enable(&pdev->dev); priv->wdev.info = &rzg2l_wdt_ident; From 07bec0e09c1afbab4c5674fd2341f4f52d594f30 Mon Sep 17 00:00:00 2001 From: ruanjinjie Date: Wed, 16 Nov 2022 17:49:50 +0800 Subject: [PATCH 33/52] watchdog: at91sam9_wdt: use devm_request_irq to avoid missing free_irq() in error path free_irq() is missing in case of error in at91_wdt_init(), use devm_request_irq to fix that. Fixes: 5161b31dc39a ("watchdog: at91sam9_wdt: better watchdog support") Signed-off-by: ruanjinjie Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221116094950.3141943-1-ruanjinjie@huawei.com [groeck: Adjust multi-line alignment] Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/at91sam9_wdt.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index 292b5a1ca831..fed7be246442 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c @@ -206,10 +206,9 @@ static int at91_wdt_init(struct platform_device *pdev, struct at91wdt *wdt) "min heartbeat and max heartbeat might be too close for the system to handle it correctly\n"); if ((tmp & AT91_WDT_WDFIEN) && wdt->irq) { - err = request_irq(wdt->irq, wdt_interrupt, - IRQF_SHARED | IRQF_IRQPOLL | - IRQF_NO_SUSPEND, - pdev->name, wdt); + err = devm_request_irq(dev, wdt->irq, wdt_interrupt, + IRQF_SHARED | IRQF_IRQPOLL | IRQF_NO_SUSPEND, + pdev->name, wdt); if (err) return err; } From a243cb9357cc21a441c464e63b151e292a732d56 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 5 Nov 2022 12:09:34 +0100 Subject: [PATCH 34/52] watchdog: Include when appropriate The kstrto() functions have been moved from kernel.h to kstrtox.h. So, in order to eventually remove from , include the latter directly in the appropriate files. Signed-off-by: Christophe JAILLET Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/08fd5512e569558231247515c04c8596a1d11004.1667646547.git.christophe.jaillet@wanadoo.fr Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/aspeed_wdt.c | 1 + drivers/watchdog/watchdog_dev.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 86b5331bc491..c1e79874a2bb 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 55574ed42504..f31608f3e324 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -35,6 +35,7 @@ #include /* For __init/__exit/... */ #include /* For hrtimers */ #include /* For printk/panic/... */ +#include /* For kstrto* */ #include /* For kthread_work */ #include /* For handling misc devices */ #include /* For module stuff/... */ From 13721a2ac66b246f5802ba1b75ad8637e53eeecc Mon Sep 17 00:00:00 2001 From: Chen Jun Date: Wed, 16 Nov 2022 01:27:14 +0000 Subject: [PATCH 35/52] watchdog: Fix kmemleak in watchdog_cdev_register kmemleak reports memory leaks in watchdog_dev_register, as follows: unreferenced object 0xffff888116233000 (size 2048): comm ""modprobe"", pid 28147, jiffies 4353426116 (age 61.741s) hex dump (first 32 bytes): 80 fa b9 05 81 88 ff ff 08 30 23 16 81 88 ff ff .........0#..... 08 30 23 16 81 88 ff ff 00 00 00 00 00 00 00 00 .0#............. backtrace: [<000000007f001ffd>] __kmem_cache_alloc_node+0x157/0x220 [<000000006a389304>] kmalloc_trace+0x21/0x110 [<000000008d640eea>] watchdog_dev_register+0x4e/0x780 [watchdog] [<0000000053c9f248>] __watchdog_register_device+0x4f0/0x680 [watchdog] [<00000000b2979824>] watchdog_register_device+0xd2/0x110 [watchdog] [<000000001f730178>] 0xffffffffc10880ae [<000000007a1a8bcc>] do_one_initcall+0xcb/0x4d0 [<00000000b98be325>] do_init_module+0x1ca/0x5f0 [<0000000046d08e7c>] load_module+0x6133/0x70f0 ... unreferenced object 0xffff888105b9fa80 (size 16): comm ""modprobe"", pid 28147, jiffies 4353426116 (age 61.741s) hex dump (first 16 bytes): 77 61 74 63 68 64 6f 67 31 00 b9 05 81 88 ff ff watchdog1....... backtrace: [<000000007f001ffd>] __kmem_cache_alloc_node+0x157/0x220 [<00000000486ab89b>] __kmalloc_node_track_caller+0x44/0x1b0 [<000000005a39aab0>] kvasprintf+0xb5/0x140 [<0000000024806f85>] kvasprintf_const+0x55/0x180 [<000000009276cb7f>] kobject_set_name_vargs+0x56/0x150 [<00000000a92e820b>] dev_set_name+0xab/0xe0 [<00000000cec812c6>] watchdog_dev_register+0x285/0x780 [watchdog] [<0000000053c9f248>] __watchdog_register_device+0x4f0/0x680 [watchdog] [<00000000b2979824>] watchdog_register_device+0xd2/0x110 [watchdog] [<000000001f730178>] 0xffffffffc10880ae [<000000007a1a8bcc>] do_one_initcall+0xcb/0x4d0 [<00000000b98be325>] do_init_module+0x1ca/0x5f0 [<0000000046d08e7c>] load_module+0x6133/0x70f0 ... The reason is that put_device is not be called if cdev_device_add fails and wdd->id != 0. watchdog_cdev_register wd_data = kzalloc [1] err = dev_set_name [2] .. err = cdev_device_add if (err) { if (wdd->id == 0) { // wdd->id != 0 .. } return err; // [1],[2] would be leaked To fix it, call put_device in all wdd->id cases. Fixes: 72139dfa2464 ("watchdog: Fix the race between the release of watchdog_core_data and cdev") Signed-off-by: Chen Jun Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221116012714.102066-1-chenjun102@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/watchdog_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index f31608f3e324..455a9a572d7b 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -1062,8 +1062,8 @@ static int watchdog_cdev_register(struct watchdog_device *wdd) if (wdd->id == 0) { misc_deregister(&watchdog_miscdev); old_wd_data = NULL; - put_device(&wd_data->dev); } + put_device(&wd_data->dev); return err; } From 8e103beca676b871e06d282ed140bf5a3631e381 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 13 Jan 2023 11:33:40 +0100 Subject: [PATCH 36/52] dt-bindings: watchdog: qcom-wdt: require fallback for IPQ4019 The device specific compatibles ("qcom,kpss-wdt-ipq4019") should be follwed by fallback "qcom,kpss-wdt", which is actually used by Linux driver for binding. Signed-off-by: Krzysztof Kozlowski Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221212163532.142533-1-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index a1f17c9e02db..e76364c52fc7 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -17,6 +17,7 @@ properties: oneOf: - items: - enum: + - qcom,kpss-wdt-ipq4019 - qcom,apss-wdt-msm8994 - qcom,apss-wdt-qcs404 - qcom,apss-wdt-sc7180 @@ -35,7 +36,6 @@ properties: - 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 From f8e6b3d9e3cf60bb111ccc9294eb3fe7c7759193 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 13 Jan 2023 11:33:41 +0100 Subject: [PATCH 37/52] dt-bindings: watchdog: qcom-wdt: do not allow fallback alone The compatible "qcom,kpss-wdt" is too generic and should not be used alone. Mark it as deprecated when not prepended by specific compatible. Signed-off-by: Krzysztof Kozlowski Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221212163532.142533-2-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index e76364c52fc7..3e0b30a817d6 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -31,9 +31,10 @@ properties: - qcom,apss-wdt-sm8150 - qcom,apss-wdt-sm8250 - const: qcom,kpss-wdt + - const: qcom,kpss-wdt + deprecated: true - items: - enum: - - qcom,kpss-wdt - qcom,kpss-timer - qcom,kpss-wdt-apq8064 - qcom,kpss-wdt-ipq8064 From b8c8f8649ba1765cbd7e5c92f36c6553a9fadedf Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 13 Jan 2023 11:33:42 +0100 Subject: [PATCH 38/52] dt-bindings: watchdog: qcom-wdt: fix list of MSM timer compatibles The MSM timer ("qcom,msm-timer") is a bit different timer and watchdog device than KPSS watchdog. It has its own generic and specific compatibles, so fix the list to reflect this. Adjust the example to show the newer KPSS watchdog. Signed-off-by: Krzysztof Kozlowski Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221212163532.142533-3-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../devicetree/bindings/watchdog/qcom-wdt.yaml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index 3e0b30a817d6..93e4381067dd 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -33,13 +33,16 @@ properties: - const: qcom,kpss-wdt - const: qcom,kpss-wdt deprecated: true + - items: + - const: qcom,scss-timer + - const: qcom,msm-timer - items: - enum: - - qcom,kpss-timer - qcom,kpss-wdt-apq8064 - qcom,kpss-wdt-ipq8064 - qcom,kpss-wdt-msm8960 - - qcom,scss-timer + - const: qcom,kpss-timer + - const: qcom,msm-timer reg: maxItems: 1 @@ -56,9 +59,11 @@ unevaluatedProperties: false examples: - | - watchdog@208a038 { - compatible = "qcom,kpss-wdt-ipq8064"; - reg = <0x0208a038 0x40>; + #include + + watchdog@17c10000 { + compatible = "qcom,apss-wdt-sm8150", "qcom,kpss-wdt"; + reg = <0x17c10000 0x1000>; clocks = <&sleep_clk>; timeout-sec = <10>; }; From 2bb28d179891cb073ea96fb9238257f871e158c1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 13 Jan 2023 11:33:43 +0100 Subject: [PATCH 39/52] dt-bindings: watchdog: qcom-wdt: add qcom,kpss-wdt-mdm9615 Document new MDM9615 qcom,kpss-wdt-mdm9615 watchdog/timer compatible. Signed-off-by: Krzysztof Kozlowski Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221212163532.142533-4-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index 93e4381067dd..1828eaf70b3b 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -40,6 +40,7 @@ properties: - enum: - qcom,kpss-wdt-apq8064 - qcom,kpss-wdt-ipq8064 + - qcom,kpss-wdt-mdm9615 - qcom,kpss-wdt-msm8960 - const: qcom,kpss-timer - const: qcom,msm-timer From 7c631cdff391dd8af4e56fc4cd162d6e6504aeec Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 13 Jan 2023 11:33:44 +0100 Subject: [PATCH 40/52] dt-bindings: watchdog: qcom-wdt: allow interrupts Both of type of watchdogs described in the binding (the KPSS watchdog and APSS WDT timer) have interrupts. Allow interrupts and describe them for KPSS watchdog to fix warnings like: watchdog@17c10000: Unevaluated properties are not allowed ('interrupts' was unexpected) Signed-off-by: Krzysztof Kozlowski Reviewed-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221212163532.142533-5-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/qcom-wdt.yaml | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index 1828eaf70b3b..b7fc57f4800e 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -9,9 +9,6 @@ title: Qualcomm Krait Processor Sub-system (KPSS) Watchdog timer maintainers: - Sai Prakash Ranjan -allOf: - - $ref: watchdog.yaml# - properties: compatible: oneOf: @@ -51,11 +48,31 @@ properties: clocks: maxItems: 1 + interrupts: + minItems: 1 + maxItems: 5 + required: - compatible - reg - clocks +allOf: + - $ref: watchdog.yaml# + + - if: + properties: + compatible: + contains: + const: qcom,kpss-wdt + then: + properties: + interrupts: + minItems: 1 + items: + - description: Bark + - description: Bite + unevaluatedProperties: false examples: @@ -66,5 +83,6 @@ examples: compatible = "qcom,apss-wdt-sm8150", "qcom,kpss-wdt"; reg = <0x17c10000 0x1000>; clocks = <&sleep_clk>; + interrupts = ; timeout-sec = <10>; }; From 733318534849044089de8c818a2fb1c67fa39bd1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 13 Jan 2023 11:33:45 +0100 Subject: [PATCH 41/52] dt-bindings: watchdog: qcom-wdt: merge MSM timer Merge Qualcomm MSM timer bindings into watchdog, because the timer compatibles are already included here and the hardware is quite similar. While converting the MSM timer bindings, adjust clock-frequency property to take only one frequency, instead of two, because: 1. DT schema does not allow to frequencies, 2. The Linux timer driver reads only first frequency. Signed-off-by: Krzysztof Kozlowski Acked-by: Daniel Lezcano Reviewed-by: Guenter Roeck Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20221212163532.142533-6-krzysztof.kozlowski@linaro.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/timer/qcom,msm-timer.txt | 47 ------------------ .../bindings/watchdog/qcom-wdt.yaml | 49 +++++++++++++++++++ 2 files changed, 49 insertions(+), 47 deletions(-) delete mode 100644 Documentation/devicetree/bindings/timer/qcom,msm-timer.txt diff --git a/Documentation/devicetree/bindings/timer/qcom,msm-timer.txt b/Documentation/devicetree/bindings/timer/qcom,msm-timer.txt deleted file mode 100644 index 5e10c345548f..000000000000 --- a/Documentation/devicetree/bindings/timer/qcom,msm-timer.txt +++ /dev/null @@ -1,47 +0,0 @@ -* MSM Timer - -Properties: - -- compatible : Should at least contain "qcom,msm-timer". More specific - properties specify which subsystem the timers are paired with. - - "qcom,kpss-timer" - krait subsystem - "qcom,scss-timer" - scorpion subsystem - -- interrupts : Interrupts for the debug timer, the first general purpose - timer, and optionally a second general purpose timer, and - optionally as well, 2 watchdog interrupts, in that order. - -- reg : Specifies the base address of the timer registers. - -- clocks: Reference to the parent clocks, one per output clock. The parents - must appear in the same order as the clock names. - -- clock-names: The name of the clocks as free-form strings. They should be in - the same order as the clocks. - -- clock-frequency : The frequency of the debug timer and the general purpose - timer(s) in Hz in that order. - -Optional: - -- cpu-offset : per-cpu offset used when the timer is accessed without the - CPU remapping facilities. The offset is - cpu-offset + (0x10000 * cpu-nr). - -Example: - - timer@200a000 { - compatible = "qcom,scss-timer", "qcom,msm-timer"; - interrupts = <1 1 0x301>, - <1 2 0x301>, - <1 3 0x301>, - <1 4 0x301>, - <1 5 0x301>; - reg = <0x0200a000 0x100>; - clock-frequency = <19200000>, - <32768>; - clocks = <&sleep_clk>; - clock-names = "sleep"; - cpu-offset = <0x40000>; - }; diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index b7fc57f4800e..837ce9112071 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -10,6 +10,9 @@ maintainers: - Sai Prakash Ranjan properties: + $nodename: + pattern: "^(watchdog|timer)@[0-9a-f]+$" + compatible: oneOf: - items: @@ -48,6 +51,20 @@ properties: clocks: maxItems: 1 + clock-names: + items: + - const: sleep + + clock-frequency: + description: + The frequency of the general purpose timer in Hz. + + cpu-offset: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Per-CPU offset used when the timer is accessed without the CPU remapping + facilities. The offset is cpu-offset + (0x10000 * cpu-nr). + interrupts: minItems: 1 maxItems: 5 @@ -67,12 +84,27 @@ allOf: const: qcom,kpss-wdt then: properties: + clock-frequency: false + cpu-offset: false interrupts: minItems: 1 items: - description: Bark - description: Bite + else: + properties: + interrupts: + minItems: 3 + items: + - description: Debug + - description: First general purpose timer + - description: Second general purpose timer + - description: First watchdog + - description: Second watchdog + required: + - clock-frequency + unevaluatedProperties: false examples: @@ -86,3 +118,20 @@ examples: interrupts = ; timeout-sec = <10>; }; + + - | + #include + + watchdog@200a000 { + compatible = "qcom,kpss-wdt-ipq8064", "qcom,kpss-timer", "qcom,msm-timer"; + interrupts = , + , + , + , + ; + reg = <0x0200a000 0x100>; + clock-frequency = <25000000>; + clocks = <&sleep_clk>; + clock-names = "sleep"; + cpu-offset = <0x80000>; + }; From 7d06c07c67100fd0f8e6b3ab7145ce789f788117 Mon Sep 17 00:00:00 2001 From: Li Hua Date: Wed, 16 Nov 2022 10:07:06 +0800 Subject: [PATCH 42/52] watchdog: pcwd_usb: Fix attempting to access uninitialized memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stack variable msb and lsb may be used uninitialized in function usb_pcwd_get_temperature and usb_pcwd_get_timeleft when usb card no response. The build waring is: drivers/watchdog/pcwd_usb.c:336:22: error: ‘lsb’ is used uninitialized in this function [-Werror=uninitialized] *temperature = (lsb * 9 / 5) + 32; ~~~~^~~ drivers/watchdog/pcwd_usb.c:328:21: note: ‘lsb’ was declared here unsigned char msb, lsb; ^~~ cc1: all warnings being treated as errors scripts/Makefile.build:250: recipe for target 'drivers/watchdog/pcwd_usb.o' failed make[3]: *** [drivers/watchdog/pcwd_usb.o] Error 1 Fixes: b7e04f8c61a4 ("mv watchdog tree under drivers") Signed-off-by: Li Hua Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221116020706.70847-1-hucool.lihua@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pcwd_usb.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index 1bdaf17c1d38..8202f0a6b093 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c @@ -325,7 +325,8 @@ static int usb_pcwd_set_heartbeat(struct usb_pcwd_private *usb_pcwd, int t) static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, int *temperature) { - unsigned char msb, lsb; + unsigned char msb = 0x00; + unsigned char lsb = 0x00; usb_pcwd_send_command(usb_pcwd, CMD_READ_TEMP, &msb, &lsb); @@ -341,7 +342,8 @@ static int usb_pcwd_get_temperature(struct usb_pcwd_private *usb_pcwd, static int usb_pcwd_get_timeleft(struct usb_pcwd_private *usb_pcwd, int *time_left) { - unsigned char msb, lsb; + unsigned char msb = 0x00; + unsigned char lsb = 0x00; /* Read the time that's left before rebooting */ /* Note: if the board is not yet armed then we will read 0xFFFF */ From e42c73f1ef0da5970a71f98440193fa9b1e9fb86 Mon Sep 17 00:00:00 2001 From: Andrej Picej Date: Fri, 4 Nov 2022 08:03:56 +0100 Subject: [PATCH 43/52] watchdog: imx2_wdg: suspend watchdog in WAIT mode Putting device into the "Suspend-To-Idle" mode causes watchdog to trigger and resets the board after set watchdog timeout period elapses. Introduce new device-tree property "fsl,suspend-in-wait" which suspends watchdog in WAIT mode. This is done by setting WDW bit in WCR (Watchdog Control Register). Watchdog operation is restored after exiting WAIT mode as expected. WAIT mode corresponds with Linux's "Suspend-To-Idle". Signed-off-by: Andrej Picej Reviewed-by: Fabio Estevam Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221104070358.426657-2-andrej.picej@norik.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/imx2_wdt.c | 55 +++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index d0c5d47ddede..19ab7b3d286b 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #define IMX2_WDT_WCR 0x00 /* Control Register */ #define IMX2_WDT_WCR_WT (0xFF << 8) /* -> Watchdog Timeout Field */ +#define IMX2_WDT_WCR_WDW BIT(7) /* -> Watchdog disable for WAIT */ #define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */ #define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */ #define IMX2_WDT_WCR_WRE BIT(3) /* -> WDOG Reset Enable */ @@ -60,13 +62,19 @@ #define WDOG_SEC_TO_COUNT(s) ((s * 2 - 1) << 8) +struct imx2_wdt_data { + bool wdw_supported; +}; + struct imx2_wdt_device { struct clk *clk; struct regmap *regmap; struct watchdog_device wdog; + const struct imx2_wdt_data *data; bool ext_reset; bool clk_is_on; bool no_ping; + bool sleep_wait; }; static bool nowayout = WATCHDOG_NOWAYOUT; @@ -129,6 +137,9 @@ static inline void imx2_wdt_setup(struct watchdog_device *wdog) /* Suspend timer in low power mode, write once-only */ val |= IMX2_WDT_WCR_WDZST; + /* Suspend timer in low power WAIT mode, write once-only */ + if (wdev->sleep_wait) + val |= IMX2_WDT_WCR_WDW; /* Strip the old watchdog Time-Out value */ val &= ~IMX2_WDT_WCR_WT; /* Generate internal chip-level reset if WDOG times out */ @@ -292,6 +303,8 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) wdog->max_hw_heartbeat_ms = IMX2_WDT_MAX_TIME * 1000; wdog->parent = dev; + wdev->data = of_device_get_match_data(dev); + ret = platform_get_irq(pdev, 0); if (ret > 0) if (!devm_request_irq(dev, ret, imx2_wdt_isr, 0, @@ -313,9 +326,18 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) wdev->ext_reset = of_property_read_bool(dev->of_node, "fsl,ext-reset-output"); + + if (of_property_read_bool(dev->of_node, "fsl,suspend-in-wait")) { + if (!wdev->data->wdw_supported) { + dev_err(dev, "suspend-in-wait not supported\n"); + return -EINVAL; + } + wdev->sleep_wait = true; + } + /* * The i.MX7D doesn't support low power mode, so we need to ping the watchdog - * during suspend. + * during suspend. Interaction with "fsl,suspend-in-wait" is unknown! */ wdev->no_ping = !of_device_is_compatible(dev->of_node, "fsl,imx7d-wdt"); platform_set_drvdata(pdev, wdog); @@ -417,9 +439,36 @@ static int __maybe_unused imx2_wdt_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(imx2_wdt_pm_ops, imx2_wdt_suspend, imx2_wdt_resume); +struct imx2_wdt_data imx_wdt = { + .wdw_supported = true, +}; + +struct imx2_wdt_data imx_wdt_legacy = { + .wdw_supported = false, +}; + static const struct of_device_id imx2_wdt_dt_ids[] = { - { .compatible = "fsl,imx21-wdt", }, - { .compatible = "fsl,imx7d-wdt", }, + { .compatible = "fsl,imx21-wdt", .data = &imx_wdt_legacy }, + { .compatible = "fsl,imx25-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx27-wdt", .data = &imx_wdt_legacy }, + { .compatible = "fsl,imx31-wdt", .data = &imx_wdt_legacy }, + { .compatible = "fsl,imx35-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx50-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx51-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx53-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx6q-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx6sl-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx6sll-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx6sx-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx6ul-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx7d-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx8mm-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx8mn-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx8mp-wdt", .data = &imx_wdt }, + { .compatible = "fsl,imx8mq-wdt", .data = &imx_wdt }, + { .compatible = "fsl,ls1012a-wdt", .data = &imx_wdt_legacy }, + { .compatible = "fsl,ls1043a-wdt", .data = &imx_wdt_legacy }, + { .compatible = "fsl,vf610-wdt", .data = &imx_wdt }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, imx2_wdt_dt_ids); From 12878a9fff5a2d45f4f5c71c83fee77f94aa1f8c Mon Sep 17 00:00:00 2001 From: Andrej Picej Date: Fri, 4 Nov 2022 08:03:57 +0100 Subject: [PATCH 44/52] dt-bindings: watchdog: fsl-imx: document suspend in wait mode Property "fsl,suspend-in-wait" suspends watchdog in "WAIT" mode which corresponds to Linux's Suspend-to-Idle S0 mode. If this property is not set and the device is put into Suspend-to-Idle mode, the watchdog triggers a reset after 128 seconds. Signed-off-by: Andrej Picej Reviewed-by: Fabio Estevam Reviewed-by: Krzysztof Kozlowski Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221104070358.426657-3-andrej.picej@norik.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/fsl-imx-wdt.yaml | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml index fb7695515be1..181f0cc5b5bd 100644 --- a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml @@ -9,9 +9,6 @@ title: Freescale i.MX Watchdog Timer (WDT) Controller maintainers: - Anson Huang -allOf: - - $ref: "watchdog.yaml#" - properties: compatible: oneOf: @@ -55,11 +52,45 @@ properties: If present, the watchdog device is configured to assert its external reset (WDOG_B) instead of issuing a software reset. + fsl,suspend-in-wait: + $ref: /schemas/types.yaml#/definitions/flag + description: | + If present, the watchdog device is suspended in WAIT mode + (Suspend-to-Idle). Only supported on certain devices. + required: - compatible - interrupts - reg +allOf: + - $ref: watchdog.yaml# + - if: + not: + properties: + compatible: + contains: + enum: + - fsl,imx25-wdt + - fsl,imx35-wdt + - fsl,imx50-wdt + - fsl,imx51-wdt + - fsl,imx53-wdt + - fsl,imx6q-wdt + - fsl,imx6sl-wdt + - fsl,imx6sll-wdt + - fsl,imx6sx-wdt + - fsl,imx6ul-wdt + - fsl,imx7d-wdt + - fsl,imx8mm-wdt + - fsl,imx8mn-wdt + - fsl,imx8mp-wdt + - fsl,imx8mq-wdt + - fsl,vf610-wdt + then: + properties: + fsl,suspend-in-wait: false + unevaluatedProperties: false examples: From b852e7a4a9ab6a1fb08c5aa36b1043672fd814dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 19 Dec 2022 21:30:39 +0000 Subject: [PATCH 45/52] watchdog: report fw_version in sysfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This synchronizes the information reported by ioctl and sysfs. The mismatch is confusing because "wdctl" from util-linux uses the ioctl when used with root privileges and sysfs without. The file is called "fw_version" instead of "firmware_version" as "firmware_version" is already used as custom attribute by single drivers. Signed-off-by: Thomas Weißschuh Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221216-watchdog-sysfs-v2-1-6189311103a9@weissschuh.net Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/ABI/testing/sysfs-class-watchdog | 7 +++++++ drivers/watchdog/watchdog_dev.c | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-watchdog b/Documentation/ABI/testing/sysfs-class-watchdog index 585caecda3a5..27c000238fe4 100644 --- a/Documentation/ABI/testing/sysfs-class-watchdog +++ b/Documentation/ABI/testing/sysfs-class-watchdog @@ -6,6 +6,13 @@ Description: device at boot. It is equivalent to WDIOC_GETBOOTSTATUS of ioctl interface. +What: /sys/class/watchdog/watchdogn/fw_version +Date: April 2023 +Contact: Thomas Weißschuh +Description: + It is a read only file. It contains firmware version of + watchdog device. + What: /sys/class/watchdog/watchdogn/identity Date: August 2015 Contact: Wim Van Sebroeck diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 455a9a572d7b..bd5612fa2190 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -547,6 +547,15 @@ static ssize_t pretimeout_show(struct device *dev, } static DEVICE_ATTR_RO(pretimeout); +static ssize_t fw_version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%d\n", wdd->info->firmware_version); +} +static DEVICE_ATTR_RO(fw_version); + static ssize_t identity_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -618,6 +627,7 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr, } static struct attribute *wdt_attrs[] = { &dev_attr_state.attr, + &dev_attr_fw_version.attr, &dev_attr_identity.attr, &dev_attr_timeout.attr, &dev_attr_min_timeout.attr, From ad8bc199b2e3197f53228fba05128069e31893c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 19 Dec 2022 21:30:40 +0000 Subject: [PATCH 46/52] watchdog: report options in sysfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This synchronizes the information reported by ioctl and sysfs. The mismatch is confusing because "wdctl" from util-linux uses the ioctl when used with root privileges and sysfs without. Signed-off-by: Thomas Weißschuh Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20221216-watchdog-sysfs-v2-2-6189311103a9@weissschuh.net [groeck: Fixed continuation line alignment] Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/ABI/testing/sysfs-class-watchdog | 6 ++++++ drivers/watchdog/watchdog_dev.c | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-watchdog b/Documentation/ABI/testing/sysfs-class-watchdog index 27c000238fe4..94fb74615951 100644 --- a/Documentation/ABI/testing/sysfs-class-watchdog +++ b/Documentation/ABI/testing/sysfs-class-watchdog @@ -6,6 +6,12 @@ Description: device at boot. It is equivalent to WDIOC_GETBOOTSTATUS of ioctl interface. +What: /sys/class/watchdog/watchdogn/options +Date: April 2023 +Contact: Thomas Weißschuh +Description: + It is a read only file. It contains options of watchdog device. + What: /sys/class/watchdog/watchdogn/fw_version Date: April 2023 Contact: Thomas Weißschuh diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index bd5612fa2190..0122e8796879 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -547,6 +547,15 @@ static ssize_t pretimeout_show(struct device *dev, } static DEVICE_ATTR_RO(pretimeout); +static ssize_t options_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "0x%x\n", wdd->info->options); +} +static DEVICE_ATTR_RO(options); + static ssize_t fw_version_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -627,6 +636,7 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr, } static struct attribute *wdt_attrs[] = { &dev_attr_state.attr, + &dev_attr_options.attr, &dev_attr_fw_version.attr, &dev_attr_identity.attr, &dev_attr_timeout.attr, From c76675f4ef35504eb1df8f0f0f0c1e2675d75f67 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 1 Feb 2023 16:20:36 +0100 Subject: [PATCH 47/52] dt-bindings: watchdog: qcom-wdt: add qcom,apss-wdt-sa8775p compatible Add a compatible for the sa8775p platform's KPSS watchdog. Signed-off-by: Bartosz Golaszewski Acked-by: Krzysztof Kozlowski Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20230201152038.203387-4-brgl@bgdev.pl Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml index 837ce9112071..6448b633c970 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -20,6 +20,7 @@ properties: - qcom,kpss-wdt-ipq4019 - qcom,apss-wdt-msm8994 - qcom,apss-wdt-qcs404 + - qcom,apss-wdt-sa8775p - qcom,apss-wdt-sc7180 - qcom,apss-wdt-sc7280 - qcom,apss-wdt-sc8180x From 000987a38b53c172f435142a4026dd71378ca464 Mon Sep 17 00:00:00 2001 From: George Cherian Date: Thu, 9 Feb 2023 02:11:17 +0000 Subject: [PATCH 48/52] watchdog: sbsa_wdog: Make sure the timeout programming is within the limits Make sure to honour the max_hw_heartbeat_ms while programming the timeout value to WOR. Clamp the timeout passed to sbsa_gwdt_set_timeout() to make sure the programmed value is within the permissible range. Fixes: abd3ac7902fb ("watchdog: sbsa: Support architecture version 1") Signed-off-by: George Cherian Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20230209021117.1512097-1-george.cherian@marvell.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sbsa_gwdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c index 9791c74aebd4..63862803421f 100644 --- a/drivers/watchdog/sbsa_gwdt.c +++ b/drivers/watchdog/sbsa_gwdt.c @@ -150,6 +150,7 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd, struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); wdd->timeout = timeout; + timeout = clamp_t(unsigned int, timeout, 1, wdd->max_hw_heartbeat_ms / 1000); if (action) sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt); From ff75e4eb71cb1b64da07a5a7e8140e202b365887 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Tue, 14 Feb 2023 11:39:32 +0100 Subject: [PATCH 49/52] dt-bindings: watchdog: mt7621-wdt: add phandle to access system controller registers MT7621 SoC provides a system controller node for accessing to some registers. Add a phandle in this node to avoid using MIPS related arch operations and includes in watchdog driver code. Acked-by: Krzysztof Kozlowski Signed-off-by: Sergio Paracuellos Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20230214103936.1061078-2-sergio.paracuellos@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../devicetree/bindings/watchdog/mediatek,mt7621-wdt.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/watchdog/mediatek,mt7621-wdt.yaml b/Documentation/devicetree/bindings/watchdog/mediatek,mt7621-wdt.yaml index b2b17fdf4e39..a668d0c2f14b 100644 --- a/Documentation/devicetree/bindings/watchdog/mediatek,mt7621-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/mediatek,mt7621-wdt.yaml @@ -19,6 +19,12 @@ properties: reg: maxItems: 1 + mediatek,sysctl: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to system controller 'sysc' syscon node which + controls system registers + required: - compatible - reg @@ -30,4 +36,5 @@ examples: watchdog@100 { compatible = "mediatek,mt7621-wdt"; reg = <0x100 0x100>; + mediatek,sysctl = <&sysc>; }; From 783c7cb4659b53b5e1b809dac5e8cdf250145919 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Tue, 14 Feb 2023 11:39:35 +0100 Subject: [PATCH 50/52] watchdog: mt7621-wdt: avoid static global declarations Instead of using static global definitions in driver code, refactor code introducing a new watchdog driver data structure and use it along the code. Reviewed-by: Guenter Roeck Signed-off-by: Sergio Paracuellos Link: https://lore.kernel.org/r/20230214103936.1061078-5-sergio.paracuellos@gmail.com [groeck: unsigned -> unsigned int] Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mt7621_wdt.c | 102 ++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/drivers/watchdog/mt7621_wdt.c b/drivers/watchdog/mt7621_wdt.c index a8aa3522cfda..b02c1415fc71 100644 --- a/drivers/watchdog/mt7621_wdt.c +++ b/drivers/watchdog/mt7621_wdt.c @@ -31,8 +31,11 @@ #define TMR1CTL_RESTART BIT(9) #define TMR1CTL_PRESCALE_SHIFT 16 -static void __iomem *mt7621_wdt_base; -static struct reset_control *mt7621_wdt_reset; +struct mt7621_wdt_data { + void __iomem *base; + struct reset_control *rst; + struct watchdog_device wdt; +}; static bool nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, bool, 0); @@ -40,27 +43,31 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -static inline void rt_wdt_w32(unsigned reg, u32 val) +static inline void rt_wdt_w32(void __iomem *base, unsigned int reg, u32 val) { - iowrite32(val, mt7621_wdt_base + reg); + iowrite32(val, base + reg); } -static inline u32 rt_wdt_r32(unsigned reg) +static inline u32 rt_wdt_r32(void __iomem *base, unsigned int reg) { - return ioread32(mt7621_wdt_base + reg); + return ioread32(base + reg); } static int mt7621_wdt_ping(struct watchdog_device *w) { - rt_wdt_w32(TIMER_REG_TMRSTAT, TMR1CTL_RESTART); + struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); + + rt_wdt_w32(drvdata->base, TIMER_REG_TMRSTAT, TMR1CTL_RESTART); return 0; } static int mt7621_wdt_set_timeout(struct watchdog_device *w, unsigned int t) { + struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); + w->timeout = t; - rt_wdt_w32(TIMER_REG_TMR1LOAD, t * 1000); + rt_wdt_w32(drvdata->base, TIMER_REG_TMR1LOAD, t * 1000); mt7621_wdt_ping(w); return 0; @@ -68,29 +75,31 @@ static int mt7621_wdt_set_timeout(struct watchdog_device *w, unsigned int t) static int mt7621_wdt_start(struct watchdog_device *w) { + struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); u32 t; /* set the prescaler to 1ms == 1000us */ - rt_wdt_w32(TIMER_REG_TMR1CTL, 1000 << TMR1CTL_PRESCALE_SHIFT); + rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, 1000 << TMR1CTL_PRESCALE_SHIFT); mt7621_wdt_set_timeout(w, w->timeout); - t = rt_wdt_r32(TIMER_REG_TMR1CTL); + t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL); t |= TMR1CTL_ENABLE; - rt_wdt_w32(TIMER_REG_TMR1CTL, t); + rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t); return 0; } static int mt7621_wdt_stop(struct watchdog_device *w) { + struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); u32 t; mt7621_wdt_ping(w); - t = rt_wdt_r32(TIMER_REG_TMR1CTL); + t = rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL); t &= ~TMR1CTL_ENABLE; - rt_wdt_w32(TIMER_REG_TMR1CTL, t); + rt_wdt_w32(drvdata->base, TIMER_REG_TMR1CTL, t); return 0; } @@ -105,7 +114,9 @@ static int mt7621_wdt_bootcause(void) static int mt7621_wdt_is_running(struct watchdog_device *w) { - return !!(rt_wdt_r32(TIMER_REG_TMR1CTL) & TMR1CTL_ENABLE); + struct mt7621_wdt_data *drvdata = watchdog_get_drvdata(w); + + return !!(rt_wdt_r32(drvdata->base, TIMER_REG_TMR1CTL) & TMR1CTL_ENABLE); } static const struct watchdog_info mt7621_wdt_info = { @@ -121,30 +132,39 @@ static const struct watchdog_ops mt7621_wdt_ops = { .set_timeout = mt7621_wdt_set_timeout, }; -static struct watchdog_device mt7621_wdt_dev = { - .info = &mt7621_wdt_info, - .ops = &mt7621_wdt_ops, - .min_timeout = 1, - .max_timeout = 0xfffful / 1000, -}; - static int mt7621_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - mt7621_wdt_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(mt7621_wdt_base)) - return PTR_ERR(mt7621_wdt_base); + struct watchdog_device *mt7621_wdt; + struct mt7621_wdt_data *drvdata; + int err; - mt7621_wdt_reset = devm_reset_control_get_exclusive(dev, NULL); - if (!IS_ERR(mt7621_wdt_reset)) - reset_control_deassert(mt7621_wdt_reset); + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; - mt7621_wdt_dev.bootstatus = mt7621_wdt_bootcause(); + drvdata->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(drvdata->base)) + return PTR_ERR(drvdata->base); - watchdog_init_timeout(&mt7621_wdt_dev, mt7621_wdt_dev.max_timeout, - dev); - watchdog_set_nowayout(&mt7621_wdt_dev, nowayout); - if (mt7621_wdt_is_running(&mt7621_wdt_dev)) { + drvdata->rst = devm_reset_control_get_exclusive(dev, NULL); + if (!IS_ERR(drvdata->rst)) + reset_control_deassert(drvdata->rst); + + mt7621_wdt = &drvdata->wdt; + mt7621_wdt->info = &mt7621_wdt_info; + mt7621_wdt->ops = &mt7621_wdt_ops; + mt7621_wdt->min_timeout = 1; + mt7621_wdt->max_timeout = 0xfffful / 1000; + mt7621_wdt->parent = dev; + + mt7621_wdt->bootstatus = mt7621_wdt_bootcause(); + + watchdog_init_timeout(mt7621_wdt, mt7621_wdt->max_timeout, dev); + watchdog_set_nowayout(mt7621_wdt, nowayout); + watchdog_set_drvdata(mt7621_wdt, drvdata); + + if (mt7621_wdt_is_running(mt7621_wdt)) { /* * Make sure to apply timeout from watchdog core, taking * the prescaler of this driver here into account (the @@ -154,17 +174,25 @@ static int mt7621_wdt_probe(struct platform_device *pdev) * we first disable the watchdog, set the new prescaler * and timeout, and then re-enable the watchdog. */ - mt7621_wdt_stop(&mt7621_wdt_dev); - mt7621_wdt_start(&mt7621_wdt_dev); - set_bit(WDOG_HW_RUNNING, &mt7621_wdt_dev.status); + mt7621_wdt_stop(mt7621_wdt); + mt7621_wdt_start(mt7621_wdt); + set_bit(WDOG_HW_RUNNING, &mt7621_wdt->status); } - return devm_watchdog_register_device(dev, &mt7621_wdt_dev); + err = devm_watchdog_register_device(dev, &drvdata->wdt); + if (err) + return err; + + platform_set_drvdata(pdev, drvdata); + + return 0; } static void mt7621_wdt_shutdown(struct platform_device *pdev) { - mt7621_wdt_stop(&mt7621_wdt_dev); + struct mt7621_wdt_data *drvdata = platform_get_drvdata(pdev); + + mt7621_wdt_stop(&drvdata->wdt); } static const struct of_device_id mt7621_wdt_match[] = { From ff8ec4ac39ad413b580d611dbf68e1d8a82eba56 Mon Sep 17 00:00:00 2001 From: Sergio Paracuellos Date: Tue, 14 Feb 2023 11:39:36 +0100 Subject: [PATCH 51/52] watchdog: mt7621-wdt: avoid ralink architecture dependent code MT7621 SoC has a system controller node. Watchdog need to access to reset status register. Ralink architecture and related driver are old and from the beggining they are using some architecture dependent operations for accessing this shared registers through 'asm/mach-ralink/ralink_regs.h' header file. However this is not ideal from a driver perspective which can just access to the system controller registers in an arch independent way using regmap syscon APIs. Update Kconfig accordingly to select new added dependencies and allow driver to be compile tested. Signed-off-by: Sergio Paracuellos Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20230214103936.1061078-6-sergio.paracuellos@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 4 +++- drivers/watchdog/mt7621_wdt.c | 22 +++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0bc40b763b06..3df3638ac8b0 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1872,7 +1872,9 @@ config GXP_WATCHDOG config MT7621_WDT tristate "Mediatek SoC watchdog" select WATCHDOG_CORE - depends on SOC_MT7620 || SOC_MT7621 + select REGMAP_MMIO + select MFD_SYSCON + depends on SOC_MT7620 || SOC_MT7621 || COMPILE_TEST help Hardware driver for the Mediatek/Ralink MT7621/8 SoC Watchdog Timer. diff --git a/drivers/watchdog/mt7621_wdt.c b/drivers/watchdog/mt7621_wdt.c index b02c1415fc71..442731bba194 100644 --- a/drivers/watchdog/mt7621_wdt.c +++ b/drivers/watchdog/mt7621_wdt.c @@ -15,8 +15,8 @@ #include #include #include - -#include +#include +#include #define SYSC_RSTSTAT 0x38 #define WDT_RST_CAUSE BIT(1) @@ -34,6 +34,7 @@ struct mt7621_wdt_data { void __iomem *base; struct reset_control *rst; + struct regmap *sysc; struct watchdog_device wdt; }; @@ -104,9 +105,12 @@ static int mt7621_wdt_stop(struct watchdog_device *w) return 0; } -static int mt7621_wdt_bootcause(void) +static int mt7621_wdt_bootcause(struct mt7621_wdt_data *d) { - if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE) + u32 val; + + regmap_read(d->sysc, SYSC_RSTSTAT, &val); + if (val & WDT_RST_CAUSE) return WDIOF_CARDRESET; return 0; @@ -134,6 +138,7 @@ static const struct watchdog_ops mt7621_wdt_ops = { static int mt7621_wdt_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; struct watchdog_device *mt7621_wdt; struct mt7621_wdt_data *drvdata; @@ -143,6 +148,13 @@ static int mt7621_wdt_probe(struct platform_device *pdev) if (!drvdata) return -ENOMEM; + drvdata->sysc = syscon_regmap_lookup_by_phandle(np, "mediatek,sysctl"); + if (IS_ERR(drvdata->sysc)) { + drvdata->sysc = syscon_regmap_lookup_by_compatible("mediatek,mt7621-sysc"); + if (IS_ERR(drvdata->sysc)) + return PTR_ERR(drvdata->sysc); + } + drvdata->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(drvdata->base)) return PTR_ERR(drvdata->base); @@ -158,7 +170,7 @@ static int mt7621_wdt_probe(struct platform_device *pdev) mt7621_wdt->max_timeout = 0xfffful / 1000; mt7621_wdt->parent = dev; - mt7621_wdt->bootstatus = mt7621_wdt_bootcause(); + mt7621_wdt->bootstatus = mt7621_wdt_bootcause(drvdata); watchdog_init_timeout(mt7621_wdt, mt7621_wdt->max_timeout, dev); watchdog_set_nowayout(mt7621_wdt, nowayout); From cf3be7e82b129ed34f811f116f2b113f6299d449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 17 Feb 2023 10:53:17 +0100 Subject: [PATCH 52/52] watchdog: at91rm9200: Only warn once about problems in .remove() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The single difference between returning 0 and returning an error code in a platform remove callback is that in the latter case the platform core emits a warning about the error being ignored. at91wdt_remove() already emits a warning in the error case, so suppress the more generic (and less helpful) one by returning 0. Signed-off-by: Uwe Kleine-König Reviewed-by: Claudiu Beznea Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20230217095317.1213387-1-u.kleine-koenig@pengutronix.de Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/at91rm9200_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index 5126454bb861..d57409c1a4d1 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -270,7 +270,7 @@ static int at91wdt_remove(struct platform_device *pdev) misc_deregister(&at91wdt_miscdev); at91wdt_miscdev.parent = NULL; - return res; + return 0; } static void at91wdt_shutdown(struct platform_device *pdev)