Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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-controller/mt2712-resets.h>
 13#include <dt-bindings/reset-controller/mt8183-resets.h>
 14#include <linux/delay.h>
 15#include <linux/err.h>
 16#include <linux/init.h>
 17#include <linux/io.h>
 18#include <linux/kernel.h>
 19#include <linux/module.h>
 20#include <linux/moduleparam.h>
 21#include <linux/of.h>
 22#include <linux/of_device.h>
 23#include <linux/platform_device.h>
 24#include <linux/reset-controller.h>
 25#include <linux/types.h>
 26#include <linux/watchdog.h>
 27
 28#define WDT_MAX_TIMEOUT		31
 29#define WDT_MIN_TIMEOUT		1
 30#define WDT_LENGTH_TIMEOUT(n)	((n) << 5)
 31
 32#define WDT_LENGTH		0x04
 33#define WDT_LENGTH_KEY		0x8
 34
 35#define WDT_RST			0x08
 36#define WDT_RST_RELOAD		0x1971
 37
 38#define WDT_MODE		0x00
 39#define WDT_MODE_EN		(1 << 0)
 40#define WDT_MODE_EXT_POL_LOW	(0 << 1)
 41#define WDT_MODE_EXT_POL_HIGH	(1 << 1)
 42#define WDT_MODE_EXRST_EN	(1 << 2)
 43#define WDT_MODE_IRQ_EN		(1 << 3)
 44#define WDT_MODE_AUTO_START	(1 << 4)
 45#define WDT_MODE_DUAL_EN	(1 << 6)
 46#define WDT_MODE_KEY		0x22000000
 47
 48#define WDT_SWRST		0x14
 49#define WDT_SWRST_KEY		0x1209
 50
 51#define WDT_SWSYSRST		0x18U
 52#define WDT_SWSYS_RST_KEY	0x88000000
 53
 54#define DRV_NAME		"mtk-wdt"
 55#define DRV_VERSION		"1.0"
 56
 57static bool nowayout = WATCHDOG_NOWAYOUT;
 58static unsigned int timeout;
 59
 60struct mtk_wdt_dev {
 61	struct watchdog_device wdt_dev;
 62	void __iomem *wdt_base;
 63	spinlock_t lock; /* protects WDT_SWSYSRST reg */
 64	struct reset_controller_dev rcdev;
 65};
 66
 67struct mtk_wdt_data {
 68	int toprgu_sw_rst_num;
 69};
 70
 71static const struct mtk_wdt_data mt2712_data = {
 72	.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
 73};
 74
 75static const struct mtk_wdt_data mt8183_data = {
 76	.toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM,
 77};
 78
 79static int toprgu_reset_update(struct reset_controller_dev *rcdev,
 80			       unsigned long id, bool assert)
 81{
 82	unsigned int tmp;
 83	unsigned long flags;
 84	struct mtk_wdt_dev *data =
 85		 container_of(rcdev, struct mtk_wdt_dev, rcdev);
 86
 87	spin_lock_irqsave(&data->lock, flags);
 88
 89	tmp = readl(data->wdt_base + WDT_SWSYSRST);
 90	if (assert)
 91		tmp |= BIT(id);
 92	else
 93		tmp &= ~BIT(id);
 94	tmp |= WDT_SWSYS_RST_KEY;
 95	writel(tmp, data->wdt_base + WDT_SWSYSRST);
 96
 97	spin_unlock_irqrestore(&data->lock, flags);
 98
 99	return 0;
100}
101
102static int toprgu_reset_assert(struct reset_controller_dev *rcdev,
103			       unsigned long id)
104{
105	return toprgu_reset_update(rcdev, id, true);
106}
107
108static int toprgu_reset_deassert(struct reset_controller_dev *rcdev,
109				 unsigned long id)
110{
111	return toprgu_reset_update(rcdev, id, false);
112}
113
114static int toprgu_reset(struct reset_controller_dev *rcdev,
115			unsigned long id)
116{
117	int ret;
118
119	ret = toprgu_reset_assert(rcdev, id);
120	if (ret)
121		return ret;
122
123	return toprgu_reset_deassert(rcdev, id);
124}
125
126static const struct reset_control_ops toprgu_reset_ops = {
127	.assert = toprgu_reset_assert,
128	.deassert = toprgu_reset_deassert,
129	.reset = toprgu_reset,
130};
131
132static int toprgu_register_reset_controller(struct platform_device *pdev,
133					    int rst_num)
134{
135	int ret;
136	struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
137
138	spin_lock_init(&mtk_wdt->lock);
139
140	mtk_wdt->rcdev.owner = THIS_MODULE;
141	mtk_wdt->rcdev.nr_resets = rst_num;
142	mtk_wdt->rcdev.ops = &toprgu_reset_ops;
143	mtk_wdt->rcdev.of_node = pdev->dev.of_node;
144	ret = devm_reset_controller_register(&pdev->dev, &mtk_wdt->rcdev);
145	if (ret != 0)
146		dev_err(&pdev->dev,
147			"couldn't register wdt reset controller: %d\n", ret);
148	return ret;
149}
150
151static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
152			   unsigned long action, void *data)
153{
154	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
155	void __iomem *wdt_base;
156
157	wdt_base = mtk_wdt->wdt_base;
158
159	while (1) {
160		writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
161		mdelay(5);
162	}
163
164	return 0;
165}
166
167static int mtk_wdt_ping(struct watchdog_device *wdt_dev)
168{
169	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
170	void __iomem *wdt_base = mtk_wdt->wdt_base;
171
172	iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST);
173
174	return 0;
175}
176
177static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev,
178				unsigned int timeout)
179{
180	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
181	void __iomem *wdt_base = mtk_wdt->wdt_base;
182	u32 reg;
183
184	wdt_dev->timeout = timeout;
185
186	/*
187	 * One bit is the value of 512 ticks
188	 * The clock has 32 KHz
189	 */
190	reg = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY;
191	iowrite32(reg, wdt_base + WDT_LENGTH);
192
193	mtk_wdt_ping(wdt_dev);
194
195	return 0;
196}
197
198static int mtk_wdt_stop(struct watchdog_device *wdt_dev)
199{
200	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
201	void __iomem *wdt_base = mtk_wdt->wdt_base;
202	u32 reg;
203
204	reg = readl(wdt_base + WDT_MODE);
205	reg &= ~WDT_MODE_EN;
206	reg |= WDT_MODE_KEY;
207	iowrite32(reg, wdt_base + WDT_MODE);
208
209	return 0;
210}
211
212static int mtk_wdt_start(struct watchdog_device *wdt_dev)
213{
214	u32 reg;
215	struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
216	void __iomem *wdt_base = mtk_wdt->wdt_base;
217	int ret;
218
219	ret = mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
220	if (ret < 0)
221		return ret;
222
223	reg = ioread32(wdt_base + WDT_MODE);
224	reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
225	reg |= (WDT_MODE_EN | WDT_MODE_KEY);
226	iowrite32(reg, wdt_base + WDT_MODE);
227
228	return 0;
229}
230
231static const struct watchdog_info mtk_wdt_info = {
232	.identity	= DRV_NAME,
233	.options	= WDIOF_SETTIMEOUT |
234			  WDIOF_KEEPALIVEPING |
235			  WDIOF_MAGICCLOSE,
236};
237
238static const struct watchdog_ops mtk_wdt_ops = {
239	.owner		= THIS_MODULE,
240	.start		= mtk_wdt_start,
241	.stop		= mtk_wdt_stop,
242	.ping		= mtk_wdt_ping,
243	.set_timeout	= mtk_wdt_set_timeout,
244	.restart	= mtk_wdt_restart,
245};
246
247static int mtk_wdt_probe(struct platform_device *pdev)
248{
249	struct device *dev = &pdev->dev;
250	struct mtk_wdt_dev *mtk_wdt;
251	const struct mtk_wdt_data *wdt_data;
252	int err;
253
254	mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL);
255	if (!mtk_wdt)
256		return -ENOMEM;
257
258	platform_set_drvdata(pdev, mtk_wdt);
259
260	mtk_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0);
261	if (IS_ERR(mtk_wdt->wdt_base))
262		return PTR_ERR(mtk_wdt->wdt_base);
263
264	mtk_wdt->wdt_dev.info = &mtk_wdt_info;
265	mtk_wdt->wdt_dev.ops = &mtk_wdt_ops;
266	mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT;
267	mtk_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT;
268	mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT;
269	mtk_wdt->wdt_dev.parent = dev;
270
271	watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev);
272	watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout);
273	watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128);
274
275	watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt);
276
277	mtk_wdt_stop(&mtk_wdt->wdt_dev);
278
279	watchdog_stop_on_reboot(&mtk_wdt->wdt_dev);
280	err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev);
281	if (unlikely(err))
282		return err;
283
284	dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
285		 mtk_wdt->wdt_dev.timeout, nowayout);
286
287	wdt_data = of_device_get_match_data(dev);
288	if (wdt_data) {
289		err = toprgu_register_reset_controller(pdev,
290						       wdt_data->toprgu_sw_rst_num);
291		if (err)
292			return err;
293	}
294	return 0;
295}
296
297#ifdef CONFIG_PM_SLEEP
298static int mtk_wdt_suspend(struct device *dev)
299{
300	struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev);
301
302	if (watchdog_active(&mtk_wdt->wdt_dev))
303		mtk_wdt_stop(&mtk_wdt->wdt_dev);
304
305	return 0;
306}
307
308static int mtk_wdt_resume(struct device *dev)
309{
310	struct mtk_wdt_dev *mtk_wdt = dev_get_drvdata(dev);
311
312	if (watchdog_active(&mtk_wdt->wdt_dev)) {
313		mtk_wdt_start(&mtk_wdt->wdt_dev);
314		mtk_wdt_ping(&mtk_wdt->wdt_dev);
315	}
316
317	return 0;
318}
319#endif
320
321static const struct of_device_id mtk_wdt_dt_ids[] = {
322	{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
323	{ .compatible = "mediatek,mt6589-wdt" },
324	{ .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
325	{ /* sentinel */ }
326};
327MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
328
329static const struct dev_pm_ops mtk_wdt_pm_ops = {
330	SET_SYSTEM_SLEEP_PM_OPS(mtk_wdt_suspend,
331				mtk_wdt_resume)
332};
333
334static struct platform_driver mtk_wdt_driver = {
335	.probe		= mtk_wdt_probe,
336	.driver		= {
337		.name		= DRV_NAME,
338		.pm		= &mtk_wdt_pm_ops,
339		.of_match_table	= mtk_wdt_dt_ids,
340	},
341};
342
343module_platform_driver(mtk_wdt_driver);
344
345module_param(timeout, uint, 0);
346MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds");
347
348module_param(nowayout, bool, 0);
349MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
350			__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
351
352MODULE_LICENSE("GPL");
353MODULE_AUTHOR("Matthias Brugger <matthias.bgg@gmail.com>");
354MODULE_DESCRIPTION("Mediatek WatchDog Timer Driver");
355MODULE_VERSION(DRV_VERSION);