1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2010-2011 Picochip Ltd., Jamie Iles 4 * http://www.picochip.com 5 * 6 * This file implements a driver for the Synopsys DesignWare watchdog device 7 * in the many subsystems. The watchdog has 16 different timeout periods 8 * and these are a function of the input clock frequency. 9 * 10 * The DesignWare watchdog cannot be stopped once it has been started so we 11 * do not implement a stop function. The watchdog core will continue to send 12 * heartbeat requests after the watchdog device has been closed. 13 */ 14 15 #include <linux/bitops.h> 16 #include <linux/clk.h> 17 #include <linux/delay.h> 18 #include <linux/err.h> 19 #include <linux/io.h> 20 #include <linux/kernel.h> 21 #include <linux/module.h> 22 #include <linux/moduleparam.h> 23 #include <linux/of.h> 24 #include <linux/pm.h> 25 #include <linux/platform_device.h> 26 #include <linux/reset.h> 27 #include <linux/watchdog.h> 28 29 #define WDOG_CONTROL_REG_OFFSET 0x00 30 #define WDOG_CONTROL_REG_WDT_EN_MASK 0x01 31 #define WDOG_CONTROL_REG_RESP_MODE_MASK 0x02 32 #define WDOG_TIMEOUT_RANGE_REG_OFFSET 0x04 33 #define WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT 4 34 #define WDOG_CURRENT_COUNT_REG_OFFSET 0x08 35 #define WDOG_COUNTER_RESTART_REG_OFFSET 0x0c 36 #define WDOG_COUNTER_RESTART_KICK_VALUE 0x76 37 38 /* The maximum TOP (timeout period) value that can be set in the watchdog. */ 39 #define DW_WDT_MAX_TOP 15 40 41 #define DW_WDT_DEFAULT_SECONDS 30 42 43 static bool nowayout = WATCHDOG_NOWAYOUT; 44 module_param(nowayout, bool, 0); 45 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " 46 "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 47 48 struct dw_wdt { 49 void __iomem *regs; 50 struct clk *clk; 51 unsigned long rate; 52 struct watchdog_device wdd; 53 struct reset_control *rst; 54 /* Save/restore */ 55 u32 control; 56 u32 timeout; 57 }; 58 59 #define to_dw_wdt(wdd) container_of(wdd, struct dw_wdt, wdd) 60 61 static inline int dw_wdt_is_enabled(struct dw_wdt *dw_wdt) 62 { 63 return readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET) & 64 WDOG_CONTROL_REG_WDT_EN_MASK; 65 } 66 67 static inline int dw_wdt_top_in_seconds(struct dw_wdt *dw_wdt, unsigned top) 68 { 69 /* 70 * There are 16 possible timeout values in 0..15 where the number of 71 * cycles is 2 ^ (16 + i) and the watchdog counts down. 72 */ 73 return (1U << (16 + top)) / dw_wdt->rate; 74 } 75 76 static int dw_wdt_get_top(struct dw_wdt *dw_wdt) 77 { 78 int top = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET) & 0xF; 79 80 return dw_wdt_top_in_seconds(dw_wdt, top); 81 } 82 83 static int dw_wdt_ping(struct watchdog_device *wdd) 84 { 85 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); 86 87 writel(WDOG_COUNTER_RESTART_KICK_VALUE, dw_wdt->regs + 88 WDOG_COUNTER_RESTART_REG_OFFSET); 89 90 return 0; 91 } 92 93 static int dw_wdt_set_timeout(struct watchdog_device *wdd, unsigned int top_s) 94 { 95 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); 96 int i, top_val = DW_WDT_MAX_TOP; 97 98 /* 99 * Iterate over the timeout values until we find the closest match. We 100 * always look for >=. 101 */ 102 for (i = 0; i <= DW_WDT_MAX_TOP; ++i) 103 if (dw_wdt_top_in_seconds(dw_wdt, i) >= top_s) { 104 top_val = i; 105 break; 106 } 107 108 /* 109 * Set the new value in the watchdog. Some versions of dw_wdt 110 * have have TOPINIT in the TIMEOUT_RANGE register (as per 111 * CP_WDT_DUAL_TOP in WDT_COMP_PARAMS_1). On those we 112 * effectively get a pat of the watchdog right here. 113 */ 114 writel(top_val | top_val << WDOG_TIMEOUT_RANGE_TOPINIT_SHIFT, 115 dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); 116 117 /* 118 * In case users set bigger timeout value than HW can support, 119 * kernel(watchdog_dev.c) helps to feed watchdog before 120 * wdd->max_hw_heartbeat_ms 121 */ 122 if (top_s * 1000 <= wdd->max_hw_heartbeat_ms) 123 wdd->timeout = dw_wdt_top_in_seconds(dw_wdt, top_val); 124 else 125 wdd->timeout = top_s; 126 127 return 0; 128 } 129 130 static void dw_wdt_arm_system_reset(struct dw_wdt *dw_wdt) 131 { 132 u32 val = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); 133 134 /* Disable interrupt mode; always perform system reset. */ 135 val &= ~WDOG_CONTROL_REG_RESP_MODE_MASK; 136 /* Enable watchdog. */ 137 val |= WDOG_CONTROL_REG_WDT_EN_MASK; 138 writel(val, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); 139 } 140 141 static int dw_wdt_start(struct watchdog_device *wdd) 142 { 143 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); 144 145 dw_wdt_set_timeout(wdd, wdd->timeout); 146 dw_wdt_ping(&dw_wdt->wdd); 147 dw_wdt_arm_system_reset(dw_wdt); 148 149 return 0; 150 } 151 152 static int dw_wdt_stop(struct watchdog_device *wdd) 153 { 154 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); 155 156 if (!dw_wdt->rst) { 157 set_bit(WDOG_HW_RUNNING, &wdd->status); 158 return 0; 159 } 160 161 reset_control_assert(dw_wdt->rst); 162 reset_control_deassert(dw_wdt->rst); 163 164 return 0; 165 } 166 167 static int dw_wdt_restart(struct watchdog_device *wdd, 168 unsigned long action, void *data) 169 { 170 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); 171 172 writel(0, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); 173 if (dw_wdt_is_enabled(dw_wdt)) 174 writel(WDOG_COUNTER_RESTART_KICK_VALUE, 175 dw_wdt->regs + WDOG_COUNTER_RESTART_REG_OFFSET); 176 else 177 dw_wdt_arm_system_reset(dw_wdt); 178 179 /* wait for reset to assert... */ 180 mdelay(500); 181 182 return 0; 183 } 184 185 static unsigned int dw_wdt_get_timeleft(struct watchdog_device *wdd) 186 { 187 struct dw_wdt *dw_wdt = to_dw_wdt(wdd); 188 189 return readl(dw_wdt->regs + WDOG_CURRENT_COUNT_REG_OFFSET) / 190 dw_wdt->rate; 191 } 192 193 static const struct watchdog_info dw_wdt_ident = { 194 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | 195 WDIOF_MAGICCLOSE, 196 .identity = "Synopsys DesignWare Watchdog", 197 }; 198 199 static const struct watchdog_ops dw_wdt_ops = { 200 .owner = THIS_MODULE, 201 .start = dw_wdt_start, 202 .stop = dw_wdt_stop, 203 .ping = dw_wdt_ping, 204 .set_timeout = dw_wdt_set_timeout, 205 .get_timeleft = dw_wdt_get_timeleft, 206 .restart = dw_wdt_restart, 207 }; 208 209 #ifdef CONFIG_PM_SLEEP 210 static int dw_wdt_suspend(struct device *dev) 211 { 212 struct dw_wdt *dw_wdt = dev_get_drvdata(dev); 213 214 dw_wdt->control = readl(dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); 215 dw_wdt->timeout = readl(dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); 216 217 clk_disable_unprepare(dw_wdt->clk); 218 219 return 0; 220 } 221 222 static int dw_wdt_resume(struct device *dev) 223 { 224 struct dw_wdt *dw_wdt = dev_get_drvdata(dev); 225 int err = clk_prepare_enable(dw_wdt->clk); 226 227 if (err) 228 return err; 229 230 writel(dw_wdt->timeout, dw_wdt->regs + WDOG_TIMEOUT_RANGE_REG_OFFSET); 231 writel(dw_wdt->control, dw_wdt->regs + WDOG_CONTROL_REG_OFFSET); 232 233 dw_wdt_ping(&dw_wdt->wdd); 234 235 return 0; 236 } 237 #endif /* CONFIG_PM_SLEEP */ 238 239 static SIMPLE_DEV_PM_OPS(dw_wdt_pm_ops, dw_wdt_suspend, dw_wdt_resume); 240 241 static int dw_wdt_drv_probe(struct platform_device *pdev) 242 { 243 struct device *dev = &pdev->dev; 244 struct watchdog_device *wdd; 245 struct dw_wdt *dw_wdt; 246 int ret; 247 248 dw_wdt = devm_kzalloc(dev, sizeof(*dw_wdt), GFP_KERNEL); 249 if (!dw_wdt) 250 return -ENOMEM; 251 252 dw_wdt->regs = devm_platform_ioremap_resource(pdev, 0); 253 if (IS_ERR(dw_wdt->regs)) 254 return PTR_ERR(dw_wdt->regs); 255 256 dw_wdt->clk = devm_clk_get(dev, NULL); 257 if (IS_ERR(dw_wdt->clk)) 258 return PTR_ERR(dw_wdt->clk); 259 260 ret = clk_prepare_enable(dw_wdt->clk); 261 if (ret) 262 return ret; 263 264 dw_wdt->rate = clk_get_rate(dw_wdt->clk); 265 if (dw_wdt->rate == 0) { 266 ret = -EINVAL; 267 goto out_disable_clk; 268 } 269 270 dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); 271 if (IS_ERR(dw_wdt->rst)) { 272 ret = PTR_ERR(dw_wdt->rst); 273 goto out_disable_clk; 274 } 275 276 reset_control_deassert(dw_wdt->rst); 277 278 wdd = &dw_wdt->wdd; 279 wdd->info = &dw_wdt_ident; 280 wdd->ops = &dw_wdt_ops; 281 wdd->min_timeout = 1; 282 wdd->max_hw_heartbeat_ms = 283 dw_wdt_top_in_seconds(dw_wdt, DW_WDT_MAX_TOP) * 1000; 284 wdd->parent = dev; 285 286 watchdog_set_drvdata(wdd, dw_wdt); 287 watchdog_set_nowayout(wdd, nowayout); 288 watchdog_init_timeout(wdd, 0, dev); 289 290 /* 291 * If the watchdog is already running, use its already configured 292 * timeout. Otherwise use the default or the value provided through 293 * devicetree. 294 */ 295 if (dw_wdt_is_enabled(dw_wdt)) { 296 wdd->timeout = dw_wdt_get_top(dw_wdt); 297 set_bit(WDOG_HW_RUNNING, &wdd->status); 298 } else { 299 wdd->timeout = DW_WDT_DEFAULT_SECONDS; 300 watchdog_init_timeout(wdd, 0, dev); 301 } 302 303 platform_set_drvdata(pdev, dw_wdt); 304 305 watchdog_set_restart_priority(wdd, 128); 306 307 ret = watchdog_register_device(wdd); 308 if (ret) 309 goto out_disable_clk; 310 311 return 0; 312 313 out_disable_clk: 314 clk_disable_unprepare(dw_wdt->clk); 315 return ret; 316 } 317 318 static int dw_wdt_drv_remove(struct platform_device *pdev) 319 { 320 struct dw_wdt *dw_wdt = platform_get_drvdata(pdev); 321 322 watchdog_unregister_device(&dw_wdt->wdd); 323 reset_control_assert(dw_wdt->rst); 324 clk_disable_unprepare(dw_wdt->clk); 325 326 return 0; 327 } 328 329 #ifdef CONFIG_OF 330 static const struct of_device_id dw_wdt_of_match[] = { 331 { .compatible = "snps,dw-wdt", }, 332 { /* sentinel */ } 333 }; 334 MODULE_DEVICE_TABLE(of, dw_wdt_of_match); 335 #endif 336 337 static struct platform_driver dw_wdt_driver = { 338 .probe = dw_wdt_drv_probe, 339 .remove = dw_wdt_drv_remove, 340 .driver = { 341 .name = "dw_wdt", 342 .of_match_table = of_match_ptr(dw_wdt_of_match), 343 .pm = &dw_wdt_pm_ops, 344 }, 345 }; 346 347 module_platform_driver(dw_wdt_driver); 348 349 MODULE_AUTHOR("Jamie Iles"); 350 MODULE_DESCRIPTION("Synopsys DesignWare Watchdog Driver"); 351 MODULE_LICENSE("GPL"); 352