hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/watchdog/mtk_wdt.c
....@@ -9,6 +9,9 @@
99 * Based on sunxi_wdt.c
1010 */
1111
12
+#include <dt-bindings/reset-controller/mt2712-resets.h>
13
+#include <dt-bindings/reset-controller/mt8183-resets.h>
14
+#include <linux/delay.h>
1215 #include <linux/err.h>
1316 #include <linux/init.h>
1417 #include <linux/io.h>
....@@ -16,10 +19,11 @@
1619 #include <linux/module.h>
1720 #include <linux/moduleparam.h>
1821 #include <linux/of.h>
22
+#include <linux/of_device.h>
1923 #include <linux/platform_device.h>
24
+#include <linux/reset-controller.h>
2025 #include <linux/types.h>
2126 #include <linux/watchdog.h>
22
-#include <linux/delay.h>
2327
2428 #define WDT_MAX_TIMEOUT 31
2529 #define WDT_MIN_TIMEOUT 1
....@@ -44,6 +48,9 @@
4448 #define WDT_SWRST 0x14
4549 #define WDT_SWRST_KEY 0x1209
4650
51
+#define WDT_SWSYSRST 0x18U
52
+#define WDT_SWSYS_RST_KEY 0x88000000
53
+
4754 #define DRV_NAME "mtk-wdt"
4855 #define DRV_VERSION "1.0"
4956
....@@ -53,7 +60,93 @@
5360 struct mtk_wdt_dev {
5461 struct watchdog_device wdt_dev;
5562 void __iomem *wdt_base;
63
+ spinlock_t lock; /* protects WDT_SWSYSRST reg */
64
+ struct reset_controller_dev rcdev;
5665 };
66
+
67
+struct mtk_wdt_data {
68
+ int toprgu_sw_rst_num;
69
+};
70
+
71
+static const struct mtk_wdt_data mt2712_data = {
72
+ .toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
73
+};
74
+
75
+static const struct mtk_wdt_data mt8183_data = {
76
+ .toprgu_sw_rst_num = MT8183_TOPRGU_SW_RST_NUM,
77
+};
78
+
79
+static int toprgu_reset_update(struct reset_controller_dev *rcdev,
80
+ unsigned long id, bool assert)
81
+{
82
+ unsigned int tmp;
83
+ unsigned long flags;
84
+ struct mtk_wdt_dev *data =
85
+ container_of(rcdev, struct mtk_wdt_dev, rcdev);
86
+
87
+ spin_lock_irqsave(&data->lock, flags);
88
+
89
+ tmp = readl(data->wdt_base + WDT_SWSYSRST);
90
+ if (assert)
91
+ tmp |= BIT(id);
92
+ else
93
+ tmp &= ~BIT(id);
94
+ tmp |= WDT_SWSYS_RST_KEY;
95
+ writel(tmp, data->wdt_base + WDT_SWSYSRST);
96
+
97
+ spin_unlock_irqrestore(&data->lock, flags);
98
+
99
+ return 0;
100
+}
101
+
102
+static int toprgu_reset_assert(struct reset_controller_dev *rcdev,
103
+ unsigned long id)
104
+{
105
+ return toprgu_reset_update(rcdev, id, true);
106
+}
107
+
108
+static int toprgu_reset_deassert(struct reset_controller_dev *rcdev,
109
+ unsigned long id)
110
+{
111
+ return toprgu_reset_update(rcdev, id, false);
112
+}
113
+
114
+static int toprgu_reset(struct reset_controller_dev *rcdev,
115
+ unsigned long id)
116
+{
117
+ int ret;
118
+
119
+ ret = toprgu_reset_assert(rcdev, id);
120
+ if (ret)
121
+ return ret;
122
+
123
+ return toprgu_reset_deassert(rcdev, id);
124
+}
125
+
126
+static const struct reset_control_ops toprgu_reset_ops = {
127
+ .assert = toprgu_reset_assert,
128
+ .deassert = toprgu_reset_deassert,
129
+ .reset = toprgu_reset,
130
+};
131
+
132
+static int toprgu_register_reset_controller(struct platform_device *pdev,
133
+ int rst_num)
134
+{
135
+ int ret;
136
+ struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
137
+
138
+ spin_lock_init(&mtk_wdt->lock);
139
+
140
+ mtk_wdt->rcdev.owner = THIS_MODULE;
141
+ mtk_wdt->rcdev.nr_resets = rst_num;
142
+ mtk_wdt->rcdev.ops = &toprgu_reset_ops;
143
+ mtk_wdt->rcdev.of_node = pdev->dev.of_node;
144
+ ret = devm_reset_controller_register(&pdev->dev, &mtk_wdt->rcdev);
145
+ if (ret != 0)
146
+ dev_err(&pdev->dev,
147
+ "couldn't register wdt reset controller: %d\n", ret);
148
+ return ret;
149
+}
57150
58151 static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
59152 unsigned long action, void *data)
....@@ -153,18 +246,18 @@
153246
154247 static int mtk_wdt_probe(struct platform_device *pdev)
155248 {
249
+ struct device *dev = &pdev->dev;
156250 struct mtk_wdt_dev *mtk_wdt;
157
- struct resource *res;
251
+ const struct mtk_wdt_data *wdt_data;
158252 int err;
159253
160
- mtk_wdt = devm_kzalloc(&pdev->dev, sizeof(*mtk_wdt), GFP_KERNEL);
254
+ mtk_wdt = devm_kzalloc(dev, sizeof(*mtk_wdt), GFP_KERNEL);
161255 if (!mtk_wdt)
162256 return -ENOMEM;
163257
164258 platform_set_drvdata(pdev, mtk_wdt);
165259
166
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
167
- mtk_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res);
260
+ mtk_wdt->wdt_base = devm_platform_ioremap_resource(pdev, 0);
168261 if (IS_ERR(mtk_wdt->wdt_base))
169262 return PTR_ERR(mtk_wdt->wdt_base);
170263
....@@ -173,9 +266,9 @@
173266 mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT;
174267 mtk_wdt->wdt_dev.max_timeout = WDT_MAX_TIMEOUT;
175268 mtk_wdt->wdt_dev.min_timeout = WDT_MIN_TIMEOUT;
176
- mtk_wdt->wdt_dev.parent = &pdev->dev;
269
+ mtk_wdt->wdt_dev.parent = dev;
177270
178
- watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, &pdev->dev);
271
+ watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, dev);
179272 watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout);
180273 watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128);
181274
....@@ -183,30 +276,21 @@
183276
184277 mtk_wdt_stop(&mtk_wdt->wdt_dev);
185278
186
- err = watchdog_register_device(&mtk_wdt->wdt_dev);
279
+ watchdog_stop_on_reboot(&mtk_wdt->wdt_dev);
280
+ err = devm_watchdog_register_device(dev, &mtk_wdt->wdt_dev);
187281 if (unlikely(err))
188282 return err;
189283
190
- dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
191
- mtk_wdt->wdt_dev.timeout, nowayout);
284
+ dev_info(dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n",
285
+ mtk_wdt->wdt_dev.timeout, nowayout);
192286
193
- return 0;
194
-}
195
-
196
-static void mtk_wdt_shutdown(struct platform_device *pdev)
197
-{
198
- struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
199
-
200
- if (watchdog_active(&mtk_wdt->wdt_dev))
201
- mtk_wdt_stop(&mtk_wdt->wdt_dev);
202
-}
203
-
204
-static int mtk_wdt_remove(struct platform_device *pdev)
205
-{
206
- struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev);
207
-
208
- watchdog_unregister_device(&mtk_wdt->wdt_dev);
209
-
287
+ wdt_data = of_device_get_match_data(dev);
288
+ if (wdt_data) {
289
+ err = toprgu_register_reset_controller(pdev,
290
+ wdt_data->toprgu_sw_rst_num);
291
+ if (err)
292
+ return err;
293
+ }
210294 return 0;
211295 }
212296
....@@ -235,7 +319,9 @@
235319 #endif
236320
237321 static const struct of_device_id mtk_wdt_dt_ids[] = {
322
+ { .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
238323 { .compatible = "mediatek,mt6589-wdt" },
324
+ { .compatible = "mediatek,mt8183-wdt", .data = &mt8183_data },
239325 { /* sentinel */ }
240326 };
241327 MODULE_DEVICE_TABLE(of, mtk_wdt_dt_ids);
....@@ -247,8 +333,6 @@
247333
248334 static struct platform_driver mtk_wdt_driver = {
249335 .probe = mtk_wdt_probe,
250
- .remove = mtk_wdt_remove,
251
- .shutdown = mtk_wdt_shutdown,
252336 .driver = {
253337 .name = DRV_NAME,
254338 .pm = &mtk_wdt_pm_ops,