Lines Matching +full:watchdog +full:- +full:enable

1 // SPDX-License-Identifier: GPL-2.0
3 * Starfive Watchdog driver
15 #include <linux/watchdog.h>
17 /* JH7100 Watchdog register define */
31 /* JH7110 Watchdog register define */
35 * [0]: reset enable;
36 * [1]: interrupt enable && watchdog enable
56 #define STARFIVE_WDT_JH7100_INTCLR_AVA_SHIFT 1 /* Watchdog can clear interrupt when 0 */
74 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (default="
77 "Watchdog is started at boot time if set to 1, default="
79 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
83 unsigned int control; /* Watchdog Control Resgister for reset enable */
84 unsigned int load; /* Watchdog Load register */
85 unsigned int reload; /* Watchdog Reload Control register */
86 unsigned int enable; /* Watchdog Enable Register */ member
87 unsigned int value; /* Watchdog Counter Value Register */
88 unsigned int int_clr; /* Watchdog Interrupt Clear Register */
89 unsigned int unlock; /* Watchdog Lock Register */
90 unsigned int int_status; /* Watchdog Interrupt Status Register */
97 bool double_timeout; /* The watchdog need twice timeout to reboot */
117 .enable = STARFIVE_WDT_JH7100_EN,
134 .enable = STARFIVE_WDT_JH7110_CONTROL,
150 ret = clk_prepare_enable(wdt->apb_clk); in starfive_wdt_enable_clock()
152 return dev_err_probe(wdt->wdd.parent, ret, "failed to enable apb clock\n"); in starfive_wdt_enable_clock()
154 ret = clk_prepare_enable(wdt->core_clk); in starfive_wdt_enable_clock()
156 clk_disable_unprepare(wdt->apb_clk); in starfive_wdt_enable_clock()
157 return dev_err_probe(wdt->wdd.parent, ret, "failed to enable core clock\n"); in starfive_wdt_enable_clock()
165 clk_disable_unprepare(wdt->core_clk); in starfive_wdt_disable_clock()
166 clk_disable_unprepare(wdt->apb_clk); in starfive_wdt_disable_clock()
171 struct device *dev = wdt->wdd.parent; in starfive_wdt_get_clock()
173 wdt->apb_clk = devm_clk_get(dev, "apb"); in starfive_wdt_get_clock()
174 if (IS_ERR(wdt->apb_clk)) in starfive_wdt_get_clock()
175 return dev_err_probe(dev, PTR_ERR(wdt->apb_clk), "failed to get apb clock\n"); in starfive_wdt_get_clock()
177 wdt->core_clk = devm_clk_get(dev, "core"); in starfive_wdt_get_clock()
178 if (IS_ERR(wdt->core_clk)) in starfive_wdt_get_clock()
179 return dev_err_probe(dev, PTR_ERR(wdt->core_clk), "failed to get core clock\n"); in starfive_wdt_get_clock()
202 return DIV_ROUND_CLOSEST(ticks, wdt->freq); in starfive_wdt_ticks_to_sec()
205 /* Write unlock-key to unlock. Write other value to lock. */
207 __acquires(&wdt->lock) in starfive_wdt_unlock()
209 spin_lock(&wdt->lock); in starfive_wdt_unlock()
210 writel(wdt->variant->unlock_key, wdt->base + wdt->variant->unlock); in starfive_wdt_unlock()
214 __releases(&wdt->lock) in starfive_wdt_lock()
216 writel(~wdt->variant->unlock_key, wdt->base + wdt->variant->unlock); in starfive_wdt_lock()
217 spin_unlock(&wdt->lock); in starfive_wdt_lock()
220 /* enable watchdog interrupt to reset/reboot */
225 val = readl(wdt->base + wdt->variant->control); in starfive_wdt_enable_reset()
226 val |= STARFIVE_WDT_RESET_EN << wdt->variant->enrst_shift; in starfive_wdt_enable_reset()
227 writel(val, wdt->base + wdt->variant->control); in starfive_wdt_enable_reset()
233 return !!readl(wdt->base + wdt->variant->int_status); in starfive_wdt_raise_irq_status()
241 return readl_poll_timeout_atomic(wdt->base + wdt->variant->int_clr, value, in starfive_wdt_wait_int_free()
242 !(value & BIT(wdt->variant->intclr_ava_shift)), in starfive_wdt_wait_int_free()
251 if (wdt->variant->intclr_check) { in starfive_wdt_int_clr()
254 return dev_err_probe(wdt->wdd.parent, ret, in starfive_wdt_int_clr()
255 "watchdog is not ready to clear interrupt.\n"); in starfive_wdt_int_clr()
257 writel(STARFIVE_WDT_INTCLR, wdt->base + wdt->variant->int_clr); in starfive_wdt_int_clr()
264 writel(val, wdt->base + wdt->variant->load); in starfive_wdt_set_count()
269 return readl(wdt->base + wdt->variant->value); in starfive_wdt_get_count()
272 /* enable watchdog */
277 val = readl(wdt->base + wdt->variant->enable); in starfive_wdt_enable()
278 val |= STARFIVE_WDT_ENABLE << wdt->variant->en_shift; in starfive_wdt_enable()
279 writel(val, wdt->base + wdt->variant->enable); in starfive_wdt_enable()
282 /* disable watchdog */
287 val = readl(wdt->base + wdt->variant->enable); in starfive_wdt_disable()
288 val &= ~(STARFIVE_WDT_ENABLE << wdt->variant->en_shift); in starfive_wdt_disable()
289 writel(val, wdt->base + wdt->variant->enable); in starfive_wdt_disable()
297 if (wdt->variant->reload) in starfive_wdt_set_reload_count()
298 writel(0x1, wdt->base + wdt->variant->reload); in starfive_wdt_set_reload_count()
303 if (wdt->variant->double_timeout) in starfive_wdt_max_timeout()
304 return DIV_ROUND_UP(STARFIVE_WDT_MAXCNT, (wdt->freq / 2)) - 1; in starfive_wdt_max_timeout()
306 return DIV_ROUND_UP(STARFIVE_WDT_MAXCNT, wdt->freq) - 1; in starfive_wdt_max_timeout()
315 * If the watchdog takes twice timeout and set half count value, in starfive_wdt_get_timeleft()
319 if (wdt->variant->double_timeout && !starfive_wdt_raise_irq_status(wdt)) in starfive_wdt_get_timeleft()
320 count += wdt->count; in starfive_wdt_get_timeleft()
335 starfive_wdt_set_reload_count(wdt, wdt->count); in starfive_wdt_keepalive()
348 /* disable watchdog, to be safe */ in starfive_wdt_start()
356 starfive_wdt_set_count(wdt, wdt->count); in starfive_wdt_start()
374 int ret = pm_runtime_get_sync(wdd->parent); in starfive_wdt_pm_start()
387 return pm_runtime_put_sync(wdd->parent); in starfive_wdt_pm_stop()
394 unsigned long count = timeout * wdt->freq; in starfive_wdt_set_timeout()
397 if (wdt->variant->double_timeout) in starfive_wdt_set_timeout()
400 wdt->count = count; in starfive_wdt_set_timeout()
401 wdd->timeout = timeout; in starfive_wdt_set_timeout()
405 starfive_wdt_set_reload_count(wdt, wdt->count); in starfive_wdt_set_timeout()
416 .identity = "StarFive Watchdog",
433 wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL); in starfive_wdt_probe()
435 return -ENOMEM; in starfive_wdt_probe()
437 wdt->base = devm_platform_ioremap_resource(pdev, 0); in starfive_wdt_probe()
438 if (IS_ERR(wdt->base)) in starfive_wdt_probe()
439 return dev_err_probe(&pdev->dev, PTR_ERR(wdt->base), "error mapping registers\n"); in starfive_wdt_probe()
441 wdt->wdd.parent = &pdev->dev; in starfive_wdt_probe()
447 pm_runtime_enable(&pdev->dev); in starfive_wdt_probe()
448 if (pm_runtime_enabled(&pdev->dev)) { in starfive_wdt_probe()
449 ret = pm_runtime_get_sync(&pdev->dev); in starfive_wdt_probe()
459 ret = starfive_wdt_reset_init(&pdev->dev); in starfive_wdt_probe()
463 watchdog_set_drvdata(&wdt->wdd, wdt); in starfive_wdt_probe()
464 wdt->wdd.info = &starfive_wdt_info; in starfive_wdt_probe()
465 wdt->wdd.ops = &starfive_wdt_ops; in starfive_wdt_probe()
466 wdt->variant = of_device_get_match_data(&pdev->dev); in starfive_wdt_probe()
467 spin_lock_init(&wdt->lock); in starfive_wdt_probe()
469 wdt->freq = clk_get_rate(wdt->core_clk); in starfive_wdt_probe()
470 if (!wdt->freq) { in starfive_wdt_probe()
471 dev_err(&pdev->dev, "get clock rate failed.\n"); in starfive_wdt_probe()
472 ret = -EINVAL; in starfive_wdt_probe()
476 wdt->wdd.min_timeout = 1; in starfive_wdt_probe()
477 wdt->wdd.max_timeout = starfive_wdt_max_timeout(wdt); in starfive_wdt_probe()
478 wdt->wdd.timeout = STARFIVE_WDT_DEFAULT_TIME; in starfive_wdt_probe()
479 watchdog_init_timeout(&wdt->wdd, heartbeat, &pdev->dev); in starfive_wdt_probe()
480 starfive_wdt_set_timeout(&wdt->wdd, wdt->wdd.timeout); in starfive_wdt_probe()
482 watchdog_set_nowayout(&wdt->wdd, nowayout); in starfive_wdt_probe()
483 watchdog_stop_on_reboot(&wdt->wdd); in starfive_wdt_probe()
484 watchdog_stop_on_unregister(&wdt->wdd); in starfive_wdt_probe()
490 set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); in starfive_wdt_probe()
495 ret = watchdog_register_device(&wdt->wdd); in starfive_wdt_probe()
500 if (pm_runtime_enabled(&pdev->dev)) { in starfive_wdt_probe()
501 ret = pm_runtime_put_sync(&pdev->dev); in starfive_wdt_probe()
511 pm_runtime_disable(&pdev->dev); in starfive_wdt_probe()
521 watchdog_unregister_device(&wdt->wdd); in starfive_wdt_remove()
523 if (pm_runtime_enabled(&pdev->dev)) in starfive_wdt_remove()
524 pm_runtime_disable(&pdev->dev); in starfive_wdt_remove()
534 starfive_wdt_pm_stop(&wdt->wdd); in starfive_wdt_shutdown()
541 /* Save watchdog state, and turn it off. */ in starfive_wdt_suspend()
542 wdt->reload = starfive_wdt_get_count(wdt); in starfive_wdt_suspend()
560 /* Restore watchdog state. */ in starfive_wdt_resume()
561 starfive_wdt_set_reload_count(wdt, wdt->reload); in starfive_wdt_resume()
564 if (watchdog_active(&wdt->wdd)) in starfive_wdt_resume()
592 { .compatible = "starfive,jh7100-wdt", .data = &starfive_wdt_jh7100_variant },
593 { .compatible = "starfive,jh7110-wdt", .data = &starfive_wdt_jh7110_variant },
603 .name = "starfive-wdt",
612 MODULE_DESCRIPTION("StarFive Watchdog Device Driver");