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