hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/watchdog/renesas_wdt.c
....@@ -1,15 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * Watchdog driver for Renesas WDT watchdog
34 *
45 * Copyright (C) 2015-17 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>
56 * Copyright (C) 2015-17 Renesas Electronics Corporation
6
- *
7
- * This program is free software; you can redistribute it and/or modify it
8
- * under the terms of the GNU General Public License version 2 as published by
9
- * the Free Software Foundation.
107 */
118 #include <linux/bitops.h>
129 #include <linux/clk.h>
10
+#include <linux/delay.h>
1311 #include <linux/io.h>
1412 #include <linux/kernel.h>
1513 #include <linux/module.h>
....@@ -51,7 +49,6 @@
5149 void __iomem *base;
5250 struct watchdog_device wdev;
5351 unsigned long clk_rate;
54
- u16 time_left;
5552 u8 cks;
5653 };
5754
....@@ -74,6 +71,15 @@
7471 return 0;
7572 }
7673
74
+static void rwdt_wait_cycles(struct rwdt_priv *priv, unsigned int cycles)
75
+{
76
+ unsigned int delay;
77
+
78
+ delay = DIV_ROUND_UP(cycles * 1000000, priv->clk_rate);
79
+
80
+ usleep_range(delay, 2 * delay);
81
+}
82
+
7783 static int rwdt_start(struct watchdog_device *wdev)
7884 {
7985 struct rwdt_priv *priv = watchdog_get_drvdata(wdev);
....@@ -84,6 +90,8 @@
8490 /* Stop the timer before we modify any register */
8591 val = readb_relaxed(priv->base + RWTCSRA) & ~RWTCSRA_TME;
8692 rwdt_write(priv, val, RWTCSRA);
93
+ /* Delay 2 cycles before setting watchdog counter */
94
+ rwdt_wait_cycles(priv, 2);
8795
8896 rwdt_init_timeout(wdev);
8997 rwdt_write(priv, priv->cks, RWTCSRA);
....@@ -102,6 +110,8 @@
102110 struct rwdt_priv *priv = watchdog_get_drvdata(wdev);
103111
104112 rwdt_write(priv, priv->cks, RWTCSRA);
113
+ /* Delay 3 cycles before disabling module clock */
114
+ rwdt_wait_cycles(priv, 3);
105115 pm_runtime_put(wdev->parent);
106116
107117 return 0;
....@@ -155,7 +165,6 @@
155165 .data = (void *)1, /* needs single CPU */
156166 }, {
157167 .soc_id = "r8a7792",
158
- .revision = "*",
159168 .data = (void *)0, /* needs SMP disabled */
160169 },
161170 { /* sentinel */ }
....@@ -180,34 +189,34 @@
180189
181190 static int rwdt_probe(struct platform_device *pdev)
182191 {
192
+ struct device *dev = &pdev->dev;
183193 struct rwdt_priv *priv;
184
- struct resource *res;
185194 struct clk *clk;
186195 unsigned long clks_per_sec;
187196 int ret, i;
197
+ u8 csra;
188198
189
- if (rwdt_blacklisted(&pdev->dev))
199
+ if (rwdt_blacklisted(dev))
190200 return -ENODEV;
191201
192
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
202
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
193203 if (!priv)
194204 return -ENOMEM;
195205
196
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
197
- priv->base = devm_ioremap_resource(&pdev->dev, res);
206
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
198207 if (IS_ERR(priv->base))
199208 return PTR_ERR(priv->base);
200209
201
- clk = devm_clk_get(&pdev->dev, NULL);
210
+ clk = devm_clk_get(dev, NULL);
202211 if (IS_ERR(clk))
203212 return PTR_ERR(clk);
204213
205
- pm_runtime_enable(&pdev->dev);
206
- pm_runtime_get_sync(&pdev->dev);
214
+ pm_runtime_enable(dev);
215
+ pm_runtime_get_sync(dev);
207216 priv->clk_rate = clk_get_rate(clk);
208
- priv->wdev.bootstatus = (readb_relaxed(priv->base + RWTCSRA) &
209
- RWTCSRA_WOVF) ? WDIOF_CARDRESET : 0;
210
- pm_runtime_put(&pdev->dev);
217
+ csra = readb_relaxed(priv->base + RWTCSRA);
218
+ priv->wdev.bootstatus = csra & RWTCSRA_WOVF ? WDIOF_CARDRESET : 0;
219
+ pm_runtime_put(dev);
211220
212221 if (!priv->clk_rate) {
213222 ret = -ENOENT;
....@@ -223,14 +232,14 @@
223232 }
224233
225234 if (i < 0) {
226
- dev_err(&pdev->dev, "Can't find suitable clock divider\n");
235
+ dev_err(dev, "Can't find suitable clock divider\n");
227236 ret = -ERANGE;
228237 goto out_pm_disable;
229238 }
230239
231
- priv->wdev.info = &rwdt_ident,
232
- priv->wdev.ops = &rwdt_ops,
233
- priv->wdev.parent = &pdev->dev;
240
+ priv->wdev.info = &rwdt_ident;
241
+ priv->wdev.ops = &rwdt_ops;
242
+ priv->wdev.parent = dev;
234243 priv->wdev.min_timeout = 1;
235244 priv->wdev.max_timeout = DIV_BY_CLKS_PER_SEC(priv, 65536);
236245 priv->wdev.timeout = min(priv->wdev.max_timeout, RWDT_DEFAULT_TIMEOUT);
....@@ -242,9 +251,14 @@
242251 watchdog_stop_on_unregister(&priv->wdev);
243252
244253 /* This overrides the default timeout only if DT configuration was found */
245
- ret = watchdog_init_timeout(&priv->wdev, 0, &pdev->dev);
246
- if (ret)
247
- dev_warn(&pdev->dev, "Specified timeout value invalid, using default\n");
254
+ watchdog_init_timeout(&priv->wdev, 0, dev);
255
+
256
+ /* Check if FW enabled the watchdog */
257
+ if (csra & RWTCSRA_TME) {
258
+ /* Ensure properly initialized dividers */
259
+ rwdt_start(&priv->wdev);
260
+ set_bit(WDOG_HW_RUNNING, &priv->wdev.status);
261
+ }
248262
249263 ret = watchdog_register_device(&priv->wdev);
250264 if (ret < 0)
....@@ -253,7 +267,7 @@
253267 return 0;
254268
255269 out_pm_disable:
256
- pm_runtime_disable(&pdev->dev);
270
+ pm_runtime_disable(dev);
257271 return ret;
258272 }
259273
....@@ -271,10 +285,9 @@
271285 {
272286 struct rwdt_priv *priv = dev_get_drvdata(dev);
273287
274
- if (watchdog_active(&priv->wdev)) {
275
- priv->time_left = readw(priv->base + RWTCNT);
288
+ if (watchdog_active(&priv->wdev))
276289 rwdt_stop(&priv->wdev);
277
- }
290
+
278291 return 0;
279292 }
280293
....@@ -282,10 +295,9 @@
282295 {
283296 struct rwdt_priv *priv = dev_get_drvdata(dev);
284297
285
- if (watchdog_active(&priv->wdev)) {
298
+ if (watchdog_active(&priv->wdev))
286299 rwdt_start(&priv->wdev);
287
- rwdt_write(priv, priv->time_left, RWTCNT);
288
- }
300
+
289301 return 0;
290302 }
291303