0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/kernel.h>
0013 #include <linux/mfd/rave-sp.h>
0014 #include <linux/module.h>
0015 #include <linux/nvmem-consumer.h>
0016 #include <linux/of_device.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/reboot.h>
0019 #include <linux/slab.h>
0020 #include <linux/watchdog.h>
0021
0022 enum {
0023 RAVE_SP_RESET_BYTE = 1,
0024 RAVE_SP_RESET_REASON_NORMAL = 0,
0025 RAVE_SP_RESET_DELAY_MS = 500,
0026 };
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 struct rave_sp_wdt_variant {
0038 unsigned int max_timeout;
0039 unsigned int min_timeout;
0040
0041 int (*configure)(struct watchdog_device *, bool);
0042 int (*restart)(struct watchdog_device *);
0043 };
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 struct rave_sp_wdt {
0054 struct watchdog_device wdd;
0055 struct rave_sp *sp;
0056 const struct rave_sp_wdt_variant *variant;
0057 struct notifier_block reboot_notifier;
0058 };
0059
0060 static struct rave_sp_wdt *to_rave_sp_wdt(struct watchdog_device *wdd)
0061 {
0062 return container_of(wdd, struct rave_sp_wdt, wdd);
0063 }
0064
0065 static int rave_sp_wdt_exec(struct watchdog_device *wdd, void *data,
0066 size_t data_size)
0067 {
0068 return rave_sp_exec(to_rave_sp_wdt(wdd)->sp,
0069 data, data_size, NULL, 0);
0070 }
0071
0072 static int rave_sp_wdt_legacy_configure(struct watchdog_device *wdd, bool on)
0073 {
0074 u8 cmd[] = {
0075 [0] = RAVE_SP_CMD_SW_WDT,
0076 [1] = 0,
0077 [2] = 0,
0078 [3] = on,
0079 [4] = on ? wdd->timeout : 0,
0080 };
0081
0082 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
0083 }
0084
0085 static int rave_sp_wdt_rdu_configure(struct watchdog_device *wdd, bool on)
0086 {
0087 u8 cmd[] = {
0088 [0] = RAVE_SP_CMD_SW_WDT,
0089 [1] = 0,
0090 [2] = on,
0091 [3] = (u8)wdd->timeout,
0092 [4] = (u8)(wdd->timeout >> 8),
0093 };
0094
0095 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
0096 }
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 static int rave_sp_wdt_configure(struct watchdog_device *wdd, bool on)
0113 {
0114 return to_rave_sp_wdt(wdd)->variant->configure(wdd, on);
0115 }
0116
0117 static int rave_sp_wdt_legacy_restart(struct watchdog_device *wdd)
0118 {
0119 u8 cmd[] = {
0120 [0] = RAVE_SP_CMD_RESET,
0121 [1] = 0,
0122 [2] = RAVE_SP_RESET_BYTE
0123 };
0124
0125 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
0126 }
0127
0128 static int rave_sp_wdt_rdu_restart(struct watchdog_device *wdd)
0129 {
0130 u8 cmd[] = {
0131 [0] = RAVE_SP_CMD_RESET,
0132 [1] = 0,
0133 [2] = RAVE_SP_RESET_BYTE,
0134 [3] = RAVE_SP_RESET_REASON_NORMAL
0135 };
0136
0137 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
0138 }
0139
0140 static int rave_sp_wdt_reboot_notifier(struct notifier_block *nb,
0141 unsigned long action, void *data)
0142 {
0143
0144
0145
0146
0147
0148
0149
0150 if (action == SYS_DOWN || action == SYS_HALT) {
0151 struct rave_sp_wdt *sp_wd =
0152 container_of(nb, struct rave_sp_wdt, reboot_notifier);
0153
0154 const int ret = sp_wd->variant->restart(&sp_wd->wdd);
0155
0156 if (ret < 0)
0157 dev_err(sp_wd->wdd.parent,
0158 "Failed to issue restart command (%d)", ret);
0159 return NOTIFY_OK;
0160 }
0161
0162 return NOTIFY_DONE;
0163 }
0164
0165 static int rave_sp_wdt_restart(struct watchdog_device *wdd,
0166 unsigned long action, void *data)
0167 {
0168
0169
0170
0171
0172
0173
0174 mdelay(2 * RAVE_SP_RESET_DELAY_MS);
0175
0176 return -EIO;
0177 }
0178
0179 static int rave_sp_wdt_start(struct watchdog_device *wdd)
0180 {
0181 int ret;
0182
0183 ret = rave_sp_wdt_configure(wdd, true);
0184 if (!ret)
0185 set_bit(WDOG_HW_RUNNING, &wdd->status);
0186
0187 return ret;
0188 }
0189
0190 static int rave_sp_wdt_stop(struct watchdog_device *wdd)
0191 {
0192 return rave_sp_wdt_configure(wdd, false);
0193 }
0194
0195 static int rave_sp_wdt_set_timeout(struct watchdog_device *wdd,
0196 unsigned int timeout)
0197 {
0198 wdd->timeout = timeout;
0199
0200 return rave_sp_wdt_configure(wdd, watchdog_active(wdd));
0201 }
0202
0203 static int rave_sp_wdt_ping(struct watchdog_device *wdd)
0204 {
0205 u8 cmd[] = {
0206 [0] = RAVE_SP_CMD_PET_WDT,
0207 [1] = 0,
0208 };
0209
0210 return rave_sp_wdt_exec(wdd, cmd, sizeof(cmd));
0211 }
0212
0213 static const struct watchdog_info rave_sp_wdt_info = {
0214 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
0215 .identity = "RAVE SP Watchdog",
0216 };
0217
0218 static const struct watchdog_ops rave_sp_wdt_ops = {
0219 .owner = THIS_MODULE,
0220 .start = rave_sp_wdt_start,
0221 .stop = rave_sp_wdt_stop,
0222 .ping = rave_sp_wdt_ping,
0223 .set_timeout = rave_sp_wdt_set_timeout,
0224 .restart = rave_sp_wdt_restart,
0225 };
0226
0227 static const struct rave_sp_wdt_variant rave_sp_wdt_legacy = {
0228 .max_timeout = 255,
0229 .min_timeout = 1,
0230 .configure = rave_sp_wdt_legacy_configure,
0231 .restart = rave_sp_wdt_legacy_restart,
0232 };
0233
0234 static const struct rave_sp_wdt_variant rave_sp_wdt_rdu = {
0235 .max_timeout = 180,
0236 .min_timeout = 60,
0237 .configure = rave_sp_wdt_rdu_configure,
0238 .restart = rave_sp_wdt_rdu_restart,
0239 };
0240
0241 static const struct of_device_id rave_sp_wdt_of_match[] = {
0242 {
0243 .compatible = "zii,rave-sp-watchdog-legacy",
0244 .data = &rave_sp_wdt_legacy,
0245 },
0246 {
0247 .compatible = "zii,rave-sp-watchdog",
0248 .data = &rave_sp_wdt_rdu,
0249 },
0250 { }
0251 };
0252
0253 static int rave_sp_wdt_probe(struct platform_device *pdev)
0254 {
0255 struct device *dev = &pdev->dev;
0256 struct watchdog_device *wdd;
0257 struct rave_sp_wdt *sp_wd;
0258 struct nvmem_cell *cell;
0259 __le16 timeout = 0;
0260 int ret;
0261
0262 sp_wd = devm_kzalloc(dev, sizeof(*sp_wd), GFP_KERNEL);
0263 if (!sp_wd)
0264 return -ENOMEM;
0265
0266 sp_wd->variant = of_device_get_match_data(dev);
0267 sp_wd->sp = dev_get_drvdata(dev->parent);
0268
0269 wdd = &sp_wd->wdd;
0270 wdd->parent = dev;
0271 wdd->info = &rave_sp_wdt_info;
0272 wdd->ops = &rave_sp_wdt_ops;
0273 wdd->min_timeout = sp_wd->variant->min_timeout;
0274 wdd->max_timeout = sp_wd->variant->max_timeout;
0275 wdd->status = WATCHDOG_NOWAYOUT_INIT_STATUS;
0276 wdd->timeout = 60;
0277
0278 cell = nvmem_cell_get(dev, "wdt-timeout");
0279 if (!IS_ERR(cell)) {
0280 size_t len;
0281 void *value = nvmem_cell_read(cell, &len);
0282
0283 if (!IS_ERR(value)) {
0284 memcpy(&timeout, value, min(len, sizeof(timeout)));
0285 kfree(value);
0286 }
0287 nvmem_cell_put(cell);
0288 }
0289 watchdog_init_timeout(wdd, le16_to_cpu(timeout), dev);
0290 watchdog_set_restart_priority(wdd, 255);
0291 watchdog_stop_on_unregister(wdd);
0292
0293 sp_wd->reboot_notifier.notifier_call = rave_sp_wdt_reboot_notifier;
0294 ret = devm_register_reboot_notifier(dev, &sp_wd->reboot_notifier);
0295 if (ret) {
0296 dev_err(dev, "Failed to register reboot notifier\n");
0297 return ret;
0298 }
0299
0300
0301
0302
0303
0304 wdd->max_hw_heartbeat_ms = wdd->max_timeout * 1000;
0305 ret = rave_sp_wdt_start(wdd);
0306 if (ret) {
0307 dev_err(dev, "Watchdog didn't start\n");
0308 return ret;
0309 }
0310
0311 ret = devm_watchdog_register_device(dev, wdd);
0312 if (ret) {
0313 rave_sp_wdt_stop(wdd);
0314 return ret;
0315 }
0316
0317 return 0;
0318 }
0319
0320 static struct platform_driver rave_sp_wdt_driver = {
0321 .probe = rave_sp_wdt_probe,
0322 .driver = {
0323 .name = KBUILD_MODNAME,
0324 .of_match_table = rave_sp_wdt_of_match,
0325 },
0326 };
0327
0328 module_platform_driver(rave_sp_wdt_driver);
0329
0330 MODULE_DEVICE_TABLE(of, rave_sp_wdt_of_match);
0331 MODULE_LICENSE("GPL");
0332 MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
0333 MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
0334 MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
0335 MODULE_DESCRIPTION("RAVE SP Watchdog driver");
0336 MODULE_ALIAS("platform:rave-sp-watchdog");