1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Watchdog driver for the K3 RTI module
4 *
5 * (c) Copyright 2019-2020 Texas Instruments Inc.
6 * All rights reserved.
7 */
8
9 #include <linux/clk.h>
10 #include <linux/device.h>
11 #include <linux/err.h>
12 #include <linux/io.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/moduleparam.h>
16 #include <linux/of.h>
17 #include <linux/of_reserved_mem.h>
18 #include <linux/platform_device.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/types.h>
21 #include <linux/watchdog.h>
22
23 #define DEFAULT_HEARTBEAT 60
24
25 /* Max heartbeat is calculated at 32kHz source clock */
26 #define MAX_HEARTBEAT 1000
27
28 /* Timer register set definition */
29 #define RTIDWDCTRL 0x90
30 #define RTIDWDPRLD 0x94
31 #define RTIWDSTATUS 0x98
32 #define RTIWDKEY 0x9c
33 #define RTIDWDCNTR 0xa0
34 #define RTIWWDRXCTRL 0xa4
35 #define RTIWWDSIZECTRL 0xa8
36
37 #define RTIWWDRXN_RST 0x5
38 #define RTIWWDRXN_NMI 0xa
39
40 #define RTIWWDSIZE_50P 0x50
41 #define RTIWWDSIZE_25P 0x500
42 #define RTIWWDSIZE_12P5 0x5000
43 #define RTIWWDSIZE_6P25 0x50000
44 #define RTIWWDSIZE_3P125 0x500000
45
46 #define WDENABLE_KEY 0xa98559da
47
48 #define WDKEY_SEQ0 0xe51a
49 #define WDKEY_SEQ1 0xa35c
50
51 #define WDT_PRELOAD_SHIFT 13
52
53 #define WDT_PRELOAD_MAX 0xfff
54
55 #define DWDST BIT(1)
56
57 #define PON_REASON_SOF_NUM 0xBBBBCCCC
58 #define PON_REASON_MAGIC_NUM 0xDDDDDDDD
59 #define PON_REASON_EOF_NUM 0xCCCCBBBB
60 #define RESERVED_MEM_MIN_SIZE 12
61
62 #define MAX_HW_ERROR 250
63
64 static int heartbeat;
65
66 struct rti_wdt_data {
67 bool nmi;
68 };
69
70 /*
71 * struct to hold data for each WDT device
72 * @base - base io address of WD device
73 * @freq - source clock frequency of WDT
74 * @wdd - hold watchdog device as is in WDT core
75 * @nmi - Set if this WDT instance supports generating NMI
76 */
77 struct rti_wdt_device {
78 void __iomem *base;
79 unsigned long freq;
80 struct watchdog_device wdd;
81 bool nmi;
82 };
83
rti_wdt_start(struct watchdog_device * wdd)84 static int rti_wdt_start(struct watchdog_device *wdd)
85 {
86 u32 timer_margin;
87 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
88 u8 reaction;
89 int ret;
90
91 ret = pm_runtime_resume_and_get(wdd->parent);
92 if (ret)
93 return ret;
94
95 /* set timeout period */
96 timer_margin = (u64)wdd->timeout * wdt->freq;
97 timer_margin >>= WDT_PRELOAD_SHIFT;
98 if (timer_margin > WDT_PRELOAD_MAX)
99 timer_margin = WDT_PRELOAD_MAX;
100 writel_relaxed(timer_margin, wdt->base + RTIDWDPRLD);
101
102 /*
103 * RTI only supports a windowed mode, where the watchdog can only
104 * be petted during the open window; not too early or not too late.
105 * The HW configuration options only allow for the open window size
106 * to be 50% or less than that; we obviouly want to configure the open
107 * window as large as possible so we select the 50% option.
108 */
109 wdd->min_hw_heartbeat_ms = 520 * wdd->timeout + MAX_HW_ERROR;
110
111 /* When WDT expires, generate NMI or reset if NMI not supported */
112 if (wdt->nmi)
113 reaction = RTIWWDRXN_NMI;
114 else
115 reaction = RTIWWDRXN_RST;
116
117 writel_relaxed(reaction, wdt->base + RTIWWDRXCTRL);
118
119 /* Open window size 50%; this is the largest window size available */
120 writel_relaxed(RTIWWDSIZE_50P, wdt->base + RTIWWDSIZECTRL);
121
122 readl_relaxed(wdt->base + RTIWWDSIZECTRL);
123
124 /* enable watchdog */
125 writel_relaxed(WDENABLE_KEY, wdt->base + RTIDWDCTRL);
126 return 0;
127 }
128
rti_wdt_ping(struct watchdog_device * wdd)129 static int rti_wdt_ping(struct watchdog_device *wdd)
130 {
131 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
132
133 /* put watchdog in service state */
134 writel_relaxed(WDKEY_SEQ0, wdt->base + RTIWDKEY);
135 /* put watchdog in active state */
136 writel_relaxed(WDKEY_SEQ1, wdt->base + RTIWDKEY);
137
138 return 0;
139 }
140
rti_wdt_setup_hw_hb(struct watchdog_device * wdd,u32 wsize)141 static int rti_wdt_setup_hw_hb(struct watchdog_device *wdd, u32 wsize)
142 {
143 /*
144 * RTI only supports a windowed mode, where the watchdog can only
145 * be petted during the open window; not too early or not too late.
146 * The HW configuration options only allow for the open window size
147 * to be 50% or less than that.
148 * To avoid any glitches, we accommodate 2% + max hardware error
149 * safety margin.
150 */
151 switch (wsize) {
152 case RTIWWDSIZE_50P:
153 /* 50% open window => 52% min heartbeat */
154 wdd->min_hw_heartbeat_ms = 520 * heartbeat + MAX_HW_ERROR;
155 break;
156
157 case RTIWWDSIZE_25P:
158 /* 25% open window => 77% min heartbeat */
159 wdd->min_hw_heartbeat_ms = 770 * heartbeat + MAX_HW_ERROR;
160 break;
161
162 case RTIWWDSIZE_12P5:
163 /* 12.5% open window => 89.5% min heartbeat */
164 wdd->min_hw_heartbeat_ms = 895 * heartbeat + MAX_HW_ERROR;
165 break;
166
167 case RTIWWDSIZE_6P25:
168 /* 6.5% open window => 95.5% min heartbeat */
169 wdd->min_hw_heartbeat_ms = 955 * heartbeat + MAX_HW_ERROR;
170 break;
171
172 case RTIWWDSIZE_3P125:
173 /* 3.125% open window => 98.9% min heartbeat */
174 wdd->min_hw_heartbeat_ms = 989 * heartbeat + MAX_HW_ERROR;
175 break;
176
177 default:
178 return -EINVAL;
179 }
180
181 return 0;
182 }
183
rti_wdt_get_timeleft_ms(struct watchdog_device * wdd)184 static unsigned int rti_wdt_get_timeleft_ms(struct watchdog_device *wdd)
185 {
186 u64 timer_counter;
187 u32 val;
188 struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
189
190 /* if timeout has occurred then return 0 */
191 val = readl_relaxed(wdt->base + RTIWDSTATUS);
192 if (val & DWDST)
193 return 0;
194
195 timer_counter = readl_relaxed(wdt->base + RTIDWDCNTR);
196
197 timer_counter *= 1000;
198
199 do_div(timer_counter, wdt->freq);
200
201 return timer_counter;
202 }
203
rti_wdt_get_timeleft(struct watchdog_device * wdd)204 static unsigned int rti_wdt_get_timeleft(struct watchdog_device *wdd)
205 {
206 return rti_wdt_get_timeleft_ms(wdd) / 1000;
207 }
208
209 static const struct watchdog_info rti_wdt_info = {
210 .options = WDIOF_KEEPALIVEPING,
211 .identity = "K3 RTI Watchdog",
212 };
213
214 static const struct watchdog_ops rti_wdt_ops = {
215 .owner = THIS_MODULE,
216 .start = rti_wdt_start,
217 .ping = rti_wdt_ping,
218 .get_timeleft = rti_wdt_get_timeleft,
219 };
220
rti_wdt_probe(struct platform_device * pdev)221 static int rti_wdt_probe(struct platform_device *pdev)
222 {
223 int ret = 0;
224 struct device *dev = &pdev->dev;
225 const struct rti_wdt_data *data;
226 struct watchdog_device *wdd;
227 struct rti_wdt_device *wdt;
228 struct clk *clk;
229 u32 last_ping = 0;
230 u32 reserved_mem_size;
231 struct resource res;
232 u32 *vaddr;
233 u64 paddr;
234
235 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
236 if (!wdt)
237 return -ENOMEM;
238
239 clk = clk_get(dev, NULL);
240 if (IS_ERR(clk))
241 return dev_err_probe(dev, PTR_ERR(clk), "failed to get clock\n");
242
243 wdt->freq = clk_get_rate(clk);
244
245 clk_put(clk);
246
247 if (!wdt->freq) {
248 dev_err(dev, "Failed to get fck rate.\n");
249 return -EINVAL;
250 }
251
252 pm_runtime_enable(dev);
253 ret = pm_runtime_resume_and_get(dev);
254 if (ret < 0) {
255 pm_runtime_disable(&pdev->dev);
256 return dev_err_probe(dev, ret, "runtime pm failed\n");
257 }
258
259 platform_set_drvdata(pdev, wdt);
260
261 wdd = &wdt->wdd;
262 wdd->info = &rti_wdt_info;
263 wdd->ops = &rti_wdt_ops;
264 wdd->min_timeout = 1;
265 wdd->max_hw_heartbeat_ms = (WDT_PRELOAD_MAX << WDT_PRELOAD_SHIFT) /
266 wdt->freq * 1000;
267 wdd->timeout = DEFAULT_HEARTBEAT;
268 wdd->parent = dev;
269
270 data = device_get_match_data(dev);
271 if (!data) {
272 ret = -ENODEV;
273 goto err_iomap;
274 }
275
276 wdt->nmi = data->nmi;
277
278 watchdog_set_drvdata(wdd, wdt);
279 watchdog_set_nowayout(wdd, 1);
280 watchdog_set_restart_priority(wdd, 128);
281
282 wdt->base = devm_platform_ioremap_resource(pdev, 0);
283 if (IS_ERR(wdt->base)) {
284 ret = PTR_ERR(wdt->base);
285 goto err_iomap;
286 }
287
288 if (readl(wdt->base + RTIDWDCTRL) == WDENABLE_KEY) {
289 int preset_heartbeat;
290 u32 time_left_ms;
291 u64 heartbeat_ms;
292 u32 wsize;
293
294 set_bit(WDOG_HW_RUNNING, &wdd->status);
295 time_left_ms = rti_wdt_get_timeleft_ms(wdd);
296 /* AM62x TRM: texp = (RTIDWDPRLD + 1) * (2^13) / RTICLK1 */
297 heartbeat_ms = readl(wdt->base + RTIDWDPRLD) + 1;
298 heartbeat_ms <<= WDT_PRELOAD_SHIFT;
299 heartbeat_ms *= 1000;
300 do_div(heartbeat_ms, wdt->freq);
301 preset_heartbeat = heartbeat_ms + 500;
302 preset_heartbeat /= 1000;
303 if (preset_heartbeat != heartbeat)
304 dev_warn(dev, "watchdog already running, ignoring heartbeat config!\n");
305
306 heartbeat = preset_heartbeat;
307
308 wsize = readl(wdt->base + RTIWWDSIZECTRL);
309 ret = rti_wdt_setup_hw_hb(wdd, wsize);
310 if (ret) {
311 dev_err(dev, "bad window size.\n");
312 goto err_iomap;
313 }
314
315 last_ping = heartbeat_ms - time_left_ms;
316 if (time_left_ms > heartbeat_ms) {
317 dev_warn(dev, "time_left > heartbeat? Assuming last ping just before now.\n");
318 last_ping = 0;
319 }
320 }
321
322 ret = of_reserved_mem_region_to_resource(pdev->dev.of_node, 0, &res);
323 if (!ret) {
324 /*
325 * If reserved memory is defined for watchdog reset cause.
326 * Readout the Power-on(PON) reason and pass to bootstatus.
327 */
328 paddr = res.start;
329 reserved_mem_size = resource_size(&res);
330 if (reserved_mem_size < RESERVED_MEM_MIN_SIZE) {
331 dev_err(dev, "The size of reserved memory is too small.\n");
332 ret = -EINVAL;
333 goto err_iomap;
334 }
335
336 vaddr = memremap(paddr, reserved_mem_size, MEMREMAP_WB);
337 if (!vaddr) {
338 dev_err(dev, "Failed to map memory-region.\n");
339 ret = -ENOMEM;
340 goto err_iomap;
341 }
342
343 if (vaddr[0] == PON_REASON_SOF_NUM &&
344 vaddr[1] == PON_REASON_MAGIC_NUM &&
345 vaddr[2] == PON_REASON_EOF_NUM) {
346 wdd->bootstatus |= WDIOF_CARDRESET;
347 }
348 memset(vaddr, 0, reserved_mem_size);
349 memunmap(vaddr);
350 }
351
352 watchdog_init_timeout(wdd, heartbeat, dev);
353
354 ret = watchdog_register_device(wdd);
355 if (ret)
356 goto err_iomap;
357
358 if (last_ping)
359 watchdog_set_last_hw_keepalive(wdd, last_ping);
360
361 if (!watchdog_hw_running(wdd))
362 pm_runtime_put_sync(&pdev->dev);
363
364 return 0;
365
366 err_iomap:
367 pm_runtime_put_sync(&pdev->dev);
368 pm_runtime_disable(&pdev->dev);
369
370 return ret;
371 }
372
rti_wdt_remove(struct platform_device * pdev)373 static void rti_wdt_remove(struct platform_device *pdev)
374 {
375 struct rti_wdt_device *wdt = platform_get_drvdata(pdev);
376
377 watchdog_unregister_device(&wdt->wdd);
378
379 if (!pm_runtime_suspended(&pdev->dev))
380 pm_runtime_put(&pdev->dev);
381
382 pm_runtime_disable(&pdev->dev);
383 }
384
385 static const struct rti_wdt_data rti_wdt_j7_data = {
386 .nmi = true,
387 };
388
389 static const struct rti_wdt_data rti_wdt_am62l_data = {
390 .nmi = false,
391 };
392
393 static const struct of_device_id rti_wdt_of_match[] = {
394 { .compatible = "ti,j7-rti-wdt", .data = &rti_wdt_j7_data },
395 { .compatible = "ti,am62l-rti-wdt", .data = &rti_wdt_am62l_data },
396 {},
397 };
398 MODULE_DEVICE_TABLE(of, rti_wdt_of_match);
399
400 static struct platform_driver rti_wdt_driver = {
401 .driver = {
402 .name = "rti-wdt",
403 .of_match_table = rti_wdt_of_match,
404 },
405 .probe = rti_wdt_probe,
406 .remove = rti_wdt_remove,
407 };
408
409 module_platform_driver(rti_wdt_driver);
410
411 MODULE_AUTHOR("Tero Kristo <t-kristo@ti.com>");
412 MODULE_DESCRIPTION("K3 RTI Watchdog Driver");
413
414 module_param(heartbeat, int, 0);
415 MODULE_PARM_DESC(heartbeat,
416 "Watchdog heartbeat period in seconds from 1 to "
417 __MODULE_STRING(MAX_HEARTBEAT) ", default "
418 __MODULE_STRING(DEFAULT_HEARTBEAT));
419
420 MODULE_LICENSE("GPL");
421 MODULE_ALIAS("platform:rti-wdt");
422