1 // SPDX-License-Identifier: GPL-2.0-only
3 * Ralink RT288x/RT3xxx/MT76xx built-in hardware watchdog timer
5 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
6 * Copyright (C) 2013 John Crispin <john@phrozen.org>
8 * This driver was based on: drivers/watchdog/softdog.c
11 #include <linux/clk.h>
12 #include <linux/reset.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/watchdog.h>
16 #include <linux/moduleparam.h>
17 #include <linux/platform_device.h>
18 #include <linux/mod_devicetable.h>
20 #include <asm/mach-ralink/ralink_regs.h>
22 #define SYSC_RSTSTAT 0x38
23 #define WDT_RST_CAUSE BIT(1)
25 #define RALINK_WDT_TIMEOUT 30
26 #define RALINK_WDT_PRESCALE 65536
28 #define TIMER_REG_TMR1LOAD 0x00
29 #define TIMER_REG_TMR1CTL 0x08
31 #define TMRSTAT_TMR1RST BIT(5)
33 #define TMR1CTL_ENABLE BIT(7)
34 #define TMR1CTL_MODE_SHIFT 4
35 #define TMR1CTL_MODE_MASK 0x3
36 #define TMR1CTL_MODE_FREE_RUNNING 0x0
37 #define TMR1CTL_MODE_PERIODIC 0x1
38 #define TMR1CTL_MODE_TIMEOUT 0x2
39 #define TMR1CTL_MODE_WDT 0x3
40 #define TMR1CTL_PRESCALE_MASK 0xf
41 #define TMR1CTL_PRESCALE_65536 0xf
43 struct rt2880_wdt_data
{
47 struct reset_control
*rst
;
48 struct watchdog_device wdt
;
51 static bool nowayout
= WATCHDOG_NOWAYOUT
;
52 module_param(nowayout
, bool, 0);
53 MODULE_PARM_DESC(nowayout
,
54 "Watchdog cannot be stopped once started (default="
55 __MODULE_STRING(WATCHDOG_NOWAYOUT
) ")");
57 static inline void rt_wdt_w32(void __iomem
*base
, unsigned int reg
, u32 val
)
59 iowrite32(val
, base
+ reg
);
62 static inline u32
rt_wdt_r32(void __iomem
*base
, unsigned int reg
)
64 return ioread32(base
+ reg
);
67 static int rt288x_wdt_ping(struct watchdog_device
*w
)
69 struct rt2880_wdt_data
*drvdata
= watchdog_get_drvdata(w
);
71 rt_wdt_w32(drvdata
->base
, TIMER_REG_TMR1LOAD
, w
->timeout
* drvdata
->freq
);
76 static int rt288x_wdt_start(struct watchdog_device
*w
)
78 struct rt2880_wdt_data
*drvdata
= watchdog_get_drvdata(w
);
81 t
= rt_wdt_r32(drvdata
->base
, TIMER_REG_TMR1CTL
);
82 t
&= ~(TMR1CTL_MODE_MASK
<< TMR1CTL_MODE_SHIFT
|
83 TMR1CTL_PRESCALE_MASK
);
84 t
|= (TMR1CTL_MODE_WDT
<< TMR1CTL_MODE_SHIFT
|
85 TMR1CTL_PRESCALE_65536
);
86 rt_wdt_w32(drvdata
->base
, TIMER_REG_TMR1CTL
, t
);
90 t
= rt_wdt_r32(drvdata
->base
, TIMER_REG_TMR1CTL
);
92 rt_wdt_w32(drvdata
->base
, TIMER_REG_TMR1CTL
, t
);
97 static int rt288x_wdt_stop(struct watchdog_device
*w
)
99 struct rt2880_wdt_data
*drvdata
= watchdog_get_drvdata(w
);
104 t
= rt_wdt_r32(drvdata
->base
, TIMER_REG_TMR1CTL
);
105 t
&= ~TMR1CTL_ENABLE
;
106 rt_wdt_w32(drvdata
->base
, TIMER_REG_TMR1CTL
, t
);
111 static int rt288x_wdt_set_timeout(struct watchdog_device
*w
, unsigned int t
)
119 static int rt288x_wdt_bootcause(void)
121 if (rt_sysc_r32(SYSC_RSTSTAT
) & WDT_RST_CAUSE
)
122 return WDIOF_CARDRESET
;
127 static const struct watchdog_info rt288x_wdt_info
= {
128 .identity
= "Ralink Watchdog",
129 .options
= WDIOF_SETTIMEOUT
| WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE
,
132 static const struct watchdog_ops rt288x_wdt_ops
= {
133 .owner
= THIS_MODULE
,
134 .start
= rt288x_wdt_start
,
135 .stop
= rt288x_wdt_stop
,
136 .ping
= rt288x_wdt_ping
,
137 .set_timeout
= rt288x_wdt_set_timeout
,
140 static int rt288x_wdt_probe(struct platform_device
*pdev
)
142 struct device
*dev
= &pdev
->dev
;
143 struct watchdog_device
*wdt
;
144 struct rt2880_wdt_data
*drvdata
;
147 drvdata
= devm_kzalloc(dev
, sizeof(*drvdata
), GFP_KERNEL
);
151 drvdata
->base
= devm_platform_ioremap_resource(pdev
, 0);
152 if (IS_ERR(drvdata
->base
))
153 return PTR_ERR(drvdata
->base
);
155 drvdata
->clk
= devm_clk_get(dev
, NULL
);
156 if (IS_ERR(drvdata
->clk
))
157 return PTR_ERR(drvdata
->clk
);
159 drvdata
->rst
= devm_reset_control_get_exclusive(dev
, NULL
);
160 if (!IS_ERR(drvdata
->rst
))
161 reset_control_deassert(drvdata
->rst
);
163 drvdata
->freq
= clk_get_rate(drvdata
->clk
) / RALINK_WDT_PRESCALE
;
166 wdt
->info
= &rt288x_wdt_info
;
167 wdt
->ops
= &rt288x_wdt_ops
;
168 wdt
->min_timeout
= 1;
169 wdt
->max_timeout
= (0xfffful
/ drvdata
->freq
);
171 wdt
->bootstatus
= rt288x_wdt_bootcause();
173 watchdog_init_timeout(wdt
, wdt
->max_timeout
, dev
);
174 watchdog_set_nowayout(wdt
, nowayout
);
175 watchdog_set_drvdata(wdt
, drvdata
);
177 watchdog_stop_on_reboot(wdt
);
178 ret
= devm_watchdog_register_device(dev
, &drvdata
->wdt
);
180 dev_info(dev
, "Initialized\n");
185 static const struct of_device_id rt288x_wdt_match
[] = {
186 { .compatible
= "ralink,rt2880-wdt" },
189 MODULE_DEVICE_TABLE(of
, rt288x_wdt_match
);
191 static struct platform_driver rt288x_wdt_driver
= {
192 .probe
= rt288x_wdt_probe
,
194 .name
= KBUILD_MODNAME
,
195 .of_match_table
= rt288x_wdt_match
,
199 module_platform_driver(rt288x_wdt_driver
);
201 MODULE_DESCRIPTION("MediaTek/Ralink RT288x/RT3xxx hardware watchdog driver");
202 MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org");
203 MODULE_LICENSE("GPL v2");