xref: /openbmc/linux/drivers/watchdog/mtk_wdt.c (revision ed4543328f7108e1047b83b96ca7f7208747d930)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Mediatek Watchdog Driver
4  *
5  * Copyright (C) 2014 Matthias Brugger
6  *
7  * Matthias Brugger <matthias.bgg@gmail.com>
8  *
9  * Based on sunxi_wdt.c
10  */
11 
12 #include <dt-bindings/reset/mt2712-resets.h>
13 #include <dt-bindings/reset/mediatek,mt6735-wdt.h>
14 #include <dt-bindings/reset/mediatek,mt6795-resets.h>
15 #include <dt-bindings/reset/mt7986-resets.h>
16 #include <dt-bindings/reset/mt8183-resets.h>
17 #include <dt-bindings/reset/mt8186-resets.h>
18 #include <dt-bindings/reset/mt8188-resets.h>
19 #include <dt-bindings/reset/mt8192-resets.h>
20 #include <dt-bindings/reset/mt8195-resets.h>
21 #include <linux/delay.h>
22 #include <linux/err.h>
23 #include <linux/init.h>
24 #include <linux/io.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/moduleparam.h>
28 #include <linux/of.h>
29 #include <linux/platform_device.h>
30 #include <linux/reset-controller.h>
31 #include <linux/types.h>
32 #include <linux/watchdog.h>
33 #include <linux/interrupt.h>
34 
35 #define WDT_MAX_TIMEOUT		31
36 #define WDT_MIN_TIMEOUT		2
37 #define WDT_LENGTH_TIMEOUT(n)	((n) << 5)
38 
39 #define WDT_LENGTH		0x04
40 #define WDT_LENGTH_KEY		0x8
41 
42 #define WDT_RST			0x08
43 #define WDT_RST_RELOAD		0x1971
44 
45 #define WDT_MODE		0x00
46 #define WDT_MODE_EN		(1 << 0)
47 #define WDT_MODE_EXT_POL_LOW	(0 << 1)
48 #define WDT_MODE_EXT_POL_HIGH	(1 << 1)
49 #define WDT_MODE_EXRST_EN	(1 << 2)
50 #define WDT_MODE_IRQ_EN		(1 << 3)
51 #define WDT_MODE_AUTO_START	(1 << 4)
52 #define WDT_MODE_DUAL_EN	(1 << 6)
53 #define WDT_MODE_CNT_SEL	(1 << 8)
54 #define WDT_MODE_KEY		0x22000000
55 
56 #define WDT_SWRST		0x14
57 #define WDT_SWRST_KEY		0x1209
58 
59 #define WDT_SWSYSRST		0x18U
60 #define WDT_SWSYS_RST_KEY	0x88000000
61 
62 #define DRV_NAME		"mtk-wdt"
63 #define DRV_VERSION		"1.0"
64 
65 static bool nowayout = WATCHDOG_NOWAYOUT;
66 static unsigned int timeout;
67 
68 struct mtk_wdt_dev {
69 	struct watchdog_device wdt_dev;
70 	void __iomem *wdt_base;
71 	spinlock_t lock; /* protects WDT_SWSYSRST reg */
72 	struct reset_controller_dev rcdev;
73 	bool disable_wdt_extrst;
74 	bool reset_by_toprgu;
75 };
76 
77 struct mtk_wdt_data {
78 	int toprgu_sw_rst_num;
79 };
80 
81 static const struct mtk_wdt_data mt2712_data = {
82 	.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
83 };
84 
85 static const struct mtk_wdt_data mt6735_data = {
86 	.toprgu_sw_rst_num = MT6735_TOPRGU_RST_NUM,
87 };
88 
89 static const struct mtk_wdt_data mt6795_data = {
90 	.toprgu_sw_rst_num = MT6795_TOPRGU_SW_RST_NUM,
91 };
92 
93 static const struct mtk_wdt_data mt7986_data = {
94 	.toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM,
95 };
96 
97 static const struct mtk_wdt_data mt8183_data = {
98 	.toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM,
99 };
100 
101 static const struct mtk_wdt_data mt8186_data = {
102 	.toprgu_sw_rst_num = MT8186_TOPRGU_SW_RST_NUM,
103 };
104 
105 static const struct mtk_wdt_data mt8188_data = {
106 	.toprgu_sw_rst_num = MT8188_TOPRGU_SW_RST_NUM,
107 };
108 
109 static const struct mtk_wdt_data mt8192_data = {
110 	.toprgu_sw_rst_num = MT8192_TOPRGU_SW_RST_NUM,
111 };
112 
113 static const struct mtk_wdt_data mt8195_data = {
114 	.toprgu_sw_rst_num = MT8195_TOPRGU_SW_RST_NUM,
115 };
116 
toprgu_reset_update(struct reset_controller_dev * rcdev,unsigned long id,bool assert)117 static int toprgu_reset_update(struct reset_controller_dev *rcdev,
118 			       unsigned long id, bool assert)
119 {
120 	unsigned int tmp;
121 	unsigned long flags;
122 	struct mtk_wdt_dev *data =
123 		 container_of(rcdev, struct mtk_wdt_dev, rcdev);
124 
125 	spin_lock_irqsave(&data->lock, flags);
126 
127 	tmp = readl(data->wdt_base + WDT_SWSYSRST);
128 	if (assert)
129 		tmp |= BIT(id);
130 	else
131 		tmp &= ~BIT(id);
132 	tmp |= WDT_SWSYS_RST_KEY;
133 	writel(tmp, data->wdt_base + WDT_SWSYSRST);
134 
135 	spin_unlock_irqrestore(&data->lock, flags);
136 
137 	return 0;
138 }
139 
toprgu_reset_assert(struct reset_controller_dev * rcdev,unsigned long id)140 static int toprgu_reset_assert(struct reset_controller_dev *rcdev,
141 			       unsigned long id)
142 {
143 	return toprgu_reset_update(rcdev, id, true);
144 }
145 
toprgu_reset_deassert(struct reset_controller_dev * rcdev,unsigned long id)146 static int toprgu_reset_deassert(struct reset_controller_dev *rcdev,
147 				 unsigned long id)
148 {
149 	return toprgu_reset_update(rcdev, id, false);
150 }
151 
toprgu_reset(struct reset_controller_dev * rcdev,unsigned long id)152 static int toprgu_reset(struct reset_controller_dev *rcdev,
153 			unsigned long id)
154 {
155 	int ret;
156 
157 	ret = toprgu_reset_assert(rcdev, id);
158 	if (ret)
159 		return ret;
160 
161 	return toprgu_reset_deassert(rcdev, id);
162 }
163 
164 static const struct reset_control_ops toprgu_reset_ops = {
165 	.assert = toprgu_reset_assert,
166 	.deassert = toprgu_reset_deassert,
167 	.reset = toprgu_reset,
168 };
169 
toprgu_register_reset_controller(struct platform_device * pdev,int rst_num)170 static int toprgu_register_reset_controller(struct platform_device *pdev,
171 					    int rst_num)
172 {
173 	int ret;
174 	struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
175 
176 	spin_lock_init(&mtk_wdt->lock);
177 
178 	mtk_wdt->rcdev.owner = THIS_MODULE;
179 	mtk_wdt->rcdev.nr_resets = rst_num;
180 	mtk_wdt->rcdev.ops = &toprgu_reset_ops;
181 	mtk_wdt->rcdev.of_node = pdev->dev.of_node;
182 	ret = devm_reset_controller_register(&pdev->dev, &mtk_wdt->rcdev);
183 	if (ret != 0)
184 		dev_err(&pdev->dev,
185 			"couldn't register wdt reset controller: %d\n", ret);
186 	return ret;
187 }
188 
mtk_wdt_restart(struct watchdog_device * wdt_dev,unsigned long action,void * data)189 static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
190 			   unsigned long action, void *data)
191 {
192 	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
193 	void __iomem *wdt_base;
194 	u32 reg;
195 
196 	wdt_base = mtk_wdt->wdt_base;
197 
198 	/* Enable reset in order to issue a system reset instead of an IRQ */
199 	reg = readl(wdt_base + WDT_MODE);
200 	reg &= ~WDT_MODE_IRQ_EN;
201 	writel(reg | WDT_MODE_KEY, wdt_base + WDT_MODE);
202 
203 	while (1) {
204 		writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
205 		mdelay(5);
206 	}
207 
208 	return 0;
209 }
210 
mtk_wdt_ping(struct watchdog_device * wdt_dev)211 static int mtk_wdt_ping(struct watchdog_device *wdt_dev)
212 {
213 	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
214 	void __iomem *wdt_base = mtk_wdt->wdt_base;
215 
216 	iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST);
217 
218 	return 0;
219 }
220 
mtk_wdt_set_timeout(struct watchdog_device * wdt_dev,unsigned int timeout)221 static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev,
222 				unsigned int timeout)
223 {
224 	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
225 	void __iomem *wdt_base = mtk_wdt->wdt_base;
226 	u32 reg;
227 
228 	wdt_dev->timeout = timeout;
229 	/*
230 	 * In dual mode, irq will be triggered at timeout / 2
231 	 * the real timeout occurs at timeout
232 	 */
233 	if (wdt_dev->pretimeout)
234 		wdt_dev->pretimeout = timeout / 2;
235 
236 	/*
237 	 * One bit is the value of 512 ticks
238 	 * The clock has 32 KHz
239 	 */
240 	reg = WDT_LENGTH_TIMEOUT((timeout - wdt_dev->pretimeout) << 6)
241 			| WDT_LENGTH_KEY;
242 	iowrite32(reg, wdt_base + WDT_LENGTH);
243 
244 	mtk_wdt_ping(wdt_dev);
245 
246 	return 0;
247 }
248 
mtk_wdt_init(struct watchdog_device * wdt_dev)249 static void mtk_wdt_init(struct watchdog_device *wdt_dev)
250 {
251 	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
252 	void __iomem *wdt_base;
253 
254 	wdt_base = mtk_wdt->wdt_base;
255 
256 	if (readl(wdt_base + WDT_MODE) & WDT_MODE_EN) {
257 		set_bit(WDOG_HW_RUNNING, &wdt_dev->status);
258 		mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
259 	}
260 }
261 
mtk_wdt_stop(struct watchdog_device * wdt_dev)262 static int mtk_wdt_stop(struct watchdog_device *wdt_dev)
263 {
264 	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
265 	void __iomem *wdt_base = mtk_wdt->wdt_base;
266 	u32 reg;
267 
268 	reg = readl(wdt_base + WDT_MODE);
269 	reg &= ~WDT_MODE_EN;
270 	reg |= WDT_MODE_KEY;
271 	iowrite32(reg, wdt_base + WDT_MODE);
272 
273 	return 0;
274 }
275 
mtk_wdt_start(struct watchdog_device * wdt_dev)276 static int mtk_wdt_start(struct watchdog_device *wdt_dev)
277 {
278 	u32 reg;
279 	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
280 	void __iomem *wdt_base = mtk_wdt->wdt_base;
281 	int ret;
282 
283 	ret = mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
284 	if (ret < 0)
285 		return ret;
286 
287 	reg = ioread32(wdt_base + WDT_MODE);
288 	if (wdt_dev->pretimeout)
289 		reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
290 	else
291 		reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
292 	if (mtk_wdt->disable_wdt_extrst)
293 		reg &= ~WDT_MODE_EXRST_EN;
294 	if (mtk_wdt->reset_by_toprgu)
295 		reg |= WDT_MODE_CNT_SEL;
296 	reg |= (WDT_MODE_EN | WDT_MODE_KEY);
297 	iowrite32(reg, wdt_base + WDT_MODE);
298 
299 	return 0;
300 }
301 
mtk_wdt_set_pretimeout(struct watchdog_device * wdd,unsigned int timeout)302 static int mtk_wdt_set_pretimeout(struct watchdog_device *wdd,
303 				  unsigned int timeout)
304 {
305 	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdd);
306 	void __iomem *wdt_base = mtk_wdt->wdt_base;
307 	u32 reg = ioread32(wdt_base + WDT_MODE);
308 
309 	if (timeout && !wdd->pretimeout) {
310 		wdd->pretimeout = wdd->timeout / 2;
311 		reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
312 	} else if (!timeout && wdd->pretimeout) {
313 		wdd->pretimeout = 0;
314 		reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
315 	} else {
316 		return 0;
317 	}
318 
319 	reg |= WDT_MODE_KEY;
320 	iowrite32(reg, wdt_base + WDT_MODE);
321 
322 	return mtk_wdt_set_timeout(wdd, wdd->timeout);
323 }
324 
mtk_wdt_isr(int irq,void * arg)325 static irqreturn_t mtk_wdt_isr(int irq, void *arg)
326 {
327 	struct watchdog_device *wdd = arg;
328 
329 	watchdog_notify_pretimeout(wdd);
330 
331 	return IRQ_HANDLED;
332 }
333 
334 static const struct watchdog_info mtk_wdt_info = {
335 	.identity	= DRV_NAME,
336 	.options	= WDIOF_SETTIMEOUT |
337 			  WDIOF_KEEPALIVEPING |
338 			  WDIOF_MAGICCLOSE,
339 };
340 
341 static const struct watchdog_info mtk_wdt_pt_info = {
342 	.identity	= DRV_NAME,
343 	.options	= WDIOF_SETTIMEOUT |
344 			  WDIOF_PRETIMEOUT |
345 			  WDIOF_KEEPALIVEPING |
346 			  WDIOF_MAGICCLOSE,
347 };
348 
349 static const struct watchdog_ops mtk_wdt_ops = {
350 	.owner		= THIS_MODULE,
351 	.start		= mtk_wdt_start,
352 	.stop		= mtk_wdt_stop,
353 	.ping		= mtk_wdt_ping,
354 	.set_timeout	= mtk_wdt_set_timeout,
355 	.set_pretimeout	= mtk_wdt_set_pretimeout,
356 	.restart	= mtk_wdt_restart,
357 };
358 
mtk_wdt_probe(struct platform_device * pdev)359 static int mtk_wdt_probe(struct platform_device *pdev)
360 {
361 	struct device *dev = &pdev->dev;
362 	struct mtk_wdt_dev *mtk_wdt;
363 	const struct mtk_wdt_data *wdt_data;
364 	int err, irq;
365 
366 	mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL);
367 	if (!mtk_wdt)
368 		return -ENOMEM;
369 
370 	platform_set_drvdata(pdev, mtk_wdt);
371 
372 	mtk_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0);
373 	if (IS_ERR(mtk_wdt->wdt_base))
374 		return PTR_ERR(mtk_wdt->wdt_base);
375 
376 	irq = platform_get_irq_optional(pdev, 0);
377 	if (irq > 0) {
378 		err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark",
379 				       &mtk_wdt->wdt_dev);
380 		if (err)
381 			return err;
382 
383 		mtk_wdt->wdt_dev.info = &mtk_wdt_pt_info;
384 		mtk_wdt->wdt_dev.pretimeout = WDT_MAX_TIMEOUT / 2;
385 	} else {
386 		if (irq == -EPROBE_DEFER)
387 			return -EPROBE_DEFER;
388 
389 		mtk_wdt->wdt_dev.info = &mtk_wdt_info;
390 	}
391 
392 	mtk_wdt->wdt_dev.ops = &mtk_wdt_ops;
393 	mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT;
394 	mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000;
395 	mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT;
396 	mtk_wdt->wdt_dev.parent = dev;
397 
398 	watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev);
399 	watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout);
400 	watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128);
401 
402 	watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt);
403 
404 	mtk_wdt_init(&mtk_wdt->wdt_dev);
405 
406 	watchdog_stop_on_reboot(&mtk_wdt->wdt_dev);
407 	err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev);
408 	if (unlikely(err))
409 		return err;
410 
411 	dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
412 		 mtk_wdt->wdt_dev.timeout, nowayout);
413 
414 	wdt_data = of_device_get_match_data(dev);
415 	if (wdt_data) {
416 		err = toprgu_register_reset_controller(pdev,
417 						       wdt_data->toprgu_sw_rst_num);
418 		if (err)
419 			return err;
420 	}
421 
422 	mtk_wdt->disable_wdt_extrst =
423 		of_property_read_bool(dev->of_node, "mediatek,disable-extrst");
424 
425 	mtk_wdt->reset_by_toprgu =
426 		of_property_read_bool(dev->of_node, "mediatek,reset-by-toprgu");
427 
428 	return 0;
429 }
430 
mtk_wdt_suspend(struct device * dev)431 static int mtk_wdt_suspend(struct device *dev)
432 {
433 	struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev);
434 
435 	if (watchdog_active(&mtk_wdt->wdt_dev))
436 		mtk_wdt_stop(&mtk_wdt->wdt_dev);
437 
438 	return 0;
439 }
440 
mtk_wdt_resume(struct device * dev)441 static int mtk_wdt_resume(struct device *dev)
442 {
443 	struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev);
444 
445 	if (watchdog_active(&mtk_wdt->wdt_dev)) {
446 		mtk_wdt_start(&mtk_wdt->wdt_dev);
447 		mtk_wdt_ping(&mtk_wdt->wdt_dev);
448 	}
449 
450 	return 0;
451 }
452 
453 static const struct of_device_id mtk_wdt_dt_ids[] = {
454 	{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
455 	{ .compatible = "mediatek,mt6589-wdt" },
456 	{ .compatible = "mediatek,mt6735-wdt", .data = &mt6735_data },
457 	{ .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data },
458 	{ .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
459 	{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
460 	{ .compatible = "mediatek,mt8186-wdt", .data = &mt8186_data },
461 	{ .compatible = "mediatek,mt8188-wdt", .data = &mt8188_data },
462 	{ .compatible = "mediatek,mt8192-wdt", .data = &mt8192_data },
463 	{ .compatible = "mediatek,mt8195-wdt", .data = &mt8195_data },
464 	{ /* sentinel */ }
465 };
466 MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
467 
468 static DEFINE_SIMPLE_DEV_PM_OPS(mtk_wdt_pm_ops,
469 				mtk_wdt_suspend, mtk_wdt_resume);
470 
471 static struct platform_driver mtk_wdt_driver = {
472 	.probe		= mtk_wdt_probe,
473 	.driver		= {
474 		.name		= DRV_NAME,
475 		.pm		= pm_sleep_ptr(&mtk_wdt_pm_ops),
476 		.of_match_table	= mtk_wdt_dt_ids,
477 	},
478 };
479 
480 module_platform_driver(mtk_wdt_driver);
481 
482 module_param(timeout, uint, 0);
483 MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds");
484 
485 module_param(nowayout, bool, 0);
486 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
487 			__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
488 
489 MODULE_LICENSE("GPL");
490 MODULE_AUTHOR("Matthias Brugger <matthias.bgg@gmail.com>");
491 MODULE_DESCRIPTION("Mediatek WatchDog Timer Driver");
492 MODULE_VERSION(DRV_VERSION);
493