ftwdt010_wdt.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Watchdog driver for the FTWDT010 Watch Dog Driver
  4. *
  5. * (c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com)
  6. * Based on sa1100_wdt.c by Oleg Drokin <green@crimea.edu>
  7. * Based on SoftDog driver by Alan Cox <alan@redhat.com>
  8. *
  9. * Copyright (C) 2011 Andes Technology Corporation
  10. * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
  11. *
  12. * 27/11/2004 Initial release, Faraday.
  13. * 12/01/2011 Port to u-boot, Macpaul Lin.
  14. * 22/08/2022 Port to DM
  15. */
  16. #include <common.h>
  17. #include <dm.h>
  18. #include <wdt.h>
  19. #include <log.h>
  20. #include <asm/io.h>
  21. #include <faraday/ftwdt010_wdt.h>
  22. struct ftwdt010_wdt_priv {
  23. struct ftwdt010_wdt __iomem *regs;
  24. };
  25. static int ftwdt010_wdt_reset(struct udevice *dev)
  26. {
  27. struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
  28. struct ftwdt010_wdt *wd = priv->regs;
  29. debug("Reset WDT..\n");
  30. /* clear control register */
  31. writel(0, &wd->wdcr);
  32. /* Write Magic number */
  33. writel(FTWDT010_WDRESTART_MAGIC, &wd->wdrestart);
  34. /* Enable WDT */
  35. writel(FTWDT010_WDCR_RST | FTWDT010_WDCR_ENABLE, &wd->wdcr);
  36. return 0;
  37. }
  38. /*
  39. * Set the watchdog time interval and start the timer.
  40. * Counter is 32 bit.
  41. */
  42. static int ftwdt010_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
  43. {
  44. struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
  45. struct ftwdt010_wdt *wd = priv->regs;
  46. unsigned int reg;
  47. debug("Activating WDT %llu ms\n", timeout_ms);
  48. /* Check if disabled */
  49. if (readl(&wd->wdcr) & ~FTWDT010_WDCR_ENABLE) {
  50. printf("sorry, watchdog is disabled\n");
  51. return -1;
  52. }
  53. /*
  54. * In a 66MHz system,
  55. * if you set WDLOAD as 0x03EF1480 (66000000)
  56. * the reset timer is 1 second.
  57. */
  58. reg = FTWDT010_WDLOAD(timeout_ms * FTWDT010_TIMEOUT_FACTOR);
  59. writel(reg, &wd->wdload);
  60. return ftwdt010_wdt_reset(dev);
  61. }
  62. static int ftwdt010_wdt_stop(struct udevice *dev)
  63. {
  64. struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
  65. struct ftwdt010_wdt *wd = priv->regs;
  66. debug("Deactivating WDT..\n");
  67. /*
  68. * It was defined with CONFIG_WATCHDOG_NOWAYOUT in Linux
  69. *
  70. * Shut off the timer.
  71. * Lock it in if it's a module and we defined ...NOWAYOUT
  72. */
  73. writel(0, &wd->wdcr);
  74. return 0;
  75. }
  76. static int ftwdt010_wdt_expire_now(struct udevice *dev, ulong flags)
  77. {
  78. struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
  79. struct ftwdt010_wdt *wd = priv->regs;
  80. debug("Expiring WDT..\n");
  81. writel(FTWDT010_WDLOAD(0), &wd->wdload);
  82. return ftwdt010_wdt_reset(dev);
  83. }
  84. static int ftwdt010_wdt_probe(struct udevice *dev)
  85. {
  86. struct ftwdt010_wdt_priv *priv = dev_get_priv(dev);
  87. priv->regs = dev_read_addr_ptr(dev);
  88. if (!priv->regs)
  89. return -EINVAL;
  90. return 0;
  91. }
  92. static const struct wdt_ops ftwdt010_wdt_ops = {
  93. .start = ftwdt010_wdt_start,
  94. .reset = ftwdt010_wdt_reset,
  95. .stop = ftwdt010_wdt_stop,
  96. .expire_now = ftwdt010_wdt_expire_now,
  97. };
  98. static const struct udevice_id ftwdt010_wdt_ids[] = {
  99. { .compatible = "faraday,ftwdt010" },
  100. {}
  101. };
  102. U_BOOT_DRIVER(ftwdt010_wdt) = {
  103. .name = "ftwdt010_wdt",
  104. .id = UCLASS_WDT,
  105. .of_match = ftwdt010_wdt_ids,
  106. .ops = &ftwdt010_wdt_ops,
  107. .probe = ftwdt010_wdt_probe,
  108. .priv_auto = sizeof(struct ftwdt010_wdt_priv),
  109. };