hal_watchdog.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright 2018 Rockchip Electronics Co., Ltd
  3. *
  4. */
  5. #include <stdio.h>
  6. #include <hal_osal.h>
  7. #include <barrier.h>
  8. #include "sunxi_hal_common.h"
  9. #include "platform_watchdog.h"
  10. #define writel_wdt hal_writel
  11. #define readl_wdt hal_readl
  12. static unsigned long running;
  13. static unsigned long running_saved;
  14. static const int wdt_timeout_map[] =
  15. {
  16. [1] = 0x1, /* 1s 32000cycles*/
  17. [2] = 0x2, /* 2s 64000*/
  18. [3] = 0x3, /* 3s 96000*/
  19. [4] = 0x4, /* 4s 128000*/
  20. [5] = 0x5, /* 5s 160000*/
  21. [6] = 0x6, /* 6s 192000*/
  22. [8] = 0x7, /* 8s 256000*/
  23. [10] = 0x8, /* 10s 320000*/
  24. [12] = 0x9, /* 12s 384000*/
  25. [14] = 0xA, /* 14s 448000*/
  26. [16] = 0xB, /* 16s 512000*/
  27. };
  28. int hal_watchdog_is_running(void)
  29. {
  30. return running_saved;
  31. }
  32. int hal_watchdog_suspend(int timeout)
  33. {
  34. running_saved = running;
  35. pr_debug("%s()\n", __func__);
  36. if (hal_watchdog_is_running()) {
  37. pr_debug("%s()\n", __func__);
  38. hal_watchdog_stop(timeout);
  39. }
  40. return 0;
  41. }
  42. int hal_watchdog_resume(int timeout)
  43. {
  44. pr_debug("%s()\n", __func__);
  45. if (hal_watchdog_is_running()) {
  46. pr_debug("%s()\n", __func__);
  47. hal_watchdog_start(timeout);
  48. }
  49. return 0;
  50. }
  51. void hal_watchdog_info(void)
  52. {
  53. struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
  54. printf("mode: 0x%x, cfg=0x%x, ctl=0x%x\n",
  55. (unsigned int)(wdt->mode), (unsigned int)(wdt->cfg), (unsigned int)(wdt->ctl));
  56. }
  57. void hal_watchdog_disable(void)
  58. {
  59. struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
  60. unsigned int wtmode;
  61. pr_debug("%s()\n", __func__);
  62. wtmode = readl_wdt(&wdt->mode);
  63. wtmode &= ~WDT_MODE_EN;
  64. wtmode |= KEY_FIELD_MAGIC;
  65. writel_wdt(wtmode, &wdt->mode);
  66. isb();
  67. running = 0;
  68. }
  69. void hal_watchdog_reset(int timeout)
  70. {
  71. int timeout_set = timeout;
  72. struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
  73. unsigned int wtmode;
  74. pr_debug("%s()\n", __func__);
  75. hal_watchdog_disable();
  76. if (timeout > 16)
  77. {
  78. timeout_set = 16;
  79. }
  80. if (wdt_timeout_map[timeout_set] == 0)
  81. {
  82. timeout_set++;
  83. }
  84. wtmode = KEY_FIELD_MAGIC | (wdt_timeout_map[timeout_set] << 4) | WDT_MODE_EN;
  85. writel_wdt(KEY_FIELD_MAGIC | WDT_CFG_RESET, &wdt->cfg);
  86. writel_wdt(wtmode, &wdt->mode);
  87. isb();
  88. writel_wdt(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdt->ctl);
  89. running = 1;
  90. }
  91. void hal_watchdog_restart(void)
  92. {
  93. struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
  94. pr_debug("%s()\n", __func__);
  95. hal_watchdog_disable();
  96. /* add delay for watchdog disable */
  97. udelay(50);
  98. /* Set the watchdog for its shortest interval (.5s) and wait */
  99. writel_wdt(KEY_FIELD_MAGIC | WDT_CFG_RESET, &wdt->cfg);
  100. isb();
  101. writel_wdt(KEY_FIELD_MAGIC | WDT_MODE_EN, &wdt->mode);
  102. while (1) {};
  103. }
  104. void hal_watchdog_init(void)
  105. {
  106. pr_debug("%s()\n", __func__);
  107. running = 0;
  108. running_saved = 0;
  109. }
  110. void hal_watchdog_stop(int timeout)
  111. {
  112. pr_debug("%s()\n", __func__);
  113. hal_watchdog_disable();
  114. }
  115. void hal_watchdog_start(int timeout)
  116. {
  117. pr_debug("%s()\n", __func__);
  118. hal_watchdog_reset(timeout);
  119. }
  120. void hal_watchdog_feed(void)
  121. {
  122. struct hal_sunxi_wdt *wdt = (struct hal_sunxi_wdt *)WDT_BASE;
  123. pr_debug("%s()\n", __func__);
  124. writel_wdt(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdt->ctl);
  125. }