Lines Matching refs:dw_wdt
83 struct dw_wdt { struct
101 #define to_dw_wdt(wdd) container_of(wdd, struct dw_wdt, wdd) argument
103 static inline int dw_wdt_is_enabled(struct dw_wdt *dw_wdt) in dw_wdt_is_enabled() argument
105 return readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET) & in dw_wdt_is_enabled()
109 static void dw_wdt_update_mode(struct dw_wdt *dw_wdt, enum dw_wdt_rmod rmod) in dw_wdt_update_mode() argument
113 val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); in dw_wdt_update_mode()
118 writel(val, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); in dw_wdt_update_mode()
120 dw_wdt->rmod = rmod; in dw_wdt_update_mode()
123 static unsigned int dw_wdt_find_best_top(struct dw_wdt *dw_wdt, in dw_wdt_find_best_top() argument
134 if (dw_wdt->timeouts[idx].sec >= timeout) in dw_wdt_find_best_top()
141 *top_val = dw_wdt->timeouts[idx].top_val; in dw_wdt_find_best_top()
143 return dw_wdt->timeouts[idx].sec; in dw_wdt_find_best_top()
146 static unsigned int dw_wdt_get_min_timeout(struct dw_wdt *dw_wdt) in dw_wdt_get_min_timeout() argument
155 if (dw_wdt->timeouts[idx].sec) in dw_wdt_get_min_timeout()
159 return dw_wdt->timeouts[idx].sec; in dw_wdt_get_min_timeout()
162 static unsigned int dw_wdt_get_max_timeout_ms(struct dw_wdt *dw_wdt) in dw_wdt_get_max_timeout_ms() argument
164 struct dw_wdt_timeout *timeout = &dw_wdt->timeouts[DW_WDT_NUM_TOPS - 1]; in dw_wdt_get_max_timeout_ms()
172 static unsigned int dw_wdt_get_timeout(struct dw_wdt *dw_wdt) in dw_wdt_get_timeout() argument
174 int top_val = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET) & 0xF; in dw_wdt_get_timeout()
178 if (dw_wdt->timeouts[idx].top_val == top_val) in dw_wdt_get_timeout()
186 return dw_wdt->timeouts[idx].sec * dw_wdt->rmod; in dw_wdt_get_timeout()
191 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); in dw_wdt_ping() local
193 writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt->regs + in dw_wdt_ping()
201 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); in dw_wdt_set_timeout() local
213 timeout = dw_wdt_find_best_top(dw_wdt, DIV_ROUND_UP(top_s, dw_wdt->rmod), in dw_wdt_set_timeout()
215 if (dw_wdt->rmod == DW_WDT_RMOD_IRQ) in dw_wdt_set_timeout()
227 dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); in dw_wdt_set_timeout()
239 wdd->timeout = timeout * dw_wdt->rmod; in dw_wdt_set_timeout()
248 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); in dw_wdt_set_pretimeout() local
255 dw_wdt_update_mode(dw_wdt, req ? DW_WDT_RMOD_IRQ : DW_WDT_RMOD_RESET); in dw_wdt_set_pretimeout()
261 static void dw_wdt_arm_system_reset(struct dw_wdt *dw_wdt) in dw_wdt_arm_system_reset() argument
263 u32 val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); in dw_wdt_arm_system_reset()
266 if (dw_wdt->rmod == DW_WDT_RMOD_IRQ) in dw_wdt_arm_system_reset()
272 writel(val, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); in dw_wdt_arm_system_reset()
277 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); in dw_wdt_start() local
280 dw_wdt_ping(&dw_wdt->wdd); in dw_wdt_start()
281 dw_wdt_arm_system_reset(dw_wdt); in dw_wdt_start()
288 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); in dw_wdt_stop() local
290 if (!dw_wdt->rst) { in dw_wdt_stop()
295 reset_control_assert(dw_wdt->rst); in dw_wdt_stop()
296 reset_control_deassert(dw_wdt->rst); in dw_wdt_stop()
304 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); in dw_wdt_restart() local
306 writel(0, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); in dw_wdt_restart()
307 dw_wdt_update_mode(dw_wdt, DW_WDT_RMOD_RESET); in dw_wdt_restart()
308 if (dw_wdt_is_enabled(dw_wdt)) in dw_wdt_restart()
310 dw_wdt->regs + WDOG_COUNTER_RESTART_REG_OFFSET); in dw_wdt_restart()
312 dw_wdt_arm_system_reset(dw_wdt); in dw_wdt_restart()
322 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); in dw_wdt_get_timeleft() local
326 val = readl(dw_wdt->regs + WDOG_CURRENT_COUNT_REG_OFFSET); in dw_wdt_get_timeleft()
327 sec = val / dw_wdt->rate; in dw_wdt_get_timeleft()
329 if (dw_wdt->rmod == DW_WDT_RMOD_IRQ) { in dw_wdt_get_timeleft()
330 val = readl(dw_wdt->regs + WDOG_INTERRUPT_STATUS_REG_OFFSET); in dw_wdt_get_timeleft()
363 struct dw_wdt *dw_wdt = devid; in dw_wdt_irq() local
370 val = readl(dw_wdt->regs + WDOG_INTERRUPT_STATUS_REG_OFFSET); in dw_wdt_irq()
374 watchdog_notify_pretimeout(&dw_wdt->wdd); in dw_wdt_irq()
382 struct dw_wdt *dw_wdt = dev_get_drvdata(dev); in dw_wdt_suspend() local
384 dw_wdt->control = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); in dw_wdt_suspend()
385 dw_wdt->timeout = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); in dw_wdt_suspend()
387 clk_disable_unprepare(dw_wdt->pclk); in dw_wdt_suspend()
388 clk_disable_unprepare(dw_wdt->clk); in dw_wdt_suspend()
395 struct dw_wdt *dw_wdt = dev_get_drvdata(dev); in dw_wdt_resume() local
396 int err = clk_prepare_enable(dw_wdt->clk); in dw_wdt_resume()
401 err = clk_prepare_enable(dw_wdt->pclk); in dw_wdt_resume()
403 clk_disable_unprepare(dw_wdt->clk); in dw_wdt_resume()
407 writel(dw_wdt->timeout, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); in dw_wdt_resume()
408 writel(dw_wdt->control, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); in dw_wdt_resume()
410 dw_wdt_ping(&dw_wdt->wdd); in dw_wdt_resume()
426 static void dw_wdt_handle_tops(struct dw_wdt *dw_wdt, const u32 *tops) in dw_wdt_handle_tops() argument
440 tout.sec = tops[val] / dw_wdt->rate; in dw_wdt_handle_tops()
442 do_div(msec, dw_wdt->rate); in dw_wdt_handle_tops()
450 dst = &dw_wdt->timeouts[tidx]; in dw_wdt_handle_tops()
458 dw_wdt->timeouts[val] = tout; in dw_wdt_handle_tops()
462 static int dw_wdt_init_timeouts(struct dw_wdt *dw_wdt, struct device *dev) in dw_wdt_init_timeouts() argument
473 data = readl(dw_wdt->regs + WDOG_COMP_PARAMS_1_REG_OFFSET); in dw_wdt_init_timeouts()
489 dw_wdt_handle_tops(dw_wdt, tops); in dw_wdt_init_timeouts()
490 if (!dw_wdt->timeouts[DW_WDT_NUM_TOPS - 1].sec) { in dw_wdt_init_timeouts()
521 static void dw_wdt_dbgfs_init(struct dw_wdt *dw_wdt) in dw_wdt_dbgfs_init() argument
523 struct device *dev = dw_wdt->wdd.parent; in dw_wdt_dbgfs_init()
532 regset->base = dw_wdt->regs; in dw_wdt_dbgfs_init()
534 dw_wdt->dbgfs_dir = debugfs_create_dir(dev_name(dev), NULL); in dw_wdt_dbgfs_init()
536 debugfs_create_regset32("registers", 0444, dw_wdt->dbgfs_dir, regset); in dw_wdt_dbgfs_init()
539 static void dw_wdt_dbgfs_clear(struct dw_wdt *dw_wdt) in dw_wdt_dbgfs_clear() argument
541 debugfs_remove_recursive(dw_wdt->dbgfs_dir); in dw_wdt_dbgfs_clear()
546 static void dw_wdt_dbgfs_init(struct dw_wdt *dw_wdt) {} in dw_wdt_dbgfs_init() argument
547 static void dw_wdt_dbgfs_clear(struct dw_wdt *dw_wdt) {} in dw_wdt_dbgfs_clear() argument
555 struct dw_wdt *dw_wdt; in dw_wdt_drv_probe() local
558 dw_wdt = devm_kzalloc(dev, sizeof(*dw_wdt), GFP_KERNEL); in dw_wdt_drv_probe()
559 if (!dw_wdt) in dw_wdt_drv_probe()
562 dw_wdt->regs = devm_platform_ioremap_resource(pdev, 0); in dw_wdt_drv_probe()
563 if (IS_ERR(dw_wdt->regs)) in dw_wdt_drv_probe()
564 return PTR_ERR(dw_wdt->regs); in dw_wdt_drv_probe()
572 dw_wdt->clk = devm_clk_get(dev, "tclk"); in dw_wdt_drv_probe()
573 if (IS_ERR(dw_wdt->clk)) { in dw_wdt_drv_probe()
574 dw_wdt->clk = devm_clk_get(dev, NULL); in dw_wdt_drv_probe()
575 if (IS_ERR(dw_wdt->clk)) in dw_wdt_drv_probe()
576 return PTR_ERR(dw_wdt->clk); in dw_wdt_drv_probe()
579 ret = clk_prepare_enable(dw_wdt->clk); in dw_wdt_drv_probe()
583 dw_wdt->rate = clk_get_rate(dw_wdt->clk); in dw_wdt_drv_probe()
584 if (dw_wdt->rate == 0) { in dw_wdt_drv_probe()
596 dw_wdt->pclk = devm_clk_get_optional(dev, "pclk"); in dw_wdt_drv_probe()
597 if (IS_ERR(dw_wdt->pclk)) { in dw_wdt_drv_probe()
598 ret = PTR_ERR(dw_wdt->pclk); in dw_wdt_drv_probe()
602 ret = clk_prepare_enable(dw_wdt->pclk); in dw_wdt_drv_probe()
606 dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); in dw_wdt_drv_probe()
607 if (IS_ERR(dw_wdt->rst)) { in dw_wdt_drv_probe()
608 ret = PTR_ERR(dw_wdt->rst); in dw_wdt_drv_probe()
613 dw_wdt_update_mode(dw_wdt, DW_WDT_RMOD_RESET); in dw_wdt_drv_probe()
625 pdev->name, dw_wdt); in dw_wdt_drv_probe()
629 dw_wdt->wdd.info = &dw_wdt_pt_ident; in dw_wdt_drv_probe()
634 dw_wdt->wdd.info = &dw_wdt_ident; in dw_wdt_drv_probe()
637 reset_control_deassert(dw_wdt->rst); in dw_wdt_drv_probe()
639 ret = dw_wdt_init_timeouts(dw_wdt, dev); in dw_wdt_drv_probe()
643 wdd = &dw_wdt->wdd; in dw_wdt_drv_probe()
645 wdd->min_timeout = dw_wdt_get_min_timeout(dw_wdt); in dw_wdt_drv_probe()
646 wdd->max_hw_heartbeat_ms = dw_wdt_get_max_timeout_ms(dw_wdt); in dw_wdt_drv_probe()
649 watchdog_set_drvdata(wdd, dw_wdt); in dw_wdt_drv_probe()
658 if (dw_wdt_is_enabled(dw_wdt)) { in dw_wdt_drv_probe()
659 wdd->timeout = dw_wdt_get_timeout(dw_wdt); in dw_wdt_drv_probe()
666 platform_set_drvdata(pdev, dw_wdt); in dw_wdt_drv_probe()
674 dw_wdt_dbgfs_init(dw_wdt); in dw_wdt_drv_probe()
679 clk_disable_unprepare(dw_wdt->pclk); in dw_wdt_drv_probe()
682 clk_disable_unprepare(dw_wdt->clk); in dw_wdt_drv_probe()
688 struct dw_wdt *dw_wdt = platform_get_drvdata(pdev); in dw_wdt_drv_remove() local
690 dw_wdt_dbgfs_clear(dw_wdt); in dw_wdt_drv_remove()
692 watchdog_unregister_device(&dw_wdt->wdd); in dw_wdt_drv_remove()
693 reset_control_assert(dw_wdt->rst); in dw_wdt_drv_remove()
694 clk_disable_unprepare(dw_wdt->pclk); in dw_wdt_drv_remove()
695 clk_disable_unprepare(dw_wdt->clk); in dw_wdt_drv_remove()