0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/watchdog.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/uaccess.h>
0013 #include <linux/slab.h>
0014 #include <linux/i2c.h>
0015 #include <linux/delay.h>
0016 #include <linux/jiffies.h>
0017 #include <linux/mfd/da9062/registers.h>
0018 #include <linux/mfd/da9062/core.h>
0019 #include <linux/property.h>
0020 #include <linux/regmap.h>
0021 #include <linux/of.h>
0022
0023 static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
0024 #define DA9062_TWDSCALE_DISABLE 0
0025 #define DA9062_TWDSCALE_MIN 1
0026 #define DA9062_TWDSCALE_MAX (ARRAY_SIZE(wdt_timeout) - 1)
0027 #define DA9062_WDT_MIN_TIMEOUT wdt_timeout[DA9062_TWDSCALE_MIN]
0028 #define DA9062_WDT_MAX_TIMEOUT wdt_timeout[DA9062_TWDSCALE_MAX]
0029 #define DA9062_WDG_DEFAULT_TIMEOUT wdt_timeout[DA9062_TWDSCALE_MAX-1]
0030 #define DA9062_RESET_PROTECTION_MS 300
0031
0032 struct da9062_watchdog {
0033 struct da9062 *hw;
0034 struct watchdog_device wdtdev;
0035 bool use_sw_pm;
0036 };
0037
0038 static unsigned int da9062_wdt_read_timeout(struct da9062_watchdog *wdt)
0039 {
0040 unsigned int val;
0041
0042 regmap_read(wdt->hw->regmap, DA9062AA_CONTROL_D, &val);
0043
0044 return wdt_timeout[val & DA9062AA_TWDSCALE_MASK];
0045 }
0046
0047 static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
0048 {
0049 unsigned int i;
0050
0051 for (i = DA9062_TWDSCALE_MIN; i <= DA9062_TWDSCALE_MAX; i++) {
0052 if (wdt_timeout[i] >= secs)
0053 return i;
0054 }
0055
0056 return DA9062_TWDSCALE_MAX;
0057 }
0058
0059 static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt)
0060 {
0061 return regmap_update_bits(wdt->hw->regmap, DA9062AA_CONTROL_F,
0062 DA9062AA_WATCHDOG_MASK,
0063 DA9062AA_WATCHDOG_MASK);
0064 }
0065
0066 static int da9062_wdt_update_timeout_register(struct da9062_watchdog *wdt,
0067 unsigned int regval)
0068 {
0069 struct da9062 *chip = wdt->hw;
0070
0071 regmap_update_bits(chip->regmap,
0072 DA9062AA_CONTROL_D,
0073 DA9062AA_TWDSCALE_MASK,
0074 DA9062_TWDSCALE_DISABLE);
0075
0076 usleep_range(150, 300);
0077
0078 return regmap_update_bits(chip->regmap,
0079 DA9062AA_CONTROL_D,
0080 DA9062AA_TWDSCALE_MASK,
0081 regval);
0082 }
0083
0084 static int da9062_wdt_start(struct watchdog_device *wdd)
0085 {
0086 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
0087 unsigned int selector;
0088 int ret;
0089
0090 selector = da9062_wdt_timeout_to_sel(wdt->wdtdev.timeout);
0091 ret = da9062_wdt_update_timeout_register(wdt, selector);
0092 if (ret)
0093 dev_err(wdt->hw->dev, "Watchdog failed to start (err = %d)\n",
0094 ret);
0095
0096 return ret;
0097 }
0098
0099 static int da9062_wdt_stop(struct watchdog_device *wdd)
0100 {
0101 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
0102 int ret;
0103
0104 ret = regmap_update_bits(wdt->hw->regmap,
0105 DA9062AA_CONTROL_D,
0106 DA9062AA_TWDSCALE_MASK,
0107 DA9062_TWDSCALE_DISABLE);
0108 if (ret)
0109 dev_err(wdt->hw->dev, "Watchdog failed to stop (err = %d)\n",
0110 ret);
0111
0112 return ret;
0113 }
0114
0115 static int da9062_wdt_ping(struct watchdog_device *wdd)
0116 {
0117 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
0118 int ret;
0119
0120
0121
0122
0123
0124 if (system_state > SYSTEM_RUNNING)
0125 return 0;
0126
0127 ret = da9062_reset_watchdog_timer(wdt);
0128 if (ret)
0129 dev_err(wdt->hw->dev, "Failed to ping the watchdog (err = %d)\n",
0130 ret);
0131
0132 return ret;
0133 }
0134
0135 static int da9062_wdt_set_timeout(struct watchdog_device *wdd,
0136 unsigned int timeout)
0137 {
0138 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
0139 unsigned int selector;
0140 int ret;
0141
0142 selector = da9062_wdt_timeout_to_sel(timeout);
0143 ret = da9062_wdt_update_timeout_register(wdt, selector);
0144 if (ret)
0145 dev_err(wdt->hw->dev, "Failed to set watchdog timeout (err = %d)\n",
0146 ret);
0147 else
0148 wdd->timeout = wdt_timeout[selector];
0149
0150 return ret;
0151 }
0152
0153 static int da9062_wdt_restart(struct watchdog_device *wdd, unsigned long action,
0154 void *data)
0155 {
0156 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
0157 struct i2c_client *client = to_i2c_client(wdt->hw->dev);
0158 int ret;
0159
0160
0161 ret = i2c_smbus_write_byte_data(client, DA9062AA_CONTROL_F,
0162 DA9062AA_SHUTDOWN_MASK);
0163 if (ret < 0)
0164 dev_alert(wdt->hw->dev, "Failed to shutdown (err = %d)\n",
0165 ret);
0166
0167
0168 mdelay(500);
0169
0170 return ret;
0171 }
0172
0173 static const struct watchdog_info da9062_watchdog_info = {
0174 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
0175 .identity = "DA9062 WDT",
0176 };
0177
0178 static const struct watchdog_ops da9062_watchdog_ops = {
0179 .owner = THIS_MODULE,
0180 .start = da9062_wdt_start,
0181 .stop = da9062_wdt_stop,
0182 .ping = da9062_wdt_ping,
0183 .set_timeout = da9062_wdt_set_timeout,
0184 .restart = da9062_wdt_restart,
0185 };
0186
0187 static const struct of_device_id da9062_compatible_id_table[] = {
0188 { .compatible = "dlg,da9062-watchdog", },
0189 { },
0190 };
0191
0192 MODULE_DEVICE_TABLE(of, da9062_compatible_id_table);
0193
0194 static int da9062_wdt_probe(struct platform_device *pdev)
0195 {
0196 struct device *dev = &pdev->dev;
0197 unsigned int timeout;
0198 struct da9062 *chip;
0199 struct da9062_watchdog *wdt;
0200
0201 chip = dev_get_drvdata(dev->parent);
0202 if (!chip)
0203 return -EINVAL;
0204
0205 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
0206 if (!wdt)
0207 return -ENOMEM;
0208
0209 wdt->use_sw_pm = device_property_present(dev, "dlg,use-sw-pm");
0210
0211 wdt->hw = chip;
0212
0213 wdt->wdtdev.info = &da9062_watchdog_info;
0214 wdt->wdtdev.ops = &da9062_watchdog_ops;
0215 wdt->wdtdev.min_timeout = DA9062_WDT_MIN_TIMEOUT;
0216 wdt->wdtdev.max_timeout = DA9062_WDT_MAX_TIMEOUT;
0217 wdt->wdtdev.min_hw_heartbeat_ms = DA9062_RESET_PROTECTION_MS;
0218 wdt->wdtdev.timeout = DA9062_WDG_DEFAULT_TIMEOUT;
0219 wdt->wdtdev.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
0220 wdt->wdtdev.parent = dev;
0221
0222 watchdog_set_restart_priority(&wdt->wdtdev, 128);
0223
0224 watchdog_set_drvdata(&wdt->wdtdev, wdt);
0225 dev_set_drvdata(dev, &wdt->wdtdev);
0226
0227 timeout = da9062_wdt_read_timeout(wdt);
0228 if (timeout)
0229 wdt->wdtdev.timeout = timeout;
0230
0231
0232 watchdog_init_timeout(&wdt->wdtdev, 0, dev);
0233
0234 if (timeout) {
0235 da9062_wdt_set_timeout(&wdt->wdtdev, wdt->wdtdev.timeout);
0236 set_bit(WDOG_HW_RUNNING, &wdt->wdtdev.status);
0237 }
0238
0239 return devm_watchdog_register_device(dev, &wdt->wdtdev);
0240 }
0241
0242 static int __maybe_unused da9062_wdt_suspend(struct device *dev)
0243 {
0244 struct watchdog_device *wdd = dev_get_drvdata(dev);
0245 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
0246
0247 if (!wdt->use_sw_pm)
0248 return 0;
0249
0250 if (watchdog_active(wdd))
0251 return da9062_wdt_stop(wdd);
0252
0253 return 0;
0254 }
0255
0256 static int __maybe_unused da9062_wdt_resume(struct device *dev)
0257 {
0258 struct watchdog_device *wdd = dev_get_drvdata(dev);
0259 struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
0260
0261 if (!wdt->use_sw_pm)
0262 return 0;
0263
0264 if (watchdog_active(wdd))
0265 return da9062_wdt_start(wdd);
0266
0267 return 0;
0268 }
0269
0270 static SIMPLE_DEV_PM_OPS(da9062_wdt_pm_ops,
0271 da9062_wdt_suspend, da9062_wdt_resume);
0272
0273 static struct platform_driver da9062_wdt_driver = {
0274 .probe = da9062_wdt_probe,
0275 .driver = {
0276 .name = "da9062-watchdog",
0277 .pm = &da9062_wdt_pm_ops,
0278 .of_match_table = da9062_compatible_id_table,
0279 },
0280 };
0281 module_platform_driver(da9062_wdt_driver);
0282
0283 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
0284 MODULE_DESCRIPTION("WDT device driver for Dialog DA9062 and DA9061");
0285 MODULE_LICENSE("GPL");
0286 MODULE_ALIAS("platform:da9062-watchdog");