1 // SPDX-License-Identifier: GPL-2.0-only
3 * Spreadtrum watchdog driver
4 * Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.com
7 #include <linux/bitops.h>
9 #include <linux/device.h>
10 #include <linux/err.h>
11 #include <linux/interrupt.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
16 #include <linux/of_address.h>
17 #include <linux/platform_device.h>
18 #include <linux/watchdog.h>
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
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)
39 #define SPRD_WDT_INT_CLEAR_BIT BIT(0)
40 #define SPRD_WDT_RST_CLEAR_BIT BIT(3)
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)
47 /* 1s equal to 32768 counter steps */
48 #define SPRD_WDT_CNT_STEP 32768
50 #define SPRD_WDT_UNLOCK_KEY 0xe551
51 #define SPRD_WDT_MIN_TIMEOUT 3
52 #define SPRD_WDT_MAX_TIMEOUT 60
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
60 struct watchdog_device wdd
;
62 struct clk
*rtc_enable
;
66 static inline struct sprd_wdt
*to_sprd_wdt(struct watchdog_device
*wdd
)
68 return container_of(wdd
, struct sprd_wdt
, wdd
);
71 static inline void sprd_wdt_lock(void __iomem
*addr
)
73 writel_relaxed(0x0, addr
+ SPRD_WDT_LOCK
);
76 static inline void sprd_wdt_unlock(void __iomem
*addr
)
78 writel_relaxed(SPRD_WDT_UNLOCK_KEY
, addr
+ SPRD_WDT_LOCK
);
81 static irqreturn_t
sprd_wdt_isr(int irq
, void *dev_id
)
83 struct sprd_wdt
*wdt
= (struct sprd_wdt
*)dev_id
;
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
);
92 static u32
sprd_wdt_get_cnt_value(struct sprd_wdt
*wdt
)
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
;
104 static int sprd_wdt_load_value(struct sprd_wdt
*wdt
, u32 timeout
,
107 u32 val
, delay_cnt
= 0;
108 u32 tmr_step
= timeout
* SPRD_WDT_CNT_STEP
;
109 u32 prtmr_step
= pretimeout
* SPRD_WDT_CNT_STEP
;
111 sprd_wdt_unlock(wdt
->base
);
112 writel_relaxed((tmr_step
>> SPRD_WDT_CNT_HIGH_SHIFT
) &
113 SPRD_WDT_LOW_VALUE_MASK
, wdt
->base
+ SPRD_WDT_LOAD_HIGH
);
114 writel_relaxed((tmr_step
& SPRD_WDT_LOW_VALUE_MASK
),
115 wdt
->base
+ SPRD_WDT_LOAD_LOW
);
116 writel_relaxed((prtmr_step
>> SPRD_WDT_CNT_HIGH_SHIFT
) &
117 SPRD_WDT_LOW_VALUE_MASK
,
118 wdt
->base
+ SPRD_WDT_IRQ_LOAD_HIGH
);
119 writel_relaxed(prtmr_step
& SPRD_WDT_LOW_VALUE_MASK
,
120 wdt
->base
+ SPRD_WDT_IRQ_LOAD_LOW
);
121 sprd_wdt_lock(wdt
->base
);
124 * Waiting the load value operation done,
125 * it needs two or three RTC clock cycles.
128 val
= readl_relaxed(wdt
->base
+ SPRD_WDT_INT_RAW
);
129 if (!(val
& SPRD_WDT_LD_BUSY_BIT
))
133 } while (delay_cnt
++ < SPRD_WDT_LOAD_TIMEOUT
);
135 if (delay_cnt
>= SPRD_WDT_LOAD_TIMEOUT
)
140 static int sprd_wdt_enable(struct sprd_wdt
*wdt
)
145 ret
= clk_prepare_enable(wdt
->enable
);
148 ret
= clk_prepare_enable(wdt
->rtc_enable
);
150 clk_disable_unprepare(wdt
->enable
);
154 sprd_wdt_unlock(wdt
->base
);
155 val
= readl_relaxed(wdt
->base
+ SPRD_WDT_CTRL
);
156 val
|= SPRD_WDT_NEW_VER_EN
;
157 writel_relaxed(val
, wdt
->base
+ SPRD_WDT_CTRL
);
158 sprd_wdt_lock(wdt
->base
);
162 static void sprd_wdt_disable(void *_data
)
164 struct sprd_wdt
*wdt
= _data
;
166 sprd_wdt_unlock(wdt
->base
);
167 writel_relaxed(0x0, wdt
->base
+ SPRD_WDT_CTRL
);
168 sprd_wdt_lock(wdt
->base
);
170 clk_disable_unprepare(wdt
->rtc_enable
);
171 clk_disable_unprepare(wdt
->enable
);
174 static int sprd_wdt_start(struct watchdog_device
*wdd
)
176 struct sprd_wdt
*wdt
= to_sprd_wdt(wdd
);
180 ret
= sprd_wdt_load_value(wdt
, wdd
->timeout
, wdd
->pretimeout
);
184 sprd_wdt_unlock(wdt
->base
);
185 val
= readl_relaxed(wdt
->base
+ SPRD_WDT_CTRL
);
186 val
|= SPRD_WDT_CNT_EN_BIT
| SPRD_WDT_INT_EN_BIT
| SPRD_WDT_RST_EN_BIT
;
187 writel_relaxed(val
, wdt
->base
+ SPRD_WDT_CTRL
);
188 sprd_wdt_lock(wdt
->base
);
189 set_bit(WDOG_HW_RUNNING
, &wdd
->status
);
194 static int sprd_wdt_stop(struct watchdog_device
*wdd
)
196 struct sprd_wdt
*wdt
= to_sprd_wdt(wdd
);
199 sprd_wdt_unlock(wdt
->base
);
200 val
= readl_relaxed(wdt
->base
+ SPRD_WDT_CTRL
);
201 val
&= ~(SPRD_WDT_CNT_EN_BIT
| SPRD_WDT_RST_EN_BIT
|
202 SPRD_WDT_INT_EN_BIT
);
203 writel_relaxed(val
, wdt
->base
+ SPRD_WDT_CTRL
);
204 sprd_wdt_lock(wdt
->base
);
208 static int sprd_wdt_set_timeout(struct watchdog_device
*wdd
,
211 struct sprd_wdt
*wdt
= to_sprd_wdt(wdd
);
213 if (timeout
== wdd
->timeout
)
216 wdd
->timeout
= timeout
;
218 return sprd_wdt_load_value(wdt
, timeout
, wdd
->pretimeout
);
221 static int sprd_wdt_set_pretimeout(struct watchdog_device
*wdd
,
224 struct sprd_wdt
*wdt
= to_sprd_wdt(wdd
);
226 if (new_pretimeout
< wdd
->min_timeout
)
229 wdd
->pretimeout
= new_pretimeout
;
231 return sprd_wdt_load_value(wdt
, wdd
->timeout
, new_pretimeout
);
234 static u32
sprd_wdt_get_timeleft(struct watchdog_device
*wdd
)
236 struct sprd_wdt
*wdt
= to_sprd_wdt(wdd
);
239 val
= sprd_wdt_get_cnt_value(wdt
);
240 return val
/ SPRD_WDT_CNT_STEP
;
243 static const struct watchdog_ops sprd_wdt_ops
= {
244 .owner
= THIS_MODULE
,
245 .start
= sprd_wdt_start
,
246 .stop
= sprd_wdt_stop
,
247 .set_timeout
= sprd_wdt_set_timeout
,
248 .set_pretimeout
= sprd_wdt_set_pretimeout
,
249 .get_timeleft
= sprd_wdt_get_timeleft
,
252 static const struct watchdog_info sprd_wdt_info
= {
253 .options
= WDIOF_SETTIMEOUT
|
257 .identity
= "Spreadtrum Watchdog Timer",
260 static int sprd_wdt_probe(struct platform_device
*pdev
)
262 struct device
*dev
= &pdev
->dev
;
263 struct sprd_wdt
*wdt
;
266 wdt
= devm_kzalloc(dev
, sizeof(*wdt
), GFP_KERNEL
);
270 wdt
->base
= devm_platform_ioremap_resource(pdev
, 0);
271 if (IS_ERR(wdt
->base
))
272 return PTR_ERR(wdt
->base
);
274 wdt
->enable
= devm_clk_get(dev
, "enable");
275 if (IS_ERR(wdt
->enable
)) {
276 dev_err(dev
, "can't get the enable clock\n");
277 return PTR_ERR(wdt
->enable
);
280 wdt
->rtc_enable
= devm_clk_get(dev
, "rtc_enable");
281 if (IS_ERR(wdt
->rtc_enable
)) {
282 dev_err(dev
, "can't get the rtc enable clock\n");
283 return PTR_ERR(wdt
->rtc_enable
);
286 wdt
->irq
= platform_get_irq(pdev
, 0);
290 ret
= devm_request_irq(dev
, wdt
->irq
, sprd_wdt_isr
, IRQF_NO_SUSPEND
,
291 "sprd-wdt", (void *)wdt
);
293 dev_err(dev
, "failed to register irq\n");
297 wdt
->wdd
.info
= &sprd_wdt_info
;
298 wdt
->wdd
.ops
= &sprd_wdt_ops
;
299 wdt
->wdd
.parent
= dev
;
300 wdt
->wdd
.min_timeout
= SPRD_WDT_MIN_TIMEOUT
;
301 wdt
->wdd
.max_timeout
= SPRD_WDT_MAX_TIMEOUT
;
302 wdt
->wdd
.timeout
= SPRD_WDT_MAX_TIMEOUT
;
304 ret
= sprd_wdt_enable(wdt
);
306 dev_err(dev
, "failed to enable wdt\n");
309 ret
= devm_add_action_or_reset(dev
, sprd_wdt_disable
, wdt
);
311 dev_err(dev
, "Failed to add wdt disable action\n");
315 watchdog_set_nowayout(&wdt
->wdd
, WATCHDOG_NOWAYOUT
);
316 watchdog_init_timeout(&wdt
->wdd
, 0, dev
);
318 ret
= devm_watchdog_register_device(dev
, &wdt
->wdd
);
320 sprd_wdt_disable(wdt
);
323 platform_set_drvdata(pdev
, wdt
);
328 static int __maybe_unused
sprd_wdt_pm_suspend(struct device
*dev
)
330 struct sprd_wdt
*wdt
= dev_get_drvdata(dev
);
332 if (watchdog_active(&wdt
->wdd
))
333 sprd_wdt_stop(&wdt
->wdd
);
334 sprd_wdt_disable(wdt
);
339 static int __maybe_unused
sprd_wdt_pm_resume(struct device
*dev
)
341 struct sprd_wdt
*wdt
= dev_get_drvdata(dev
);
344 ret
= sprd_wdt_enable(wdt
);
348 if (watchdog_active(&wdt
->wdd
)) {
349 ret
= sprd_wdt_start(&wdt
->wdd
);
351 sprd_wdt_disable(wdt
);
359 static const struct dev_pm_ops sprd_wdt_pm_ops
= {
360 SET_SYSTEM_SLEEP_PM_OPS(sprd_wdt_pm_suspend
,
364 static const struct of_device_id sprd_wdt_match_table
[] = {
365 { .compatible
= "sprd,sp9860-wdt", },
368 MODULE_DEVICE_TABLE(of
, sprd_wdt_match_table
);
370 static struct platform_driver sprd_watchdog_driver
= {
371 .probe
= sprd_wdt_probe
,
374 .of_match_table
= sprd_wdt_match_table
,
375 .pm
= &sprd_wdt_pm_ops
,
378 module_platform_driver(sprd_watchdog_driver
);
380 MODULE_AUTHOR("Eric Long <eric.long@spreadtrum.com>");
381 MODULE_DESCRIPTION("Spreadtrum Watchdog Timer Controller Driver");
382 MODULE_LICENSE("GPL v2");