From 29353816300c79cb5157ed2719cc71285c7b77aa Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:45 +0530 Subject: [PATCH 01/56] watchdog: keembay: Update WDT pre-timeout during the initialization The pretimeout register has a default reset value. Hence when a smaller WDT timeout is set which would be lesser than the default pretimeout, the system behaves abnormally, starts triggering the pretimeout interrupt even when the WDT is not enabled, most of the times leading to system crash. Hence an update in the pre-timeout is also required for the default timeout that is being configured. Fixes: fa0f8d51e90d ("watchdog: Add watchdog driver for Intel Keembay Soc") Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-2-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index 547d3fea33ff..f2f5c9fae29c 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -29,6 +29,7 @@ #define WDT_LOAD_MAX U32_MAX #define WDT_LOAD_MIN 1 #define WDT_TIMEOUT 5 +#define WDT_PRETIMEOUT 4 static unsigned int timeout = WDT_TIMEOUT; module_param(timeout, int, 0); @@ -224,11 +225,13 @@ static int keembay_wdt_probe(struct platform_device *pdev) wdt->wdd.min_timeout = WDT_LOAD_MIN; wdt->wdd.max_timeout = WDT_LOAD_MAX / wdt->rate; wdt->wdd.timeout = WDT_TIMEOUT; + wdt->wdd.pretimeout = WDT_PRETIMEOUT; watchdog_set_drvdata(&wdt->wdd, wdt); watchdog_set_nowayout(&wdt->wdd, nowayout); watchdog_init_timeout(&wdt->wdd, timeout, dev); keembay_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout); + keembay_wdt_set_pretimeout(&wdt->wdd, wdt->wdd.pretimeout); ret = devm_watchdog_register_device(dev, &wdt->wdd); if (ret) From 0f7bfaf10c0abc979220442bae2af4f1f869c41e Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:46 +0530 Subject: [PATCH 02/56] watchdog: keembay: Upadate WDT pretimeout for every update in timeout The pre-timeout value to be programmed to the register has to be calculated and updated for every change in the timeout value. Else the threshold time wouldn't be calculated to its corresponding timeout. Fixes: fa0f8d51e90d ("watchdog: Add watchdog driver for Intel Keembay Soc") Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-3-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index f2f5c9fae29c..b2afeb4a60e3 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -109,6 +109,7 @@ static int keembay_wdt_set_timeout(struct watchdog_device *wdog, u32 t) { wdog->timeout = t; keembay_wdt_set_timeout_reg(wdog); + keembay_wdt_set_pretimeout_reg(wdog); return 0; } From 75f6c56dfeec92c53e09a72896547888ac9a27d7 Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:47 +0530 Subject: [PATCH 03/56] watchdog: keembay: Update pretimeout to zero in the TH ISR The pretimeout has to be updated to zero during the ISR of the ThresHold interrupt. Else the TH interrupt would be triggerred for every tick until the timeout. Fixes: fa0f8d51e90d ("watchdog: Add watchdog driver for Intel Keembay Soc") Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-4-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index b2afeb4a60e3..6053416b8d3d 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -154,6 +154,8 @@ static irqreturn_t keembay_wdt_th_isr(int irq, void *dev_id) struct keembay_wdt *wdt = dev_id; struct arm_smccc_res res; + keembay_wdt_set_pretimeout(&wdt->wdd, 0x0); + arm_smccc_smc(WDT_ISR_CLEAR, WDT_ISR_MASK, 0, 0, 0, 0, 0, 0, &res); dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt pre-timeout.\n"); watchdog_notify_pretimeout(&wdt->wdd); From 0e36a09faea25f4564d41a0c28938199b605148e Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:48 +0530 Subject: [PATCH 04/56] watchdog: keembay: Clear either the TO or TH interrupt bit During the interrupt service routine of the TimeOut interrupt and the ThresHold interrupt, the respective interrupt clear bit have to be cleared and not both. Fixes: fa0f8d51e90d ("watchdog: Add watchdog driver for Intel Keembay Soc") Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-5-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index 6053416b8d3d..f2a16c9933c3 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -23,7 +23,8 @@ #define TIM_WDOG_EN 0x8 #define TIM_SAFE 0xc -#define WDT_ISR_MASK GENMASK(9, 8) +#define WDT_TH_INT_MASK BIT(8) +#define WDT_TO_INT_MASK BIT(9) #define WDT_ISR_CLEAR 0x8200ff18 #define WDT_UNLOCK 0xf1d0dead #define WDT_LOAD_MAX U32_MAX @@ -142,7 +143,7 @@ static irqreturn_t keembay_wdt_to_isr(int irq, void *dev_id) struct arm_smccc_res res; keembay_wdt_writel(wdt, TIM_WATCHDOG, 1); - arm_smccc_smc(WDT_ISR_CLEAR, WDT_ISR_MASK, 0, 0, 0, 0, 0, 0, &res); + arm_smccc_smc(WDT_ISR_CLEAR, WDT_TO_INT_MASK, 0, 0, 0, 0, 0, 0, &res); dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt timeout.\n"); emergency_restart(); @@ -156,7 +157,7 @@ static irqreturn_t keembay_wdt_th_isr(int irq, void *dev_id) keembay_wdt_set_pretimeout(&wdt->wdd, 0x0); - arm_smccc_smc(WDT_ISR_CLEAR, WDT_ISR_MASK, 0, 0, 0, 0, 0, 0, &res); + arm_smccc_smc(WDT_ISR_CLEAR, WDT_TH_INT_MASK, 0, 0, 0, 0, 0, 0, &res); dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt pre-timeout.\n"); watchdog_notify_pretimeout(&wdt->wdd); From 9eb25269271c679e8cfcc7df5c0c5e9d0572fc27 Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:49 +0530 Subject: [PATCH 05/56] watchdog: keembay: Remove timeout update in the WDT start function Removed set timeout from the start WDT function. There is a function defined to set the timeout. Hence no need to set the timeout again in start function as the timeout would have been already updated before calling the start/enable. Fixes: fa0f8d51e90d ("watchdog: Add watchdog driver for Intel Keembay Soc") Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-6-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index f2a16c9933c3..039753b9932b 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -84,7 +84,6 @@ static int keembay_wdt_start(struct watchdog_device *wdog) { struct keembay_wdt *wdt = watchdog_get_drvdata(wdog); - keembay_wdt_set_timeout_reg(wdog); keembay_wdt_writel(wdt, TIM_WDOG_EN, 1); return 0; From 624873f1e7f8aa9f19333546aff3777ee10c8934 Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:51 +0530 Subject: [PATCH 06/56] watchdog: keembay: MACRO for WDT enable and disable values Introduced MACRO's for WDT enable and disable values for better readability Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-8-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index 039753b9932b..389932295f59 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -27,6 +27,8 @@ #define WDT_TO_INT_MASK BIT(9) #define WDT_ISR_CLEAR 0x8200ff18 #define WDT_UNLOCK 0xf1d0dead +#define WDT_DISABLE 0x0 +#define WDT_ENABLE 0x1 #define WDT_LOAD_MAX U32_MAX #define WDT_LOAD_MIN 1 #define WDT_TIMEOUT 5 @@ -84,7 +86,7 @@ static int keembay_wdt_start(struct watchdog_device *wdog) { struct keembay_wdt *wdt = watchdog_get_drvdata(wdog); - keembay_wdt_writel(wdt, TIM_WDOG_EN, 1); + keembay_wdt_writel(wdt, TIM_WDOG_EN, WDT_ENABLE); return 0; } @@ -93,7 +95,7 @@ static int keembay_wdt_stop(struct watchdog_device *wdog) { struct keembay_wdt *wdt = watchdog_get_drvdata(wdog); - keembay_wdt_writel(wdt, TIM_WDOG_EN, 0); + keembay_wdt_writel(wdt, TIM_WDOG_EN, WDT_DISABLE); return 0; } From 3168be5d66ac6c3508a880022f79b5a887865d5d Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:50 +0530 Subject: [PATCH 07/56] watchdog: keembay: Removed timeout update in the TO ISR In the TO ISR removed updating the Timeout value because its not serving any purpose as the timer would have already expired and the system would be rebooting. Fixes: fa0f8d51e90d ("watchdog: Add watchdog driver for Intel Keembay Soc") Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-7-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index 389932295f59..d8c50b6291cd 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -143,7 +143,6 @@ static irqreturn_t keembay_wdt_to_isr(int irq, void *dev_id) struct keembay_wdt *wdt = dev_id; struct arm_smccc_res res; - keembay_wdt_writel(wdt, TIM_WATCHDOG, 1); arm_smccc_smc(WDT_ISR_CLEAR, WDT_TO_INT_MASK, 0, 0, 0, 0, 0, 0, &res); dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt timeout.\n"); emergency_restart(); From 613c4db220260304c9da4a865e5c4735414a11b4 Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:52 +0530 Subject: [PATCH 08/56] watchdog: keembay: WDT SMC handler MACRO name update Updated the WDT SMC handler MACRO name to make it clear that its a ARM SMC handler that helps in clearing the WDT interrupt bit. Reviewed-by: Guenter Roeck Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-9-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index d8c50b6291cd..5ac823487b70 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -25,7 +25,7 @@ #define WDT_TH_INT_MASK BIT(8) #define WDT_TO_INT_MASK BIT(9) -#define WDT_ISR_CLEAR 0x8200ff18 +#define WDT_INT_CLEAR_SMC 0x8200ff18 #define WDT_UNLOCK 0xf1d0dead #define WDT_DISABLE 0x0 #define WDT_ENABLE 0x1 @@ -143,7 +143,7 @@ static irqreturn_t keembay_wdt_to_isr(int irq, void *dev_id) struct keembay_wdt *wdt = dev_id; struct arm_smccc_res res; - arm_smccc_smc(WDT_ISR_CLEAR, WDT_TO_INT_MASK, 0, 0, 0, 0, 0, 0, &res); + arm_smccc_smc(WDT_INT_CLEAR_SMC, WDT_TO_INT_MASK, 0, 0, 0, 0, 0, 0, &res); dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt timeout.\n"); emergency_restart(); @@ -157,7 +157,7 @@ static irqreturn_t keembay_wdt_th_isr(int irq, void *dev_id) keembay_wdt_set_pretimeout(&wdt->wdd, 0x0); - arm_smccc_smc(WDT_ISR_CLEAR, WDT_TH_INT_MASK, 0, 0, 0, 0, 0, 0, &res); + arm_smccc_smc(WDT_INT_CLEAR_SMC, WDT_TH_INT_MASK, 0, 0, 0, 0, 0, 0, &res); dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt pre-timeout.\n"); watchdog_notify_pretimeout(&wdt->wdd); From d1fb8bbd769f11e406955ee1a81413d8d78b957b Mon Sep 17 00:00:00 2001 From: Shruthi Sanil Date: Mon, 17 May 2021 23:19:53 +0530 Subject: [PATCH 09/56] watchdog: keembay: Typo corrections and other blank operations Corrected typos, aligned the tabs and added new lines wherever required for better readability Reviewed-by: Guenter Roeck Reviewed-by: Andy Shevchenko Tested-by: Kris Pan Signed-off-by: Shruthi Sanil Link: https://lore.kernel.org/r/20210517174953.19404-10-shruthi.sanil@intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/keembay_wdt.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index 5ac823487b70..2a39114dbc64 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -26,11 +26,14 @@ #define WDT_TH_INT_MASK BIT(8) #define WDT_TO_INT_MASK BIT(9) #define WDT_INT_CLEAR_SMC 0x8200ff18 + #define WDT_UNLOCK 0xf1d0dead #define WDT_DISABLE 0x0 #define WDT_ENABLE 0x1 + #define WDT_LOAD_MAX U32_MAX #define WDT_LOAD_MIN 1 + #define WDT_TIMEOUT 5 #define WDT_PRETIMEOUT 4 @@ -144,7 +147,7 @@ static irqreturn_t keembay_wdt_to_isr(int irq, void *dev_id) struct arm_smccc_res res; arm_smccc_smc(WDT_INT_CLEAR_SMC, WDT_TO_INT_MASK, 0, 0, 0, 0, 0, 0, &res); - dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt timeout.\n"); + dev_crit(wdt->wdd.parent, "Intel Keem Bay non-secure wdt timeout.\n"); emergency_restart(); return IRQ_HANDLED; @@ -158,7 +161,7 @@ static irqreturn_t keembay_wdt_th_isr(int irq, void *dev_id) keembay_wdt_set_pretimeout(&wdt->wdd, 0x0); arm_smccc_smc(WDT_INT_CLEAR_SMC, WDT_TH_INT_MASK, 0, 0, 0, 0, 0, 0, &res); - dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt pre-timeout.\n"); + dev_crit(wdt->wdd.parent, "Intel Keem Bay non-secure wdt pre-timeout.\n"); watchdog_notify_pretimeout(&wdt->wdd); return IRQ_HANDLED; @@ -278,8 +281,8 @@ static const struct of_device_id keembay_wdt_match[] = { MODULE_DEVICE_TABLE(of, keembay_wdt_match); static struct platform_driver keembay_wdt_driver = { - .probe = keembay_wdt_probe, - .driver = { + .probe = keembay_wdt_probe, + .driver = { .name = "keembay_wdt", .of_match_table = keembay_wdt_match, .pm = &keembay_wdt_pm_ops, From abd3ac7902fb77f8386f485f7284253fc0c4d803 Mon Sep 17 00:00:00 2001 From: Shaokun Zhang Date: Mon, 17 May 2021 20:10:08 +0800 Subject: [PATCH 10/56] watchdog: sbsa: Support architecture version 1 For Armv8.6, The frequency of CNTFRQ_EL0 is standardized to a frequency of 1GHz, so Arm Base System Architecture 1.0[1] has introduced watchdog revision 1 that increases the length the watchdog offset register to 48 bit, while other operation of the watchdog remains the same. The driver can determine which version of the watchdog is implemented through the watchdog interface identification register (W_IID). If the version is 0x1, the watchdog offset register will be 48 bit, otherwise it will be 32 bit. [1] https://developer.arm.com/documentation/den0094/latest Cc: Wim Van Sebroeck Cc: Guenter Roeck Cc: Suravee Suthikulpanit Cc: Al Stone Cc: Jianchao Hu Cc: Huiqiang Wang Signed-off-by: Shaokun Zhang Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1621253408-23401-1-git-send-email-zhangshaokun@hisilicon.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sbsa_gwdt.c | 54 ++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c index f0f1e3b2e463..ee9ff38929eb 100644 --- a/drivers/watchdog/sbsa_gwdt.c +++ b/drivers/watchdog/sbsa_gwdt.c @@ -73,16 +73,21 @@ #define SBSA_GWDT_WCS_WS0 BIT(1) #define SBSA_GWDT_WCS_WS1 BIT(2) +#define SBSA_GWDT_VERSION_MASK 0xF +#define SBSA_GWDT_VERSION_SHIFT 16 + /** * struct sbsa_gwdt - Internal representation of the SBSA GWDT * @wdd: kernel watchdog_device structure * @clk: store the System Counter clock frequency, in Hz. + * @version: store the architecture version * @refresh_base: Virtual address of the watchdog refresh frame * @control_base: Virtual address of the watchdog control frame */ struct sbsa_gwdt { struct watchdog_device wdd; u32 clk; + int version; void __iomem *refresh_base; void __iomem *control_base; }; @@ -112,6 +117,30 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +/* + * Arm Base System Architecture 1.0 introduces watchdog v1 which + * increases the length watchdog offset register to 48 bits. + * - For version 0: WOR is 32 bits; + * - For version 1: WOR is 48 bits which comprises the register + * offset 0x8 and 0xC, and the bits [63:48] are reserved which are + * Read-As-Zero and Writes-Ignored. + */ +static u64 sbsa_gwdt_reg_read(struct sbsa_gwdt *gwdt) +{ + if (gwdt->version == 0) + return readl(gwdt->control_base + SBSA_GWDT_WOR); + else + return readq(gwdt->control_base + SBSA_GWDT_WOR); +} + +static void sbsa_gwdt_reg_write(u64 val, struct sbsa_gwdt *gwdt) +{ + if (gwdt->version == 0) + writel((u32)val, gwdt->control_base + SBSA_GWDT_WOR); + else + writeq(val, gwdt->control_base + SBSA_GWDT_WOR); +} + /* * watchdog operation functions */ @@ -123,16 +152,14 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd, wdd->timeout = timeout; if (action) - writel(gwdt->clk * timeout, - gwdt->control_base + SBSA_GWDT_WOR); + sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt); else /* * In the single stage mode, The first signal (WS0) is ignored, * the timeout is (WOR * 2), so the WOR should be configured * to half value of timeout. */ - writel(gwdt->clk / 2 * timeout, - gwdt->control_base + SBSA_GWDT_WOR); + sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt); return 0; } @@ -149,7 +176,7 @@ static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd) */ if (!action && !(readl(gwdt->control_base + SBSA_GWDT_WCS) & SBSA_GWDT_WCS_WS0)) - timeleft += readl(gwdt->control_base + SBSA_GWDT_WOR); + timeleft += sbsa_gwdt_reg_read(gwdt); timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) - arch_timer_read_counter(); @@ -172,6 +199,17 @@ static int sbsa_gwdt_keepalive(struct watchdog_device *wdd) return 0; } +static void sbsa_gwdt_get_version(struct watchdog_device *wdd) +{ + struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); + int ver; + + ver = readl(gwdt->control_base + SBSA_GWDT_W_IIDR); + ver = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK; + + gwdt->version = ver; +} + static int sbsa_gwdt_start(struct watchdog_device *wdd) { struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); @@ -252,10 +290,14 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) wdd->info = &sbsa_gwdt_info; wdd->ops = &sbsa_gwdt_ops; wdd->min_timeout = 1; - wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000; wdd->timeout = DEFAULT_TIMEOUT; watchdog_set_drvdata(wdd, gwdt); watchdog_set_nowayout(wdd, nowayout); + sbsa_gwdt_get_version(wdd); + if (gwdt->version == 0) + wdd->max_hw_heartbeat_ms = U32_MAX / gwdt->clk * 1000; + else + wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000; status = readl(cf_base + SBSA_GWDT_WCS); if (status & SBSA_GWDT_WCS_WS1) { From 76215889be9d2cd388207545424bbbe3bf80e1ea Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 16 May 2021 14:17:03 -0700 Subject: [PATCH 11/56] watchdog: mtx-1: drop au1000.h header file The mtx-1_wdt driver does not need the au1000.h header file. Instead, the header file causes build errors, so drop it. This change fixes multiple build errors, all in au1000.h. E.g.: In file included from ../drivers/watchdog/mtx-1_wdt.c:44: ../arch/mips/include/asm/mach-au1x00/au1000.h: In function 'alchemy_rdsys': ../arch/mips/include/asm/mach-au1x00/au1000.h:603:36: error: implicit declaration of function 'KSEG1ADDR'; did you mean 'CKSEG1ADDR'? [-Werror=implicit-function-declaration] 603 | void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR); ../arch/mips/include/asm/mach-au1x00/au1000.h:603:20: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 603 | void __iomem *b = (void __iomem *)KSEG1ADDR(AU1000_SYS_PHYS_ADDR); Fixes: da2a68b3eb47 ("watchdog: Enable COMPILE_TEST where possible") Signed-off-by: Randy Dunlap Cc: Wim Van Sebroeck Cc: Guenter Roeck Cc: linux-watchdog@vger.kernel.org Cc: Florian Fainelli Reviewed-by: Guenter Roeck Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20210516211703.25349-1-rdunlap@infradead.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtx-1_wdt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index 8aa1cb4a295f..ea1bbf5ee528 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c @@ -41,8 +41,6 @@ #include #include -#include - #define MTX1_WDT_INTERVAL (5 * HZ) static int ticks = 100 * HZ; From e0b101ab01c719a5a81b21ff16bbd33a868f9189 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Sat, 15 May 2021 01:21:15 +0800 Subject: [PATCH 12/56] watchdog: imx2_wdt: avoid to ping before resume back Since watchdog_ping_work is not freezable so that it maybe scheduled before imx2_wdt_resume where watchdog clock enabled, hence, kernel will hang in imx2_wdt_ping without clock, and then watchdog reset happen. Add clk_is_on to prevent the above case by ignoring ping until watchdog driver resume back indeed. Signed-off-by: Robin Gong Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1621012875-22667-1-git-send-email-yibin.gong@nxp.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/imx2_wdt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index b84f80f7d342..cc86018c5eb5 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -65,6 +65,7 @@ struct imx2_wdt_device { struct regmap *regmap; struct watchdog_device wdog; bool ext_reset; + bool clk_is_on; }; static bool nowayout = WATCHDOG_NOWAYOUT; @@ -160,6 +161,9 @@ static int imx2_wdt_ping(struct watchdog_device *wdog) { struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog); + if (!wdev->clk_is_on) + return 0; + regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ1); regmap_write(wdev->regmap, IMX2_WDT_WSR, IMX2_WDT_SEQ2); return 0; @@ -301,6 +305,8 @@ static int __init imx2_wdt_probe(struct platform_device *pdev) if (ret) return ret; + wdev->clk_is_on = true; + regmap_read(wdev->regmap, IMX2_WDT_WRSR, &val); wdog->bootstatus = val & IMX2_WDT_WRSR_TOUT ? WDIOF_CARDRESET : 0; @@ -361,6 +367,8 @@ static int __maybe_unused imx2_wdt_suspend(struct device *dev) clk_disable_unprepare(wdev->clk); + wdev->clk_is_on = false; + return 0; } @@ -375,6 +383,8 @@ static int __maybe_unused imx2_wdt_resume(struct device *dev) if (ret) return ret; + wdev->clk_is_on = true; + if (watchdog_active(wdog) && !imx2_wdt_is_running(wdev)) { /* * If the watchdog is still active and resumes From c08a6b31e4917034f0ed0cb457c3bb209576f542 Mon Sep 17 00:00:00 2001 From: Zou Wei Date: Tue, 11 May 2021 15:01:35 +0800 Subject: [PATCH 13/56] watchdog: Fix possible use-after-free in wdt_startup() This module's remove path calls del_timer(). However, that function does not wait until the timer handler finishes. This means that the timer handler may still be running after the driver's remove function has finished, which would result in a use-after-free. Fix by calling del_timer_sync(), which makes sure the timer handler has finished, and unable to re-schedule itself. Reported-by: Hulk Robot Signed-off-by: Zou Wei Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1620716495-108352-1-git-send-email-zou_wei@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sbc60xxwdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index a947a63fb44a..7b974802dfc7 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c @@ -146,7 +146,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); inb_p(wdt_stop); pr_info("Watchdog timer is now disabled...\n"); } From 5185c4e8a8cc584382c6dd08dcd4f59e1e90638d Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Thu, 13 May 2021 19:09:42 +0800 Subject: [PATCH 14/56] watchdog: dw_wdt: Fix duplicate included linux/kernel.h Clean up the following includecheck warning: ./drivers/watchdog/dw_wdt.c: linux/kernel.h is included more than once. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1620904182-74107-1-git-send-email-jiapeng.chong@linux.alibaba.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/dw_wdt.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 32d0e1781e63..cd578843277e 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -13,22 +13,21 @@ */ #include -#include -#include #include +#include #include #include +#include #include #include +#include #include #include -#include #include -#include #include +#include #include #include -#include #define WDOG_CONTROL_REG_OFFSET 0x00 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 From 742b80c56135971e35e6753c7400d7d6ee842a90 Mon Sep 17 00:00:00 2001 From: Jerry Hoemann Date: Wed, 12 May 2021 22:03:32 -0600 Subject: [PATCH 15/56] watchdog/hpwdt: New PCI IDs New hardware with new PCI ID info. Signed-off-by: Jerry Hoemann Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1620878612-24736-2-git-send-email-jerry.hoemann@hpe.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/hpwdt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 22ddba3802ef..a5006a58e0db 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -45,6 +45,7 @@ static unsigned long __iomem *hpwdt_timer_con; static const struct pci_device_id hpwdt_devices[] = { { PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) }, /* iLO2 */ { PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) }, /* iLO3 */ + { PCI_DEVICE(PCI_VENDOR_ID_HP_3PAR, 0x0389) }, /* PCtrl */ {0}, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, hpwdt_devices); From 05f0a994cd27bac4f49c9c4f961922f91a582295 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 17 May 2021 20:44:56 +0300 Subject: [PATCH 16/56] watchdog: sp805: Use devm_clk_get_optional() Replace open coded variants of devm_clk_get_optional(). While at it, drop unneeded OF and ACPI dependency as the APIs in use are provider agnostic. Cc: Srinath Mannam Signed-off-by: Andy Shevchenko Reviewed-by: Guenter Roeck Reviewed-by: Srinath Mannam Link: https://lore.kernel.org/r/20210517174456.22050-1-andriy.shevchenko@linux.intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sp805_wdt.c | 40 +++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 58a00e1ab23b..531551216c8c 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -11,7 +11,6 @@ * warranty of any kind, whether express or implied. */ -#include #include #include #include @@ -23,8 +22,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -231,6 +230,7 @@ static int sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) { struct sp805_wdt *wdt; + u64 rate = 0; int ret = 0; wdt = devm_kzalloc(&adev->dev, sizeof(*wdt), GFP_KERNEL); @@ -243,25 +243,23 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id) if (IS_ERR(wdt->base)) return PTR_ERR(wdt->base); - if (adev->dev.of_node) { - wdt->clk = devm_clk_get(&adev->dev, NULL); - if (IS_ERR(wdt->clk)) { - dev_err(&adev->dev, "Clock not found\n"); - return PTR_ERR(wdt->clk); - } - wdt->rate = clk_get_rate(wdt->clk); - } else if (has_acpi_companion(&adev->dev)) { - /* - * When Driver probe with ACPI device, clock devices - * are not available, so watchdog rate get from - * clock-frequency property given in _DSD object. - */ - device_property_read_u64(&adev->dev, "clock-frequency", - &wdt->rate); - if (!wdt->rate) { - dev_err(&adev->dev, "no clock-frequency property\n"); - return -ENODEV; - } + /* + * When driver probe with ACPI device, clock devices + * are not available, so watchdog rate get from + * clock-frequency property given in _DSD object. + */ + device_property_read_u64(&adev->dev, "clock-frequency", &rate); + + wdt->clk = devm_clk_get_optional(&adev->dev, NULL); + if (IS_ERR(wdt->clk)) + return dev_err_probe(&adev->dev, PTR_ERR(wdt->clk), "Clock not found\n"); + + wdt->rate = clk_get_rate(wdt->clk); + if (!wdt->rate) + wdt->rate = rate; + if (!wdt->rate) { + dev_err(&adev->dev, "no clock-frequency property\n"); + return -ENODEV; } wdt->adev = adev; From 3452239effed2b6ea25835f93bdb8a31f6829ffe Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 17 May 2021 20:49:12 +0300 Subject: [PATCH 17/56] watchdog: sp805: Fix kernel doc description Kernel doc validation script is not happy CHECK .../sp805_wdt.c .../sp805_wdt.c:73: warning: Function parameter or member 'rate' not described in 'sp805_wdt' Fix this by describing rate parameter. While at it, mark clk one optional. Fixes: dc0e4a3bb7dc ("watchdog: sp805: Add clock-frequency property") Cc: Srinath Mannam Signed-off-by: Andy Shevchenko Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210517174912.26419-1-andriy.shevchenko@linux.intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sp805_wdt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c index 531551216c8c..dbeb2146c968 100644 --- a/drivers/watchdog/sp805_wdt.c +++ b/drivers/watchdog/sp805_wdt.c @@ -57,7 +57,8 @@ * @wdd: instance of struct watchdog_device * @lock: spin lock protecting dev structure and io access * @base: base address of wdt - * @clk: clock structure of wdt + * @clk: (optional) clock structure of wdt + * @rate: (optional) clock rate when provided via properties * @adev: amba device structure of wdt * @status: current status of wdt * @load_val: load value to be set for current timeout From 6ddf5087f8022847556a4fec1d37a613f7e395d5 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Tue, 11 May 2021 08:29:53 +0200 Subject: [PATCH 18/56] watchdog: Add {min,max}_timeout sysfs nodes The valid range for the 'timeout' value is useful information so expose the min and max timeout values via sysfs. Signed-off-by: Juerg Haefliger Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210511062953.485252-1-juergh@canonical.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/watchdog_dev.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 2946f3a63110..74070661d368 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -525,6 +525,24 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(timeout); +static ssize_t min_timeout_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", wdd->min_timeout); +} +static DEVICE_ATTR_RO(min_timeout); + +static ssize_t max_timeout_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct watchdog_device *wdd = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", wdd->max_timeout); +} +static DEVICE_ATTR_RO(max_timeout); + static ssize_t pretimeout_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -609,6 +627,8 @@ static struct attribute *wdt_attrs[] = { &dev_attr_state.attr, &dev_attr_identity.attr, &dev_attr_timeout.attr, + &dev_attr_min_timeout.attr, + &dev_attr_max_timeout.attr, &dev_attr_pretimeout.attr, &dev_attr_timeleft.attr, &dev_attr_bootstatus.attr, From 90b7c141132244e8e49a34a4c1e445cce33e07f4 Mon Sep 17 00:00:00 2001 From: Zou Wei Date: Tue, 11 May 2021 15:04:51 +0800 Subject: [PATCH 19/56] watchdog: sc520_wdt: Fix possible use-after-free in wdt_turnoff() This module's remove path calls del_timer(). However, that function does not wait until the timer handler finishes. This means that the timer handler may still be running after the driver's remove function has finished, which would result in a use-after-free. Fix by calling del_timer_sync(), which makes sure the timer handler has finished, and unable to re-schedule itself. Reported-by: Hulk Robot Signed-off-by: Zou Wei Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1620716691-108460-1-git-send-email-zou_wei@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sc520_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index e66e6b905964..ca65468f4b9c 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -186,7 +186,7 @@ static int wdt_startup(void) static int wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); /* Stop the watchdog */ wdt_config(0); From d0212f095ab56672f6f36aabc605bda205e1e0bf Mon Sep 17 00:00:00 2001 From: Zou Wei Date: Wed, 12 May 2021 14:57:56 +0800 Subject: [PATCH 20/56] watchdog: Fix possible use-after-free by calling del_timer_sync() This driver's remove path calls del_timer(). However, that function does not wait until the timer handler finishes. This means that the timer handler may still be running after the driver's remove function has finished, which would result in a use-after-free. Fix by calling del_timer_sync(), which makes sure the timer handler has finished, and unable to re-schedule itself. Reported-by: Hulk Robot Signed-off-by: Zou Wei Reviewed-by: Guenter Roeck Acked-by: Vladimir Zapolskiy Link: https://lore.kernel.org/r/1620802676-19701-1-git-send-email-zou_wei@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/lpc18xx_wdt.c | 2 +- drivers/watchdog/w83877f_wdt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c index 78cf11c94941..60b6d74f267d 100644 --- a/drivers/watchdog/lpc18xx_wdt.c +++ b/drivers/watchdog/lpc18xx_wdt.c @@ -292,7 +292,7 @@ static int lpc18xx_wdt_remove(struct platform_device *pdev) struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n"); - del_timer(&lpc18xx_wdt->timer); + del_timer_sync(&lpc18xx_wdt->timer); return 0; } diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 5772cc5d3780..f2650863fd02 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c @@ -166,7 +166,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); wdt_change(WDT_DISABLE); From 3bb21781d13516baf14dc051dbe2b3145c704cda Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Tue, 11 May 2021 08:18:12 +0200 Subject: [PATCH 21/56] watchdog: Use sysfs_emit() and sysfs_emit_at() in "show" functions Convert sprintf() in sysfs "show" functions to sysfs_emit() and sysfs_emit_at() in order to check for buffer overruns in sysfs outputs. Signed-off-by: Juerg Haefliger Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210511061812.480172-1-juergh@canonical.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/aspeed_wdt.c | 4 ++-- drivers/watchdog/watchdog_dev.c | 19 ++++++++++--------- drivers/watchdog/watchdog_pretimeout.c | 4 ++-- drivers/watchdog/ziirave_wdt.c | 12 +++++++----- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 7e00960651fa..933998e5a9de 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -175,8 +175,8 @@ static ssize_t access_cs0_show(struct device *dev, struct aspeed_wdt *wdt = dev_get_drvdata(dev); u32 status = readl(wdt->base + WDT_TIMEOUT_STATUS); - return sprintf(buf, "%u\n", - !(status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY)); + return sysfs_emit(buf, "%u\n", + !(status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY)); } static ssize_t access_cs0_store(struct device *dev, diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 74070661d368..7c1007ab1b71 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -451,7 +451,8 @@ static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status)); + return sysfs_emit(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, + &wdd->status)); } static ssize_t nowayout_store(struct device *dev, struct device_attribute *attr, @@ -485,7 +486,7 @@ static ssize_t status_show(struct device *dev, struct device_attribute *attr, status = watchdog_get_status(wdd); mutex_unlock(&wd_data->lock); - return sprintf(buf, "0x%x\n", status); + return sysfs_emit(buf, "0x%x\n", status); } static DEVICE_ATTR_RO(status); @@ -494,7 +495,7 @@ static ssize_t bootstatus_show(struct device *dev, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", wdd->bootstatus); + return sysfs_emit(buf, "%u\n", wdd->bootstatus); } static DEVICE_ATTR_RO(bootstatus); @@ -510,7 +511,7 @@ static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr, status = watchdog_get_timeleft(wdd, &val); mutex_unlock(&wd_data->lock); if (!status) - status = sprintf(buf, "%u\n", val); + status = sysfs_emit(buf, "%u\n", val); return status; } @@ -521,7 +522,7 @@ static ssize_t timeout_show(struct device *dev, struct device_attribute *attr, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", wdd->timeout); + return sysfs_emit(buf, "%u\n", wdd->timeout); } static DEVICE_ATTR_RO(timeout); @@ -548,7 +549,7 @@ static ssize_t pretimeout_show(struct device *dev, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", wdd->pretimeout); + return sysfs_emit(buf, "%u\n", wdd->pretimeout); } static DEVICE_ATTR_RO(pretimeout); @@ -557,7 +558,7 @@ static ssize_t identity_show(struct device *dev, struct device_attribute *attr, { struct watchdog_device *wdd = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", wdd->info->identity); + return sysfs_emit(buf, "%s\n", wdd->info->identity); } static DEVICE_ATTR_RO(identity); @@ -567,9 +568,9 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, struct watchdog_device *wdd = dev_get_drvdata(dev); if (watchdog_active(wdd)) - return sprintf(buf, "active\n"); + return sysfs_emit(buf, "active\n"); - return sprintf(buf, "inactive\n"); + return sysfs_emit(buf, "inactive\n"); } static DEVICE_ATTR_RO(state); diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c index 01ca84be240f..7f257c3485cd 100644 --- a/drivers/watchdog/watchdog_pretimeout.c +++ b/drivers/watchdog/watchdog_pretimeout.c @@ -55,7 +55,7 @@ int watchdog_pretimeout_available_governors_get(char *buf) mutex_lock(&governor_lock); list_for_each_entry(priv, &governor_list, entry) - count += sprintf(buf + count, "%s\n", priv->gov->name); + count += sysfs_emit_at(buf, count, "%s\n", priv->gov->name); mutex_unlock(&governor_lock); @@ -68,7 +68,7 @@ int watchdog_pretimeout_governor_get(struct watchdog_device *wdd, char *buf) spin_lock_irq(&pretimeout_lock); if (wdd->gov) - count = sprintf(buf, "%s\n", wdd->gov->name); + count = sysfs_emit(buf, "%s\n", wdd->gov->name); spin_unlock_irq(&pretimeout_lock); return count; diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c index 4297280807ca..6c9414d09684 100644 --- a/drivers/watchdog/ziirave_wdt.c +++ b/drivers/watchdog/ziirave_wdt.c @@ -445,8 +445,9 @@ static ssize_t ziirave_wdt_sysfs_show_firm(struct device *dev, if (ret) return ret; - ret = sprintf(buf, ZIIRAVE_FW_VERSION_FMT, w_priv->firmware_rev.major, - w_priv->firmware_rev.minor); + ret = sysfs_emit(buf, ZIIRAVE_FW_VERSION_FMT, + w_priv->firmware_rev.major, + w_priv->firmware_rev.minor); mutex_unlock(&w_priv->sysfs_mutex); @@ -468,8 +469,9 @@ static ssize_t ziirave_wdt_sysfs_show_boot(struct device *dev, if (ret) return ret; - ret = sprintf(buf, ZIIRAVE_BL_VERSION_FMT, w_priv->bootloader_rev.major, - w_priv->bootloader_rev.minor); + ret = sysfs_emit(buf, ZIIRAVE_BL_VERSION_FMT, + w_priv->bootloader_rev.major, + w_priv->bootloader_rev.minor); mutex_unlock(&w_priv->sysfs_mutex); @@ -491,7 +493,7 @@ static ssize_t ziirave_wdt_sysfs_show_reason(struct device *dev, if (ret) return ret; - ret = sprintf(buf, "%s", ziirave_reasons[w_priv->reset_reason]); + ret = sysfs_emit(buf, "%s", ziirave_reasons[w_priv->reset_reason]); mutex_unlock(&w_priv->sysfs_mutex); From 0102882979582b6f9a351edcf600da9574030193 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 18 Apr 2021 17:07:03 -0700 Subject: [PATCH 22/56] watchdog: clean up the Kconfig file Change a non-working ftp: URL to https:. Wrap long lines earlier. Spell "IP" with capital letters. Change "it`s" to "it's". The backtick (grave accent) is not an apostrophe. Signed-off-by: Randy Dunlap Cc: Wim Van Sebroeck Cc: Guenter Roeck Cc: linux-watchdog@vger.kernel.org Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210419000704.17745-1-rdunlap@infradead.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 51 ++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 355100dad60a..ad99d62fe06b 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -22,9 +22,9 @@ menuconfig WATCHDOG The watchdog is usually used together with the watchdog daemon which is available from - . This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. + . This daemon + can also monitor NFS connections and can reboot the machine when the + process table is full. If unsure, say N. @@ -302,7 +302,7 @@ config XILINX_WATCHDOG depends on HAS_IOMEM select WATCHDOG_CORE help - Watchdog driver for the xps_timebase_wdt ip core. + Watchdog driver for the xps_timebase_wdt IP core. To compile this driver as a module, choose M here: the module will be called of_xilinx_wdt. @@ -404,8 +404,8 @@ config ASM9260_WATCHDOG select WATCHDOG_CORE select RESET_CONTROLLER help - Watchdog timer embedded into Alphascale asm9260 chips. This will reboot your - system when the timeout is reached. + Watchdog timer embedded into Alphascale asm9260 chips. This will + reboot your system when the timeout is reached. config AT91RM9200_WATCHDOG tristate "AT91RM9200 watchdog" @@ -548,8 +548,9 @@ config OMAP_WATCHDOG depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || COMPILE_TEST select WATCHDOG_CORE help - Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog. Say 'Y' - here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. + Support for TI OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog. + Say 'Y' here to enable the + OMAP1610/OMAP1710/OMAP2420/OMAP3430/OMAP4430 watchdog timer. config PNX4008_WATCHDOG tristate "LPC32XX Watchdog" @@ -1096,13 +1097,16 @@ config SBC_FITPC2_WATCHDOG This is the driver for the built-in watchdog timer on the fit-PC2, fit-PC2i, CM-iAM single-board computers made by Compulab. - It`s possible to enable watchdog timer either from BIOS (F2) or from booted Linux. - When "Watchdog Timer Value" enabled one can set 31-255 s operational range. + It's possible to enable the watchdog timer either from BIOS (F2) or + from booted Linux. + When the "Watchdog Timer Value" is enabled one can set 31-255 seconds + operational range. - Entering BIOS setup temporary disables watchdog operation regardless to current state, - so system will not be restarted while user in BIOS setup. + Entering BIOS setup temporarily disables watchdog operation regardless + of current state, so system will not be restarted while user is in + BIOS setup. - Once watchdog was enabled the system will be restarted every + Once the watchdog is enabled the system will be restarted every "Watchdog Timer Value" period, so to prevent it user can restart or disable the watchdog. @@ -1124,11 +1128,12 @@ config IB700_WDT depends on X86 help This is the driver for the hardware watchdog on the IB700 Single - Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog - simply watches your kernel to make sure it doesn't freeze, and if - it does, it reboots your computer after a certain amount of time. + Board Computer produced by TMC Technology (www.tmc-uk.com). This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of time. - This driver is like the WDT501 driver but for slightly different hardware. + This driver is like the WDT501 driver but for slightly different + hardware. To compile this driver as a module, choose M here: the module will be called ib700wdt. @@ -1807,10 +1812,10 @@ config PIC32_DMT select WATCHDOG_CORE depends on MACH_PIC32 || (MIPS && COMPILE_TEST) help - Watchdog driver for PIC32 instruction fetch counting timer. This specific - timer is typically be used in misson critical and safety critical - applications, where any single failure of the software functionality - and sequencing must be detected. + Watchdog driver for PIC32 instruction fetch counting timer. This + specific timer is typically be used in mission critical and safety + critical applications, where any single failure of the software + functionality and sequencing must be detected. To compile this driver as a loadable module, choose M here. The module will be called pic32-dmt. @@ -2013,8 +2018,8 @@ config PCWATCHDOG This card simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain amount of time. This driver is like the WDT501 driver but for different - hardware. Please read . The PC - watchdog cards can be ordered from . + hardware. Please read . + The PC watchdog cards can be ordered from . To compile this driver as a module, choose M here: the module will be called pcwd. From e7dc481c92060f9ce872878b0b7a08c24713a7e5 Mon Sep 17 00:00:00 2001 From: Tao Ren Date: Fri, 16 Apr 2021 20:42:49 -0700 Subject: [PATCH 23/56] watchdog: aspeed: fix hardware timeout calculation Fix hardware timeout calculation in aspeed_wdt_set_timeout function to ensure the reload value does not exceed the hardware limit. Fixes: efa859f7d786 ("watchdog: Add Aspeed watchdog driver") Reported-by: Amithash Prasad Signed-off-by: Tao Ren Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210417034249.5978-1-rentao.bupt@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/aspeed_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 933998e5a9de..436571b6fc79 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -147,7 +147,7 @@ static int aspeed_wdt_set_timeout(struct watchdog_device *wdd, wdd->timeout = timeout; - actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000); + actual = min(timeout, wdd->max_hw_heartbeat_ms / 1000); writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE); writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART); From 4d12252b37a2f907a1d08ac705caed9f780cabfa Mon Sep 17 00:00:00 2001 From: Jiapeng Chong Date: Tue, 13 Apr 2021 17:34:20 +0800 Subject: [PATCH 24/56] watchdog: it87_wdt: remove useless function Fix the following clang warning: drivers/watchdog/it87_wdt.c:155:20: warning: unused function 'superio_outw' [-Wunused-function]. Reported-by: Abaci Robot Signed-off-by: Jiapeng Chong Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1618306460-57286-1-git-send-email-jiapeng.chong@linux.alibaba.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/it87_wdt.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index 2b4831842162..bb1122909396 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c @@ -152,14 +152,6 @@ static inline int superio_inw(int reg) return val; } -static inline void superio_outw(int val, int reg) -{ - outb(reg++, REG); - outb(val >> 8, VAL); - outb(reg, REG); - outb(val, VAL); -} - /* Internal function, should be called after superio_select(GPIO) */ static void _wdt_update_timeout(unsigned int t) { From c891ef7d80da1855b5bba478a564c184df314ea4 Mon Sep 17 00:00:00 2001 From: Wong Vee Khee Date: Thu, 1 Apr 2021 11:32:09 +0800 Subject: [PATCH 25/56] watchdog: Fix a typo in Kconfig s/thershold/threshold Cc: Vijayakannan Ayyathurai Signed-off-by: Wong Vee Khee Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210401033209.9929-1-vee.khee.wong@linux.intel.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index ad99d62fe06b..433ca1ffe01c 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -2120,7 +2120,7 @@ config KEEMBAY_WATCHDOG This option enable support for an In-secure watchdog timer driver for Intel Keem Bay SoC. This WDT has a 32 bit timer and decrements in every count unit. An interrupt will be triggered, when the count crosses - the thershold configured in the register. + the threshold configured in the register. To compile this driver as a module, choose M here: the module will be called keembay_wdt. From 0a1186e49b010b4ecdcc60dd356b5751d7642dd4 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Thu, 1 Apr 2021 10:25:21 +0800 Subject: [PATCH 26/56] watchdog: meson_wdt: Use device_get_match_data() helper Use the device_get_match_data() helper instead of open coding. Signed-off-by: Tian Tao Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1617243921-56774-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/meson_wdt.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/watchdog/meson_wdt.c b/drivers/watchdog/meson_wdt.c index 459f3ae02c91..539feaa1f904 100644 --- a/drivers/watchdog/meson_wdt.c +++ b/drivers/watchdog/meson_wdt.c @@ -162,7 +162,6 @@ static int meson_wdt_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct meson_wdt_dev *meson_wdt; - const struct of_device_id *of_id; int err; meson_wdt = devm_kzalloc(dev, sizeof(*meson_wdt), GFP_KERNEL); @@ -173,12 +172,7 @@ static int meson_wdt_probe(struct platform_device *pdev) if (IS_ERR(meson_wdt->wdt_base)) return PTR_ERR(meson_wdt->wdt_base); - of_id = of_match_device(meson_wdt_dt_ids, dev); - if (!of_id) { - dev_err(dev, "Unable to initialize WDT data\n"); - return -ENODEV; - } - meson_wdt->data = of_id->data; + meson_wdt->data = device_get_match_data(dev); meson_wdt->wdt_dev.parent = dev; meson_wdt->wdt_dev.info = &meson_wdt_info; From b2802e78beca7c98805f20cbb4adb97c000703b1 Mon Sep 17 00:00:00 2001 From: Srinivas Goud Date: Mon, 29 Mar 2021 21:49:35 +0530 Subject: [PATCH 27/56] watchdog: of_xilinx_wdt: Add comment to spinlock Based on checkpatch every spinlock should be documented. The patch is fixing this issue: ./scripts/checkpatch.pl --strict -f drivers/watchdog/of_xilinx_wdt.c CHECK: spinlock_t definition without comment + spinlock_t spinlock; Signed-off-by: Srinivas Goud Signed-off-by: Michal Simek Signed-off-by: Srinivas Neeli Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210329161939.37680-2-srinivas.neeli@xilinx.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 7fe4f7c3f7ce..00549164b3d7 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -40,7 +40,7 @@ struct xwdt_device { void __iomem *base; u32 wdt_interval; - spinlock_t spinlock; + spinlock_t spinlock; /* spinlock for register handling */ struct watchdog_device xilinx_wdt_wdd; struct clk *clk; }; From 73ec94403190c7a3a8c174614ea65f04f0b9617e Mon Sep 17 00:00:00 2001 From: Srinivas Goud Date: Mon, 29 Mar 2021 21:49:36 +0530 Subject: [PATCH 28/56] watchdog: of_xilinx_wdt: Used BIT macro Used BIT macro instead of mask value. Signed-off-by: Srinivas Goud Signed-off-by: Michal Simek Signed-off-by: Srinivas Neeli Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210329161939.37680-3-srinivas.neeli@xilinx.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 00549164b3d7..f76ec56859a4 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -6,6 +6,7 @@ * (C) Copyright 2011 (Alejandro Cabrera ) */ +#include #include #include #include @@ -24,12 +25,12 @@ #define XWT_TBR_OFFSET 0x8 /* Timebase Register Offset */ /* Control/Status Register Masks */ -#define XWT_CSR0_WRS_MASK 0x00000008 /* Reset status */ -#define XWT_CSR0_WDS_MASK 0x00000004 /* Timer state */ -#define XWT_CSR0_EWDT1_MASK 0x00000002 /* Enable bit 1 */ +#define XWT_CSR0_WRS_MASK BIT(3) /* Reset status */ +#define XWT_CSR0_WDS_MASK BIT(2) /* Timer state */ +#define XWT_CSR0_EWDT1_MASK BIT(1) /* Enable bit 1 */ /* Control/Status Register 0/1 bits */ -#define XWT_CSRX_EWDT2_MASK 0x00000001 /* Enable bit 2 */ +#define XWT_CSRX_EWDT2_MASK BIT(0) /* Enable bit 2 */ /* SelfTest constants */ #define XWT_MAX_SELFTEST_LOOP_COUNT 0x00010000 From a40b2c3dc360d2c8c8614864f523dd0923b5f876 Mon Sep 17 00:00:00 2001 From: Srinivas Goud Date: Mon, 29 Mar 2021 21:49:37 +0530 Subject: [PATCH 29/56] watchdog: of_xilinx_wdt: Used dev_dbg() This patch removes pr_info in stop function and adds dev_dbg() in start/stop function to display device specific debug info. Signed-off-by: Srinivas Goud Signed-off-by: Michal Simek Signed-off-by: Srinivas Neeli Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210329161939.37680-4-srinivas.neeli@xilinx.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index f76ec56859a4..5f31fdea517a 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -71,6 +71,8 @@ static int xilinx_wdt_start(struct watchdog_device *wdd) spin_unlock(&xdev->spinlock); + dev_dbg(wdd->parent, "Watchdog Started!\n"); + return 0; } @@ -92,7 +94,7 @@ static int xilinx_wdt_stop(struct watchdog_device *wdd) clk_disable(xdev->clk); - pr_info("Stopped!\n"); + dev_dbg(wdd->parent, "Watchdog Stopped!\n"); return 0; } From f185de2231ce3214bb242f56b5d73641d5269508 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Mon, 29 Mar 2021 21:49:38 +0530 Subject: [PATCH 30/56] watchdog: of_xilinx_wdt: Remove passing null pointer clk is an optional property, if clock not defined, calling clk_prepare_enable() and devm_add_action_or_reset() are not useful. so calling these two apis only when clock is present. Addresses-Coverity:"FORWARD_NULL" Signed-off-by: Srinivas Neeli Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210329161939.37680-5-srinivas.neeli@xilinx.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index 5f31fdea517a..afbff79cce42 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -211,6 +211,15 @@ 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; } /* @@ -224,16 +233,6 @@ static int xwdt_probe(struct platform_device *pdev) spin_lock_init(&xdev->spinlock); watchdog_set_drvdata(xilinx_wdt_wdd, xdev); - 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; - rc = xwdt_selftest(xdev); if (rc == XWT_TIMER_FAILED) { dev_err(dev, "SelfTest routine error\n"); From 48027d0d9a77e051619f9cd5d311be12a4cb9380 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Mon, 29 Mar 2021 21:49:39 +0530 Subject: [PATCH 31/56] watchdog: of_xilinx_wdt: Skip printing pointer value "%p" is not printing the pointer value. In driver, printing pointer value is not useful so avoiding print. iSigned-off-by: Srinivas Neeli Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210329161939.37680-6-srinivas.neeli@xilinx.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/of_xilinx_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c index afbff79cce42..3318544366b8 100644 --- a/drivers/watchdog/of_xilinx_wdt.c +++ b/drivers/watchdog/of_xilinx_wdt.c @@ -245,8 +245,8 @@ static int xwdt_probe(struct platform_device *pdev) clk_disable(xdev->clk); - dev_info(dev, "Xilinx Watchdog Timer at %p with timeout %ds\n", - xdev->base, xilinx_wdt_wdd->timeout); + dev_info(dev, "Xilinx Watchdog Timer with timeout %ds\n", + xilinx_wdt_wdd->timeout); platform_set_drvdata(pdev, xdev); From 879a70843afdf6cc66dd70f4f04a44e1d8afed7d Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Sun, 21 Mar 2021 03:03:01 +0530 Subject: [PATCH 32/56] watchdog: sl28cpld_wdt: Fix a typo s/parmeter/parameter/ Signed-off-by: Bhaskar Chowdhury Acked-by: Randy Dunlap Reviewed-by: Guenter Roeck Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210320213301.8513-1-unixbhaskar@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sl28cpld_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/sl28cpld_wdt.c b/drivers/watchdog/sl28cpld_wdt.c index a45047d8d9ab..2de93298475f 100644 --- a/drivers/watchdog/sl28cpld_wdt.c +++ b/drivers/watchdog/sl28cpld_wdt.c @@ -164,7 +164,7 @@ static int sl28cpld_wdt_probe(struct platform_device *pdev) /* * Initial timeout value, may be overwritten by device tree or module - * parmeter in watchdog_init_timeout(). + * parameter in watchdog_init_timeout(). * * Reading a zero here means that either the hardware has a default * value of zero (which is very unlikely and definitely a hardware From e379c2199de4280243e43118dceb4ea5e97059a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 23 Feb 2021 09:00:42 +0100 Subject: [PATCH 33/56] watchdog: bcm7038_wdt: add big endian support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bcm7038_wdt can be used on bmips big endian (bcm63xx) devices too. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210223080042.29569-1-noltari@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/bcm7038_wdt.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c index 979caa18d3c8..acaaa0005d5b 100644 --- a/drivers/watchdog/bcm7038_wdt.c +++ b/drivers/watchdog/bcm7038_wdt.c @@ -34,6 +34,25 @@ struct bcm7038_watchdog { static bool nowayout = WATCHDOG_NOWAYOUT; +static inline void bcm7038_wdt_write(u32 value, void __iomem *addr) +{ + /* MIPS chips strapped for BE will automagically configure the + * peripheral registers for CPU-native byte order. + */ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + __raw_writel(value, addr); + else + writel_relaxed(value, addr); +} + +static inline u32 bcm7038_wdt_read(void __iomem *addr) +{ + if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) + return __raw_readl(addr); + else + return readl_relaxed(addr); +} + static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog) { struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); @@ -41,15 +60,15 @@ static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog) timeout = wdt->rate * wdog->timeout; - writel(timeout, wdt->base + WDT_TIMEOUT_REG); + bcm7038_wdt_write(timeout, wdt->base + WDT_TIMEOUT_REG); } static int bcm7038_wdt_ping(struct watchdog_device *wdog) { struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); - writel(WDT_START_1, wdt->base + WDT_CMD_REG); - writel(WDT_START_2, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_START_1, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_START_2, wdt->base + WDT_CMD_REG); return 0; } @@ -66,8 +85,8 @@ static int bcm7038_wdt_stop(struct watchdog_device *wdog) { struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); - writel(WDT_STOP_1, wdt->base + WDT_CMD_REG); - writel(WDT_STOP_2, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_STOP_1, wdt->base + WDT_CMD_REG); + bcm7038_wdt_write(WDT_STOP_2, wdt->base + WDT_CMD_REG); return 0; } @@ -88,7 +107,7 @@ static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog) struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog); u32 time_left; - time_left = readl(wdt->base + WDT_CMD_REG); + time_left = bcm7038_wdt_read(wdt->base + WDT_CMD_REG); return time_left / wdt->rate; } From fdc46a1485853e6d275b1ce68eb44986fa96480d Mon Sep 17 00:00:00 2001 From: Flavio Suligoi Date: Tue, 16 Feb 2021 15:17:27 +0100 Subject: [PATCH 34/56] watchdog: wdat_wdg: fix typo Fix the following typo: "recommeded" --> "recommended" "firmare" --> "firmware" Signed-off-by: Flavio Suligoi Reviewed-by: Mika Westerberg Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210216141727.641224-1-f.suligoi@asem.it Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/wdat_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index cec7917790e5..195c8c004b69 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -208,7 +208,7 @@ static int wdat_wdt_enable_reboot(struct wdat_wdt *wdat) /* * WDAT specification says that the watchdog is required to reboot * the system when it fires. However, it also states that it is - * recommeded to make it configurable through hardware register. We + * recommended to make it configurable through hardware register. We * enable reboot now if it is configurable, just in case. */ ret = wdat_wdt_run_action(wdat, ACPI_WDAT_SET_REBOOT, 0, NULL); @@ -475,7 +475,7 @@ static int wdat_wdt_suspend_noirq(struct device *dev) return 0; /* - * We need to stop the watchdog if firmare is not doing it or if we + * We need to stop the watchdog if firmware is not doing it or if we * are going suspend to idle (where firmware is not involved). If * firmware is stopping the watchdog we kick it here one more time * to give it some time. From 4700df05d3848c8ceb92662792d45d938e533f5a Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Mon, 22 Mar 2021 07:53:37 +0100 Subject: [PATCH 35/56] watchdog: fix syntactic kernel-doc issues The command 'find drivers/watchdog | xargs ./scripts/kernel-doc -none' reports a number of kernel-doc warnings in the watchdog subsystem. Address the kernel-doc warnings that were purely syntactic issues with kernel-doc comments. The remaining kernel-doc warnings are of type "Excess function parameter" and "Function parameter or member not described". These warnings would need to be addressed in a second pass with a bit more insight into the APIs and purpose of the functions in the watchdog subsystem. Signed-off-by: Lukas Bulwahn Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210322065337.617-1-lukas.bulwahn@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/booke_wdt.c | 2 +- drivers/watchdog/eurotechwdt.c | 2 +- drivers/watchdog/mei_wdt.c | 8 ++++---- drivers/watchdog/octeon-wdt-main.c | 12 +++++++----- drivers/watchdog/pc87413_wdt.c | 2 +- drivers/watchdog/wdt.c | 4 ++-- drivers/watchdog/wdt_pci.c | 2 +- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 7817fb976f9c..5e4dc1a0f2c6 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -148,7 +148,7 @@ static void __booke_wdt_enable(void *data) } /** - * booke_wdt_disable - disable the watchdog on the given CPU + * __booke_wdt_disable - disable the watchdog on the given CPU * * This function is called on each CPU. It disables the watchdog on that CPU. * diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index 2418ebb707bd..ce682942662c 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c @@ -392,7 +392,7 @@ static struct notifier_block eurwdt_notifier = { }; /** - * cleanup_module: + * eurwdt_exit: * * Unload the watchdog. You cannot do this with any file handles open. * If your watchdog is set to continue ticking on close and you unload diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index e023d7d90d66..c7a7235e6224 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -105,7 +105,7 @@ struct mei_wdt { #endif /* CONFIG_DEBUG_FS */ }; -/* +/** * struct mei_mc_hdr - Management Control Command Header * * @command: Management Control (0x2) @@ -121,7 +121,7 @@ struct mei_mc_hdr { }; /** - * struct mei_wdt_start_request watchdog start/ping + * struct mei_wdt_start_request - watchdog start/ping * * @hdr: Management Control Command Header * @timeout: timeout value @@ -134,7 +134,7 @@ struct mei_wdt_start_request { } __packed; /** - * struct mei_wdt_start_response watchdog start/ping response + * struct mei_wdt_start_response - watchdog start/ping response * * @hdr: Management Control Command Header * @status: operation status @@ -474,7 +474,7 @@ out: complete(&wdt->response); } -/* +/** * mei_wdt_notif - callback for event notification * * @cldev: bus device diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index fde9e739b436..298c070884c4 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c @@ -119,7 +119,7 @@ static int cpu2core(int cpu) } /** - * Poke the watchdog when an interrupt is received + * octeon_wdt_poke_irq - Poke the watchdog when an interrupt is received * * @cpl: * @dev_id: @@ -153,7 +153,7 @@ static irqreturn_t octeon_wdt_poke_irq(int cpl, void *dev_id) extern int prom_putchar(char c); /** - * Write a string to the uart + * octeon_wdt_write_string - Write a string to the uart * * @str: String to write */ @@ -165,7 +165,7 @@ static void octeon_wdt_write_string(const char *str) } /** - * Write a hex number out of the uart + * octeon_wdt_write_hex() - Write a hex number out of the uart * * @value: Number to display * @digits: Number of digits to print (1 to 16) @@ -192,6 +192,8 @@ static const char reg_name[][3] = { }; /** + * octeon_wdt_nmi_stage3: + * * NMI stage 3 handler. NMIs are handled in the following manner: * 1) The first NMI handler enables CVMSEG and transfers from * the bootbus region into normal memory. It is careful to not @@ -513,7 +515,7 @@ static struct watchdog_device octeon_wdt = { static enum cpuhp_state octeon_wdt_online; /** - * Module/ driver initialization. + * octeon_wdt_init - Module/ driver initialization. * * Returns Zero on success */ @@ -585,7 +587,7 @@ err: } /** - * Module / driver shutdown + * octeon_wdt_cleanup - Module / driver shutdown */ static void __exit octeon_wdt_cleanup(void) { diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 2d4504302c9e..9f9a340427fc 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -445,7 +445,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd, /* -- Notifier funtions -----------------------------------------*/ /** - * notify_sys: + * pc87413_notify_sys: * @this: our notifier block * @code: the event being reported * @unused: unused diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index a9e40b5c633e..183876156243 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c @@ -494,7 +494,7 @@ static int wdt_temp_release(struct inode *inode, struct file *file) } /** - * notify_sys: + * wdt_notify_sys: * @this: our notifier block * @code: the event being reported * @unused: unused @@ -558,7 +558,7 @@ static struct notifier_block wdt_notifier = { }; /** - * cleanup_module: + * wdt_exit: * * Unload the watchdog. You cannot do this with any file handles open. * If your watchdog is set to continue ticking on close and you unload diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index c3254ba5ace6..d5e56b601351 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c @@ -537,7 +537,7 @@ static int wdtpci_temp_release(struct inode *inode, struct file *file) } /** - * notify_sys: + * wdtpci_notify_sys: * @this: our notifier block * @code: the event being reported * @unused: unused From 1bbce7792bd19b95e44fd37db88b98091191e199 Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Sun, 25 Apr 2021 09:52:06 +0800 Subject: [PATCH 36/56] watchdog: mtk: support pre-timeout when the bark irq is available Use the bark interrupt as the pretimeout notifier if available. When the watchdog timer expires in dual mode, an interrupt will be triggered first, then the timing restarts. The reset signal will be initiated when the timer expires again. The pretimeout notification shall occur at timeout-sec/2. V2: - panic() by default if WATCHDOG_PRETIMEOUT_GOV is not enabled. V3: - Modify the pretimeout behavior, manually reset after the pretimeout - is processed and wait until timeout. V4: - Remove pretimeout related processing. - Add dual mode control separately. V5: - Fix some formatting and printing problems. V6: - Realize pretimeout processing through dualmode. V7: - Add set_pretimeout(). V8/V9: - Fix some formatting problems. Signed-off-by: Wang Qing Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1619315527-8171-2-git-send-email-wangqing@vivo.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/mtk_wdt.c | 77 +++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 97ca993bd009..16b6aff324a7 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -25,9 +25,10 @@ #include #include #include +#include #define WDT_MAX_TIMEOUT 31 -#define WDT_MIN_TIMEOUT 1 +#define WDT_MIN_TIMEOUT 2 #define WDT_LENGTH_TIMEOUT(n) ((n) << 5) #define WDT_LENGTH 0x04 @@ -187,12 +188,19 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev, u32 reg; wdt_dev->timeout = timeout; + /* + * In dual mode, irq will be triggered at timeout / 2 + * the real timeout occurs at timeout + */ + if (wdt_dev->pretimeout) + wdt_dev->pretimeout = timeout / 2; /* * One bit is the value of 512 ticks * The clock has 32 KHz */ - reg = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY; + reg = WDT_LENGTH_TIMEOUT((timeout - wdt_dev->pretimeout) << 6) + | WDT_LENGTH_KEY; iowrite32(reg, wdt_base + WDT_LENGTH); mtk_wdt_ping(wdt_dev); @@ -239,13 +247,48 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) return ret; reg = ioread32(wdt_base + WDT_MODE); - reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + if (wdt_dev->pretimeout) + reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + else + reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); reg |= (WDT_MODE_EN | WDT_MODE_KEY); iowrite32(reg, wdt_base + WDT_MODE); return 0; } +static int mtk_wdt_set_pretimeout(struct watchdog_device *wdd, + unsigned int timeout) +{ + struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdd); + void __iomem *wdt_base = mtk_wdt->wdt_base; + u32 reg = ioread32(wdt_base + WDT_MODE); + + if (timeout && !wdd->pretimeout) { + wdd->pretimeout = wdd->timeout / 2; + reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + } else if (!timeout && wdd->pretimeout) { + wdd->pretimeout = 0; + reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + } else { + return 0; + } + + reg |= WDT_MODE_KEY; + iowrite32(reg, wdt_base + WDT_MODE); + + return mtk_wdt_set_timeout(wdd, wdd->timeout); +} + +static irqreturn_t mtk_wdt_isr(int irq, void *arg) +{ + struct watchdog_device *wdd = arg; + + watchdog_notify_pretimeout(wdd); + + return IRQ_HANDLED; +} + static const struct watchdog_info mtk_wdt_info = { .identity = DRV_NAME, .options = WDIOF_SETTIMEOUT | @@ -253,12 +296,21 @@ static const struct watchdog_info mtk_wdt_info = { WDIOF_MAGICCLOSE, }; +static const struct watchdog_info mtk_wdt_pt_info = { + .identity = DRV_NAME, + .options = WDIOF_SETTIMEOUT | + WDIOF_PRETIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, +}; + static const struct watchdog_ops mtk_wdt_ops = { .owner = THIS_MODULE, .start = mtk_wdt_start, .stop = mtk_wdt_stop, .ping = mtk_wdt_ping, .set_timeout = mtk_wdt_set_timeout, + .set_pretimeout = mtk_wdt_set_pretimeout, .restart = mtk_wdt_restart, }; @@ -267,7 +319,7 @@ static int mtk_wdt_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct mtk_wdt_dev *mtk_wdt; const struct mtk_wdt_data *wdt_data; - int err; + int err, irq; mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL); if (!mtk_wdt) @@ -279,7 +331,22 @@ static int mtk_wdt_probe(struct platform_device *pdev) if (IS_ERR(mtk_wdt->wdt_base)) return PTR_ERR(mtk_wdt->wdt_base); - mtk_wdt->wdt_dev.info = &mtk_wdt_info; + irq = platform_get_irq(pdev, 0); + if (irq > 0) { + err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark", + &mtk_wdt->wdt_dev); + if (err) + return err; + + mtk_wdt->wdt_dev.info = &mtk_wdt_pt_info; + mtk_wdt->wdt_dev.pretimeout = WDT_MAX_TIMEOUT / 2; + } else { + if (irq == -EPROBE_DEFER) + return -EPROBE_DEFER; + + mtk_wdt->wdt_dev.info = &mtk_wdt_info; + } + mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000; From 5f8ebd4766dd072c8152255d45b352d444592a33 Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Sun, 25 Apr 2021 09:52:07 +0800 Subject: [PATCH 37/56] doc: mtk-wdt: support pre-timeout when the bark irq is available Add description of pre-timeout in mtk-wdt. Signed-off-by: Wang Qing Acked-by: Rob Herring Link: https://lore.kernel.org/r/1619148020-2236-3-git-send-email-wangqing@vivo.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/mtk-wdt.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt index e36ba60de829..8e277778f923 100644 --- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt @@ -1,5 +1,8 @@ Mediatek SoCs Watchdog timer +The watchdog supports a pre-timeout interrupt that fires timeout-sec/2 +before the expiry. + Required properties: - compatible should contain: @@ -17,6 +20,7 @@ Required properties: - reg : Specifies base physical address and size of the registers. Optional properties: +- interrupts: Watchdog pre-timeout (bark) interrupt. - timeout-sec: contains the watchdog timeout in seconds. - #reset-cells: Should be 1. @@ -26,6 +30,7 @@ watchdog: watchdog@10007000 { compatible = "mediatek,mt8183-wdt", "mediatek,mt6589-wdt"; reg = <0 0x10007000 0 0x100>; + interrupts = ; timeout-sec = <10>; #reset-cells = <1>; }; From bc65baf73b68448e79e8ff797522d1976788deb1 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Thu, 18 Mar 2021 17:25:06 +0000 Subject: [PATCH 38/56] watchdog: Remove MV64x60 watchdog driver Commit 92c8c16f3457 ("powerpc/embedded6xx: Remove C2K board support") removed the last selector of CONFIG_MV64X60. Therefore CONFIG_MV64X60_WDT cannot be selected anymore and can be removed. Signed-off-by: Christophe Leroy Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/9c2952bcfaec3b1789909eaa36bbce2afbfab7ab.1616085654.git.christophe.leroy@csgroup.eu Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 4 - drivers/watchdog/Makefile | 1 - drivers/watchdog/mv64x60_wdt.c | 324 --------------------------------- include/linux/mv643xx.h | 8 - 4 files changed, 337 deletions(-) delete mode 100644 drivers/watchdog/mv64x60_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 433ca1ffe01c..fcc61c948f01 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1849,10 +1849,6 @@ config 8xxx_WDT For BookE processors (MPC85xx) use the BOOKE_WDT driver instead. -config MV64X60_WDT - tristate "MV64X60 (Marvell Discovery) Watchdog Timer" - depends on MV64X60 || COMPILE_TEST - config PIKA_WDT tristate "PIKA FPGA Watchdog" depends on WARP || (PPC64 && COMPILE_TEST) diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index a7eade8b4d45..578bd6e5fbd0 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -175,7 +175,6 @@ obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o # POWERPC Architecture obj-$(CONFIG_GEF_WDT) += gef_wdt.o obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o -obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o obj-$(CONFIG_PIKA_WDT) += pika_wdt.o obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o obj-$(CONFIG_MEN_A21_WDT) += mena21_wdt.o diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c deleted file mode 100644 index 894aa63488d3..000000000000 --- a/drivers/watchdog/mv64x60_wdt.c +++ /dev/null @@ -1,324 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface - * - * Author: James Chapman - * - * Platform-specific setup code should configure the dog to generate - * interrupt or reset as required. This code only enables/disables - * and services the watchdog. - * - * Derived from mpc8xx_wdt.c, with the following copyright. - * - * 2002 (c) Florian Schirmer - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MV64x60_WDT_WDC_OFFSET 0 - -/* - * The watchdog configuration register contains a pair of 2-bit fields, - * 1. a reload field, bits 27-26, which triggers a reload of - * the countdown register, and - * 2. an enable field, bits 25-24, which toggles between - * enabling and disabling the watchdog timer. - * Bit 31 is a read-only field which indicates whether the - * watchdog timer is currently enabled. - * - * The low 24 bits contain the timer reload value. - */ -#define MV64x60_WDC_ENABLE_SHIFT 24 -#define MV64x60_WDC_SERVICE_SHIFT 26 -#define MV64x60_WDC_ENABLED_SHIFT 31 - -#define MV64x60_WDC_ENABLED_TRUE 1 -#define MV64x60_WDC_ENABLED_FALSE 0 - -/* Flags bits */ -#define MV64x60_WDOG_FLAG_OPENED 0 - -static unsigned long wdt_flags; -static int wdt_status; -static void __iomem *mv64x60_wdt_regs; -static int mv64x60_wdt_timeout; -static int mv64x60_wdt_count; -static unsigned int bus_clk; -static char expect_close; -static DEFINE_SPINLOCK(mv64x60_wdt_spinlock); - -static bool nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, bool, 0); -MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) -{ - u32 data; - u32 enabled; - int ret = 0; - - spin_lock(&mv64x60_wdt_spinlock); - data = readl(mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); - enabled = (data >> MV64x60_WDC_ENABLED_SHIFT) & 1; - - /* only toggle the requested field if enabled state matches predicate */ - if ((enabled ^ enabled_predicate) == 0) { - /* We write a 1, then a 2 -- to the appropriate field */ - data = (1 << field_shift) | mv64x60_wdt_count; - writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); - - data = (2 << field_shift) | mv64x60_wdt_count; - writel(data, mv64x60_wdt_regs + MV64x60_WDT_WDC_OFFSET); - ret = 1; - } - spin_unlock(&mv64x60_wdt_spinlock); - - return ret; -} - -static void mv64x60_wdt_service(void) -{ - mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, - MV64x60_WDC_SERVICE_SHIFT); -} - -static void mv64x60_wdt_handler_enable(void) -{ - if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_FALSE, - MV64x60_WDC_ENABLE_SHIFT)) { - mv64x60_wdt_service(); - pr_notice("watchdog activated\n"); - } -} - -static void mv64x60_wdt_handler_disable(void) -{ - if (mv64x60_wdt_toggle_wdc(MV64x60_WDC_ENABLED_TRUE, - MV64x60_WDC_ENABLE_SHIFT)) - pr_notice("watchdog deactivated\n"); -} - -static void mv64x60_wdt_set_timeout(unsigned int timeout) -{ - /* maximum bus cycle count is 0xFFFFFFFF */ - if (timeout > 0xFFFFFFFF / bus_clk) - timeout = 0xFFFFFFFF / bus_clk; - - mv64x60_wdt_count = timeout * bus_clk >> 8; - mv64x60_wdt_timeout = timeout; -} - -static int mv64x60_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) - return -EBUSY; - - if (nowayout) - __module_get(THIS_MODULE); - - mv64x60_wdt_handler_enable(); - - return stream_open(inode, file); -} - -static int mv64x60_wdt_release(struct inode *inode, struct file *file) -{ - if (expect_close == 42) - mv64x60_wdt_handler_disable(); - else { - pr_crit("unexpected close, not stopping timer!\n"); - mv64x60_wdt_service(); - } - expect_close = 0; - - clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); - - return 0; -} - -static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos) -{ - if (len) { - if (!nowayout) { - size_t i; - - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = 42; - } - } - mv64x60_wdt_service(); - } - - return len; -} - -static long mv64x60_wdt_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - int timeout; - int options; - void __user *argp = (void __user *)arg; - static const struct watchdog_info info = { - .options = WDIOF_SETTIMEOUT | - WDIOF_MAGICCLOSE | - WDIOF_KEEPALIVEPING, - .firmware_version = 0, - .identity = "MV64x60 watchdog", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - if (put_user(wdt_status, (int __user *)argp)) - return -EFAULT; - wdt_status &= ~WDIOF_KEEPALIVEPING; - break; - - case WDIOC_GETTEMP: - return -EOPNOTSUPP; - - case WDIOC_SETOPTIONS: - if (get_user(options, (int __user *)argp)) - return -EFAULT; - - if (options & WDIOS_DISABLECARD) - mv64x60_wdt_handler_disable(); - - if (options & WDIOS_ENABLECARD) - mv64x60_wdt_handler_enable(); - break; - - case WDIOC_KEEPALIVE: - mv64x60_wdt_service(); - wdt_status |= WDIOF_KEEPALIVEPING; - break; - - case WDIOC_SETTIMEOUT: - if (get_user(timeout, (int __user *)argp)) - return -EFAULT; - mv64x60_wdt_set_timeout(timeout); - fallthrough; - - case WDIOC_GETTIMEOUT: - if (put_user(mv64x60_wdt_timeout, (int __user *)argp)) - return -EFAULT; - break; - - default: - return -ENOTTY; - } - - return 0; -} - -static const struct file_operations mv64x60_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = mv64x60_wdt_write, - .unlocked_ioctl = mv64x60_wdt_ioctl, - .compat_ioctl = compat_ptr_ioctl, - .open = mv64x60_wdt_open, - .release = mv64x60_wdt_release, -}; - -static struct miscdevice mv64x60_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mv64x60_wdt_fops, -}; - -static int mv64x60_wdt_probe(struct platform_device *dev) -{ - struct mv64x60_wdt_pdata *pdata = dev_get_platdata(&dev->dev); - struct resource *r; - int timeout = 10; - - bus_clk = 133; /* in MHz */ - if (pdata) { - timeout = pdata->timeout; - bus_clk = pdata->bus_clk; - } - - /* Since bus_clk is truncated MHz, actual frequency could be - * up to 1MHz higher. Round up, since it's better to time out - * too late than too soon. - */ - bus_clk++; - bus_clk *= 1000000; /* convert to Hz */ - - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!r) - return -ENODEV; - - mv64x60_wdt_regs = devm_ioremap(&dev->dev, r->start, resource_size(r)); - if (mv64x60_wdt_regs == NULL) - return -ENOMEM; - - mv64x60_wdt_set_timeout(timeout); - - mv64x60_wdt_handler_disable(); /* in case timer was already running */ - - return misc_register(&mv64x60_wdt_miscdev); -} - -static int mv64x60_wdt_remove(struct platform_device *dev) -{ - misc_deregister(&mv64x60_wdt_miscdev); - - mv64x60_wdt_handler_disable(); - - return 0; -} - -static struct platform_driver mv64x60_wdt_driver = { - .probe = mv64x60_wdt_probe, - .remove = mv64x60_wdt_remove, - .driver = { - .name = MV64x60_WDT_NAME, - }, -}; - -static int __init mv64x60_wdt_init(void) -{ - pr_info("MV64x60 watchdog driver\n"); - - return platform_driver_register(&mv64x60_wdt_driver); -} - -static void __exit mv64x60_wdt_exit(void) -{ - platform_driver_unregister(&mv64x60_wdt_driver); -} - -module_init(mv64x60_wdt_init); -module_exit(mv64x60_wdt_exit); - -MODULE_AUTHOR("James Chapman "); -MODULE_DESCRIPTION("MV64x60 watchdog driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" MV64x60_WDT_NAME); diff --git a/include/linux/mv643xx.h b/include/linux/mv643xx.h index 47e5679b48e1..000b126acfb6 100644 --- a/include/linux/mv643xx.h +++ b/include/linux/mv643xx.h @@ -918,12 +918,4 @@ extern void mv64340_irq_init(unsigned int base); -/* Watchdog Platform Device, Driver Data */ -#define MV64x60_WDT_NAME "mv64x60_wdt" - -struct mv64x60_wdt_pdata { - int timeout; /* watchdog expiry in seconds, default 10 */ - int bus_clk; /* bus clock in MHz, default 133 */ -}; - #endif /* __ASM_MV643XX_H */ From 29e85f53fb58b45b9e9276dcdf1f1cb762dd1c9f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 4 Mar 2021 04:59:09 +0000 Subject: [PATCH 39/56] watchdog: jz4740: Fix return value check in jz4740_wdt_probe() In case of error, the function device_node_to_regmap() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Fixes: 6d532143c915 ("watchdog: jz4740: Use regmap provided by TCU driver") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Acked-by: Paul Cercueil Link: https://lore.kernel.org/r/20210304045909.945799-1-weiyongjun1@huawei.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/jz4740_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index bdf9564efa29..395bde79e292 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -176,9 +176,9 @@ static int jz4740_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(jz4740_wdt, drvdata); drvdata->map = device_node_to_regmap(dev->parent->of_node); - if (!drvdata->map) { + if (IS_ERR(drvdata->map)) { dev_err(dev, "regmap not found\n"); - return -EINVAL; + return PTR_ERR(drvdata->map); } return devm_watchdog_register_device(dev, &drvdata->wdt); From bbfdad82efb30cae910b96b2cb4045812794c89d Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Wed, 17 Mar 2021 10:47:34 +0530 Subject: [PATCH 40/56] watchdog: Fix a typo in the file orion_wdt.c s/freqency/frequency/ Signed-off-by: Bhaskar Chowdhury Acked-by: Randy Dunlap Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210317051734.97314-1-unixbhaskar@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/orion_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c index 4ddb4ea2e4a3..127eefc9161d 100644 --- a/drivers/watchdog/orion_wdt.c +++ b/drivers/watchdog/orion_wdt.c @@ -174,7 +174,7 @@ static int armadaxp_wdt_clock_init(struct platform_device *pdev, return ret; } - /* Fix the wdt and timer1 clock freqency to 25MHz */ + /* Fix the wdt and timer1 clock frequency to 25MHz */ val = WDT_AXP_FIXED_ENABLE_BIT | TIMER1_FIXED_ENABLE_BIT; atomic_io_modify(dev->reg + TIMER_CTRL, val, val); From 8442ef6f11cf3efa2d5d2fbec5aef67368a8915b Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Thu, 11 Mar 2021 01:50:04 +0530 Subject: [PATCH 41/56] watchdog: qcom: Move suspend/resume to suspend_late/resume_early During suspend/resume usecases and tests, it is common to see issues such as lockups either in suspend path or resume path because of the bugs in the corresponding device driver pm handling code. In such cases, it is important that watchdog is active to make sure that we either receive a watchdog pretimeout notification or a bite causing reset instead of a hang causing us to hard reset the machine. There are good reasons as to why we need this because: * We can have a watchdog pretimeout governor set to panic in which case we can have a backtrace which would help identify the issue with the particular driver and cause a normal reboot. * Even in case where there is no pretimeout support, a watchdog bite is still useful because some firmware has debug support to dump CPU core context on watchdog bite for post-mortem analysis. * One more usecase which comes to mind is of warm reboot. In case we hard reset the target, a cold reboot could be induced resulting in lose of ddr contents thereby losing all the debug info. Currently, the watchdog pm callback just invokes the usual suspend and resume callback which do not have any special ordering in the sense that a watchdog can be suspended before the buggy device driver suspend callback and watchdog resume can happen after the buggy device driver resume callback. This would mean that the watchdog will not be active when the buggy driver cause the lockups thereby hanging the system. So to make sure this doesn't happen, move the watchdog pm to use late/early system pm callbacks which will ensure that the watchdog is suspended late and resumed early so that it can catch such issues. Signed-off-by: Sai Prakash Ranjan Reviewed-by: Guenter Roeck Reviewed-by: Douglas Anderson Link: https://lore.kernel.org/r/20210310202004.1436-1-saiprakash.ranjan@codeaurora.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/qcom-wdt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index e38a87ffe5f5..0d2209c5eaca 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -329,7 +329,9 @@ static int __maybe_unused qcom_wdt_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(qcom_wdt_pm_ops, qcom_wdt_suspend, qcom_wdt_resume); +static const struct dev_pm_ops qcom_wdt_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(qcom_wdt_suspend, qcom_wdt_resume) +}; static const struct of_device_id qcom_wdt_of_table[] = { { .compatible = "qcom,kpss-timer", .data = &match_data_apcs_tmr }, From e1138cef88a53eb24c2536cef788a7293824c789 Mon Sep 17 00:00:00 2001 From: Sai Prakash Ranjan Date: Mon, 15 Mar 2021 11:35:01 +0530 Subject: [PATCH 42/56] dt-bindings: watchdog: Add compatible for SC7280 SoC Add compatible for watchdog timer on SC7280 SoC. Signed-off-by: Sai Prakash Ranjan Signed-off-by: Rajendra Nayak Reviewed-by: Stephen Boyd Acked-by: Rob Herring Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1615788301-29891-1-git-send-email-rnayak@codeaurora.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 b8e4118945a0..ba60bdf1fecc 100644 --- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml @@ -17,6 +17,7 @@ properties: enum: - qcom,apss-wdt-qcs404 - qcom,apss-wdt-sc7180 + - qcom,apss-wdt-sc7280 - qcom,apss-wdt-sdm845 - qcom,apss-wdt-sdx55 - qcom,apss-wdt-sm8150 From 7b7d2fdc8c3e3f9fdb3558d674e1eeddc16c7d9e Mon Sep 17 00:00:00 2001 From: Curtis Klein Date: Wed, 3 Feb 2021 12:11:30 -0800 Subject: [PATCH 43/56] watchdog: Add hrtimer-based pretimeout feature This adds the option to use a hrtimer to generate a watchdog pretimeout event for hardware watchdogs that do not natively support watchdog pretimeouts. With this enabled, all watchdogs will appear to have pretimeout support in userspace. If no pretimeout value is set, there will be no change in the watchdog's behavior. If a pretimeout value is set for a specific watchdog that does not have built-in pretimeout support, a timer will be started that should fire at the specified time before the watchdog timeout would occur. When the watchdog is successfully pinged, the timer will be restarted. If the timer is allowed to fire it will generate a pretimeout event. However because a software timer is used, it may not be able to fire in every circumstance. If the watchdog does support a pretimeout natively, that functionality will be used instead of the hrtimer. The general design of this feaure was inspired by the software watchdog, specifically its own pretimeout implementation. However the software watchdog and this feature are completely independent. They can be used together; with or without CONFIG_SOFT_WATCHDOG_PRETIMEOUT enabled. The main advantage of using the hrtimer pretimeout with a hardware watchdog, compared to running the software watchdog with a hardware watchdog, is that if the hardware watchdog driver is unable to ping the watchdog (e.g. due to a bus or communication error), then the hrtimer pretimeout would still fire whereas the software watchdog would not. Signed-off-by: Curtis Klein Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/1612383090-27110-1-git-send-email-curtis.klein@hpe.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 8 ++++ drivers/watchdog/Makefile | 1 + drivers/watchdog/watchdog_core.h | 48 +++++++++++++++++++ drivers/watchdog/watchdog_dev.c | 47 +++++++----------- .../watchdog/watchdog_hrtimer_pretimeout.c | 44 +++++++++++++++++ drivers/watchdog/watchdog_pretimeout.c | 5 +- 6 files changed, 121 insertions(+), 32 deletions(-) create mode 100644 drivers/watchdog/watchdog_hrtimer_pretimeout.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index fcc61c948f01..7a33e6a6ac23 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -73,6 +73,14 @@ config WATCHDOG_SYSFS Say Y here if you want to enable watchdog device status read through sysfs attributes. +config WATCHDOG_HRTIMER_PRETIMEOUT + bool "Enable watchdog hrtimer-based pretimeouts" + help + Enable this if you want to use a hrtimer timer based pretimeout for + watchdogs that do not natively support pretimeout support. Be aware + that because this pretimeout functionality uses hrtimers, it may not + be able to fire before the actual watchdog fires in some situations. + comment "Watchdog Pretimeout Governors" config WATCHDOG_PRETIMEOUT_GOV diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 578bd6e5fbd0..0b4d828872be 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_WATCHDOG_CORE) += watchdog.o watchdog-objs += watchdog_core.o watchdog_dev.o watchdog-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV) += watchdog_pretimeout.o +watchdog-$(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT) += watchdog_hrtimer_pretimeout.o obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP) += pretimeout_noop.o obj-$(CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC) += pretimeout_panic.o diff --git a/drivers/watchdog/watchdog_core.h b/drivers/watchdog/watchdog_core.h index a5062e8e0d13..5b35a8439e26 100644 --- a/drivers/watchdog/watchdog_core.h +++ b/drivers/watchdog/watchdog_core.h @@ -7,6 +7,8 @@ * * (c) Copyright 2008-2011 Wim Van Sebroeck . * + * (c) Copyright 2021 Hewlett Packard Enterprise Development LP. + * * This source code is part of the generic code that can be used * by all the watchdog timer drivers. * @@ -22,8 +24,38 @@ * This material is provided "AS-IS" and at no charge. */ +#include +#include + #define MAX_DOGS 32 /* Maximum number of watchdog devices */ +/* + * struct watchdog_core_data - watchdog core internal data + * @dev: The watchdog's internal device + * @cdev: The watchdog's Character device. + * @wdd: Pointer to watchdog device. + * @lock: Lock for watchdog core. + * @status: Watchdog core internal status bits. + */ +struct watchdog_core_data { + struct device dev; + struct cdev cdev; + struct watchdog_device *wdd; + struct mutex lock; + ktime_t last_keepalive; + ktime_t last_hw_keepalive; + ktime_t open_deadline; + struct hrtimer timer; + struct kthread_work work; +#if IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT) + struct hrtimer pretimeout_timer; +#endif + unsigned long status; /* Internal status bits */ +#define _WDOG_DEV_OPEN 0 /* Opened ? */ +#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ +#define _WDOG_KEEPALIVE 2 /* Did we receive a keepalive ? */ +}; + /* * Functions/procedures to be called by the core */ @@ -31,3 +63,19 @@ extern int watchdog_dev_register(struct watchdog_device *); extern void watchdog_dev_unregister(struct watchdog_device *); extern int __init watchdog_dev_init(void); extern void __exit watchdog_dev_exit(void); + +static inline bool watchdog_have_pretimeout(struct watchdog_device *wdd) +{ + return wdd->info->options & WDIOF_PRETIMEOUT || + IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT); +} + +#if IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT) +void watchdog_hrtimer_pretimeout_init(struct watchdog_device *wdd); +void watchdog_hrtimer_pretimeout_start(struct watchdog_device *wdd); +void watchdog_hrtimer_pretimeout_stop(struct watchdog_device *wdd); +#else +static inline void watchdog_hrtimer_pretimeout_init(struct watchdog_device *wdd) {} +static inline void watchdog_hrtimer_pretimeout_start(struct watchdog_device *wdd) {} +static inline void watchdog_hrtimer_pretimeout_stop(struct watchdog_device *wdd) {} +#endif diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 7c1007ab1b71..3bab32485273 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -7,6 +7,7 @@ * * (c) Copyright 2008-2011 Wim Van Sebroeck . * + * (c) Copyright 2021 Hewlett Packard Enterprise Development LP. * * This source code is part of the generic code that can be used * by all the watchdog timer drivers. @@ -46,30 +47,6 @@ #include "watchdog_core.h" #include "watchdog_pretimeout.h" -/* - * struct watchdog_core_data - watchdog core internal data - * @dev: The watchdog's internal device - * @cdev: The watchdog's Character device. - * @wdd: Pointer to watchdog device. - * @lock: Lock for watchdog core. - * @status: Watchdog core internal status bits. - */ -struct watchdog_core_data { - struct device dev; - struct cdev cdev; - struct watchdog_device *wdd; - struct mutex lock; - ktime_t last_keepalive; - ktime_t last_hw_keepalive; - ktime_t open_deadline; - struct hrtimer timer; - struct kthread_work work; - unsigned long status; /* Internal status bits */ -#define _WDOG_DEV_OPEN 0 /* Opened ? */ -#define _WDOG_ALLOW_RELEASE 1 /* Did we receive the magic char ? */ -#define _WDOG_KEEPALIVE 2 /* Did we receive a keepalive ? */ -}; - /* the dev_t structure to store the dynamically allocated watchdog devices */ static dev_t watchdog_devt; /* Reference to watchdog device behind /dev/watchdog */ @@ -185,6 +162,9 @@ static int __watchdog_ping(struct watchdog_device *wdd) else err = wdd->ops->start(wdd); /* restart watchdog */ + if (err == 0) + watchdog_hrtimer_pretimeout_start(wdd); + watchdog_update_worker(wdd); return err; @@ -275,8 +255,10 @@ static int watchdog_start(struct watchdog_device *wdd) started_at = ktime_get(); if (watchdog_hw_running(wdd) && wdd->ops->ping) { err = __watchdog_ping(wdd); - if (err == 0) + if (err == 0) { set_bit(WDOG_ACTIVE, &wdd->status); + watchdog_hrtimer_pretimeout_start(wdd); + } } else { err = wdd->ops->start(wdd); if (err == 0) { @@ -284,6 +266,7 @@ static int watchdog_start(struct watchdog_device *wdd) wd_data->last_keepalive = started_at; wd_data->last_hw_keepalive = started_at; watchdog_update_worker(wdd); + watchdog_hrtimer_pretimeout_start(wdd); } } @@ -325,6 +308,7 @@ static int watchdog_stop(struct watchdog_device *wdd) if (err == 0) { clear_bit(WDOG_ACTIVE, &wdd->status); watchdog_update_worker(wdd); + watchdog_hrtimer_pretimeout_stop(wdd); } return err; @@ -361,6 +345,9 @@ static unsigned int watchdog_get_status(struct watchdog_device *wdd) if (test_and_clear_bit(_WDOG_KEEPALIVE, &wd_data->status)) status |= WDIOF_KEEPALIVEPING; + if (IS_ENABLED(CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT)) + status |= WDIOF_PRETIMEOUT; + return status; } @@ -408,7 +395,7 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, { int err = 0; - if (!(wdd->info->options & WDIOF_PRETIMEOUT)) + if (!watchdog_have_pretimeout(wdd)) return -EOPNOTSUPP; if (watchdog_pretimeout_invalid(wdd, timeout)) @@ -613,13 +600,11 @@ static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr, if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft) mode = 0; - else if (attr == &dev_attr_pretimeout.attr && - !(wdd->info->options & WDIOF_PRETIMEOUT)) + else if (attr == &dev_attr_pretimeout.attr && !watchdog_have_pretimeout(wdd)) mode = 0; else if ((attr == &dev_attr_pretimeout_governor.attr || attr == &dev_attr_pretimeout_available_governors.attr) && - (!(wdd->info->options & WDIOF_PRETIMEOUT) || - !IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_GOV))) + (!watchdog_have_pretimeout(wdd) || !IS_ENABLED(CONFIG_WATCHDOG_PRETIMEOUT_GOV))) mode = 0; return mode; @@ -1030,6 +1015,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd) kthread_init_work(&wd_data->work, watchdog_ping_work); hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); wd_data->timer.function = watchdog_timer_expired; + watchdog_hrtimer_pretimeout_init(wdd); if (wdd->id == 0) { old_wd_data = wd_data; @@ -1117,6 +1103,7 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd) hrtimer_cancel(&wd_data->timer); kthread_cancel_work_sync(&wd_data->work); + watchdog_hrtimer_pretimeout_stop(wdd); put_device(&wd_data->dev); } diff --git a/drivers/watchdog/watchdog_hrtimer_pretimeout.c b/drivers/watchdog/watchdog_hrtimer_pretimeout.c new file mode 100644 index 000000000000..940b53718a91 --- /dev/null +++ b/drivers/watchdog/watchdog_hrtimer_pretimeout.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (c) Copyright 2021 Hewlett Packard Enterprise Development LP. + */ + +#include +#include + +#include "watchdog_core.h" +#include "watchdog_pretimeout.h" + +static enum hrtimer_restart watchdog_hrtimer_pretimeout(struct hrtimer *timer) +{ + struct watchdog_core_data *wd_data; + + wd_data = container_of(timer, struct watchdog_core_data, pretimeout_timer); + + watchdog_notify_pretimeout(wd_data->wdd); + return HRTIMER_NORESTART; +} + +void watchdog_hrtimer_pretimeout_init(struct watchdog_device *wdd) +{ + struct watchdog_core_data *wd_data = wdd->wd_data; + + hrtimer_init(&wd_data->pretimeout_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + wd_data->pretimeout_timer.function = watchdog_hrtimer_pretimeout; +} + +void watchdog_hrtimer_pretimeout_start(struct watchdog_device *wdd) +{ + if (!(wdd->info->options & WDIOF_PRETIMEOUT) && + !watchdog_pretimeout_invalid(wdd, wdd->pretimeout)) + hrtimer_start(&wdd->wd_data->pretimeout_timer, + ktime_set(wdd->timeout - wdd->pretimeout, 0), + HRTIMER_MODE_REL); + else + hrtimer_cancel(&wdd->wd_data->pretimeout_timer); +} + +void watchdog_hrtimer_pretimeout_stop(struct watchdog_device *wdd) +{ + hrtimer_cancel(&wdd->wd_data->pretimeout_timer); +} diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c index 7f257c3485cd..376a495ab80c 100644 --- a/drivers/watchdog/watchdog_pretimeout.c +++ b/drivers/watchdog/watchdog_pretimeout.c @@ -9,6 +9,7 @@ #include #include +#include "watchdog_core.h" #include "watchdog_pretimeout.h" /* Default watchdog pretimeout governor */ @@ -177,7 +178,7 @@ int watchdog_register_pretimeout(struct watchdog_device *wdd) { struct watchdog_pretimeout *p; - if (!(wdd->info->options & WDIOF_PRETIMEOUT)) + if (!watchdog_have_pretimeout(wdd)) return 0; p = kzalloc(sizeof(*p), GFP_KERNEL); @@ -197,7 +198,7 @@ void watchdog_unregister_pretimeout(struct watchdog_device *wdd) { struct watchdog_pretimeout *p, *t; - if (!(wdd->info->options & WDIOF_PRETIMEOUT)) + if (!watchdog_have_pretimeout(wdd)) return; spin_lock_irq(&pretimeout_lock); From 266b2e335ce0c396096be4b649b819cc62b8c791 Mon Sep 17 00:00:00 2001 From: Junlin Yang Date: Wed, 3 Feb 2021 20:24:04 +0800 Subject: [PATCH 44/56] watchdog: diag288_wdt: Remove redundant assignment The assign for 'ret' is redundant and can be removed, because it will be assigned before use. Signed-off-by: Junlin Yang Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210203122404.752-1-angkery@163.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/diag288_wdt.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c index aafc8d98bf9f..4cb10877017c 100644 --- a/drivers/watchdog/diag288_wdt.c +++ b/drivers/watchdog/diag288_wdt.c @@ -118,8 +118,6 @@ static int wdt_start(struct watchdog_device *dev) if (test_and_set_bit(DIAG_WDOG_BUSY, &wdt_status)) return -EBUSY; - ret = -ENODEV; - if (MACHINE_IS_VM) { ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL); if (!ebc_cmd) { @@ -167,8 +165,6 @@ static int wdt_ping(struct watchdog_device *dev) int ret; unsigned int func; - ret = -ENODEV; - if (MACHINE_IS_VM) { ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL); if (!ebc_cmd) From 854478a381078ee86ae2a7908a934b1ded399130 Mon Sep 17 00:00:00 2001 From: Stefan Eichenberger Date: Tue, 6 Apr 2021 14:12:47 +0200 Subject: [PATCH 45/56] watchdog: imx_sc_wdt: fix pretimeout If the WDIOF_PRETIMEOUT flag is not set when registering the device the driver will not show the sysfs entries or register the default governor. By moving the registering after the decision whether pretimeout is supported this gets fixed. Signed-off-by: Stefan Eichenberger Reviewed-by: Guenter Roeck Reviewed-by: Dong Aisheng Link: https://lore.kernel.org/r/20210519080311.142928-1-eichest@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/imx_sc_wdt.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c index e9ee22a7cb45..8ac021748d16 100644 --- a/drivers/watchdog/imx_sc_wdt.c +++ b/drivers/watchdog/imx_sc_wdt.c @@ -183,16 +183,12 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(wdog); watchdog_stop_on_unregister(wdog); - ret = devm_watchdog_register_device(dev, wdog); - if (ret) - return ret; - ret = imx_scu_irq_group_enable(SC_IRQ_GROUP_WDOG, SC_IRQ_WDOG, true); if (ret) { dev_warn(dev, "Enable irq failed, pretimeout NOT supported\n"); - return 0; + goto register_device; } imx_sc_wdd->wdt_notifier.notifier_call = imx_sc_wdt_notify; @@ -203,7 +199,7 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) false); dev_warn(dev, "Register irq notifier failed, pretimeout NOT supported\n"); - return 0; + goto register_device; } ret = devm_add_action_or_reset(dev, imx_sc_wdt_action, @@ -213,7 +209,8 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) else dev_warn(dev, "Add action failed, pretimeout NOT supported\n"); - return 0; +register_device: + return devm_watchdog_register_device(dev, wdog); } static int __maybe_unused imx_sc_wdt_suspend(struct device *dev) From e4c721d7167f32331ff436b036fe8fca0b70f094 Mon Sep 17 00:00:00 2001 From: Liang Chen Date: Thu, 29 Apr 2021 16:11:45 +0800 Subject: [PATCH 46/56] dt-bindings: watchdog: dw-wdt: add description for rk3568 add "rockchip,rk3568-wdt", "snps,dw-wdt" for watchdog nodes on a rk3568 platform to snps,dw-wdt.yaml. Signed-off-by: Liang Chen Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210429081151.17558-5-cl@rock-chips.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml b/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml index b58596b1831d..6461eb4f4a27 100644 --- a/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/snps,dw-wdt.yaml @@ -27,6 +27,7 @@ properties: - rockchip,rk3328-wdt - rockchip,rk3368-wdt - rockchip,rk3399-wdt + - rockchip,rk3568-wdt - rockchip,rv1108-wdt - const: snps,dw-wdt From b326f2c85f3d79996a58749d9b17b644d440d68a Mon Sep 17 00:00:00 2001 From: Seiya Wang Date: Tue, 16 Mar 2021 19:14:36 +0800 Subject: [PATCH 47/56] dt-bindings: watchdog: Add compatible for Mediatek MT8195 This commit adds dt-binding documentation of watchdog for Mediatek MT8195 SoC Platform. Signed-off-by: Seiya Wang Reviewed-by: Guenter Roeck Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210319023427.16711-5-seiya.wang@mediatek.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- Documentation/devicetree/bindings/watchdog/mtk-wdt.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt index 8e277778f923..416d716403f6 100644 --- a/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/mtk-wdt.txt @@ -16,6 +16,7 @@ Required properties: "mediatek,mt8183-wdt": for MT8183 "mediatek,mt8516-wdt", "mediatek,mt6589-wdt": for MT8516 "mediatek,mt8192-wdt": for MT8192 + "mediatek,mt8195-wdt", "mediatek,mt6589-wdt": for MT8195 - reg : Specifies base physical address and size of the registers. From 6da96e6e9244f67f6dd472a8e5f6abe1deba9048 Mon Sep 17 00:00:00 2001 From: Juerg Haefliger Date: Thu, 20 May 2021 09:29:18 +0200 Subject: [PATCH 48/56] watchdog: ziirave_wdt: Remove VERSION_FMT defines and add sysfs newlines Remove the ZIIRAVE_{BL,FW}_VERION_FMT defines since they're only used in very few places. While at it, add newlines to sysfs outputs. Suggested-By: Joe Perches Signed-off-by: Juerg Haefliger Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210520072918.76482-1-juergh@canonical.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/ziirave_wdt.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c index 6c9414d09684..c5a9b820d43a 100644 --- a/drivers/watchdog/ziirave_wdt.c +++ b/drivers/watchdog/ziirave_wdt.c @@ -69,9 +69,6 @@ static char *ziirave_reasons[] = {"power cycle", "hw watchdog", NULL, NULL, #define ZIIRAVE_CMD_JUMP_TO_BOOTLOADER_MAGIC 1 #define ZIIRAVE_CMD_RESET_PROCESSOR_MAGIC 1 -#define ZIIRAVE_FW_VERSION_FMT "02.%02u.%02u" -#define ZIIRAVE_BL_VERSION_FMT "01.%02u.%02u" - struct ziirave_wdt_rev { unsigned char major; unsigned char minor; @@ -445,7 +442,7 @@ static ssize_t ziirave_wdt_sysfs_show_firm(struct device *dev, if (ret) return ret; - ret = sysfs_emit(buf, ZIIRAVE_FW_VERSION_FMT, + ret = sysfs_emit(buf, "02.%02u.%02u\n", w_priv->firmware_rev.major, w_priv->firmware_rev.minor); @@ -469,7 +466,7 @@ static ssize_t ziirave_wdt_sysfs_show_boot(struct device *dev, if (ret) return ret; - ret = sysfs_emit(buf, ZIIRAVE_BL_VERSION_FMT, + ret = sysfs_emit(buf, "01.%02u.%02u\n", w_priv->bootloader_rev.major, w_priv->bootloader_rev.minor); @@ -493,7 +490,7 @@ static ssize_t ziirave_wdt_sysfs_show_reason(struct device *dev, if (ret) return ret; - ret = sysfs_emit(buf, "%s", ziirave_reasons[w_priv->reset_reason]); + ret = sysfs_emit(buf, "%s\n", ziirave_reasons[w_priv->reset_reason]); mutex_unlock(&w_priv->sysfs_mutex); @@ -538,7 +535,7 @@ static ssize_t ziirave_wdt_sysfs_store_firm(struct device *dev, } dev_info(&client->dev, - "Firmware updated to version " ZIIRAVE_FW_VERSION_FMT "\n", + "Firmware updated to version 02.%02u.%02u\n", w_priv->firmware_rev.major, w_priv->firmware_rev.minor); /* Restore the watchdog timeout */ @@ -679,7 +676,7 @@ static int ziirave_wdt_probe(struct i2c_client *client, } dev_info(&client->dev, - "Firmware version: " ZIIRAVE_FW_VERSION_FMT "\n", + "Firmware version: 02.%02u.%02u\n", w_priv->firmware_rev.major, w_priv->firmware_rev.minor); ret = ziirave_wdt_revision(client, &w_priv->bootloader_rev, @@ -690,7 +687,7 @@ static int ziirave_wdt_probe(struct i2c_client *client, } dev_info(&client->dev, - "Bootloader version: " ZIIRAVE_BL_VERSION_FMT "\n", + "Bootloader version: 01.%02u.%02u\n", w_priv->bootloader_rev.major, w_priv->bootloader_rev.minor); w_priv->reset_reason = i2c_smbus_read_byte_data(client, From 13b191692d917b62d50c3956ed9c6ef3d0fbb001 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 27 May 2021 13:01:18 +0300 Subject: [PATCH 49/56] dt-bindings: watchdog: sama5d4-wdt: convert to yaml Convert the old txt binding to yaml format. Signed-off-by: Eugen Hristev Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210527100120.266796-1-eugen.hristev@microchip.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/atmel,sama5d4-wdt.yaml | 73 +++++++++++++++++++ .../bindings/watchdog/atmel-sama5d4-wdt.txt | 34 --------- 2 files changed, 73 insertions(+), 34 deletions(-) create mode 100644 Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml delete mode 100644 Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt diff --git a/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml b/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml new file mode 100644 index 000000000000..0d0ab81da040 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/atmel,sama5d4-wdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel SAMA5D4 Watchdog Timer (WDT) Controller + +maintainers: + - Eugen Hristev + +allOf: + - $ref: "watchdog.yaml#" + +properties: + compatible: + enum: + - atmel,sama5d4-wdt + - microchip,sam9x60-wdt + + reg: + maxItems: 1 + + atmel,watchdog-type: + $ref: /schemas/types.yaml#/definitions/string + description: should be hardware or software. + oneOf: + - description: + Enable watchdog fault reset. A watchdog fault triggers + watchdog reset. + const: hardware + - description: + Enable watchdog fault interrupt. A watchdog fault asserts + watchdog interrupt. + const: software + default: hardware + + atmel,idle-halt: + $ref: /schemas/types.yaml#/definitions/flag + description: | + present if you want to stop the watchdog when the CPU is in idle state. + CAUTION: This property should be used with care, it actually makes the + watchdog not counting when the CPU is in idle state, therefore the + watchdog reset time depends on mean CPU usage and will not reset at all + if the CPU stop working while it is in idle state, which is probably + not what you want. + + atmel,dbg-halt: + $ref: /schemas/types.yaml#/definitions/flag + description: | + present if you want to stop the watchdog when the CPU is in debug state. + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + #include + + watchdog@fc068640 { + compatible = "atmel,sama5d4-wdt"; + reg = <0xfc068640 0x10>; + interrupts = <4 IRQ_TYPE_LEVEL_HIGH 5>; + timeout-sec = <10>; + atmel,watchdog-type = "hardware"; + atmel,dbg-halt; + atmel,idle-halt; + }; + +... diff --git a/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt deleted file mode 100644 index 44727fcc2729..000000000000 --- a/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt +++ /dev/null @@ -1,34 +0,0 @@ -* Atmel SAMA5D4 Watchdog Timer (WDT) Controller - -Required properties: -- compatible: "atmel,sama5d4-wdt" or "microchip,sam9x60-wdt" -- reg: base physical address and length of memory mapped region. - -Optional properties: -- timeout-sec: watchdog timeout value (in seconds). -- interrupts: interrupt number to the CPU. -- atmel,watchdog-type: should be "hardware" or "software". - "hardware": enable watchdog fault reset. A watchdog fault triggers - watchdog reset. - "software": enable watchdog fault interrupt. A watchdog fault asserts - watchdog interrupt. -- atmel,idle-halt: present if you want to stop the watchdog when the CPU is - in idle state. - CAUTION: This property should be used with care, it actually makes the - watchdog not counting when the CPU is in idle state, therefore the - watchdog reset time depends on mean CPU usage and will not reset at all - if the CPU stop working while it is in idle state, which is probably - not what you want. -- atmel,dbg-halt: present if you want to stop the watchdog when the CPU is - in debug state. - -Example: - watchdog@fc068640 { - compatible = "atmel,sama5d4-wdt"; - reg = <0xfc068640 0x10>; - interrupts = <4 IRQ_TYPE_LEVEL_HIGH 5>; - timeout-sec = <10>; - atmel,watchdog-type = "hardware"; - atmel,dbg-halt; - atmel,idle-halt; - }; From 5ae233fba8edee84fdd70e72a69bb7a41a273194 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 27 May 2021 13:01:19 +0300 Subject: [PATCH 50/56] watchdog: sama5d4_wdt: add support for sama7g5-wdt Add support for compatible sama7g5-wdt. The sama7g5 wdt is the same hardware block as on sam9x60. Adapt the driver to use the sam9x60/sama7g5 variant if either of the two compatibles are selected (sam9x60-wdt/sama7g5-wdt). Signed-off-by: Eugen Hristev Acked-by: Nicolas Ferre Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210527100120.266796-2-eugen.hristev@microchip.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/sama5d4_wdt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/watchdog/sama5d4_wdt.c b/drivers/watchdog/sama5d4_wdt.c index e5d11d6a2600..ec20ad4e534f 100644 --- a/drivers/watchdog/sama5d4_wdt.c +++ b/drivers/watchdog/sama5d4_wdt.c @@ -268,8 +268,10 @@ static int sama5d4_wdt_probe(struct platform_device *pdev) wdd->min_timeout = MIN_WDT_TIMEOUT; wdd->max_timeout = MAX_WDT_TIMEOUT; wdt->last_ping = jiffies; - wdt->sam9x60_support = of_device_is_compatible(dev->of_node, - "microchip,sam9x60-wdt"); + + if (of_device_is_compatible(dev->of_node, "microchip,sam9x60-wdt") || + of_device_is_compatible(dev->of_node, "microchip,sama7g5-wdt")) + wdt->sam9x60_support = true; watchdog_set_drvdata(wdd, wdt); @@ -329,6 +331,10 @@ static const struct of_device_id sama5d4_wdt_of_match[] = { { .compatible = "microchip,sam9x60-wdt", }, + { + .compatible = "microchip,sama7g5-wdt", + }, + { } }; MODULE_DEVICE_TABLE(of, sama5d4_wdt_of_match); From 12dbbf085fa1a78b6cafb02cf0f40b21160206e7 Mon Sep 17 00:00:00 2001 From: Eugen Hristev Date: Thu, 27 May 2021 13:01:20 +0300 Subject: [PATCH 51/56] dt-bindings: watchdog: sama5d4-wdt: add compatible for sama7g5-wdt This driver is also compatible with the watchdog on sama7g5 SoC. Add the corresponding compatible string to the binding. Signed-off-by: Eugen Hristev Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210527100120.266796-3-eugen.hristev@microchip.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml b/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml index 0d0ab81da040..9856cd76c28d 100644 --- a/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/atmel,sama5d4-wdt.yaml @@ -17,6 +17,7 @@ properties: enum: - atmel,sama5d4-wdt - microchip,sam9x60-wdt + - microchip,sama7g5-wdt reg: maxItems: 1 From 5b606ae892e3194c5ef42dece094306a14cf9e94 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 7 Jun 2021 14:40:22 -0500 Subject: [PATCH 52/56] dt-bindings: watchdog: Convert arm,sbsa-gwdt to DT schema Convert the arm,sbsa-gwdt binding to DT schema format. Cc: Wim Van Sebroeck Cc: Guenter Roeck Cc: Fu Wei Cc: linux-watchdog@vger.kernel.org Signed-off-by: Rob Herring Acked-by: Guenter Roeck Link: https://lore.kernel.org/r/20210607194022.3095736-1-robh@kernel.org Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/arm,sbsa-gwdt.yaml | 51 +++++++++++++++++++ .../bindings/watchdog/sbsa-gwdt.txt | 31 ----------- 2 files changed, 51 insertions(+), 31 deletions(-) create mode 100644 Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml delete mode 100644 Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt diff --git a/Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml b/Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml new file mode 100644 index 000000000000..6bfa46353c4e --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/arm,sbsa-gwdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: SBSA (Server Base System Architecture) Generic Watchdog + +maintainers: + - Fu Wei + +description: | + The SBSA Generic Watchdog Timer is used to force a reset of the system after + two stages of timeout have elapsed. A detailed definition of the watchdog + timer can be found in the ARM document: ARM-DEN-0029 - Server Base System + Architecture (SBSA) + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + const: arm,sbsa-gwdt + + reg: + items: + - description: Watchdog control frame + - description: Refresh frame + + interrupts: + description: The Watchdog Signal 0 (WS0) SPI (Shared Peripheral Interrupt) + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + + watchdog@2a440000 { + compatible = "arm,sbsa-gwdt"; + reg = <0x2a440000 0x1000>, + <0x2a450000 0x1000>; + interrupts = <0 27 4>; + timeout-sec = <30>; + }; +... diff --git a/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt b/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt deleted file mode 100644 index 6f2d5f91964d..000000000000 --- a/Documentation/devicetree/bindings/watchdog/sbsa-gwdt.txt +++ /dev/null @@ -1,31 +0,0 @@ -* SBSA (Server Base System Architecture) Generic Watchdog - -The SBSA Generic Watchdog Timer is used to force a reset of the system -after two stages of timeout have elapsed. A detailed definition of the -watchdog timer can be found in the ARM document: ARM-DEN-0029 - Server -Base System Architecture (SBSA) - -Required properties: -- compatible: Should at least contain "arm,sbsa-gwdt". - -- reg: Each entry specifies the base physical address of a register frame - and the length of that frame; currently, two frames must be defined, - in this order: - 1: Watchdog control frame; - 2: Refresh frame. - -- interrupts: Should contain the Watchdog Signal 0 (WS0) SPI (Shared - Peripheral Interrupt) number of SBSA Generic Watchdog. - -Optional properties -- timeout-sec: Watchdog timeout values (in seconds). - -Example for FVP Foundation Model v8: - -watchdog@2a440000 { - compatible = "arm,sbsa-gwdt"; - reg = <0x0 0x2a440000 0 0x1000>, - <0x0 0x2a450000 0 0x1000>; - interrupts = <0 27 4>; - timeout-sec = <30>; -}; From cb011044e34c293e139570ce5c01aed66a34345c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sun, 30 May 2021 13:24:23 +0200 Subject: [PATCH 53/56] watchdog: iTCO_wdt: Account for rebooting on second timeout This was already attempted to fix via 1fccb73011ea: If the BIOS did not enable TCO SMIs, the timer definitely needs to trigger twice in order to cause a reboot. If TCO SMIs are on, as well as SMIs in general, we can continue to assume that the BIOS will perform a reboot on the first timeout. QEMU with its ICH9 and related BIOS falls into the former category, currently taking twice the configured timeout in order to reboot the machine. For iTCO version that fall under turn_SMI_watchdog_clear_off, this is also true and was currently only addressed for v1, irrespective of the turn_SMI_watchdog_clear_off value. Signed-off-by: Jan Kiszka Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/0b8bb307-d08b-41b5-696c-305cdac6789c@siemens.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index bf31d7b67a69..3f1324871cfd 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -71,6 +71,8 @@ #define TCOBASE(p) ((p)->tco_res->start) /* SMI Control and Enable Register */ #define SMI_EN(p) ((p)->smi_res->start) +#define TCO_EN (1 << 13) +#define GBL_SMI_EN (1 << 0) #define TCO_RLD(p) (TCOBASE(p) + 0x00) /* TCO Timer Reload/Curr. Value */ #define TCOv1_TMR(p) (TCOBASE(p) + 0x01) /* TCOv1 Timer Initial Value*/ @@ -355,8 +357,12 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t) tmrval = seconds_to_ticks(p, t); - /* For TCO v1 the timer counts down twice before rebooting */ - if (p->iTCO_version == 1) + /* + * If TCO SMIs are off, the timer counts down twice before rebooting. + * Otherwise, the BIOS generally reboots when the SMI triggers. + */ + if (p->smi_res && + (SMI_EN(p) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN)) tmrval /= 2; /* from the specs: */ @@ -521,7 +527,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) * Disables TCO logic generating an SMI# */ val32 = inl(SMI_EN(p)); - val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ + val32 &= ~TCO_EN; /* Turn off SMI clearing watchdog */ outl(val32, SMI_EN(p)); } From 3e5fcb022addc4f1d32b2ca2676f0541b556512c Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Fri, 11 Jun 2021 22:07:59 +0200 Subject: [PATCH 54/56] dt-bindings: watchdog: Add Mstar MSC313e WDT devicetree bindings documentation This adds the documentation for the devicetree bindings of the Mstar MSC313e watchdog driver, found from MSC313e SoCs and newer. Signed-off-by: Romain Perier Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210611200801.52139-2-romain.perier@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- .../bindings/watchdog/mstar,msc313e-wdt.yaml | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Documentation/devicetree/bindings/watchdog/mstar,msc313e-wdt.yaml diff --git a/Documentation/devicetree/bindings/watchdog/mstar,msc313e-wdt.yaml b/Documentation/devicetree/bindings/watchdog/mstar,msc313e-wdt.yaml new file mode 100644 index 000000000000..e3e8b86dbf63 --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/mstar,msc313e-wdt.yaml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/mstar,msc313e-wdt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MStar Watchdog Device Tree Bindings + +maintainers: + - Daniel Palmer + - Romain Perier + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + enum: + - mstar,msc313e-wdt + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - compatible + - clocks + - reg + +unevaluatedProperties: false + +examples: + - | + watchdog@6000 { + compatible = "mstar,msc313e-wdt"; + reg = <0x6000 0x1f>; + clocks = <&xtal_div2>; + }; From e9800b7994642a794afd4894f072541c14277ce8 Mon Sep 17 00:00:00 2001 From: Daniel Palmer Date: Sat, 5 Jun 2021 19:04:40 +0200 Subject: [PATCH 55/56] watchdog: Add Mstar MSC313e WDT driver It adds a driver for the IP block handling the watchdog timer found for Mstar MSC313e SoCs and newer. Signed-off-by: Daniel Palmer Co-developed-by: Romain Perier Signed-off-by: Romain Perier Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210611200801.52139-3-romain.perier@gmail.com Signed-off-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck --- MAINTAINERS | 1 + drivers/watchdog/Kconfig | 12 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/msc313e_wdt.c | 166 +++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 drivers/watchdog/msc313e_wdt.c diff --git a/MAINTAINERS b/MAINTAINERS index 81e1edeceae4..a69362442310 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2175,6 +2175,7 @@ F: arch/arm/boot/dts/mstar-* F: arch/arm/mach-mstar/ F: drivers/clk/mstar/ F: drivers/gpio/gpio-msc313.c +F: drivers/watchdog/msc313e_wdt.c F: include/dt-bindings/clock/mstar-* F: include/dt-bindings/gpio/msc313-gpio.h diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 7a33e6a6ac23..546dfc1e2349 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -989,6 +989,18 @@ config VISCONTI_WATCHDOG Say Y here to include support for the watchdog timer in Toshiba Visconti SoCs. +config MSC313E_WATCHDOG + tristate "MStar MSC313e watchdog" + depends on ARCH_MSTARV7 || COMPILE_TEST + select WATCHDOG_CORE + help + Say Y here to include support for the Watchdog timer embedded + into MStar MSC313e chips. This will reboot your system when the + timeout is reached. + + To compile this driver as a module, choose M here: the + module will be called msc313e_wdt. + # X86 (i386 + ia64 + x86_64) Architecture config ACQUIRE_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 0b4d828872be..abaf2ebd814e 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -93,6 +93,7 @@ obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o +obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o # X86 (i386 + ia64 + x86_64) Architecture obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o diff --git a/drivers/watchdog/msc313e_wdt.c b/drivers/watchdog/msc313e_wdt.c new file mode 100644 index 000000000000..0d497aa0fb7d --- /dev/null +++ b/drivers/watchdog/msc313e_wdt.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MStar WDT driver + * + * Copyright (C) 2019 - 2021 Daniel Palmer + * Copyright (C) 2021 Romain Perier + * + */ + +#include +#include +#include +#include +#include +#include + +#define REG_WDT_CLR 0x0 +#define REG_WDT_MAX_PRD_L 0x10 +#define REG_WDT_MAX_PRD_H 0x14 + +#define MSC313E_WDT_MIN_TIMEOUT 1 +#define MSC313E_WDT_DEFAULT_TIMEOUT 30 + +static unsigned int timeout; + +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds"); + +struct msc313e_wdt_priv { + void __iomem *base; + struct watchdog_device wdev; + struct clk *clk; +}; + +static int msc313e_wdt_start(struct watchdog_device *wdev) +{ + struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev); + u32 timeout; + int err; + + err = clk_prepare_enable(priv->clk); + if (err) + return err; + + timeout = wdev->timeout * clk_get_rate(priv->clk); + writew(timeout & 0xffff, priv->base + REG_WDT_MAX_PRD_L); + writew((timeout >> 16) & 0xffff, priv->base + REG_WDT_MAX_PRD_H); + writew(1, priv->base + REG_WDT_CLR); + return 0; +} + +static int msc313e_wdt_ping(struct watchdog_device *wdev) +{ + struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev); + + writew(1, priv->base + REG_WDT_CLR); + return 0; +} + +static int msc313e_wdt_stop(struct watchdog_device *wdev) +{ + struct msc313e_wdt_priv *priv = watchdog_get_drvdata(wdev); + + writew(0, priv->base + REG_WDT_MAX_PRD_L); + writew(0, priv->base + REG_WDT_MAX_PRD_H); + writew(0, priv->base + REG_WDT_CLR); + clk_disable_unprepare(priv->clk); + return 0; +} + +static int msc313e_wdt_settimeout(struct watchdog_device *wdev, unsigned int new_time) +{ + wdev->timeout = new_time; + + return msc313e_wdt_start(wdev); +} + +static const struct watchdog_info msc313e_wdt_ident = { + .identity = "MSC313e watchdog", + .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, +}; + +static const struct watchdog_ops msc313e_wdt_ops = { + .owner = THIS_MODULE, + .start = msc313e_wdt_start, + .stop = msc313e_wdt_stop, + .ping = msc313e_wdt_ping, + .set_timeout = msc313e_wdt_settimeout, +}; + +static const struct of_device_id msc313e_wdt_of_match[] = { + { .compatible = "mstar,msc313e-wdt", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, msc313e_wdt_of_match); + +static int msc313e_wdt_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct msc313e_wdt_priv *priv; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "No input clock\n"); + return PTR_ERR(priv->clk); + } + + priv->wdev.info = &msc313e_wdt_ident, + priv->wdev.ops = &msc313e_wdt_ops, + priv->wdev.parent = dev; + priv->wdev.min_timeout = MSC313E_WDT_MIN_TIMEOUT; + priv->wdev.max_timeout = U32_MAX / clk_get_rate(priv->clk); + priv->wdev.timeout = MSC313E_WDT_DEFAULT_TIMEOUT; + + watchdog_set_drvdata(&priv->wdev, priv); + + watchdog_init_timeout(&priv->wdev, timeout, dev); + watchdog_stop_on_reboot(&priv->wdev); + watchdog_stop_on_unregister(&priv->wdev); + + return devm_watchdog_register_device(dev, &priv->wdev); +} + +static int __maybe_unused msc313e_wdt_suspend(struct device *dev) +{ + struct msc313e_wdt_priv *priv = dev_get_drvdata(dev); + + if (watchdog_active(&priv->wdev)) + msc313e_wdt_stop(&priv->wdev); + + return 0; +} + +static int __maybe_unused msc313e_wdt_resume(struct device *dev) +{ + struct msc313e_wdt_priv *priv = dev_get_drvdata(dev); + + if (watchdog_active(&priv->wdev)) + msc313e_wdt_start(&priv->wdev); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(msc313e_wdt_pm_ops, msc313e_wdt_suspend, msc313e_wdt_resume); + +static struct platform_driver msc313e_wdt_driver = { + .driver = { + .name = "msc313e-wdt", + .of_match_table = msc313e_wdt_of_match, + .pm = &msc313e_wdt_pm_ops, + }, + .probe = msc313e_wdt_probe, +}; +module_platform_driver(msc313e_wdt_driver); + +MODULE_AUTHOR("Daniel Palmer "); +MODULE_DESCRIPTION("Watchdog driver for MStar MSC313e"); +MODULE_LICENSE("GPL v2"); From cf813c67d9619fd474c785698cbed543b94209dd Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Wed, 16 Jun 2021 20:17:08 +0200 Subject: [PATCH 56/56] watchdog: iTCO_wdt: use dev_err() instead of pr_err() Use dev_err() instead of pr_err(), so device name is also shown in the log. Signed-off-by: Enrico Weigelt, metux IT consult Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20210616181708.19530-2-info@metux.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 3f1324871cfd..b3f604669e2c 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -485,13 +485,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev) if (!devm_request_region(dev, p->smi_res->start, resource_size(p->smi_res), pdev->name)) { - pr_err("I/O address 0x%04llx already in use, device disabled\n", + dev_err(dev, "I/O address 0x%04llx already in use, device disabled\n", (u64)SMI_EN(p)); return -EBUSY; } } else if (iTCO_vendorsupport || turn_SMI_watchdog_clear_off >= p->iTCO_version) { - pr_err("SMI I/O resource is missing\n"); + dev_err(dev, "SMI I/O resource is missing\n"); return -ENODEV; }