1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2024 ROHM Semiconductors 4 * 5 * ROHM BD96801 watchdog driver 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/interrupt.h> 10 #include <linux/kernel.h> 11 #include <linux/mfd/rohm-bd96801.h> 12 #include <linux/mfd/rohm-generic.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/reboot.h> 17 #include <linux/regmap.h> 18 #include <linux/watchdog.h> 19 20 static bool nowayout; 21 module_param(nowayout, bool, 0); 22 MODULE_PARM_DESC(nowayout, 23 "Watchdog cannot be stopped once started (default=\"false\")"); 24 25 #define BD96801_WD_TMO_SHORT_MASK 0x70 26 #define BD96801_WD_RATIO_MASK 0x3 27 #define BD96801_WD_TYPE_MASK 0x4 28 #define BD96801_WD_TYPE_SLOW 0x4 29 #define BD96801_WD_TYPE_WIN 0x0 30 31 #define BD96801_WD_EN_MASK 0x3 32 #define BD96801_WD_IF_EN 0x1 33 #define BD96801_WD_QA_EN 0x2 34 #define BD96801_WD_DISABLE 0x0 35 36 #define BD96801_WD_ASSERT_MASK 0x8 37 #define BD96801_WD_ASSERT_RST 0x8 38 #define BD96801_WD_ASSERT_IRQ 0x0 39 40 #define BD96801_WD_FEED_MASK 0x1 41 #define BD96801_WD_FEED 0x1 42 43 /* 1.1 mS */ 44 #define FASTNG_MIN 11 45 #define FASTNG_MAX_US (100 * FASTNG_MIN << 7) 46 #define SLOWNG_MAX_US (16 * FASTNG_MAX_US) 47 48 #define BD96801_WDT_DEFAULT_MARGIN_MS 1843 49 /* Unit is seconds */ 50 #define DEFAULT_TIMEOUT 30 51 52 /* 53 * BD96801 WDG supports window mode so the TMO consists of SHORT and LONG 54 * timeout values. SHORT time is meaningful only in window mode where feeding 55 * period shorter than SHORT would be an error. LONG time is used to detect if 56 * feeding is not occurring within given time limit (SoC SW hangs). The LONG 57 * timeout time is a multiple of (2, 4, 8 or 16 times) the SHORT timeout. 58 */ 59 60 struct wdtbd96801 { 61 struct device *dev; 62 struct regmap *regmap; 63 struct watchdog_device wdt; 64 }; 65 66 static int bd96801_wdt_ping(struct watchdog_device *wdt) 67 { 68 struct wdtbd96801 *w = watchdog_get_drvdata(wdt); 69 70 return regmap_update_bits(w->regmap, BD96801_REG_WD_FEED, 71 BD96801_WD_FEED_MASK, BD96801_WD_FEED); 72 } 73 74 static int bd96801_wdt_start(struct watchdog_device *wdt) 75 { 76 struct wdtbd96801 *w = watchdog_get_drvdata(wdt); 77 78 return regmap_update_bits(w->regmap, BD96801_REG_WD_CONF, 79 BD96801_WD_EN_MASK, BD96801_WD_IF_EN); 80 } 81 82 static int bd96801_wdt_stop(struct watchdog_device *wdt) 83 { 84 struct wdtbd96801 *w = watchdog_get_drvdata(wdt); 85 86 return regmap_update_bits(w->regmap, BD96801_REG_WD_CONF, 87 BD96801_WD_EN_MASK, BD96801_WD_DISABLE); 88 } 89 90 static const struct watchdog_info bd96801_wdt_info = { 91 .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING | 92 WDIOF_SETTIMEOUT, 93 .identity = "BD96801 Watchdog", 94 }; 95 96 static const struct watchdog_ops bd96801_wdt_ops = { 97 .start = bd96801_wdt_start, 98 .stop = bd96801_wdt_stop, 99 .ping = bd96801_wdt_ping, 100 }; 101 102 static int find_closest_fast(unsigned int target, int *sel, unsigned int *val) 103 { 104 unsigned int window = FASTNG_MIN; 105 int i; 106 107 for (i = 0; i < 8 && window < target; i++) 108 window <<= 1; 109 110 if (i == 8) 111 return -EINVAL; 112 113 *val = window; 114 *sel = i; 115 116 return 0; 117 } 118 119 static int find_closest_slow_by_fast(unsigned int fast_val, unsigned int *target, 120 int *slowsel) 121 { 122 static const int multipliers[] = {2, 4, 8, 16}; 123 int sel; 124 125 for (sel = 0; sel < ARRAY_SIZE(multipliers) && 126 multipliers[sel] * fast_val < *target; sel++) 127 ; 128 129 if (sel == ARRAY_SIZE(multipliers)) 130 return -EINVAL; 131 132 *slowsel = sel; 133 *target = multipliers[sel] * fast_val; 134 135 return 0; 136 } 137 138 static int find_closest_slow(unsigned int *target, int *slow_sel, int *fast_sel) 139 { 140 static const int multipliers[] = {2, 4, 8, 16}; 141 unsigned int window = FASTNG_MIN; 142 unsigned int val = 0; 143 int i, j; 144 145 for (i = 0; i < 8; i++) { 146 for (j = 0; j < ARRAY_SIZE(multipliers); j++) { 147 unsigned int slow; 148 149 slow = window * multipliers[j]; 150 if (slow >= *target && (!val || slow < val)) { 151 val = slow; 152 *fast_sel = i; 153 *slow_sel = j; 154 } 155 } 156 window <<= 1; 157 } 158 if (!val) 159 return -EINVAL; 160 161 *target = val; 162 163 return 0; 164 } 165 166 static int bd96801_set_wdt_mode(struct wdtbd96801 *w, unsigned int hw_margin, 167 unsigned int hw_margin_min) 168 { 169 int fastng, slowng, type, ret, reg, mask; 170 struct device *dev = w->dev; 171 172 173 if (hw_margin_min * 1000 > FASTNG_MAX_US) { 174 dev_err(dev, "Unsupported fast timeout %u uS [max %u]\n", 175 hw_margin_min * 1000, FASTNG_MAX_US); 176 177 return -EINVAL; 178 } 179 180 if (hw_margin * 1000 > SLOWNG_MAX_US) { 181 dev_err(dev, "Unsupported slow timeout %u uS [max %u]\n", 182 hw_margin * 1000, SLOWNG_MAX_US); 183 184 return -EINVAL; 185 } 186 187 /* 188 * Convert to 100uS to guarantee reasonable timeouts fit in 189 * 32bit maintaining also a decent accuracy. 190 */ 191 hw_margin *= 10; 192 hw_margin_min *= 10; 193 194 if (hw_margin_min) { 195 unsigned int min; 196 197 type = BD96801_WD_TYPE_WIN; 198 dev_dbg(dev, "Setting type WINDOW 0x%x\n", type); 199 ret = find_closest_fast(hw_margin_min, &fastng, &min); 200 if (ret) 201 return ret; 202 203 ret = find_closest_slow_by_fast(min, &hw_margin, &slowng); 204 if (ret) { 205 dev_err(dev, 206 "can't support slow timeout %u uS using fast %u uS. [max slow %u uS]\n", 207 hw_margin * 100, min * 100, min * 100 * 16); 208 209 return ret; 210 } 211 w->wdt.min_hw_heartbeat_ms = min / 10; 212 } else { 213 type = BD96801_WD_TYPE_SLOW; 214 dev_dbg(dev, "Setting type SLOW 0x%x\n", type); 215 ret = find_closest_slow(&hw_margin, &slowng, &fastng); 216 if (ret) 217 return ret; 218 } 219 220 w->wdt.max_hw_heartbeat_ms = hw_margin / 10; 221 222 fastng = FIELD_PREP(BD96801_WD_TMO_SHORT_MASK, fastng); 223 224 reg = slowng | fastng; 225 mask = BD96801_WD_RATIO_MASK | BD96801_WD_TMO_SHORT_MASK; 226 ret = regmap_update_bits(w->regmap, BD96801_REG_WD_TMO, 227 mask, reg); 228 if (ret) 229 return ret; 230 231 ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF, 232 BD96801_WD_TYPE_MASK, type); 233 234 return ret; 235 } 236 237 static int bd96801_set_heartbeat_from_hw(struct wdtbd96801 *w, 238 unsigned int conf_reg) 239 { 240 int ret; 241 unsigned int val, sel, fast; 242 243 /* 244 * The BD96801 supports a somewhat peculiar QA-mode, which we do not 245 * support in this driver. If the QA-mode is enabled then we just 246 * warn and bail-out. 247 */ 248 if ((conf_reg & BD96801_WD_EN_MASK) != BD96801_WD_IF_EN) { 249 dev_err(w->dev, "watchdog set to Q&A mode - exiting\n"); 250 return -EINVAL; 251 } 252 253 ret = regmap_read(w->regmap, BD96801_REG_WD_TMO, &val); 254 if (ret) 255 return ret; 256 257 sel = FIELD_GET(BD96801_WD_TMO_SHORT_MASK, val); 258 fast = FASTNG_MIN << sel; 259 260 sel = (val & BD96801_WD_RATIO_MASK) + 1; 261 w->wdt.max_hw_heartbeat_ms = (fast << sel) / USEC_PER_MSEC; 262 263 if ((conf_reg & BD96801_WD_TYPE_MASK) == BD96801_WD_TYPE_WIN) 264 w->wdt.min_hw_heartbeat_ms = fast / USEC_PER_MSEC; 265 266 return 0; 267 } 268 269 static int init_wdg_hw(struct wdtbd96801 *w) 270 { 271 u32 hw_margin[2]; 272 int count, ret; 273 u32 hw_margin_max = BD96801_WDT_DEFAULT_MARGIN_MS, hw_margin_min = 0; 274 275 count = device_property_count_u32(w->dev->parent, "rohm,hw-timeout-ms"); 276 if (count < 0 && count != -EINVAL) 277 return count; 278 279 if (count > 0) { 280 if (count > ARRAY_SIZE(hw_margin)) 281 return -EINVAL; 282 283 ret = device_property_read_u32_array(w->dev->parent, 284 "rohm,hw-timeout-ms", 285 &hw_margin[0], count); 286 if (ret < 0) 287 return ret; 288 289 if (count == 1) 290 hw_margin_max = hw_margin[0]; 291 292 if (count == 2) { 293 if (hw_margin[1] > hw_margin[0]) { 294 hw_margin_max = hw_margin[1]; 295 hw_margin_min = hw_margin[0]; 296 } else { 297 hw_margin_max = hw_margin[0]; 298 hw_margin_min = hw_margin[1]; 299 } 300 } 301 } 302 303 ret = bd96801_set_wdt_mode(w, hw_margin_max, hw_margin_min); 304 if (ret) 305 return ret; 306 307 ret = device_property_match_string(w->dev->parent, "rohm,wdg-action", 308 "prstb"); 309 if (ret >= 0) { 310 ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF, 311 BD96801_WD_ASSERT_MASK, 312 BD96801_WD_ASSERT_RST); 313 return ret; 314 } 315 316 ret = device_property_match_string(w->dev->parent, "rohm,wdg-action", 317 "intb-only"); 318 if (ret >= 0) { 319 ret = regmap_update_bits(w->regmap, BD96801_REG_WD_CONF, 320 BD96801_WD_ASSERT_MASK, 321 BD96801_WD_ASSERT_IRQ); 322 return ret; 323 } 324 325 return 0; 326 } 327 328 static irqreturn_t bd96801_irq_hnd(int irq, void *data) 329 { 330 emergency_restart(); 331 332 return IRQ_NONE; 333 } 334 335 static int bd96801_wdt_probe(struct platform_device *pdev) 336 { 337 struct wdtbd96801 *w; 338 int ret, irq; 339 unsigned int val; 340 341 w = devm_kzalloc(&pdev->dev, sizeof(*w), GFP_KERNEL); 342 if (!w) 343 return -ENOMEM; 344 345 w->regmap = dev_get_regmap(pdev->dev.parent, NULL); 346 w->dev = &pdev->dev; 347 348 w->wdt.info = &bd96801_wdt_info; 349 w->wdt.ops = &bd96801_wdt_ops; 350 w->wdt.parent = pdev->dev.parent; 351 w->wdt.timeout = DEFAULT_TIMEOUT; 352 watchdog_set_drvdata(&w->wdt, w); 353 354 ret = regmap_read(w->regmap, BD96801_REG_WD_CONF, &val); 355 if (ret) 356 return dev_err_probe(&pdev->dev, ret, 357 "Failed to get the watchdog state\n"); 358 359 /* 360 * If the WDG is already enabled we assume it is configured by boot. 361 * In this case we just update the hw-timeout based on values set to 362 * the timeout / mode registers and leave the hardware configs 363 * untouched. 364 */ 365 if ((val & BD96801_WD_EN_MASK) != BD96801_WD_DISABLE) { 366 dev_dbg(&pdev->dev, "watchdog was running during probe\n"); 367 ret = bd96801_set_heartbeat_from_hw(w, val); 368 if (ret) 369 return ret; 370 371 set_bit(WDOG_HW_RUNNING, &w->wdt.status); 372 } else { 373 /* If WDG is not running so we will initializate it */ 374 ret = init_wdg_hw(w); 375 if (ret) 376 return ret; 377 } 378 379 dev_dbg(w->dev, "heartbeat set to %u - %u\n", 380 w->wdt.min_hw_heartbeat_ms, w->wdt.max_hw_heartbeat_ms); 381 382 watchdog_init_timeout(&w->wdt, 0, pdev->dev.parent); 383 watchdog_set_nowayout(&w->wdt, nowayout); 384 watchdog_stop_on_reboot(&w->wdt); 385 386 irq = platform_get_irq_byname(pdev, "bd96801-wdg"); 387 if (irq > 0) { 388 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, 389 bd96801_irq_hnd, 390 IRQF_ONESHOT, "bd96801-wdg", 391 NULL); 392 if (ret) 393 return dev_err_probe(&pdev->dev, ret, 394 "Failed to register IRQ\n"); 395 } 396 397 return devm_watchdog_register_device(&pdev->dev, &w->wdt); 398 } 399 400 static const struct platform_device_id bd96801_wdt_id[] = { 401 { "bd96801-wdt", }, 402 { } 403 }; 404 MODULE_DEVICE_TABLE(platform, bd96801_wdt_id); 405 406 static struct platform_driver bd96801_wdt = { 407 .driver = { 408 .name = "bd96801-wdt" 409 }, 410 .probe = bd96801_wdt_probe, 411 .id_table = bd96801_wdt_id, 412 }; 413 module_platform_driver(bd96801_wdt); 414 415 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); 416 MODULE_DESCRIPTION("BD96801 watchdog driver"); 417 MODULE_LICENSE("GPL"); 418