drv_reset.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. /*
  2. * File : drv_reset.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2016Äê7ÔÂ29ÈÕ Urey the first version
  23. */
  24. #include <rthw.h>
  25. #include <rtthread.h>
  26. #include <rtdevice.h>
  27. #include <finsh.h>
  28. #include "board.h"
  29. #include "drv_clock.h"
  30. #include "drv_ost.h"
  31. #include "drv_pmu.h"
  32. #include "drv_rtc.h"
  33. static void udelay(uint32_t x)
  34. {
  35. volatile uint32_t n = 1000;
  36. while(x--)
  37. {
  38. for (n = 0; n < 1000; ++n);
  39. }
  40. }
  41. static void mdelay(uint32_t x)
  42. {
  43. while(x--)
  44. udelay(1000);
  45. }
  46. #define RECOVERY_SIGNATURE (0x001a1a)
  47. #define REBOOT_SIGNATURE (0x003535)
  48. #define UNMSAK_SIGNATURE (0x7c0000)//do not use these bits
  49. void wdt_start_count(int msecs)
  50. {
  51. int time = BOARD_RTC_CLK / 64 * msecs / 1000;
  52. if(time > 65535)
  53. time = 65535;
  54. writel(1 << 16,TCU_BASE + TCU_TSCR);
  55. writel(0,WDT_BASE + WDT_TCNT); //counter
  56. writel(time,WDT_BASE + WDT_TDR); //data
  57. writel((3<<3 | 1<<1),WDT_BASE + WDT_TCSR);
  58. writel(0,WDT_BASE + WDT_TCER);
  59. writel(1,WDT_BASE + WDT_TCER);
  60. }
  61. void wdt_stop_count(void)
  62. {
  63. writel(1 << 16,TCU_BASE + TCU_TSCR);
  64. writel(0,WDT_BASE + WDT_TCNT); //counter
  65. writel(65535,WDT_BASE + WDT_TDR); //data
  66. writel(1 << 16,TCU_BASE + TCU_TSSR);
  67. }
  68. void wdt_clear(void)
  69. {
  70. writel(0,WDT_BASE + WDT_TCNT);
  71. }
  72. /*
  73. * Function: Keep power for CPU core when reset.
  74. * So that EPC, tcsm and so on can maintain it's status after reset-key pressed.
  75. */
  76. static int inline reset_keep_power(void)
  77. {
  78. rtc_write_reg(RTC_BASE + RTC_PWRONCR, rtc_read_reg(RTC_BASE + RTC_PWRONCR) & ~(1 << 0));
  79. return 0;
  80. }
  81. void x1000_hibernate(void)
  82. {
  83. uint32_t rtc_rtccr;
  84. rt_base_t level;
  85. wdt_stop_count();
  86. level = rt_hw_interrupt_disable();
  87. /* Set minimum wakeup_n pin low-level assertion time for wakeup: 1000ms */
  88. rtc_write_reg(RTC_BASE + RTC_HWFCR, HWFCR_WAIT_TIME(1000));
  89. /* Set reset pin low-level assertion time after wakeup: must > 60ms */
  90. rtc_write_reg(RTC_BASE + RTC_HRCR, HRCR_WAIT_TIME(125));
  91. /* clear wakeup status register */
  92. rtc_write_reg(RTC_BASE + RTC_HWRSR, 0x0);
  93. rtc_write_reg(RTC_BASE + RTC_HWCR, 0x8);
  94. /* Put CPU to hibernate mode */
  95. rtc_write_reg(RTC_BASE + RTC_HCR, 0x1);
  96. /*poweroff the pmu*/
  97. // jz_notifier_call(NOTEFY_PROI_HIGH, JZ_POST_HIBERNATION, NULL);
  98. rtc_rtccr = rtc_read_reg(RTC_BASE + RTC_RTCCR);
  99. rtc_rtccr |= 0x1 << 0;
  100. rtc_write_reg(RTC_BASE + RTC_RTCCR,rtc_rtccr);
  101. mdelay(200);
  102. while(1)
  103. {
  104. rt_kprintf("%s:We should NOT come here.%08x\n",__func__, rtc_read_reg(RTC_BASE + RTC_HCR));
  105. }
  106. }
  107. void x1000_wdt_restart(char *command)
  108. {
  109. rt_kprintf("Restarting after 4 ms\n");
  110. if ((command != NULL) && !strcmp(command, "recovery"))
  111. {
  112. while (cpm_inl(CPM_CPPSR) != RECOVERY_SIGNATURE)
  113. {
  114. rt_kprintf("set RECOVERY_SIGNATURE\n");
  115. cpm_outl(0x5a5a, CPM_CPSPPR);
  116. cpm_outl(RECOVERY_SIGNATURE, CPM_CPPSR);
  117. cpm_outl(0x0, CPM_CPSPPR);
  118. udelay(100);
  119. }
  120. }
  121. else
  122. {
  123. //WDT...
  124. cpm_outl(0x5a5a, CPM_CPSPPR);
  125. cpm_outl(REBOOT_SIGNATURE, CPM_CPPSR);
  126. cpm_outl(0x0, CPM_CPSPPR);
  127. }
  128. wdt_start_count(4);
  129. mdelay(200);
  130. while(1)
  131. rt_kprintf("check wdt.\n");
  132. }
  133. void x1000_hibernate_restart(char *command)
  134. {
  135. rt_base_t level;
  136. uint32_t rtc_rtcsr,rtc_rtccr;
  137. level = rt_hw_interrupt_disable();
  138. if ((command != NULL) && !strcmp(command, "recovery"))
  139. {
  140. x1000_wdt_restart(command);
  141. }
  142. /* hibernate_restart */
  143. while(!(rtc_read_reg(RTC_BASE + RTC_RTCCR) & RTCCR_WRDY));
  144. rtc_rtcsr = rtc_read_reg(RTC_BASE + RTC_RTCSR);
  145. rtc_rtccr = rtc_read_reg(RTC_BASE + RTC_RTCCR);
  146. rtc_write_reg(RTC_RTCSAR,rtc_rtcsr + 5);
  147. rtc_rtccr &= ~(1 << 4 | 1 << 1);
  148. rtc_rtccr |= 0x3 << 2;
  149. rtc_write_reg(RTC_BASE + RTC_RTCCR,rtc_rtccr);
  150. /* Clear reset status */
  151. cpm_outl(0,CPM_RSR);
  152. /* Set minimum wakeup_n pin low-level assertion time for wakeup: 1000ms */
  153. rtc_write_reg(RTC_BASE + RTC_HWFCR, HWFCR_WAIT_TIME(1000));
  154. /* Set reset pin low-level assertion time after wakeup: must > 60ms */
  155. rtc_write_reg(RTC_BASE + RTC_HRCR, HRCR_WAIT_TIME(125));
  156. /* clear wakeup status register */
  157. rtc_write_reg(RTC_BASE + RTC_HWRSR, 0x0);
  158. rtc_write_reg(RTC_BASE + RTC_HWCR, 0x9);
  159. /* Put CPU to hibernate mode */
  160. rtc_write_reg(RTC_BASE + RTC_HCR, 0x1);
  161. rtc_rtccr = rtc_read_reg(RTC_BASE + RTC_RTCCR);
  162. rtc_rtccr |= 0x1 << 0;
  163. rtc_write_reg(RTC_BASE + RTC_RTCCR,rtc_rtccr);
  164. mdelay(200);
  165. while(1)
  166. rt_kprintf("%s:We should NOT come here.%08x\n",__func__, rtc_read_reg(RTC_BASE + RTC_HCR));
  167. }
  168. uint32_t x1000_get_last_reset(void)
  169. {
  170. return (cpm_inl(CPM_RSR) & 0x0000000F);
  171. }
  172. /* ============================wdt control proc end =============================== */
  173. /* ============================reset proc=================================== */
  174. const char *reset_command[] = {"wdt","hibernate","recovery"};
  175. #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  176. int x1000_reset(const char *reset_cmd)
  177. {
  178. rt_base_t level;
  179. int command_size = 0;
  180. int i;
  181. command_size = ARRAY_SIZE(reset_command);
  182. for (i = 0; i < command_size; i++)
  183. {
  184. if (!strncmp(reset_cmd, reset_command[i], strlen(reset_command[i])))
  185. break;
  186. }
  187. if(i == command_size)
  188. return -RT_ERROR;
  189. level = rt_hw_interrupt_disable();
  190. switch(i)
  191. {
  192. case 0:
  193. x1000_wdt_restart("wdt");
  194. break;
  195. case 1:
  196. x1000_hibernate_restart("hibernate");
  197. break;
  198. case 2:
  199. x1000_wdt_restart("recovery");
  200. break;
  201. default:
  202. rt_kprintf("not support command %d\n", i);
  203. }
  204. rt_hw_interrupt_enable(level);
  205. return RT_EOK;
  206. }
  207. struct wdt_reset
  208. {
  209. int msecs;
  210. };
  211. static struct wdt_reset _wdt_param =
  212. {
  213. .msecs = 1000,
  214. };
  215. rt_err_t _wdt_init(rt_watchdog_t *wdt)
  216. {
  217. return RT_EOK;
  218. }
  219. rt_err_t _wdt_control(rt_watchdog_t *wdt, int cmd, void *arg)
  220. {
  221. switch (cmd)
  222. {
  223. case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
  224. {
  225. int msecs = *(int *)arg * 1000;
  226. if(msecs < 1000) msecs = 1000;
  227. if(msecs > 30000) msecs = 30000;
  228. _wdt_param.msecs = msecs;
  229. rt_kprintf("WDT timeout = %d\n",msecs);
  230. }
  231. break;
  232. case RT_DEVICE_CTRL_WDT_START:
  233. wdt_start_count(_wdt_param.msecs + 1000);
  234. break;
  235. case RT_DEVICE_CTRL_WDT_STOP:
  236. wdt_stop_count();
  237. break;
  238. case RT_DEVICE_CTRL_WDT_KEEPALIVE:
  239. wdt_clear();
  240. break;
  241. default:
  242. break;
  243. }
  244. return RT_EOK;
  245. }
  246. const struct rt_watchdog_ops _wdt_ops =
  247. {
  248. .init = _wdt_init,
  249. .control = _wdt_control
  250. };
  251. static struct rt_watchdog_device _wdt_device =
  252. {
  253. .ops = (struct rt_watchdog_ops *)&_wdt_ops,
  254. };
  255. int reboot(void)
  256. {
  257. rt_hw_cpu_reset();
  258. return 0;
  259. }
  260. MSH_CMD_EXPORT(reboot,reboot system...);
  261. int shutdown(void)
  262. {
  263. rt_hw_cpu_shutdown();
  264. }
  265. MSH_CMD_EXPORT(shutdown,shutdown system...);
  266. int rt_hw_wdt_init(void)
  267. {
  268. rt_hw_watchdog_register(&_wdt_device,"WDT",RT_DEVICE_FLAG_STANDALONE,&_wdt_param);
  269. return 0;
  270. }
  271. INIT_DEVICE_EXPORT(rt_hw_wdt_init);
  272. void rt_hw_cpu_reset()
  273. {
  274. /* Disable Base_board */
  275. drv_pmu_power_down();
  276. x1000_reset("wdt");
  277. }
  278. void rt_hw_cpu_shutdown()
  279. {
  280. /* Disable Base_board */
  281. drv_pmu_power_down();
  282. x1000_hibernate();
  283. }