blob: 619fc100be05a3a0ff9658770571378427e26e05 [file] [log] [blame]
developerec4ebe42022-04-12 11:17:45 +08001diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
2index 9c3d003..30127d1 100644
3--- a/drivers/watchdog/mtk_wdt.c
4+++ b/drivers/watchdog/mtk_wdt.c
5@@ -9,6 +9,8 @@
6 * Based on sunxi_wdt.c
7 */
8
9+#include <dt-bindings/reset/mt7986-resets.h>
10+#include <linux/delay.h>
11 #include <linux/err.h>
12 #include <linux/init.h>
13 #include <linux/io.h>
14@@ -16,13 +18,15 @@
15 #include <linux/module.h>
16 #include <linux/moduleparam.h>
17 #include <linux/of.h>
18+#include <linux/of_device.h>
19 #include <linux/platform_device.h>
20+#include <linux/reset-controller.h>
21 #include <linux/types.h>
22 #include <linux/watchdog.h>
23-#include <linux/delay.h>
24+#include <linux/interrupt.h>
25
26 #define WDT_MAX_TIMEOUT 31
27-#define WDT_MIN_TIMEOUT 1
28+#define WDT_MIN_TIMEOUT 2
29 #define WDT_LENGTH_TIMEOUT(n) ((n) << 5)
30
31 #define WDT_LENGTH 0x04
32@@ -44,6 +48,9 @@
33 #define WDT_SWRST 0x14
34 #define WDT_SWRST_KEY 0x1209
35
36+#define WDT_SWSYSRST 0x18U
37+#define WDT_SWSYS_RST_KEY 0x88000000
38+
39 #define DRV_NAME "mtk-wdt"
40 #define DRV_VERSION "1.0"
41
42@@ -53,8 +60,91 @@ static unsigned int timeout;
43 struct mtk_wdt_dev {
44 struct watchdog_device wdt_dev;
45 void __iomem *wdt_base;
46+ spinlock_t lock; /* protects WDT_SWSYSRST reg */
47+ struct reset_controller_dev rcdev;
48+ bool disable_wdt_extrst;
49+};
50+
51+struct mtk_wdt_data {
52+ int toprgu_sw_rst_num;
53+};
54+
55+static const struct mtk_wdt_data mt7986_data = {
56+ .toprgu_sw_rst_num = MT7986_TOPRGU_SW_RST_NUM,
57+};
58+
59+static int toprgu_reset_update(struct reset_controller_dev *rcdev,
60+ unsigned long id, bool assert)
61+{
62+ unsigned int tmp;
63+ unsigned long flags;
64+ struct mtk_wdt_dev *data =
65+ container_of(rcdev, struct mtk_wdt_dev, rcdev);
66+
67+ spin_lock_irqsave(&data->lock, flags);
68+
69+ tmp = readl(data->wdt_base + WDT_SWSYSRST);
70+ if (assert)
71+ tmp |= BIT(id);
72+ else
73+ tmp &= ~BIT(id);
74+ tmp |= WDT_SWSYS_RST_KEY;
75+ writel(tmp, data->wdt_base + WDT_SWSYSRST);
76+
77+ spin_unlock_irqrestore(&data->lock, flags);
78+
79+ return 0;
80+}
81+
82+static int toprgu_reset_assert(struct reset_controller_dev *rcdev,
83+ unsigned long id)
84+{
85+ return toprgu_reset_update(rcdev, id, true);
86+}
87+
88+static int toprgu_reset_deassert(struct reset_controller_dev *rcdev,
89+ unsigned long id)
90+{
91+ return toprgu_reset_update(rcdev, id, false);
92+}
93+
94+static int toprgu_reset(struct reset_controller_dev *rcdev,
95+ unsigned long id)
96+{
97+ int ret;
98+
99+ ret = toprgu_reset_assert(rcdev, id);
100+ if (ret)
101+ return ret;
102+
103+ return toprgu_reset_deassert(rcdev, id);
104+}
105+
106+static const struct reset_control_ops toprgu_reset_ops = {
107+ .assert = toprgu_reset_assert,
108+ .deassert = toprgu_reset_deassert,
109+ .reset = toprgu_reset,
110 };
111
112+static int toprgu_register_reset_controller(struct platform_device *pdev,
113+ int rst_num)
114+{
115+ int ret;
116+ struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
117+
118+ spin_lock_init(&mtk_wdt->lock);
119+
120+ mtk_wdt->rcdev.owner = THIS_MODULE;
121+ mtk_wdt->rcdev.nr_resets = rst_num;
122+ mtk_wdt->rcdev.ops = &toprgu_reset_ops;
123+ mtk_wdt->rcdev.of_node = pdev->dev.of_node;
124+ ret = devm_reset_controller_register(&pdev->dev, &mtk_wdt->rcdev);
125+ if (ret != 0)
126+ dev_err(&pdev->dev,
127+ "couldn't register wdt reset controller: %d\n", ret);
128+ return ret;
129+}
130+
131 static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
132 unsigned long action, void *data)
133 {
134@@ -89,12 +179,19 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev,
135 u32 reg;
136
137 wdt_dev->timeout = timeout;
138+ /*
139+ * In dual mode, irq will be triggered at timeout / 2
140+ * the real timeout occurs at timeout
141+ */
142+ if (wdt_dev->pretimeout)
143+ wdt_dev->pretimeout = timeout / 2;
144
145 /*
146 * One bit is the value of 512 ticks
147 * The clock has 32 KHz
148 */
149- reg = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY;
150+ reg = WDT_LENGTH_TIMEOUT((timeout - wdt_dev->pretimeout) << 6)
151+ | WDT_LENGTH_KEY;
152 iowrite32(reg, wdt_base + WDT_LENGTH);
153
154 mtk_wdt_ping(wdt_dev);
155@@ -102,6 +199,19 @@ static int mtk_wdt_set_timeout(struct watchdog_device *wdt_dev,
156 return 0;
157 }
158
159+static void mtk_wdt_init(struct watchdog_device *wdt_dev)
160+{
161+ struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
162+ void __iomem *wdt_base;
163+
164+ wdt_base = mtk_wdt->wdt_base;
165+
166+ if (readl(wdt_base + WDT_MODE) & WDT_MODE_EN) {
167+ set_bit(WDOG_HW_RUNNING, &wdt_dev->status);
168+ mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
169+ }
170+}
171+
172 static int mtk_wdt_stop(struct watchdog_device *wdt_dev)
173 {
174 struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
175@@ -128,13 +238,50 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev)
176 return ret;
177
178 reg = ioread32(wdt_base + WDT_MODE);
179- reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
180+ if (wdt_dev->pretimeout)
181+ reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
182+ else
183+ reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
184+ if (mtk_wdt->disable_wdt_extrst)
185+ reg &= ~WDT_MODE_EXRST_EN;
186 reg |= (WDT_MODE_EN | WDT_MODE_KEY);
187 iowrite32(reg, wdt_base + WDT_MODE);
188
189 return 0;
190 }
191
192+static int mtk_wdt_set_pretimeout(struct watchdog_device *wdd,
193+ unsigned int timeout)
194+{
195+ struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdd);
196+ void __iomem *wdt_base = mtk_wdt->wdt_base;
197+ u32 reg = ioread32(wdt_base + WDT_MODE);
198+
199+ if (timeout && !wdd->pretimeout) {
200+ wdd->pretimeout = wdd->timeout / 2;
201+ reg |= (WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
202+ } else if (!timeout && wdd->pretimeout) {
203+ wdd->pretimeout = 0;
204+ reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN);
205+ } else {
206+ return 0;
207+ }
208+
209+ reg |= WDT_MODE_KEY;
210+ iowrite32(reg, wdt_base + WDT_MODE);
211+
212+ return mtk_wdt_set_timeout(wdd, wdd->timeout);
213+}
214+
215+static irqreturn_t mtk_wdt_isr(int irq, void *arg)
216+{
217+ struct watchdog_device *wdd = arg;
218+
219+ watchdog_notify_pretimeout(wdd);
220+
221+ return IRQ_HANDLED;
222+}
223+
224 static const struct watchdog_info mtk_wdt_info = {
225 .identity = DRV_NAME,
226 .options = WDIOF_SETTIMEOUT |
227@@ -142,12 +289,21 @@ static const struct watchdog_info mtk_wdt_info = {
228 WDIOF_MAGICCLOSE,
229 };
230
231+static const struct watchdog_info mtk_wdt_pt_info = {
232+ .identity = DRV_NAME,
233+ .options = WDIOF_SETTIMEOUT |
234+ WDIOF_PRETIMEOUT |
235+ WDIOF_KEEPALIVEPING |
236+ WDIOF_MAGICCLOSE,
237+};
238+
239 static const struct watchdog_ops mtk_wdt_ops = {
240 .owner = THIS_MODULE,
241 .start = mtk_wdt_start,
242 .stop = mtk_wdt_stop,
243 .ping = mtk_wdt_ping,
244 .set_timeout = mtk_wdt_set_timeout,
245+ .set_pretimeout = mtk_wdt_set_pretimeout,
246 .restart = mtk_wdt_restart,
247 };
248
249@@ -155,7 +311,8 @@ static int mtk_wdt_probe(struct platform_device *pdev)
250 {
251 struct device *dev = &pdev->dev;
252 struct mtk_wdt_dev *mtk_wdt;
253- int err;
254+ const struct mtk_wdt_data *wdt_data;
255+ int err, irq;
256
257 mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL);
258 if (!mtk_wdt)
259@@ -167,10 +324,25 @@ static int mtk_wdt_probe(struct platform_device *pdev)
260 if (IS_ERR(mtk_wdt->wdt_base))
261 return PTR_ERR(mtk_wdt->wdt_base);
262
263- mtk_wdt->wdt_dev.info = &mtk_wdt_info;
264+ irq = platform_get_irq(pdev, 0);
265+ if (irq > 0) {
266+ err = devm_request_irq(&pdev->dev, irq, mtk_wdt_isr, 0, "wdt_bark",
267+ &mtk_wdt->wdt_dev);
268+ if (err)
269+ return err;
270+
271+ mtk_wdt->wdt_dev.info = &mtk_wdt_pt_info;
272+ mtk_wdt->wdt_dev.pretimeout = WDT_MAX_TIMEOUT / 2;
273+ } else {
274+ if (irq == -EPROBE_DEFER)
275+ return -EPROBE_DEFER;
276+
277+ mtk_wdt->wdt_dev.info = &mtk_wdt_info;
278+ }
279+
280 mtk_wdt->wdt_dev.ops = &mtk_wdt_ops;
281 mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT;
282- mtk_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT;
283+ mtk_wdt->wdt_dev.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT * 1000;
284 mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT;
285 mtk_wdt->wdt_dev.parent = dev;
286
287@@ -180,7 +352,7 @@ static int mtk_wdt_probe(struct platform_device *pdev)
288
289 watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt);
290
291- mtk_wdt_stop(&mtk_wdt->wdt_dev);
292+ mtk_wdt_init(&mtk_wdt->wdt_dev);
293
294 watchdog_stop_on_reboot(&mtk_wdt->wdt_dev);
295 err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev);
296@@ -190,6 +362,17 @@ static int mtk_wdt_probe(struct platform_device *pdev)
297 dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
298 mtk_wdt->wdt_dev.timeout, nowayout);
299
300+ wdt_data = of_device_get_match_data(dev);
301+ if (wdt_data) {
302+ err = toprgu_register_reset_controller(pdev,
303+ wdt_data->toprgu_sw_rst_num);
304+ if (err)
305+ return err;
306+ }
307+
308+ mtk_wdt->disable_wdt_extrst =
309+ of_property_read_bool(dev->of_node, "mediatek,disable-extrst");
310+
311 return 0;
312 }
313
314@@ -219,6 +402,7 @@ static int mtk_wdt_resume(struct device *dev)
315
316 static const struct of_device_id mtk_wdt_dt_ids[] = {
317 { .compatible = "mediatek,mt6589-wdt" },
318+ { .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
319 { /* sentinel */ }
320 };
321 MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
322@@ -249,4 +433,4 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
323 MODULE_LICENSE("GPL");
324 MODULE_AUTHOR("Matthias Brugger <matthias.bgg@gmail.com>");
325 MODULE_DESCRIPTION("Mediatek WatchDog Timer Driver");
326-MODULE_VERSION(DRV_VERSION);
327+MODULE_VERSION(DRV_VERSION);
328\ No newline at end of file