1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Spreadtrum watchdog driver
4 * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com
5 */
6
7#include <linux/bitops.h>
8#include <linux/clk.h>
9#include <linux/device.h>
10#include <linux/err.h>
11#include <linux/interrupt.h>
12#include <linux/io.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/platform_device.h>
18#include <linux/watchdog.h>
19
20#define SPRD_WDT_LOAD_LOW		0x0
21#define SPRD_WDT_LOAD_HIGH		0x4
22#define SPRD_WDT_CTRL			0x8
23#define SPRD_WDT_INT_CLR		0xc
24#define SPRD_WDT_INT_RAW		0x10
25#define SPRD_WDT_INT_MSK		0x14
26#define SPRD_WDT_CNT_LOW		0x18
27#define SPRD_WDT_CNT_HIGH		0x1c
28#define SPRD_WDT_LOCK			0x20
29#define SPRD_WDT_IRQ_LOAD_LOW		0x2c
30#define SPRD_WDT_IRQ_LOAD_HIGH		0x30
31
32/* WDT_CTRL */
33#define SPRD_WDT_INT_EN_BIT		BIT(0)
34#define SPRD_WDT_CNT_EN_BIT		BIT(1)
35#define SPRD_WDT_NEW_VER_EN		BIT(2)
36#define SPRD_WDT_RST_EN_BIT		BIT(3)
37
38/* WDT_INT_CLR */
39#define SPRD_WDT_INT_CLEAR_BIT		BIT(0)
40#define SPRD_WDT_RST_CLEAR_BIT		BIT(3)
41
42/* WDT_INT_RAW */
43#define SPRD_WDT_INT_RAW_BIT		BIT(0)
44#define SPRD_WDT_RST_RAW_BIT		BIT(3)
45#define SPRD_WDT_LD_BUSY_BIT		BIT(4)
46
47/* 1s equal to 32768 counter steps */
48#define SPRD_WDT_CNT_STEP		32768
49
50#define SPRD_WDT_UNLOCK_KEY		0xe551
51#define SPRD_WDT_MIN_TIMEOUT		3
52#define SPRD_WDT_MAX_TIMEOUT		60
53
54#define SPRD_WDT_CNT_HIGH_SHIFT		16
55#define SPRD_WDT_LOW_VALUE_MASK		GENMASK(15, 0)
56#define SPRD_WDT_LOAD_TIMEOUT		1000
57
58struct sprd_wdt {
59	void __iomem *base;
60	struct watchdog_device wdd;
61	struct clk *enable;
62	struct clk *rtc_enable;
63	int irq;
64};
65
66static inline struct sprd_wdt *to_sprd_wdt(struct watchdog_device *wdd)
67{
68	return container_of(wdd, struct sprd_wdt, wdd);
69}
70
71static inline void sprd_wdt_lock(void __iomem *addr)
72{
73	writel_relaxed(0x0, addr + SPRD_WDT_LOCK);
74}
75
76static inline void sprd_wdt_unlock(void __iomem *addr)
77{
78	writel_relaxed(SPRD_WDT_UNLOCK_KEY, addr + SPRD_WDT_LOCK);
79}
80
81static irqreturn_t sprd_wdt_isr(int irq, void *dev_id)
82{
83	struct sprd_wdt *wdt = (struct sprd_wdt *)dev_id;
84
85	sprd_wdt_unlock(wdt->base);
86	writel_relaxed(SPRD_WDT_INT_CLEAR_BIT, wdt->base + SPRD_WDT_INT_CLR);
87	sprd_wdt_lock(wdt->base);
88	watchdog_notify_pretimeout(&wdt->wdd);
89	return IRQ_HANDLED;
90}
91
92static u32 sprd_wdt_get_cnt_value(struct sprd_wdt *wdt)
93{
94	u32 val;
95
96	val = readl_relaxed(wdt->base + SPRD_WDT_CNT_HIGH) <<
97		SPRD_WDT_CNT_HIGH_SHIFT;
98	val |= readl_relaxed(wdt->base + SPRD_WDT_CNT_LOW) &
99		SPRD_WDT_LOW_VALUE_MASK;
100
101	return val;
102}
103
104static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout,
105			       u32 pretimeout)
106{
107	u32 val, delay_cnt = 0;
108	u32 tmr_step = timeout * SPRD_WDT_CNT_STEP;
109	u32 prtmr_step = pretimeout * SPRD_WDT_CNT_STEP;
110
111	/*
112	 * Waiting the load value operation done,
113	 * it needs two or three RTC clock cycles.
114	 */
115	do {
116		val = readl_relaxed(wdt->base + SPRD_WDT_INT_RAW);
117		if (!(val & SPRD_WDT_LD_BUSY_BIT))
118			break;
119
120		cpu_relax();
121	} while (delay_cnt++ < SPRD_WDT_LOAD_TIMEOUT);
122
123	if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT)
124		return -EBUSY;
125
126	sprd_wdt_unlock(wdt->base);
127	writel_relaxed((tmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) &
128		      SPRD_WDT_LOW_VALUE_MASK, wdt->base + SPRD_WDT_LOAD_HIGH);
129	writel_relaxed((tmr_step & SPRD_WDT_LOW_VALUE_MASK),
130		       wdt->base + SPRD_WDT_LOAD_LOW);
131	writel_relaxed((prtmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) &
132			SPRD_WDT_LOW_VALUE_MASK,
133		       wdt->base + SPRD_WDT_IRQ_LOAD_HIGH);
134	writel_relaxed(prtmr_step & SPRD_WDT_LOW_VALUE_MASK,
135		       wdt->base + SPRD_WDT_IRQ_LOAD_LOW);
136	sprd_wdt_lock(wdt->base);
137
138	return 0;
139}
140
141static int sprd_wdt_enable(struct sprd_wdt *wdt)
142{
143	u32 val;
144	int ret;
145
146	ret = clk_prepare_enable(wdt->enable);
147	if (ret)
148		return ret;
149	ret = clk_prepare_enable(wdt->rtc_enable);
150	if (ret) {
151		clk_disable_unprepare(wdt->enable);
152		return ret;
153	}
154
155	sprd_wdt_unlock(wdt->base);
156	val = readl_relaxed(wdt->base + SPRD_WDT_CTRL);
157	val |= SPRD_WDT_NEW_VER_EN;
158	writel_relaxed(val, wdt->base + SPRD_WDT_CTRL);
159	sprd_wdt_lock(wdt->base);
160	return 0;
161}
162
163static void sprd_wdt_disable(void *_data)
164{
165	struct sprd_wdt *wdt = _data;
166
167	sprd_wdt_unlock(wdt->base);
168	writel_relaxed(0x0, wdt->base + SPRD_WDT_CTRL);
169	sprd_wdt_lock(wdt->base);
170
171	clk_disable_unprepare(wdt->rtc_enable);
172	clk_disable_unprepare(wdt->enable);
173}
174
175static int sprd_wdt_start(struct watchdog_device *wdd)
176{
177	struct sprd_wdt *wdt = to_sprd_wdt(wdd);
178	u32 val;
179	int ret;
180
181	ret = sprd_wdt_load_value(wdt, wdd->timeout, wdd->pretimeout);
182	if (ret)
183		return ret;
184
185	sprd_wdt_unlock(wdt->base);
186	val = readl_relaxed(wdt->base + SPRD_WDT_CTRL);
187	val |= SPRD_WDT_CNT_EN_BIT | SPRD_WDT_INT_EN_BIT | SPRD_WDT_RST_EN_BIT;
188	writel_relaxed(val, wdt->base + SPRD_WDT_CTRL);
189	sprd_wdt_lock(wdt->base);
190	set_bit(WDOG_HW_RUNNING, &wdd->status);
191
192	return 0;
193}
194
195static int sprd_wdt_stop(struct watchdog_device *wdd)
196{
197	struct sprd_wdt *wdt = to_sprd_wdt(wdd);
198	u32 val;
199
200	sprd_wdt_unlock(wdt->base);
201	val = readl_relaxed(wdt->base + SPRD_WDT_CTRL);
202	val &= ~(SPRD_WDT_CNT_EN_BIT | SPRD_WDT_RST_EN_BIT |
203		SPRD_WDT_INT_EN_BIT);
204	writel_relaxed(val, wdt->base + SPRD_WDT_CTRL);
205	sprd_wdt_lock(wdt->base);
206	return 0;
207}
208
209static int sprd_wdt_set_timeout(struct watchdog_device *wdd,
210				u32 timeout)
211{
212	struct sprd_wdt *wdt = to_sprd_wdt(wdd);
213
214	if (timeout == wdd->timeout)
215		return 0;
216
217	wdd->timeout = timeout;
218
219	return sprd_wdt_load_value(wdt, timeout, wdd->pretimeout);
220}
221
222static int sprd_wdt_set_pretimeout(struct watchdog_device *wdd,
223				   u32 new_pretimeout)
224{
225	struct sprd_wdt *wdt = to_sprd_wdt(wdd);
226
227	if (new_pretimeout < wdd->min_timeout)
228		return -EINVAL;
229
230	wdd->pretimeout = new_pretimeout;
231
232	return sprd_wdt_load_value(wdt, wdd->timeout, new_pretimeout);
233}
234
235static u32 sprd_wdt_get_timeleft(struct watchdog_device *wdd)
236{
237	struct sprd_wdt *wdt = to_sprd_wdt(wdd);
238	u32 val;
239
240	val = sprd_wdt_get_cnt_value(wdt);
241	return val / SPRD_WDT_CNT_STEP;
242}
243
244static const struct watchdog_ops sprd_wdt_ops = {
245	.owner = THIS_MODULE,
246	.start = sprd_wdt_start,
247	.stop = sprd_wdt_stop,
248	.set_timeout = sprd_wdt_set_timeout,
249	.set_pretimeout = sprd_wdt_set_pretimeout,
250	.get_timeleft = sprd_wdt_get_timeleft,
251};
252
253static const struct watchdog_info sprd_wdt_info = {
254	.options = WDIOF_SETTIMEOUT |
255		   WDIOF_PRETIMEOUT |
256		   WDIOF_MAGICCLOSE |
257		   WDIOF_KEEPALIVEPING,
258	.identity = "Spreadtrum Watchdog Timer",
259};
260
261static int sprd_wdt_probe(struct platform_device *pdev)
262{
263	struct device *dev = &pdev->dev;
264	struct sprd_wdt *wdt;
265	int ret;
266
267	wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
268	if (!wdt)
269		return -ENOMEM;
270
271	wdt->base = devm_platform_ioremap_resource(pdev, 0);
272	if (IS_ERR(wdt->base))
273		return PTR_ERR(wdt->base);
274
275	wdt->enable = devm_clk_get(dev, "enable");
276	if (IS_ERR(wdt->enable)) {
277		dev_err(dev, "can't get the enable clock\n");
278		return PTR_ERR(wdt->enable);
279	}
280
281	wdt->rtc_enable = devm_clk_get(dev, "rtc_enable");
282	if (IS_ERR(wdt->rtc_enable)) {
283		dev_err(dev, "can't get the rtc enable clock\n");
284		return PTR_ERR(wdt->rtc_enable);
285	}
286
287	wdt->irq = platform_get_irq(pdev, 0);
288	if (wdt->irq < 0)
289		return wdt->irq;
290
291	ret = devm_request_irq(dev, wdt->irq, sprd_wdt_isr, IRQF_NO_SUSPEND,
292			       "sprd-wdt", (void *)wdt);
293	if (ret) {
294		dev_err(dev, "failed to register irq\n");
295		return ret;
296	}
297
298	wdt->wdd.info = &sprd_wdt_info;
299	wdt->wdd.ops = &sprd_wdt_ops;
300	wdt->wdd.parent = dev;
301	wdt->wdd.min_timeout = SPRD_WDT_MIN_TIMEOUT;
302	wdt->wdd.max_timeout = SPRD_WDT_MAX_TIMEOUT;
303	wdt->wdd.timeout = SPRD_WDT_MAX_TIMEOUT;
304
305	ret = sprd_wdt_enable(wdt);
306	if (ret) {
307		dev_err(dev, "failed to enable wdt\n");
308		return ret;
309	}
310	ret = devm_add_action_or_reset(dev, sprd_wdt_disable, wdt);
311	if (ret) {
312		dev_err(dev, "Failed to add wdt disable action\n");
313		return ret;
314	}
315
316	watchdog_set_nowayout(&wdt->wdd, WATCHDOG_NOWAYOUT);
317	watchdog_init_timeout(&wdt->wdd, 0, dev);
318
319	ret = devm_watchdog_register_device(dev, &wdt->wdd);
320	if (ret) {
321		sprd_wdt_disable(wdt);
322		return ret;
323	}
324	platform_set_drvdata(pdev, wdt);
325
326	return 0;
327}
328
329static int __maybe_unused sprd_wdt_pm_suspend(struct device *dev)
330{
331	struct sprd_wdt *wdt = dev_get_drvdata(dev);
332
333	if (watchdog_active(&wdt->wdd))
334		sprd_wdt_stop(&wdt->wdd);
335	sprd_wdt_disable(wdt);
336
337	return 0;
338}
339
340static int __maybe_unused sprd_wdt_pm_resume(struct device *dev)
341{
342	struct sprd_wdt *wdt = dev_get_drvdata(dev);
343	int ret;
344
345	ret = sprd_wdt_enable(wdt);
346	if (ret)
347		return ret;
348
349	if (watchdog_active(&wdt->wdd))
350		ret = sprd_wdt_start(&wdt->wdd);
351
352	return ret;
353}
354
355static const struct dev_pm_ops sprd_wdt_pm_ops = {
356	SET_SYSTEM_SLEEP_PM_OPS(sprd_wdt_pm_suspend,
357				sprd_wdt_pm_resume)
358};
359
360static const struct of_device_id sprd_wdt_match_table[] = {
361	{ .compatible = "sprd,sp9860-wdt", },
362	{},
363};
364MODULE_DEVICE_TABLE(of, sprd_wdt_match_table);
365
366static struct platform_driver sprd_watchdog_driver = {
367	.probe	= sprd_wdt_probe,
368	.driver	= {
369		.name = "sprd-wdt",
370		.of_match_table = sprd_wdt_match_table,
371		.pm = &sprd_wdt_pm_ops,
372	},
373};
374module_platform_driver(sprd_watchdog_driver);
375
376MODULE_AUTHOR("Eric Long <eric.long@spreadtrum.com>");
377MODULE_DESCRIPTION("Spreadtrum Watchdog Timer Controller Driver");
378MODULE_LICENSE("GPL v2");
379