npcm_wdt.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2022 Nuvoton Technology, Inc
  4. */
  5. #include <dm.h>
  6. #include <errno.h>
  7. #include <log.h>
  8. #include <wdt.h>
  9. #include <asm/io.h>
  10. #include <linux/delay.h>
  11. #include <linux/err.h>
  12. #define NPCM_WTCLK (BIT(10) | BIT(11)) /* Clock divider */
  13. #define NPCM_WTE BIT(7) /* Enable */
  14. #define NPCM_WTIE BIT(6) /* Enable irq */
  15. #define NPCM_WTIS (BIT(4) | BIT(5)) /* Interval selection */
  16. #define NPCM_WTIF BIT(3) /* Interrupt flag*/
  17. #define NPCM_WTRF BIT(2) /* Reset flag */
  18. #define NPCM_WTRE BIT(1) /* Reset enable */
  19. #define NPCM_WTR BIT(0) /* Reset counter */
  20. struct npcm_wdt_priv {
  21. void __iomem *regs;
  22. };
  23. static int npcm_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
  24. {
  25. struct npcm_wdt_priv *priv = dev_get_priv(dev);
  26. u32 time_out, val;
  27. time_out = (u32)(timeout_ms) / 1000;
  28. if (time_out < 2)
  29. val = 0x800;
  30. else if (time_out < 3)
  31. val = 0x420;
  32. else if (time_out < 6)
  33. val = 0x810;
  34. else if (time_out < 11)
  35. val = 0x430;
  36. else if (time_out < 22)
  37. val = 0x820;
  38. else if (time_out < 44)
  39. val = 0xc00;
  40. else if (time_out < 87)
  41. val = 0x830;
  42. else if (time_out < 173)
  43. val = 0xc10;
  44. else if (time_out < 688)
  45. val = 0xc20;
  46. else
  47. val = 0xc30;
  48. val |= NPCM_WTRE | NPCM_WTE | NPCM_WTR | NPCM_WTIE;
  49. writel(val, priv->regs);
  50. return 0;
  51. }
  52. static int npcm_wdt_stop(struct udevice *dev)
  53. {
  54. struct npcm_wdt_priv *priv = dev_get_priv(dev);
  55. writel(0, priv->regs);
  56. return 0;
  57. }
  58. static int npcm_wdt_reset(struct udevice *dev)
  59. {
  60. struct npcm_wdt_priv *priv = dev_get_priv(dev);
  61. writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, priv->regs);
  62. return 0;
  63. }
  64. static int npcm_wdt_expire_now(struct udevice *dev, ulong flags)
  65. {
  66. return npcm_wdt_reset(dev);
  67. }
  68. static int npcm_wdt_of_to_plat(struct udevice *dev)
  69. {
  70. struct npcm_wdt_priv *priv = dev_get_priv(dev);
  71. priv->regs = dev_read_addr_ptr(dev);
  72. if (!priv->regs)
  73. return -EINVAL;
  74. return 0;
  75. }
  76. static const struct wdt_ops npcm_wdt_ops = {
  77. .expire_now = npcm_wdt_expire_now,
  78. .start = npcm_wdt_start,
  79. .reset = npcm_wdt_reset,
  80. .stop = npcm_wdt_stop,
  81. };
  82. static const struct udevice_id npcm_wdt_ids[] = {
  83. { .compatible = "nuvoton,npcm750-wdt" },
  84. { }
  85. };
  86. static int npcm_wdt_probe(struct udevice *dev)
  87. {
  88. debug("%s() wdt%u\n", __func__, dev_seq(dev));
  89. npcm_wdt_stop(dev);
  90. return 0;
  91. }
  92. U_BOOT_DRIVER(npcm_wdt) = {
  93. .name = "npcm_wdt",
  94. .id = UCLASS_WDT,
  95. .of_match = npcm_wdt_ids,
  96. .probe = npcm_wdt_probe,
  97. .priv_auto = sizeof(struct npcm_wdt_priv),
  98. .of_to_plat = npcm_wdt_of_to_plat,
  99. .ops = &npcm_wdt_ops,
  100. };