wdt.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (c) 2020, Google LLC. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <common/debug.h>
  7. #include <lib/mmio.h>
  8. #include <mt8173_def.h>
  9. #include <plat_sip_calls.h>
  10. #include <lib/psci/psci.h>
  11. #include <smccc_helpers.h>
  12. #include <wdt.h>
  13. #define WDT_BASE (RGU_BASE + 0)
  14. #define WDT_MODE (WDT_BASE + 0x00)
  15. #define WDT_LENGTH (WDT_BASE + 0x04)
  16. #define WDT_RESTART (WDT_BASE + 0x08)
  17. #define WDT_SWRST (WDT_BASE + 0x14)
  18. #define WDT_MODE_DUAL_MODE 0x40
  19. #define WDT_MODE_IRQ 0x8
  20. #define WDT_MODE_KEY 0x22000000
  21. #define WDT_MODE_EXTEN 0x4
  22. #define WDT_MODE_EN 0x1
  23. #define WDT_LENGTH_KEY 0x8
  24. #define WDT_RESTART_KEY 0x1971
  25. #define WDT_SWRST_KEY 0x1209
  26. #define WDT_MIN_TIMEOUT 1
  27. #define WDT_MAX_TIMEOUT 31
  28. enum smcwd_call {
  29. SMCWD_INFO = 0,
  30. SMCWD_SET_TIMEOUT = 1,
  31. SMCWD_ENABLE = 2,
  32. SMCWD_PET = 3,
  33. };
  34. static int wdt_enabled_before_suspend;
  35. /*
  36. * We expect the WDT registers to be correctly initialized by BL2 firmware
  37. * (which may be board specific), so we do not reinitialize them here.
  38. */
  39. void wdt_trigger_reset(void)
  40. {
  41. mmio_write_32(WDT_SWRST, WDT_SWRST_KEY);
  42. }
  43. void wdt_pet(void)
  44. {
  45. mmio_write_32(WDT_RESTART, WDT_RESTART_KEY);
  46. }
  47. int wdt_set_timeout(uint32_t timeout)
  48. {
  49. /* One tick here equals 512 32KHz ticks. 512 / 32000 * 125 / 2 = 1 */
  50. uint32_t ticks = timeout * 125 / 2;
  51. if (timeout < WDT_MIN_TIMEOUT || timeout > WDT_MAX_TIMEOUT)
  52. return PSCI_E_INVALID_PARAMS;
  53. mmio_write_32(WDT_LENGTH, ticks << 5 | WDT_LENGTH_KEY);
  54. return PSCI_E_SUCCESS;
  55. }
  56. void wdt_set_enable(int enable)
  57. {
  58. if (enable)
  59. wdt_pet();
  60. mmio_clrsetbits_32(WDT_MODE, WDT_MODE_EN,
  61. WDT_MODE_KEY | (enable ? WDT_MODE_EN : 0));
  62. }
  63. void wdt_suspend(void)
  64. {
  65. wdt_enabled_before_suspend = mmio_read_32(WDT_MODE) & WDT_MODE_EN;
  66. if (wdt_enabled_before_suspend)
  67. wdt_set_enable(0);
  68. }
  69. void wdt_resume(void)
  70. {
  71. if (wdt_enabled_before_suspend)
  72. wdt_set_enable(1);
  73. }
  74. uint64_t wdt_smc_handler(uint32_t x1,
  75. uint32_t x2,
  76. void *handle)
  77. {
  78. int ret;
  79. switch (x1) {
  80. case SMCWD_INFO:
  81. SMC_RET3(handle, PSCI_E_SUCCESS,
  82. WDT_MIN_TIMEOUT, WDT_MAX_TIMEOUT);
  83. case SMCWD_SET_TIMEOUT:
  84. ret = wdt_set_timeout(x2);
  85. SMC_RET1(handle, ret);
  86. case SMCWD_ENABLE:
  87. wdt_set_enable(x2 > 0);
  88. SMC_RET1(handle, PSCI_E_SUCCESS);
  89. case SMCWD_PET:
  90. wdt_pet();
  91. SMC_RET1(handle, PSCI_E_SUCCESS);
  92. default:
  93. ERROR("Unimplemented SMCWD call (%d)\n", x1);
  94. SMC_RET1(handle, PSCI_E_NOT_SUPPORTED);
  95. }
  96. }