drv_wdt.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-10-26 bigmagic first version
  9. */
  10. #include <rthw.h>
  11. #include "drv_wdt.h"
  12. #include "drv_gpio.h"
  13. #include "mbox.h"
  14. #include "raspi4.h"
  15. #ifdef BSP_USING_WDT
  16. #define SECS_TO_WDOG_TICKS(x) ((x) << 16)
  17. #define WDOG_TICKS_TO_SECS(x) ((x) >> 16)
  18. static struct raspi_wdt_driver bcm_wdt;
  19. void raspi_watchdog_init(rt_uint32_t time_init)
  20. {
  21. bcm_wdt.timeout = time_init;
  22. }
  23. void raspi_watchdog_start()
  24. {
  25. volatile rt_uint32_t cur;
  26. PM_WDOG = PM_PASSWORD | (SECS_TO_WDOG_TICKS(bcm_wdt.timeout) & PM_WDOG_TIME_SET);
  27. cur = (PM_RSTC);
  28. PM_RSTC = PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET;
  29. }
  30. void raspi_watchdog_stop()
  31. {
  32. PM_RSTC = PM_PASSWORD | PM_RSTC_RESET;
  33. }
  34. void raspi_watchdog_clr()
  35. {
  36. bcm_wdt.timeout = 0;
  37. }
  38. void raspi_watchdog_set_timeout(rt_uint32_t timeout_us)
  39. {
  40. bcm_wdt.timeout = timeout_us;
  41. }
  42. rt_uint64_t raspi_watchdog_get_timeout()
  43. {
  44. return bcm_wdt.timeout;
  45. }
  46. rt_uint64_t raspi_watchdog_get_timeleft()
  47. {
  48. rt_uint32_t ret = (PM_WDOG);
  49. return WDOG_TICKS_TO_SECS(ret & PM_WDOG_TIME_SET);
  50. }
  51. static rt_err_t raspi_wdg_init(rt_watchdog_t *wdt)
  52. {
  53. /* init for 10S */
  54. raspi_watchdog_init(1000000);
  55. raspi_watchdog_start();
  56. raspi_watchdog_stop();
  57. return RT_EOK;
  58. }
  59. static rt_err_t raspi_wdg_control(rt_watchdog_t *wdt, int cmd, void *arg)
  60. {
  61. rt_uint64_t timeout_us = 0;
  62. switch (cmd)
  63. {
  64. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  65. timeout_us = *((rt_uint32_t *)arg) * 1000000;
  66. if (timeout_us >= 0xFFFFFFFF)
  67. {
  68. timeout_us = 0xFFFFFFFF;
  69. }
  70. raspi_watchdog_set_timeout((rt_uint32_t)timeout_us);
  71. break;
  72. case RT_DEVICE_CTRL_WDT_GET_TIMEOUT:
  73. timeout_us = raspi_watchdog_get_timeout();
  74. *((rt_uint32_t *)arg) = timeout_us / 1000000;
  75. break;
  76. case RT_DEVICE_CTRL_WDT_GET_TIMELEFT:
  77. timeout_us = raspi_watchdog_get_timeleft();
  78. *((rt_uint32_t *)arg) = timeout_us / 1000000;
  79. break;
  80. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  81. raspi_watchdog_clr();
  82. break;
  83. case RT_DEVICE_CTRL_WDT_START:
  84. raspi_watchdog_start();
  85. break;
  86. case RT_DEVICE_CTRL_WDT_STOP:
  87. raspi_watchdog_stop();
  88. break;
  89. default:
  90. return RT_EIO;
  91. }
  92. return RT_EOK;
  93. }
  94. static const struct rt_watchdog_ops raspi_wdg_pos =
  95. {
  96. raspi_wdg_init,
  97. raspi_wdg_control,
  98. };
  99. static rt_watchdog_t raspi_wdg;
  100. int rt_hw_wdt_init(void)
  101. {
  102. raspi_wdg.ops = &raspi_wdg_pos;
  103. rt_hw_watchdog_register(&raspi_wdg, "wdg", 0, RT_NULL);
  104. return RT_EOK;
  105. }
  106. INIT_DEVICE_EXPORT(rt_hw_wdt_init);
  107. void poweroff(void)
  108. {
  109. unsigned long r;
  110. rt_kprintf("poweroff...\n");
  111. /* power off devices one by one */
  112. for (r = 0; r < 16; ++r)
  113. {
  114. bcm271x_mbox_poweroff_devices(r);
  115. }
  116. /* power off gpio pins (but not VCC pins) */
  117. GPIO_REG_GPFSEL0(GPIO_BASE) = 0;
  118. GPIO_REG_GPFSEL1(GPIO_BASE) = 0;
  119. GPIO_REG_GPFSEL2(GPIO_BASE) = 0;
  120. GPIO_REG_GPFSEL3(GPIO_BASE) = 0;
  121. GPIO_REG_GPFSEL4(GPIO_BASE) = 0;
  122. GPIO_REG_GPFSEL5(GPIO_BASE) = 0;
  123. GPIO_REG_GPPUD(GPIO_BASE) = 0;
  124. rt_thread_mdelay(150);
  125. GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0xffffffff;
  126. GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0xffffffff;
  127. rt_thread_mdelay(150);
  128. /* flush GPIO setup */
  129. GPIO_REG_GPPUDCLK0(GPIO_BASE) = 0;
  130. GPIO_REG_GPPUDCLK1(GPIO_BASE) = 0;
  131. /* power off the SoC (GPU + CPU), partition 63 used to indicate halt */
  132. r = PM_RSTS;
  133. r &= ~0xfffffaaa;
  134. r |= 0x555;
  135. PM_RSTS |= PM_PASSWORD | r;
  136. PM_WDOG |= PM_PASSWORD | 0x0A;
  137. PM_RSTC |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
  138. while (1) {};
  139. }
  140. MSH_CMD_EXPORT(poweroff, poweroff...);
  141. void reboot(void)
  142. {
  143. unsigned int r;
  144. rt_kprintf("reboot system...\n");
  145. rt_thread_mdelay(100);
  146. r = PM_RSTS;
  147. /* trigger a restart by instructing the GPU to boot from partition 0 */
  148. r &= ~0xfffffaaa;
  149. PM_RSTS |= (PM_PASSWORD | r); /* boot from partition 0 */
  150. PM_WDOG |= (PM_PASSWORD | 0x0A);
  151. PM_RSTC |= (PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET);
  152. while (1) {};
  153. }
  154. MSH_CMD_EXPORT(reboot, reboot system...);
  155. #endif /*BSP_USING_WDT */