watchdog: starfive: Get timeleft correctly
[platform/kernel/linux-starfive.git] / drivers / watchdog / starfive-wdt.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2021 StarFive, Inc <samin.guo@starfivetech.com>
4  * Copyright 2022 StarFive, Inc <xingyu.wu@starfivetech.com>
5  *
6  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING
7  * CUSTOMERS WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER
8  * FOR THEM TO SAVE TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE
9  * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY
10  * CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE
11  * BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONNECTION
12  * WITH THEIR PRODUCTS.
13  */
14
15 #include <linux/clk.h>
16 #include <linux/delay.h>
17 #include <linux/err.h>
18 #include <linux/module.h>
19 #include <linux/moduleparam.h>
20 #include <linux/mfd/syscon.h>
21 #include <linux/io.h>
22 #include <linux/iopoll.h>
23 #include <linux/interrupt.h>
24 #include <linux/of.h>
25 #include <linux/of_device.h>
26 #include <linux/platform_device.h>
27 #include <linux/slab.h>
28 #include <linux/types.h>
29 #include <linux/timer.h>
30 #include <linux/uaccess.h>
31 #include <linux/watchdog.h>
32 #include <linux/reset.h>
33 #include <linux/reset-controller.h>
34 #include <linux/pm_runtime.h>
35
36 #define WDT_INT_DIS     BIT(0)
37 #define DELAY_US        0
38 #define TIMEOUT_US      10000
39
40 /* JH7100 WatchDog register define */
41 #define JH7100_WDGINTSTAUS      0x000
42 #define JH7100_WDOGCONTROL      0x104   /* Watchdog Control Register R/W */
43 #define JH7100_WDOGLOAD         0x108   /* The initial value to be loaded */
44                                 /* into the counter and is also used */
45                                 /* as the reload value. R/W */
46 #define JH7100_WDOGEN           0x110   /* Watchdog enable Register */
47 #define JH7100_WDOGRELOAD       0x114   /* Write this register to reload preset */
48                                 /* value to counter. (Write 0 or 1 are both ok) */
49 #define JH7100_WDOGVALUE        0x118   /* Watchdog Value Register RO */
50 #define JH7100_WDOGINTCLR       0x120   /* Watchdog Clear Interrupt Register WO */
51 #define JH7100_WDOGINTMSK       0x124   /* Watchdog Interrupt Mask Register */
52 #define JH7100_WDOGLOCK         0x13c   /* Watchdog Lock Register  R/W */
53
54 #define JH7100_UNLOCK_KEY       0x378f0765
55 #define JH7100_RESEN_SHIFT      0
56 #define JH7100_EN_SHIFT         0
57 #define JH7100_INTCLR_AVA_SHIFT 1       /* Watchdog can clear interrupt when this bit is 0 */
58
59 /* JH7110 WatchDog register define */
60 #define JH7110_WDOGLOAD         0x000   /* RW: Watchdog load register */
61 #define JH7110_WDOGVALUE        0x004   /* RO: The current value for the watchdog counter */
62 #define JH7110_WDOGCONTROL      0x008   /* RW: [0]: reset enable;  [1]: int enable/wdt enable/reload counter; [31:2]: res */
63 #define JH7110_WDOGINTCLR       0x00c   /* WO: clear intterupt && reload the counter */
64 #define JH7110_WDOGRIS          0x010   /* RO: Raw interrupt status from the counter */
65 #define JH7110_WDOGIMS          0x014   /* RO: Enabled interrupt status from the counter */
66 #define JH7110_WDOGLOCK         0xc00   /* RO: Enable write access to all other registers by writing 0x1ACCE551 */
67 #define JH7110_WDOGITCR         0xf00   /* RW: When set HIGH, places the Watchdog into integraeion test mode */
68 #define JH7110_WDOGITOP         0xf04   /* WO:  [0] Integration Test WDOGRES value Integration Test Mode
69                                          * Value output on WDOGRES when in Integration Test Mode
70                                          * [1] Integration Test WDOGINT value
71                                          * Value output on WDOGINT when in Integration Test Mode
72                                          */
73
74 #define JH7110_UNLOCK_KEY       0x1acce551
75 #define JH7110_RESEN_SHIFT      1
76 #define JH7110_EN_SHIFT         0
77 #define JH7110_INT_EN_SHIFT     JH7110_EN_SHIFT
78
79 /* WDOGCONTROL */
80 #define WDOG_INT_EN     0x0
81 #define WDOG_RESET_EN   0x1
82
83 /* WDOGLOCK */
84 #define WDOG_LOCKED             BIT(0)
85
86 #define STARFIVE_WATCHDOG_INTCLR        0x1
87 #define STARFIVE_WATCHDOG_ENABLE        0x1
88 #define STARFIVE_WATCHDOG_ATBOOT        0x0
89 #define STARFIVE_WATCHDOG_MAXCNT        0xffffffff
90
91 #define STARFIVE_WATCHDOG_DEFAULT_TIME  (15)
92
93 static bool nowayout = WATCHDOG_NOWAYOUT;
94 static int tmr_margin;
95 static int tmr_atboot = STARFIVE_WATCHDOG_ATBOOT;
96 static int soft_noboot;
97
98 module_param(tmr_margin, int, 0);
99 module_param(tmr_atboot, int, 0);
100 module_param(nowayout, bool, 0);
101 module_param(soft_noboot, int, 0);
102
103 MODULE_PARM_DESC(tmr_margin, "Watchdog tmr_margin in seconds. (default="
104                 __MODULE_STRING(STARFIVE_WATCHDOG_DEFAULT_TIME) ")");
105 MODULE_PARM_DESC(tmr_atboot,
106                 "Watchdog is started at boot time if set to 1, default="
107                         __MODULE_STRING(STARFIVE_WATCHDOG_ATBOOT));
108 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
109                         __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
110 MODULE_PARM_DESC(soft_noboot,
111         "Watchdog action, set to 1 to ignore reboots, 0 to reboot (default 0)");
112
113 struct starfive_wdt_variant_t {
114         u32 unlock_key;
115         u8 enrst_shift;
116         u8 en_shift;
117         u8 intclr_check;
118         u8 intclr_ava_shift;
119 };
120
121 struct starfive_wdt_variant {
122         u32 control;
123         u32 load;
124         u32 enable;
125         u32 reload;
126         u32 value;
127         u32 int_clr;
128         u32 int_mask;
129         u32 unlock;
130         u32 enter_irq_status;
131         struct starfive_wdt_variant_t *variant;
132 };
133
134 struct starfive_wdt {
135         u64 freq;
136         struct device *dev;
137         struct watchdog_device wdt_device;
138         struct clk *core_clk;
139         struct clk *apb_clk;
140         struct reset_control *rsts;
141         const struct starfive_wdt_variant *drv_data;
142         u32 count;      /*count of timeout*/
143         u32 reload;     /*restore the count*/
144         void __iomem *base;
145         spinlock_t lock;
146
147         int irq;
148 };
149
150 #ifdef CONFIG_OF
151 static struct starfive_wdt_variant_t jh7100_variant = {
152         .unlock_key = JH7100_UNLOCK_KEY,
153         .enrst_shift = JH7100_RESEN_SHIFT,
154         .en_shift = JH7100_EN_SHIFT,
155         .intclr_check = 1,
156         .intclr_ava_shift = JH7100_INTCLR_AVA_SHIFT,
157 };
158
159 static struct starfive_wdt_variant_t jh7110_variant = {
160         .unlock_key = JH7110_UNLOCK_KEY,
161         .enrst_shift = JH7110_RESEN_SHIFT,
162         .en_shift = JH7110_EN_SHIFT,
163 };
164
165 static const struct starfive_wdt_variant drv_data_jh7100 = {
166         .control = JH7100_WDOGCONTROL,
167         .load = JH7100_WDOGLOAD,
168         .enable = JH7100_WDOGEN,
169         .reload = JH7100_WDOGRELOAD,
170         .value = JH7100_WDOGVALUE,
171         .int_clr = JH7100_WDOGINTCLR,
172         .int_mask = JH7100_WDOGINTMSK,
173         .unlock = JH7100_WDOGLOCK,
174         .variant = &jh7100_variant,
175 };
176
177 static const struct starfive_wdt_variant drv_data_jh7110 = {
178         .control = JH7110_WDOGCONTROL,
179         .load = JH7110_WDOGLOAD,
180         .enable = JH7110_WDOGCONTROL,
181         .value = JH7110_WDOGVALUE,
182         .int_clr = JH7110_WDOGINTCLR,
183         .unlock = JH7110_WDOGLOCK,
184         .enter_irq_status = JH7110_WDOGIMS,
185         .variant = &jh7110_variant,
186 };
187
188 static const struct of_device_id starfive_wdt_match[] = {
189         { .compatible = "starfive,jh7100-wdt", .data = &drv_data_jh7100 },
190         { .compatible = "starfive,jh7110-wdt", .data = &drv_data_jh7110 },
191         {},
192 };
193 MODULE_DEVICE_TABLE(of, starfive_wdt_match);
194 #endif
195
196 static const struct platform_device_id starfive_wdt_ids[] = {
197         {
198                 .name = "starfive-wdt",
199                 .driver_data = (unsigned long)&drv_data_jh7100,
200         },
201         {
202                 .name = "starfive-dskit-wdt",
203                 .driver_data = (unsigned long)&drv_data_jh7110,
204         },
205         {}
206 };
207 MODULE_DEVICE_TABLE(platform, starfive_wdt_ids);
208
209 static int starfive_wdt_get_clock_rate(struct starfive_wdt *wdt)
210 {
211         int ret;
212         u32 freq;
213
214         /* Next we try to get clock-frequency from dts.*/
215         ret = of_property_read_u32(wdt->dev->of_node, "clock-frequency", &freq);
216         if (!ret) {
217                 wdt->freq = (u64)freq;
218                 return 0;
219         }
220         dev_dbg(wdt->dev, "get rate failed, need clock-frequency define in dts.\n");
221
222         if (!IS_ERR(wdt->core_clk)) {
223                 wdt->freq = clk_get_rate(wdt->core_clk);
224                 return 0;
225         }
226         dev_err(wdt->dev, "get clock-frequency failed\n");
227         return -ENOENT;
228 }
229
230 static int starfive_wdt_enable_clock(struct starfive_wdt *wdt)
231 {
232         int err = 0;
233
234         wdt->apb_clk = devm_clk_get(wdt->dev, "apb_clk");
235         if (!IS_ERR(wdt->apb_clk)) {
236                 err = clk_prepare_enable(wdt->apb_clk);
237                 if (err)
238                         dev_warn(wdt->dev, "enable core_clk error.\n");
239         }
240
241         wdt->core_clk = devm_clk_get(wdt->dev, "core_clk");
242         if (!IS_ERR(wdt->core_clk)) {
243                 err = clk_prepare_enable(wdt->core_clk);
244                 if (err)
245                         dev_warn(wdt->dev, "enable apb_clk error.\n");
246         }
247
248         return err;
249 }
250
251 static int starfive_wdt_reset_init(struct starfive_wdt *wdt)
252 {
253         int err = 0;
254
255         wdt->rsts = devm_reset_control_array_get_exclusive(wdt->dev);
256         if (!IS_ERR(wdt->rsts)) {
257                 err = reset_control_deassert(wdt->rsts);
258                 if (err)
259                         dev_err(wdt->dev, "deassert rsts error.\n");
260         } else
261                 err = PTR_ERR(wdt->rsts);
262
263         return err;
264 }
265
266 static __maybe_unused
267 u32 starfive_wdt_sec_to_ticks(struct starfive_wdt *wdt, u32 sec)
268 {
269         return sec * wdt->freq;
270 }
271
272 static __maybe_unused
273 u32 starfive_wdt_ticks_to_sec(struct starfive_wdt *wdt, u32 ticks)
274 {
275         return DIV_ROUND_CLOSEST(ticks, wdt->freq);
276 }
277
278 /*
279  * Write unlock-key to unlock. Write other value to lock. When lock bit is 1,
280  * external accesses to other watchdog registers are ignored.
281  */
282 static int starfive_wdt_is_locked(struct starfive_wdt *wdt)
283 {
284         u32 val;
285
286         val = readl(wdt->base + wdt->drv_data->unlock);
287         return !!(val & WDOG_LOCKED);
288 }
289
290 static void starfive_wdt_unlock(struct starfive_wdt *wdt)
291 {
292         if (starfive_wdt_is_locked(wdt))
293                 writel(wdt->drv_data->variant->unlock_key,
294                         wdt->base + wdt->drv_data->unlock);
295 }
296
297 static void starfive_wdt_lock(struct starfive_wdt *wdt)
298 {
299         if (!starfive_wdt_is_locked(wdt))
300                 writel(~wdt->drv_data->variant->unlock_key,
301                         wdt->base + wdt->drv_data->unlock);
302 }
303
304 static int __maybe_unused starfive_wdt_is_running(struct starfive_wdt *wdt)
305 {
306         u32 val;
307
308         starfive_wdt_unlock(wdt);
309         val = readl(wdt->base + wdt->drv_data->enable);
310         starfive_wdt_lock(wdt);
311
312         return !!(val & STARFIVE_WATCHDOG_ENABLE <<
313                 wdt->drv_data->variant->en_shift);
314 }
315
316 static inline void starfive_wdt_int_enable(struct starfive_wdt *wdt)
317 {
318         u32 val;
319
320         if (wdt->drv_data->int_mask) {
321                 val = readl(wdt->base + wdt->drv_data->int_mask);
322                 val &= ~WDT_INT_DIS;
323                 writel(val, wdt->base + wdt->drv_data->int_mask);
324         }
325 }
326
327 static inline void starfive_wdt_int_disable(struct starfive_wdt *wdt)
328 {
329         u32 val;
330
331         if (wdt->drv_data->int_mask) {
332                 val = readl(wdt->base + wdt->drv_data->int_mask);
333                 val |= WDT_INT_DIS;
334                 writel(val, wdt->base + wdt->drv_data->int_mask);
335         }
336 }
337
338 static void starfive_wdt_enable_reset(struct starfive_wdt *wdt)
339 {
340         u32 val;
341
342         val = readl(wdt->base + wdt->drv_data->control);
343         val |= WDOG_RESET_EN << wdt->drv_data->variant->enrst_shift;
344         /* enable wdog interrupt to reset */
345         writel(val, wdt->base + wdt->drv_data->control);
346 }
347
348 static void starfive_wdt_disable_reset(struct starfive_wdt *wdt)
349 {
350         u32 val;
351
352         val = readl(wdt->base + wdt->drv_data->control);
353         val &= ~(WDOG_RESET_EN << wdt->drv_data->variant->enrst_shift);
354         /*disable wdog interrupt to reset*/
355         writel(val, wdt->base + wdt->drv_data->control);
356 }
357
358 static bool starfive_wdt_enter_irq_status(struct starfive_wdt *wdt)
359 {
360         /* interrupt status whether has entered from the counter */
361         return !!readl(wdt->base + wdt->drv_data->enter_irq_status);
362 }
363
364 static void starfive_wdt_int_clr(struct starfive_wdt *wdt)
365 {
366         void __iomem *addr;
367         u8 clr_check;
368         u8 clr_ava_shift;
369         u32 value;
370         int ret = 0;
371
372         addr = wdt->base + wdt->drv_data->int_clr;
373         clr_ava_shift = wdt->drv_data->variant->intclr_ava_shift;
374         clr_check = wdt->drv_data->variant->intclr_check;
375         if (clr_check) {
376                 /* waiting interrupt can be to clearing */
377                 value = readl(addr);
378                 ret = readl_poll_timeout_atomic(addr, value,
379                                 !(value & BIT(clr_ava_shift)), DELAY_US, TIMEOUT_US);
380         }
381
382         if (!ret)
383                 writel(STARFIVE_WATCHDOG_INTCLR, addr);
384
385         if (starfive_wdt_enter_irq_status(wdt))
386                 enable_irq(wdt->irq);
387 }
388
389 static inline void starfive_wdt_set_count(struct starfive_wdt *wdt, u32 val)
390 {
391         writel(val, wdt->base + wdt->drv_data->load);
392 }
393
394 static inline u32 starfive_wdt_get_count(struct starfive_wdt *wdt)
395 {
396         return readl(wdt->base + wdt->drv_data->value);
397 }
398
399 static inline void starfive_wdt_enable(struct starfive_wdt *wdt)
400 {
401         u32 val;
402
403         val = readl(wdt->base + wdt->drv_data->enable);
404         val |= STARFIVE_WATCHDOG_ENABLE << wdt->drv_data->variant->en_shift;
405         writel(val, wdt->base + wdt->drv_data->enable);
406 }
407
408 static inline void starfive_wdt_disable(struct starfive_wdt *wdt)
409 {
410         u32 val;
411
412         val = readl(wdt->base + wdt->drv_data->enable);
413         val &= ~(STARFIVE_WATCHDOG_ENABLE << wdt->drv_data->variant->en_shift);
414         writel(val, wdt->base + wdt->drv_data->enable);
415 }
416
417 static inline void
418 starfive_wdt_set_relod_count(struct starfive_wdt *wdt, u32 count)
419 {
420         writel(count, wdt->base + wdt->drv_data->load);
421         if (wdt->drv_data->reload)
422                 writel(0x1, wdt->base + wdt->drv_data->reload);
423         else
424                 /* jh7110 need enable controller to reload counter */
425                 starfive_wdt_enable(wdt);
426 }
427
428 static int starfive_wdt_mask_and_disable_reset(struct starfive_wdt *wdt, bool mask)
429 {
430         starfive_wdt_unlock(wdt);
431
432         if (mask)
433                 starfive_wdt_disable_reset(wdt);
434         else
435                 starfive_wdt_enable_reset(wdt);
436
437         starfive_wdt_lock(wdt);
438
439         return 0;
440 }
441
442 static unsigned int starfive_wdt_max_timeout(struct starfive_wdt *wdt)
443 {
444         return DIV_ROUND_UP(STARFIVE_WATCHDOG_MAXCNT, wdt->freq) - 1;
445 }
446
447 static unsigned int starfive_wdt_get_timeleft(struct watchdog_device *wdd)
448 {
449         struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
450         u32 count;
451         u32 irq_status;
452
453         starfive_wdt_unlock(wdt);
454         /*
455          * Because set half count value,
456          * timeleft value should add the count value before first timeout.
457          */
458         irq_status = starfive_wdt_enter_irq_status(wdt) ? 1 : 0;
459         count = starfive_wdt_get_count(wdt) + (1 - irq_status) * wdt->count;
460         starfive_wdt_lock(wdt);
461
462         return starfive_wdt_ticks_to_sec(wdt, count);
463 }
464
465 static int starfive_wdt_keepalive(struct watchdog_device *wdd)
466 {
467         struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
468
469         spin_lock(&wdt->lock);
470
471         starfive_wdt_unlock(wdt);
472         starfive_wdt_int_clr(wdt);
473         starfive_wdt_set_relod_count(wdt, wdt->count);
474         starfive_wdt_lock(wdt);
475
476         spin_unlock(&wdt->lock);
477
478         return 0;
479 }
480
481 static irqreturn_t starfive_wdt_interrupt_handler(int irq, void *data)
482 {
483         /*
484          * We don't clear the IRQ status. It's supposed to be done by the
485          * following ping operations.
486          */
487         struct platform_device *pdev = data;
488         struct starfive_wdt *wdt = platform_get_drvdata(pdev);
489
490         /* Disable the IRQ and avoid re-entry interrupt. */
491         disable_irq_nosync(wdt->irq);
492
493         return IRQ_HANDLED;
494 }
495
496 static int starfive_wdt_stop(struct watchdog_device *wdd)
497 {
498         struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
499
500         spin_lock(&wdt->lock);
501
502         starfive_wdt_unlock(wdt);
503         starfive_wdt_int_disable(wdt);
504         starfive_wdt_int_clr(wdt);
505         starfive_wdt_disable(wdt);
506         starfive_wdt_lock(wdt);
507
508         spin_unlock(&wdt->lock);
509
510         return 0;
511 }
512
513 static int starfive_wdt_pm_stop(struct watchdog_device *wdd)
514 {
515         struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
516
517         starfive_wdt_stop(wdd);
518         pm_runtime_put(wdt->dev);
519
520         return 0;
521 }
522
523 static int starfive_wdt_start(struct watchdog_device *wdd)
524 {
525         struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
526
527         pm_runtime_get_sync(wdt->dev);
528
529         spin_lock(&wdt->lock);
530
531         starfive_wdt_unlock(wdt);
532
533         if (soft_noboot)
534                 starfive_wdt_disable_reset(wdt);
535         else
536                 starfive_wdt_enable_reset(wdt);
537
538         starfive_wdt_int_clr(wdt);
539         starfive_wdt_set_count(wdt, wdt->count);
540         starfive_wdt_int_enable(wdt);
541         starfive_wdt_enable(wdt);
542
543         starfive_wdt_lock(wdt);
544
545         spin_unlock(&wdt->lock);
546
547         return 0;
548 }
549
550 static int starfive_wdt_restart(struct watchdog_device *wdd, unsigned long action,
551                                 void *data)
552 {
553         struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
554
555         starfive_wdt_unlock(wdt);
556         /* disable watchdog, to be safe */
557         starfive_wdt_disable(wdt);
558
559         if (soft_noboot)
560                 starfive_wdt_disable_reset(wdt);
561         else
562                 starfive_wdt_enable_reset(wdt);
563
564         /* put initial values into count and data */
565         starfive_wdt_set_count(wdt, wdt->count);
566
567         /* set the watchdog to go and reset... */
568         starfive_wdt_int_clr(wdt);
569         starfive_wdt_int_enable(wdt);
570         starfive_wdt_enable(wdt);
571
572         /* wait for reset to assert... */
573         mdelay(500);
574
575         starfive_wdt_lock(wdt);
576
577         return 0;
578 }
579
580 static int starfive_wdt_set_timeout(struct watchdog_device *wdd,
581                                     unsigned int timeout)
582 {
583         struct starfive_wdt *wdt = watchdog_get_drvdata(wdd);
584
585         unsigned long freq = wdt->freq;
586         unsigned int count;
587
588         if (timeout < 1)
589                 return -EINVAL;
590
591         /*
592          * This watchdog takes twice timeouts to reset.
593          * In order to reduce time to reset, should set half count value.
594          */
595         count = timeout * freq / 2;
596
597         if (count > STARFIVE_WATCHDOG_MAXCNT) {
598                 dev_warn(wdt->dev, "timeout %d too big,use the MAX-timeout set.\n",
599                                 timeout);
600                 timeout = starfive_wdt_max_timeout(wdt);
601                 count = timeout * freq;
602         }
603
604         dev_info(wdt->dev, "Heartbeat: timeout=%d, count/2=%d (%08x)\n",
605                 timeout, count, count);
606
607         starfive_wdt_unlock(wdt);
608         starfive_wdt_disable(wdt);
609         starfive_wdt_set_relod_count(wdt, count);
610         starfive_wdt_enable(wdt);
611         starfive_wdt_lock(wdt);
612
613         wdt->count = count;
614         wdd->timeout = timeout;
615
616         return 0;
617 }
618
619 #define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)
620
621 static const struct watchdog_info starfive_wdt_ident = {
622         .options        = OPTIONS,
623         .firmware_version = 0,
624         .identity       = "StarFive Watchdog",
625 };
626
627 static const struct watchdog_ops starfive_wdt_ops = {
628         .owner = THIS_MODULE,
629         .start = starfive_wdt_start,
630         .stop = starfive_wdt_pm_stop,
631         .ping = starfive_wdt_keepalive,
632         .set_timeout = starfive_wdt_set_timeout,
633         .restart = starfive_wdt_restart,
634         .get_timeleft = starfive_wdt_get_timeleft,
635 };
636
637 static const struct watchdog_device starfive_wdd = {
638         .info = &starfive_wdt_ident,
639         .ops = &starfive_wdt_ops,
640         .timeout = STARFIVE_WATCHDOG_DEFAULT_TIME,
641 };
642
643 static inline const struct starfive_wdt_variant *
644 starfive_get_wdt_drv_data(struct platform_device *pdev)
645 {
646         const struct starfive_wdt_variant *variant;
647
648         variant = of_device_get_match_data(&pdev->dev);
649         if (!variant) {
650                 /* Device matched by platform_device_id */
651                 variant = (struct starfive_wdt_variant *)
652                         platform_get_device_id(pdev)->driver_data;
653         }
654
655         return variant;
656 }
657
658 static int starfive_wdt_probe(struct platform_device *pdev)
659 {
660         struct device *dev = &pdev->dev;
661         struct starfive_wdt *wdt;
662         int started = 0;
663         int ret;
664
665         pm_runtime_enable(dev);
666
667         wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
668         if (!wdt)
669                 return -ENOMEM;
670
671         wdt->dev = dev;
672         spin_lock_init(&wdt->lock);
673         wdt->wdt_device = starfive_wdd;
674
675         wdt->drv_data = starfive_get_wdt_drv_data(pdev);
676
677         wdt->irq = platform_get_irq(pdev, 0);
678         if (wdt->irq < 0) {
679                 dev_err(dev, "can not find irq.\n");
680                 return wdt->irq;
681         }
682
683         /* get the memory region for the watchdog timer */
684         wdt->base = devm_platform_ioremap_resource(pdev, 0);
685         if (IS_ERR(wdt->base)) {
686                 ret = PTR_ERR(wdt->base);
687                 goto err;
688         }
689
690         ret = starfive_wdt_enable_clock(wdt);
691         if (ret)
692                 dev_warn(wdt->dev, "get & enable clk err\n");
693
694         starfive_wdt_get_clock_rate(wdt);
695
696         ret = starfive_wdt_reset_init(wdt);
697         if (ret)
698                 dev_warn(wdt->dev, "get & deassert rst err\n");
699
700         wdt->wdt_device.min_timeout = 1;
701         wdt->wdt_device.max_timeout = starfive_wdt_max_timeout(wdt);
702
703         watchdog_set_drvdata(&wdt->wdt_device, wdt);
704
705         /*
706          * see if we can actually set the requested timer margin,
707          * and if not, try the default value.
708          */
709         watchdog_init_timeout(&wdt->wdt_device, tmr_margin, dev);
710
711         ret = starfive_wdt_set_timeout(&wdt->wdt_device,
712                                        wdt->wdt_device.timeout);
713         if (ret) {
714                 dev_info(dev, "tmr_margin value out of range, default %d used\n",
715                                  STARFIVE_WATCHDOG_DEFAULT_TIME);
716                 starfive_wdt_set_timeout(&wdt->wdt_device,
717                                          STARFIVE_WATCHDOG_DEFAULT_TIME);
718         }
719
720         ret = devm_request_irq(dev, wdt->irq, starfive_wdt_interrupt_handler, 0,
721                                pdev->name, pdev);
722         if (ret != 0) {
723                 dev_err(dev, "failed to install irq (%d)\n", ret);
724                 goto err;
725         }
726
727         watchdog_set_nowayout(&wdt->wdt_device, nowayout);
728         watchdog_set_restart_priority(&wdt->wdt_device, 128);
729
730         wdt->wdt_device.parent = dev;
731
732         ret = watchdog_register_device(&wdt->wdt_device);
733         if (ret)
734                 goto err;
735
736         ret = starfive_wdt_mask_and_disable_reset(wdt, false);
737         if (ret < 0)
738                 goto err_unregister;
739
740         if (tmr_atboot && started == 0) {
741                 dev_info(dev, "starting watchdog timer\n");
742                 starfive_wdt_start(&wdt->wdt_device);
743         } else if (!tmr_atboot) {
744
745                 /*
746                  *if we're not enabling the watchdog, then ensure it is
747                  * disabled if it has been left running from the bootloader
748                  * or other source.
749                  */
750                 starfive_wdt_stop(&wdt->wdt_device);
751         }
752         clk_disable_unprepare(wdt->core_clk);
753         clk_disable_unprepare(wdt->apb_clk);
754
755         platform_set_drvdata(pdev, wdt);
756
757         return 0;
758
759 err_unregister:
760         watchdog_unregister_device(&wdt->wdt_device);
761 err:
762         return ret;
763 }
764
765 static int starfive_wdt_remove(struct platform_device *dev)
766 {
767         int ret;
768         struct starfive_wdt *wdt = platform_get_drvdata(dev);
769
770         ret = starfive_wdt_mask_and_disable_reset(wdt, true);
771         if (ret < 0)
772                 return ret;
773
774         watchdog_unregister_device(&wdt->wdt_device);
775
776         clk_disable_unprepare(wdt->core_clk);
777         clk_disable_unprepare(wdt->apb_clk);
778         pm_runtime_disable(wdt->dev);
779
780         return 0;
781 }
782
783 static void starfive_wdt_shutdown(struct platform_device *dev)
784 {
785         struct starfive_wdt *wdt = platform_get_drvdata(dev);
786
787         starfive_wdt_mask_and_disable_reset(wdt, true);
788
789         starfive_wdt_pm_stop(&wdt->wdt_device);
790 }
791
792 #ifdef CONFIG_PM_SLEEP
793
794 static int starfive_wdt_suspend(struct device *dev)
795 {
796         int ret;
797         struct starfive_wdt *wdt = dev_get_drvdata(dev);
798
799         starfive_wdt_unlock(wdt);
800
801         /* Save watchdog state, and turn it off. */
802         wdt->reload = starfive_wdt_get_count(wdt);
803
804         ret = starfive_wdt_mask_and_disable_reset(wdt, true);
805         if (ret < 0)
806                 return ret;
807
808         /* Note that WTCNT doesn't need to be saved. */
809         starfive_wdt_stop(&wdt->wdt_device);
810         pm_runtime_force_suspend(dev);
811
812         starfive_wdt_lock(wdt);
813
814         return 0;
815 }
816
817 static int starfive_wdt_resume(struct device *dev)
818 {
819         int ret;
820         struct starfive_wdt *wdt = dev_get_drvdata(dev);
821
822         starfive_wdt_unlock(wdt);
823
824         /* Restore watchdog state. */
825         starfive_wdt_set_relod_count(wdt, wdt->reload);
826
827         pm_runtime_force_resume(dev);
828
829         starfive_wdt_restart(&wdt->wdt_device, 0, NULL);
830
831         ret = starfive_wdt_mask_and_disable_reset(wdt, false);
832         if (ret < 0)
833                 return ret;
834
835         starfive_wdt_lock(wdt);
836
837         return 0;
838 }
839 #endif /* CONFIG_PM_SLEEP */
840
841 #ifdef CONFIG_PM
842
843 static int starfive_wdt_runtime_suspend(struct device *dev)
844 {
845         struct starfive_wdt *wdt = dev_get_drvdata(dev);
846
847         clk_disable_unprepare(wdt->apb_clk);
848         clk_disable_unprepare(wdt->core_clk);
849
850         return 0;
851 }
852
853 static int starfive_wdt_runtime_resume(struct device *dev)
854 {
855         struct starfive_wdt *wdt = dev_get_drvdata(dev);
856
857         clk_prepare_enable(wdt->apb_clk);
858         clk_prepare_enable(wdt->core_clk);
859
860         return 0;
861 }
862
863 #endif /*CONFIG_PM*/
864
865 static const struct dev_pm_ops starfive_wdt_pm_ops = {
866         SET_RUNTIME_PM_OPS(starfive_wdt_runtime_suspend, starfive_wdt_runtime_resume, NULL)
867         SET_SYSTEM_SLEEP_PM_OPS(starfive_wdt_suspend, starfive_wdt_resume)
868 };
869
870 static struct platform_driver starfive_starfive_wdt_driver = {
871         .probe          = starfive_wdt_probe,
872         .remove         = starfive_wdt_remove,
873         .shutdown       = starfive_wdt_shutdown,
874         .id_table       = starfive_wdt_ids,
875         .driver         = {
876                 .name   = "starfive-wdt",
877                 .pm     = &starfive_wdt_pm_ops,
878                 .of_match_table = of_match_ptr(starfive_wdt_match),
879         },
880 };
881
882 module_platform_driver(starfive_starfive_wdt_driver);
883
884 MODULE_AUTHOR("xingyu.wu <xingyu.wu@starfivetech.com>");
885 MODULE_AUTHOR("samin.guo <samin.guo@starfivetech.com>");
886 MODULE_DESCRIPTION("StarFive Watchdog Device Driver");
887 MODULE_LICENSE("GPL v2");