Lines Matching +full:clk +full:- +full:delay +full:- +full:cycles
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2015-17 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
6 * Copyright (C) 2015-17 Renesas Electronics Corporation
9 #include <linux/clk.h>
10 #include <linux/delay.h>
37 DIV_ROUND_UP((d) * (p)->clk_rate, clk_divs[(p)->cks])
39 /* d is 16 bit, clk_divs 12 bit -> no 32 bit overflow */
40 #define DIV_BY_CLKS_PER_SEC(p, d) ((d) * clk_divs[(p)->cks] / (p)->clk_rate)
54 struct clk *clk; member
64 writel_relaxed(val, priv->base + reg); in rwdt_write()
71 rwdt_write(priv, 65536 - MUL_BY_CLKS_PER_SEC(priv, wdev->timeout), RWTCNT); in rwdt_init_timeout()
76 static void rwdt_wait_cycles(struct rwdt_priv *priv, unsigned int cycles) in rwdt_wait_cycles() argument
78 unsigned int delay; in rwdt_wait_cycles() local
80 delay = DIV_ROUND_UP(cycles * 1000000, priv->clk_rate); in rwdt_wait_cycles()
82 usleep_range(delay, 2 * delay); in rwdt_wait_cycles()
90 pm_runtime_get_sync(wdev->parent); in rwdt_start()
93 val = readb_relaxed(priv->base + RWTCSRA) & ~RWTCSRA_TME; in rwdt_start()
95 /* Delay 2 cycles before setting watchdog counter */ in rwdt_start()
99 rwdt_write(priv, priv->cks, RWTCSRA); in rwdt_start()
102 while (readb_relaxed(priv->base + RWTCSRA) & RWTCSRA_WRFLG) in rwdt_start()
105 rwdt_write(priv, priv->cks | RWTCSRA_TME, RWTCSRA); in rwdt_start()
114 rwdt_write(priv, priv->cks, RWTCSRA); in rwdt_stop()
115 /* Delay 3 cycles before disabling module clock */ in rwdt_stop()
117 pm_runtime_put(wdev->parent); in rwdt_stop()
125 u16 val = readw_relaxed(priv->base + RWTCNT); in rwdt_get_timeleft()
127 return DIV_BY_CLKS_PER_SEC(priv, 65536 - val); in rwdt_get_timeleft()
130 /* needs to be atomic - no RPM, no usleep_range, no scheduling! */
137 clk_prepare_enable(priv->clk); in rwdt_restart()
140 val = readb_relaxed(priv->base + RWTCSRA) & ~RWTCSRA_TME; in rwdt_restart()
142 /* Delay 2 cycles before setting watchdog counter */ in rwdt_restart()
143 udelay(DIV_ROUND_UP(2 * 1000000, priv->clk_rate)); in rwdt_restart()
149 readb_poll_timeout_atomic(priv->base + RWTCSRA, val, in rwdt_restart()
154 /* wait 2 cycles, so watchdog will trigger */ in rwdt_restart()
155 udelay(DIV_ROUND_UP(2 * 1000000, priv->clk_rate)); in rwdt_restart()
177 * Watchdog-reset integration is broken on early revisions of R-Car Gen2 SoCs
200 if (attr && setup_max_cpus > (uintptr_t)attr->data) { in rwdt_blacklisted()
201 dev_info(dev, "Watchdog blacklisted on %s %s\n", attr->soc_id, in rwdt_blacklisted()
202 attr->revision); in rwdt_blacklisted()
214 struct device *dev = &pdev->dev; in rwdt_probe()
221 return -ENODEV; in rwdt_probe()
225 return -ENOMEM; in rwdt_probe()
227 priv->base = devm_platform_ioremap_resource(pdev, 0); in rwdt_probe()
228 if (IS_ERR(priv->base)) in rwdt_probe()
229 return PTR_ERR(priv->base); in rwdt_probe()
231 priv->clk = devm_clk_get(dev, NULL); in rwdt_probe()
232 if (IS_ERR(priv->clk)) in rwdt_probe()
233 return PTR_ERR(priv->clk); in rwdt_probe()
237 priv->clk_rate = clk_get_rate(priv->clk); in rwdt_probe()
238 csra = readb_relaxed(priv->base + RWTCSRA); in rwdt_probe()
239 priv->wdev.bootstatus = csra & RWTCSRA_WOVF ? WDIOF_CARDRESET : 0; in rwdt_probe()
242 if (!priv->clk_rate) { in rwdt_probe()
243 ret = -ENOENT; in rwdt_probe()
247 for (i = ARRAY_SIZE(clk_divs) - 1; i >= 0; i--) { in rwdt_probe()
248 clks_per_sec = priv->clk_rate / clk_divs[i]; in rwdt_probe()
250 priv->cks = i; in rwdt_probe()
257 ret = -ERANGE; in rwdt_probe()
261 priv->wdev.info = &rwdt_ident; in rwdt_probe()
262 priv->wdev.ops = &rwdt_ops; in rwdt_probe()
263 priv->wdev.parent = dev; in rwdt_probe()
264 priv->wdev.min_timeout = 1; in rwdt_probe()
265 priv->wdev.max_timeout = DIV_BY_CLKS_PER_SEC(priv, 65536); in rwdt_probe()
266 priv->wdev.timeout = min(priv->wdev.max_timeout, RWDT_DEFAULT_TIMEOUT); in rwdt_probe()
269 watchdog_set_drvdata(&priv->wdev, priv); in rwdt_probe()
270 watchdog_set_nowayout(&priv->wdev, nowayout); in rwdt_probe()
271 watchdog_set_restart_priority(&priv->wdev, 0); in rwdt_probe()
272 watchdog_stop_on_unregister(&priv->wdev); in rwdt_probe()
275 watchdog_init_timeout(&priv->wdev, 0, dev); in rwdt_probe()
280 rwdt_start(&priv->wdev); in rwdt_probe()
281 set_bit(WDOG_HW_RUNNING, &priv->wdev.status); in rwdt_probe()
284 ret = watchdog_register_device(&priv->wdev); in rwdt_probe()
299 watchdog_unregister_device(&priv->wdev); in rwdt_remove()
300 pm_runtime_disable(&pdev->dev); in rwdt_remove()
307 if (watchdog_active(&priv->wdev)) in rwdt_suspend()
308 rwdt_stop(&priv->wdev); in rwdt_suspend()
317 if (watchdog_active(&priv->wdev)) in rwdt_resume()
318 rwdt_start(&priv->wdev); in rwdt_resume()
326 { .compatible = "renesas,rcar-gen2-wdt", },
327 { .compatible = "renesas,rcar-gen3-wdt", },
328 { .compatible = "renesas,rcar-gen4-wdt", },
346 MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");