1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2016 IBM Corporation 4 * 5 * Joel Stanley <joel@jms.id.au> 6 */ 7 8 #include <linux/bits.h> 9 #include <linux/delay.h> 10 #include <linux/interrupt.h> 11 #include <linux/io.h> 12 #include <linux/kernel.h> 13 #include <linux/kstrtox.h> 14 #include <linux/mfd/syscon.h> 15 #include <linux/module.h> 16 #include <linux/of.h> 17 #include <linux/of_irq.h> 18 #include <linux/platform_device.h> 19 #include <linux/regmap.h> 20 #include <linux/watchdog.h> 21 22 static bool nowayout = WATCHDOG_NOWAYOUT; 23 module_param(nowayout, bool, 0); 24 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 25 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 26 struct aspeed_wdt_scu { 27 const char *compatible; 28 u32 reset_status_reg; 29 u32 wdt_reset_mask; 30 u32 wdt_reset_mask_shift; 31 }; 32 33 struct aspeed_wdt_config { 34 u32 ext_pulse_width_mask; 35 u32 irq_shift; 36 u32 irq_mask; 37 struct aspeed_wdt_scu scu; 38 }; 39 40 struct aspeed_wdt { 41 struct watchdog_device wdd; 42 void __iomem *base; 43 u32 ctrl; 44 const struct aspeed_wdt_config *cfg; 45 }; 46 47 static const struct aspeed_wdt_config ast2400_config = { 48 .ext_pulse_width_mask = 0xff, 49 .irq_shift = 0, 50 .irq_mask = 0, 51 .scu = { 52 .compatible = "aspeed,ast2400-scu", 53 .reset_status_reg = 0x3c, 54 .wdt_reset_mask = 0x1, 55 .wdt_reset_mask_shift = 1, 56 }, 57 }; 58 59 static const struct aspeed_wdt_config ast2500_config = { 60 .ext_pulse_width_mask = 0xfffff, 61 .irq_shift = 12, 62 .irq_mask = GENMASK(31, 12), 63 .scu = { 64 .compatible = "aspeed,ast2500-scu", 65 .reset_status_reg = 0x3c, 66 .wdt_reset_mask = 0x1, 67 .wdt_reset_mask_shift = 2, 68 }, 69 }; 70 71 static const struct aspeed_wdt_config ast2600_config = { 72 .ext_pulse_width_mask = 0xfffff, 73 .irq_shift = 0, 74 .irq_mask = GENMASK(31, 10), 75 .scu = { 76 .compatible = "aspeed,ast2600-scu", 77 .reset_status_reg = 0x74, 78 .wdt_reset_mask = 0xf, 79 .wdt_reset_mask_shift = 16, 80 }, 81 }; 82 83 static const struct of_device_id aspeed_wdt_of_table[] = { 84 { .compatible = "aspeed,ast2400-wdt", .data = &ast2400_config }, 85 { .compatible = "aspeed,ast2500-wdt", .data = &ast2500_config }, 86 { .compatible = "aspeed,ast2600-wdt", .data = &ast2600_config }, 87 { }, 88 }; 89 MODULE_DEVICE_TABLE(of, aspeed_wdt_of_table); 90 91 #define WDT_STATUS 0x00 92 #define WDT_RELOAD_VALUE 0x04 93 #define WDT_RESTART 0x08 94 #define WDT_CTRL 0x0C 95 #define WDT_CTRL_BOOT_SECONDARY BIT(7) 96 #define WDT_CTRL_RESET_MODE_SOC (0x00 << 5) 97 #define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5) 98 #define WDT_CTRL_RESET_MODE_ARM_CPU (0x10 << 5) 99 #define WDT_CTRL_1MHZ_CLK BIT(4) 100 #define WDT_CTRL_WDT_EXT BIT(3) 101 #define WDT_CTRL_WDT_INTR BIT(2) 102 #define WDT_CTRL_RESET_SYSTEM BIT(1) 103 #define WDT_CTRL_ENABLE BIT(0) 104 #define WDT_TIMEOUT_STATUS 0x10 105 #define WDT_TIMEOUT_STATUS_IRQ BIT(2) 106 #define WDT_TIMEOUT_STATUS_BOOT_SECONDARY BIT(1) 107 #define WDT_CLEAR_TIMEOUT_STATUS 0x14 108 #define WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION BIT(0) 109 #define WDT_RESET_MASK1 0x1c 110 #define WDT_RESET_MASK2 0x20 111 112 /* 113 * WDT_RESET_WIDTH controls the characteristics of the external pulse (if 114 * enabled), specifically: 115 * 116 * * Pulse duration 117 * * Drive mode: push-pull vs open-drain 118 * * Polarity: Active high or active low 119 * 120 * Pulse duration configuration is available on both the AST2400 and AST2500, 121 * though the field changes between SoCs: 122 * 123 * AST2400: Bits 7:0 124 * AST2500: Bits 19:0 125 * 126 * This difference is captured in struct aspeed_wdt_config. 127 * 128 * The AST2500 exposes the drive mode and polarity options, but not in a 129 * regular fashion. For read purposes, bit 31 represents active high or low, 130 * and bit 30 represents push-pull or open-drain. With respect to write, magic 131 * values need to be written to the top byte to change the state of the drive 132 * mode and polarity bits. Any other value written to the top byte has no 133 * effect on the state of the drive mode or polarity bits. However, the pulse 134 * width value must be preserved (as desired) if written. 135 */ 136 #define WDT_RESET_WIDTH 0x18 137 #define WDT_RESET_WIDTH_ACTIVE_HIGH BIT(31) 138 #define WDT_ACTIVE_HIGH_MAGIC (0xA5 << 24) 139 #define WDT_ACTIVE_LOW_MAGIC (0x5A << 24) 140 #define WDT_RESET_WIDTH_PUSH_PULL BIT(30) 141 #define WDT_PUSH_PULL_MAGIC (0xA8 << 24) 142 #define WDT_OPEN_DRAIN_MAGIC (0x8A << 24) 143 144 #define WDT_RESTART_MAGIC 0x4755 145 146 /* 32 bits at 1MHz, in milliseconds */ 147 #define WDT_MAX_TIMEOUT_MS 4294967 148 #define WDT_DEFAULT_TIMEOUT 30 149 #define WDT_RATE_1MHZ 1000000 150 151 static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd) 152 { 153 return container_of(wdd, struct aspeed_wdt, wdd); 154 } 155 156 static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count) 157 { 158 wdt->ctrl |= WDT_CTRL_ENABLE; 159 160 writel(0, wdt->base + WDT_CTRL); 161 writel(count, wdt->base + WDT_RELOAD_VALUE); 162 writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART); 163 writel(wdt->ctrl, wdt->base + WDT_CTRL); 164 } 165 166 static int aspeed_wdt_start(struct watchdog_device *wdd) 167 { 168 struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); 169 170 aspeed_wdt_enable(wdt, wdd->timeout * WDT_RATE_1MHZ); 171 172 return 0; 173 } 174 175 static int aspeed_wdt_stop(struct watchdog_device *wdd) 176 { 177 struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); 178 179 wdt->ctrl &= ~WDT_CTRL_ENABLE; 180 writel(wdt->ctrl, wdt->base + WDT_CTRL); 181 182 return 0; 183 } 184 185 static int aspeed_wdt_ping(struct watchdog_device *wdd) 186 { 187 struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); 188 189 writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART); 190 191 return 0; 192 } 193 194 static int aspeed_wdt_set_timeout(struct watchdog_device *wdd, 195 unsigned int timeout) 196 { 197 struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); 198 u32 actual; 199 200 wdd->timeout = timeout; 201 202 actual = min(timeout, wdd->max_hw_heartbeat_ms / 1000); 203 204 writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE); 205 writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART); 206 207 return 0; 208 } 209 210 static int aspeed_wdt_set_pretimeout(struct watchdog_device *wdd, 211 unsigned int pretimeout) 212 { 213 struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); 214 u32 actual = pretimeout * WDT_RATE_1MHZ; 215 u32 s = wdt->cfg->irq_shift; 216 u32 m = wdt->cfg->irq_mask; 217 218 wdd->pretimeout = pretimeout; 219 wdt->ctrl &= ~m; 220 if (pretimeout) 221 wdt->ctrl |= ((actual << s) & m) | WDT_CTRL_WDT_INTR; 222 else 223 wdt->ctrl &= ~WDT_CTRL_WDT_INTR; 224 225 writel(wdt->ctrl, wdt->base + WDT_CTRL); 226 227 return 0; 228 } 229 230 static int aspeed_wdt_restart(struct watchdog_device *wdd, 231 unsigned long action, void *data) 232 { 233 struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); 234 235 wdt->ctrl &= ~WDT_CTRL_BOOT_SECONDARY; 236 aspeed_wdt_enable(wdt, 128 * WDT_RATE_1MHZ / 1000); 237 238 mdelay(1000); 239 240 return 0; 241 } 242 243 static void aspeed_wdt_update_bootstatus(struct platform_device *pdev, 244 struct aspeed_wdt *wdt) 245 { 246 const struct resource *res; 247 struct aspeed_wdt_scu scu = wdt->cfg->scu; 248 struct regmap *scu_base; 249 u32 reset_mask_width; 250 u32 reset_mask_shift; 251 u32 idx = 0; 252 u32 status; 253 int ret; 254 255 if (!of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt")) { 256 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 257 idx = ((intptr_t)wdt->base & 0x00000fff) / (uintptr_t)resource_size(res); 258 } 259 260 scu_base = syscon_regmap_lookup_by_compatible(scu.compatible); 261 if (IS_ERR(scu_base)) { 262 wdt->wdd.bootstatus = WDIOS_UNKNOWN; 263 return; 264 } 265 266 ret = regmap_read(scu_base, scu.reset_status_reg, &status); 267 if (ret) { 268 wdt->wdd.bootstatus = WDIOS_UNKNOWN; 269 return; 270 } 271 272 reset_mask_width = hweight32(scu.wdt_reset_mask); 273 reset_mask_shift = scu.wdt_reset_mask_shift + 274 reset_mask_width * idx; 275 276 if (status & (scu.wdt_reset_mask << reset_mask_shift)) 277 wdt->wdd.bootstatus = WDIOF_CARDRESET; 278 279 /* clear wdt reset event flag */ 280 if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2400-wdt") || 281 of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-wdt")) { 282 ret = regmap_read(scu_base, scu.reset_status_reg, &status); 283 if (!ret) { 284 status &= ~(scu.wdt_reset_mask << reset_mask_shift); 285 regmap_write(scu_base, scu.reset_status_reg, status); 286 } 287 } else { 288 regmap_write(scu_base, scu.reset_status_reg, 289 scu.wdt_reset_mask << reset_mask_shift); 290 } 291 } 292 293 /* access_cs0 shows if cs0 is accessible, hence the reverted bit */ 294 static ssize_t access_cs0_show(struct device *dev, 295 struct device_attribute *attr, char *buf) 296 { 297 struct aspeed_wdt *wdt = dev_get_drvdata(dev); 298 u32 status = readl(wdt->base + WDT_TIMEOUT_STATUS); 299 300 return sysfs_emit(buf, "%u\n", 301 !(status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY)); 302 } 303 304 static ssize_t access_cs0_store(struct device *dev, 305 struct device_attribute *attr, const char *buf, 306 size_t size) 307 { 308 struct aspeed_wdt *wdt = dev_get_drvdata(dev); 309 unsigned long val; 310 311 if (kstrtoul(buf, 10, &val)) 312 return -EINVAL; 313 314 if (val) 315 writel(WDT_CLEAR_TIMEOUT_AND_BOOT_CODE_SELECTION, 316 wdt->base + WDT_CLEAR_TIMEOUT_STATUS); 317 318 return size; 319 } 320 321 /* 322 * This attribute exists only if the system has booted from the alternate 323 * flash with 'alt-boot' option. 324 * 325 * At alternate flash the 'access_cs0' sysfs node provides: 326 * ast2400: a way to get access to the primary SPI flash chip at CS0 327 * after booting from the alternate chip at CS1. 328 * ast2500: a way to restore the normal address mapping from 329 * (CS0->CS1, CS1->CS0) to (CS0->CS0, CS1->CS1). 330 * 331 * Clearing the boot code selection and timeout counter also resets to the 332 * initial state the chip select line mapping. When the SoC is in normal 333 * mapping state (i.e. booted from CS0), clearing those bits does nothing for 334 * both versions of the SoC. For alternate boot mode (booted from CS1 due to 335 * wdt2 expiration) the behavior differs as described above. 336 * 337 * This option can be used with wdt2 (watchdog1) only. 338 */ 339 static DEVICE_ATTR_RW(access_cs0); 340 341 static struct attribute *bswitch_attrs[] = { 342 &dev_attr_access_cs0.attr, 343 NULL 344 }; 345 ATTRIBUTE_GROUPS(bswitch); 346 347 static const struct watchdog_ops aspeed_wdt_ops = { 348 .start = aspeed_wdt_start, 349 .stop = aspeed_wdt_stop, 350 .ping = aspeed_wdt_ping, 351 .set_timeout = aspeed_wdt_set_timeout, 352 .set_pretimeout = aspeed_wdt_set_pretimeout, 353 .restart = aspeed_wdt_restart, 354 .owner = THIS_MODULE, 355 }; 356 357 static const struct watchdog_info aspeed_wdt_info = { 358 .options = WDIOF_KEEPALIVEPING 359 | WDIOF_MAGICCLOSE 360 | WDIOF_SETTIMEOUT, 361 .identity = KBUILD_MODNAME, 362 }; 363 364 static const struct watchdog_info aspeed_wdt_pretimeout_info = { 365 .options = WDIOF_KEEPALIVEPING 366 | WDIOF_PRETIMEOUT 367 | WDIOF_MAGICCLOSE 368 | WDIOF_SETTIMEOUT, 369 .identity = KBUILD_MODNAME, 370 }; 371 372 static irqreturn_t aspeed_wdt_irq(int irq, void *arg) 373 { 374 struct watchdog_device *wdd = arg; 375 struct aspeed_wdt *wdt = to_aspeed_wdt(wdd); 376 u32 status = readl(wdt->base + WDT_TIMEOUT_STATUS); 377 378 if (status & WDT_TIMEOUT_STATUS_IRQ) 379 watchdog_notify_pretimeout(wdd); 380 381 return IRQ_HANDLED; 382 } 383 384 static int aspeed_wdt_probe(struct platform_device *pdev) 385 { 386 struct device *dev = &pdev->dev; 387 const struct of_device_id *ofdid; 388 struct aspeed_wdt *wdt; 389 struct device_node *np; 390 const char *reset_type; 391 u32 duration; 392 u32 status; 393 int ret; 394 395 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); 396 if (!wdt) 397 return -ENOMEM; 398 399 np = dev->of_node; 400 401 ofdid = of_match_node(aspeed_wdt_of_table, np); 402 if (!ofdid) 403 return -EINVAL; 404 wdt->cfg = ofdid->data; 405 406 wdt->base = devm_platform_ioremap_resource(pdev, 0); 407 if (IS_ERR(wdt->base)) 408 return PTR_ERR(wdt->base); 409 410 wdt->wdd.info = &aspeed_wdt_info; 411 412 if (wdt->cfg->irq_mask) { 413 int irq = platform_get_irq_optional(pdev, 0); 414 415 if (irq > 0) { 416 ret = devm_request_irq(dev, irq, aspeed_wdt_irq, 417 IRQF_SHARED, dev_name(dev), 418 wdt); 419 if (ret) 420 return ret; 421 422 wdt->wdd.info = &aspeed_wdt_pretimeout_info; 423 } 424 } 425 426 wdt->wdd.ops = &aspeed_wdt_ops; 427 wdt->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS; 428 wdt->wdd.parent = dev; 429 430 wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT; 431 watchdog_init_timeout(&wdt->wdd, 0, dev); 432 433 watchdog_set_nowayout(&wdt->wdd, nowayout); 434 435 /* 436 * On clock rates: 437 * - ast2400 wdt can run at PCLK, or 1MHz 438 * - ast2500 only runs at 1MHz, hard coding bit 4 to 1 439 * - ast2600 always runs at 1MHz 440 * 441 * Set the ast2400 to run at 1MHz as it simplifies the driver. 442 */ 443 if (of_device_is_compatible(np, "aspeed,ast2400-wdt")) 444 wdt->ctrl = WDT_CTRL_1MHZ_CLK; 445 446 /* 447 * Control reset on a per-device basis to ensure the 448 * host is not affected by a BMC reboot 449 */ 450 ret = of_property_read_string(np, "aspeed,reset-type", &reset_type); 451 if (ret) { 452 wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC | WDT_CTRL_RESET_SYSTEM; 453 } else { 454 if (!strcmp(reset_type, "cpu")) 455 wdt->ctrl |= WDT_CTRL_RESET_MODE_ARM_CPU | 456 WDT_CTRL_RESET_SYSTEM; 457 else if (!strcmp(reset_type, "soc")) 458 wdt->ctrl |= WDT_CTRL_RESET_MODE_SOC | 459 WDT_CTRL_RESET_SYSTEM; 460 else if (!strcmp(reset_type, "system")) 461 wdt->ctrl |= WDT_CTRL_RESET_MODE_FULL_CHIP | 462 WDT_CTRL_RESET_SYSTEM; 463 else if (strcmp(reset_type, "none")) 464 return -EINVAL; 465 } 466 if (of_property_read_bool(np, "aspeed,external-signal")) 467 wdt->ctrl |= WDT_CTRL_WDT_EXT; 468 if (of_property_read_bool(np, "aspeed,alt-boot")) 469 wdt->ctrl |= WDT_CTRL_BOOT_SECONDARY; 470 471 if (readl(wdt->base + WDT_CTRL) & WDT_CTRL_ENABLE) { 472 /* 473 * The watchdog is running, but invoke aspeed_wdt_start() to 474 * write wdt->ctrl to WDT_CTRL to ensure the watchdog's 475 * configuration conforms to the driver's expectations. 476 * Primarily, ensure we're using the 1MHz clock source. 477 */ 478 aspeed_wdt_start(&wdt->wdd); 479 set_bit(WDOG_HW_RUNNING, &wdt->wdd.status); 480 } 481 482 if ((of_device_is_compatible(np, "aspeed,ast2500-wdt")) || 483 (of_device_is_compatible(np, "aspeed,ast2600-wdt"))) { 484 u32 reset_mask[2]; 485 size_t nrstmask = of_device_is_compatible(np, "aspeed,ast2600-wdt") ? 2 : 1; 486 u32 reg = readl(wdt->base + WDT_RESET_WIDTH); 487 488 reg &= wdt->cfg->ext_pulse_width_mask; 489 if (of_property_read_bool(np, "aspeed,ext-active-high")) 490 reg |= WDT_ACTIVE_HIGH_MAGIC; 491 else 492 reg |= WDT_ACTIVE_LOW_MAGIC; 493 494 writel(reg, wdt->base + WDT_RESET_WIDTH); 495 496 reg &= wdt->cfg->ext_pulse_width_mask; 497 if (of_property_read_bool(np, "aspeed,ext-push-pull")) 498 reg |= WDT_PUSH_PULL_MAGIC; 499 else 500 reg |= WDT_OPEN_DRAIN_MAGIC; 501 502 writel(reg, wdt->base + WDT_RESET_WIDTH); 503 504 ret = of_property_read_u32_array(np, "aspeed,reset-mask", reset_mask, nrstmask); 505 if (!ret) { 506 writel(reset_mask[0], wdt->base + WDT_RESET_MASK1); 507 if (nrstmask > 1) 508 writel(reset_mask[1], wdt->base + WDT_RESET_MASK2); 509 } 510 } 511 512 if (!of_property_read_u32(np, "aspeed,ext-pulse-duration", &duration)) { 513 u32 max_duration = wdt->cfg->ext_pulse_width_mask + 1; 514 515 if (duration == 0 || duration > max_duration) { 516 dev_err(dev, "Invalid pulse duration: %uus\n", 517 duration); 518 duration = max(1U, min(max_duration, duration)); 519 dev_info(dev, "Pulse duration set to %uus\n", 520 duration); 521 } 522 523 /* 524 * The watchdog is always configured with a 1MHz source, so 525 * there is no need to scale the microsecond value. However we 526 * need to offset it - from the datasheet: 527 * 528 * "This register decides the asserting duration of wdt_ext and 529 * wdt_rstarm signal. The default value is 0xFF. It means the 530 * default asserting duration of wdt_ext and wdt_rstarm is 531 * 256us." 532 * 533 * This implies a value of 0 gives a 1us pulse. 534 */ 535 writel(duration - 1, wdt->base + WDT_RESET_WIDTH); 536 } 537 538 aspeed_wdt_update_bootstatus(pdev, wdt); 539 540 status = readl(wdt->base + WDT_TIMEOUT_STATUS); 541 if (status & WDT_TIMEOUT_STATUS_BOOT_SECONDARY) { 542 if (of_device_is_compatible(np, "aspeed,ast2400-wdt") || 543 of_device_is_compatible(np, "aspeed,ast2500-wdt")) 544 wdt->wdd.groups = bswitch_groups; 545 } 546 547 dev_set_drvdata(dev, wdt); 548 549 return devm_watchdog_register_device(dev, &wdt->wdd); 550 } 551 552 static struct platform_driver aspeed_watchdog_driver = { 553 .probe = aspeed_wdt_probe, 554 .driver = { 555 .name = KBUILD_MODNAME, 556 .of_match_table = aspeed_wdt_of_table, 557 }, 558 }; 559 560 static int __init aspeed_wdt_init(void) 561 { 562 return platform_driver_register(&aspeed_watchdog_driver); 563 } 564 arch_initcall(aspeed_wdt_init); 565 566 static void __exit aspeed_wdt_exit(void) 567 { 568 platform_driver_unregister(&aspeed_watchdog_driver); 569 } 570 module_exit(aspeed_wdt_exit); 571 572 MODULE_DESCRIPTION("Aspeed Watchdog Driver"); 573 MODULE_LICENSE("GPL"); 574