diff options
Diffstat (limited to 'drivers/watchdog/keembay_wdt.c')
-rw-r--r-- | drivers/watchdog/keembay_wdt.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/watchdog/keembay_wdt.c b/drivers/watchdog/keembay_wdt.c index 547d3fea33ff..2a39114dbc64 100644 --- a/drivers/watchdog/keembay_wdt.c +++ b/drivers/watchdog/keembay_wdt.c @@ -23,12 +23,19 @@ #define TIM_WDOG_EN 0x8 #define TIM_SAFE 0xc -#define WDT_ISR_MASK GENMASK(9, 8) -#define WDT_ISR_CLEAR 0x8200ff18 +#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 static unsigned int timeout = WDT_TIMEOUT; module_param(timeout, int, 0); @@ -82,8 +89,7 @@ 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); + keembay_wdt_writel(wdt, TIM_WDOG_EN, WDT_ENABLE); return 0; } @@ -92,7 +98,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; } @@ -108,6 +114,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; } @@ -139,9 +146,8 @@ 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_ISR_MASK, 0, 0, 0, 0, 0, 0, &res); - dev_crit(wdt->wdd.parent, "Intel Keem Bay non-sec wdt timeout.\n"); + 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-secure wdt timeout.\n"); emergency_restart(); return IRQ_HANDLED; @@ -152,8 +158,10 @@ static irqreturn_t keembay_wdt_th_isr(int irq, void *dev_id) struct keembay_wdt *wdt = dev_id; struct arm_smccc_res res; - 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"); + 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-secure wdt pre-timeout.\n"); watchdog_notify_pretimeout(&wdt->wdd); return IRQ_HANDLED; @@ -224,11 +232,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) @@ -271,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, |