hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/watchdog/mpc8xxx_wdt.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface
34 *
....@@ -10,14 +11,7 @@
1011 *
1112 * Note: it appears that you can only actually ENABLE or DISABLE the thing
1213 * once after POR. Once enabled, you cannot disable, and vice versa.
13
- *
14
- * This program is free software; you can redistribute it and/or modify it
15
- * under the terms of the GNU General Public License as published by the
16
- * Free Software Foundation; either version 2 of the License, or (at your
17
- * option) any later version.
1814 */
19
-
20
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2115
2216 #include <linux/fs.h>
2317 #include <linux/init.h>
....@@ -49,6 +43,7 @@
4943 struct mpc8xxx_wdt_type {
5044 int prescaler;
5145 bool hw_enabled;
46
+ u32 rsr_mask;
5247 };
5348
5449 struct mpc8xxx_wdt_ddata {
....@@ -137,27 +132,45 @@
137132 struct mpc8xxx_wdt_ddata *ddata;
138133 u32 freq = fsl_get_sys_freq();
139134 bool enabled;
135
+ struct device *dev = &ofdev->dev;
140136
141
- wdt_type = of_device_get_match_data(&ofdev->dev);
137
+ wdt_type = of_device_get_match_data(dev);
142138 if (!wdt_type)
143139 return -EINVAL;
144140
145141 if (!freq || freq == -1)
146142 return -EINVAL;
147143
148
- ddata = devm_kzalloc(&ofdev->dev, sizeof(*ddata), GFP_KERNEL);
144
+ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
149145 if (!ddata)
150146 return -ENOMEM;
151147
152
- res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
153
- ddata->base = devm_ioremap_resource(&ofdev->dev, res);
148
+ ddata->base = devm_platform_ioremap_resource(ofdev, 0);
154149 if (IS_ERR(ddata->base))
155150 return PTR_ERR(ddata->base);
156151
157152 enabled = in_be32(&ddata->base->swcrr) & SWCRR_SWEN;
158153 if (!enabled && wdt_type->hw_enabled) {
159
- pr_info("could not be enabled in software\n");
154
+ dev_info(dev, "could not be enabled in software\n");
160155 return -ENODEV;
156
+ }
157
+
158
+ res = platform_get_resource(ofdev, IORESOURCE_MEM, 1);
159
+ if (res) {
160
+ bool status;
161
+ u32 __iomem *rsr = ioremap(res->start, resource_size(res));
162
+
163
+ if (!rsr)
164
+ return -ENOMEM;
165
+
166
+ status = in_be32(rsr) & wdt_type->rsr_mask;
167
+ ddata->wdd.bootstatus = status ? WDIOF_CARDRESET : 0;
168
+ /* clear reset status bits related to watchdog timer */
169
+ out_be32(rsr, wdt_type->rsr_mask);
170
+ iounmap(rsr);
171
+
172
+ dev_info(dev, "Last boot was %scaused by watchdog\n",
173
+ status ? "" : "not ");
161174 }
162175
163176 spin_lock_init(&ddata->lock);
....@@ -166,7 +179,7 @@
166179 ddata->wdd.ops = &mpc8xxx_wdt_ops,
167180
168181 ddata->wdd.timeout = WATCHDOG_TIMEOUT;
169
- watchdog_init_timeout(&ddata->wdd, timeout, &ofdev->dev);
182
+ watchdog_init_timeout(&ddata->wdd, timeout, dev);
170183
171184 watchdog_set_nowayout(&ddata->wdd, nowayout);
172185
....@@ -187,27 +200,15 @@
187200 if (ddata->wdd.timeout < ddata->wdd.min_timeout)
188201 ddata->wdd.timeout = ddata->wdd.min_timeout;
189202
190
- ret = watchdog_register_device(&ddata->wdd);
191
- if (ret) {
192
- pr_err("cannot register watchdog device (err=%d)\n", ret);
203
+ ret = devm_watchdog_register_device(dev, &ddata->wdd);
204
+ if (ret)
193205 return ret;
194
- }
195206
196
- pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d sec\n",
197
- reset ? "reset" : "interrupt", ddata->wdd.timeout);
207
+ dev_info(dev,
208
+ "WDT driver for MPC8xxx initialized. mode:%s timeout=%d sec\n",
209
+ reset ? "reset" : "interrupt", ddata->wdd.timeout);
198210
199211 platform_set_drvdata(ofdev, ddata);
200
- return 0;
201
-}
202
-
203
-static int mpc8xxx_wdt_remove(struct platform_device *ofdev)
204
-{
205
- struct mpc8xxx_wdt_ddata *ddata = platform_get_drvdata(ofdev);
206
-
207
- pr_crit("Watchdog removed, expect the %s soon!\n",
208
- reset ? "reset" : "machine check exception");
209
- watchdog_unregister_device(&ddata->wdd);
210
-
211212 return 0;
212213 }
213214
....@@ -216,6 +217,7 @@
216217 .compatible = "mpc83xx_wdt",
217218 .data = &(struct mpc8xxx_wdt_type) {
218219 .prescaler = 0x10000,
220
+ .rsr_mask = BIT(3), /* RSR Bit SWRS */
219221 },
220222 },
221223 {
....@@ -223,6 +225,7 @@
223225 .data = &(struct mpc8xxx_wdt_type) {
224226 .prescaler = 0x10000,
225227 .hw_enabled = true,
228
+ .rsr_mask = BIT(20), /* RSTRSCR Bit WDT_RR */
226229 },
227230 },
228231 {
....@@ -230,6 +233,7 @@
230233 .data = &(struct mpc8xxx_wdt_type) {
231234 .prescaler = 0x800,
232235 .hw_enabled = true,
236
+ .rsr_mask = BIT(28), /* RSR Bit SWRS */
233237 },
234238 },
235239 {},
....@@ -238,7 +242,6 @@
238242
239243 static struct platform_driver mpc8xxx_wdt_driver = {
240244 .probe = mpc8xxx_wdt_probe,
241
- .remove = mpc8xxx_wdt_remove,
242245 .driver = {
243246 .name = "mpc8xxx_wdt",
244247 .of_match_table = mpc8xxx_wdt_match,