hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/watchdog/da9062_wdt.c
....@@ -11,10 +11,12 @@
1111 #include <linux/platform_device.h>
1212 #include <linux/uaccess.h>
1313 #include <linux/slab.h>
14
+#include <linux/i2c.h>
1415 #include <linux/delay.h>
1516 #include <linux/jiffies.h>
1617 #include <linux/mfd/da9062/registers.h>
1718 #include <linux/mfd/da9062/core.h>
19
+#include <linux/property.h>
1820 #include <linux/regmap.h>
1921 #include <linux/of.h>
2022
....@@ -30,7 +32,17 @@
3032 struct da9062_watchdog {
3133 struct da9062 *hw;
3234 struct watchdog_device wdtdev;
35
+ bool use_sw_pm;
3336 };
37
+
38
+static unsigned int da9062_wdt_read_timeout(struct da9062_watchdog *wdt)
39
+{
40
+ unsigned int val;
41
+
42
+ regmap_read(wdt->hw->regmap, DA9062AA_CONTROL_D, &val);
43
+
44
+ return wdt_timeout[val & DA9062AA_TWDSCALE_MASK];
45
+}
3446
3547 static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
3648 {
....@@ -46,14 +58,9 @@
4658
4759 static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt)
4860 {
49
- int ret;
50
-
51
- ret = regmap_update_bits(wdt->hw->regmap,
52
- DA9062AA_CONTROL_F,
53
- DA9062AA_WATCHDOG_MASK,
54
- DA9062AA_WATCHDOG_MASK);
55
-
56
- return ret;
61
+ return regmap_update_bits(wdt->hw->regmap, DA9062AA_CONTROL_F,
62
+ DA9062AA_WATCHDOG_MASK,
63
+ DA9062AA_WATCHDOG_MASK);
5764 }
5865
5966 static int da9062_wdt_update_timeout_register(struct da9062_watchdog *wdt,
....@@ -140,12 +147,13 @@
140147 void *data)
141148 {
142149 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
150
+ struct i2c_client *client = to_i2c_client(wdt->hw->dev);
143151 int ret;
144152
145
- ret = regmap_write(wdt->hw->regmap,
146
- DA9062AA_CONTROL_F,
147
- DA9062AA_SHUTDOWN_MASK);
148
- if (ret)
153
+ /* Don't use regmap because it is not atomic safe */
154
+ ret = i2c_smbus_write_byte_data(client, DA9062AA_CONTROL_F,
155
+ DA9062AA_SHUTDOWN_MASK);
156
+ if (ret < 0)
149157 dev_alert(wdt->hw->dev, "Failed to shutdown (err = %d)\n",
150158 ret);
151159
....@@ -178,17 +186,20 @@
178186
179187 static int da9062_wdt_probe(struct platform_device *pdev)
180188 {
181
- int ret;
189
+ struct device *dev = &pdev->dev;
190
+ unsigned int timeout;
182191 struct da9062 *chip;
183192 struct da9062_watchdog *wdt;
184193
185
- chip = dev_get_drvdata(pdev->dev.parent);
194
+ chip = dev_get_drvdata(dev->parent);
186195 if (!chip)
187196 return -EINVAL;
188197
189
- wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
198
+ wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
190199 if (!wdt)
191200 return -ENOMEM;
201
+
202
+ wdt->use_sw_pm = device_property_present(dev, "dlg,use-sw-pm");
192203
193204 wdt->hw = chip;
194205
....@@ -199,26 +210,64 @@
199210 wdt->wdtdev.min_hw_heartbeat_ms = DA9062_RESET_PROTECTION_MS;
200211 wdt->wdtdev.timeout = DA9062_WDG_DEFAULT_TIMEOUT;
201212 wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
202
- wdt->wdtdev.parent = &pdev->dev;
213
+ wdt->wdtdev.parent = dev;
203214
204215 watchdog_set_restart_priority(&wdt->wdtdev, 128);
205216
206217 watchdog_set_drvdata(&wdt->wdtdev, wdt);
218
+ dev_set_drvdata(dev, &wdt->wdtdev);
207219
208
- ret = devm_watchdog_register_device(&pdev->dev, &wdt->wdtdev);
209
- if (ret < 0) {
210
- dev_err(wdt->hw->dev,
211
- "watchdog registration failed (%d)\n", ret);
212
- return ret;
220
+ timeout = da9062_wdt_read_timeout(wdt);
221
+ if (timeout)
222
+ wdt->wdtdev.timeout = timeout;
223
+
224
+ /* Set timeout from DT value if available */
225
+ watchdog_init_timeout(&wdt->wdtdev, 0, dev);
226
+
227
+ if (timeout) {
228
+ da9062_wdt_set_timeout(&wdt->wdtdev, wdt->wdtdev.timeout);
229
+ set_bit(WDOG_HW_RUNNING, &wdt->wdtdev.status);
213230 }
214231
215
- return da9062_wdt_ping(&wdt->wdtdev);
232
+ return devm_watchdog_register_device(dev, &wdt->wdtdev);
216233 }
234
+
235
+static int __maybe_unused da9062_wdt_suspend(struct device *dev)
236
+{
237
+ struct watchdog_device *wdd = dev_get_drvdata(dev);
238
+ struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
239
+
240
+ if (!wdt->use_sw_pm)
241
+ return 0;
242
+
243
+ if (watchdog_active(wdd))
244
+ return da9062_wdt_stop(wdd);
245
+
246
+ return 0;
247
+}
248
+
249
+static int __maybe_unused da9062_wdt_resume(struct device *dev)
250
+{
251
+ struct watchdog_device *wdd = dev_get_drvdata(dev);
252
+ struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
253
+
254
+ if (!wdt->use_sw_pm)
255
+ return 0;
256
+
257
+ if (watchdog_active(wdd))
258
+ return da9062_wdt_start(wdd);
259
+
260
+ return 0;
261
+}
262
+
263
+static SIMPLE_DEV_PM_OPS(da9062_wdt_pm_ops,
264
+ da9062_wdt_suspend, da9062_wdt_resume);
217265
218266 static struct platform_driver da9062_wdt_driver = {
219267 .probe = da9062_wdt_probe,
220268 .driver = {
221269 .name = "da9062-watchdog",
270
+ .pm = &da9062_wdt_pm_ops,
222271 .of_match_table = da9062_compatible_id_table,
223272 },
224273 };