drv_pm.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-03-22 Sherman first version
  9. */
  10. // #define DRV_DEBUG
  11. #define DBG_TAG "drv.pm"
  12. #ifdef DRV_DEBUG
  13. #define DBG_LVL DBG_LOG
  14. #else
  15. #define DBG_LVL DBG_INFO
  16. #endif /* DRV_DEBUG */
  17. #include <rtdbg.h>
  18. #include <rtthread.h>
  19. #include <rtdevice.h>
  20. #include <hal_data.h>
  21. #include <drivers/pm.h>
  22. #define RESET_VALUE (0x00)
  23. #define CLOCK_START (0U)
  24. #define CLOCK_STOP (1U)
  25. /* Control block configuration in LPM mode */
  26. #ifdef BSP_LPM_SLEEP
  27. #define LPM_SLEEP_CTRL (lpm_instance_ctrl_t *)&g_lpm_sleep_ctrl
  28. #define LPM_SLEEP_CFG (lpm_cfg_t *)&g_lpm_sleep_cfg
  29. #else
  30. #define LPM_SLEEP_CTRL RT_NULL
  31. #define LPM_SLEEP_CFG RT_NULL
  32. #endif
  33. #ifdef BSP_LPM_STANDBY
  34. #define LPM_SW_STANDBY_CTRL (lpm_instance_ctrl_t *)&g_lpm_sw_standby_ctrl
  35. #define LPM_SW_STANDBY_CFG (lpm_cfg_t *)&g_lpm_sw_standby_cfg
  36. #else
  37. #define LPM_SW_STANDBY_CTRL RT_NULL
  38. #define LPM_SW_STANDBY_CFG RT_NULL
  39. #endif
  40. #ifdef BSP_LPM_SNOOZE
  41. #define LPM_SW_SNOOZE_CTRL (lpm_instance_ctrl_t *)&g_lpm_sw_standby_with_snooze_ctrl
  42. #define LPM_SW_SNOOZE_CFG (lpm_cfg_t *)&g_lpm_sw_standby_with_snooze_cfg
  43. #else
  44. #define LPM_SW_SNOOZE_CFG RT_NULL
  45. #define LPM_SW_SNOOZE_CTRL RT_NULL
  46. #endif
  47. /**
  48. * These are LPM Mode instances for Sleep, Software Standby, Snooze and Deep
  49. * Software Standby Modes.These instances are created by the FSP. We need these
  50. * at the Application level to take the MCU to different LPM modes with configured
  51. * trigger/cancel sources
  52. */
  53. lpm_instance_ctrl_t *g_lpm_ctrl_instance_ctrls[] =
  54. {
  55. LPM_SLEEP_CTRL,
  56. LPM_SW_STANDBY_CTRL,
  57. LPM_SW_SNOOZE_CTRL,
  58. };
  59. lpm_cfg_t *g_lpm_ctrl_instance_cfgs[] =
  60. {
  61. LPM_SLEEP_CFG,
  62. LPM_SW_STANDBY_CFG,
  63. LPM_SW_SNOOZE_CFG,
  64. };
  65. /**
  66. * Low Power Mode Definitions for LPM app
  67. * Since there are no Normal mode definition in LPM driver, use this enum to keep LPM app state including:
  68. * Sleep, SW Standby, SW Standby with Snooze enabled, Deep SW Standby, Normal.
  69. * Power consumption: NORMAL_STATE > SLEEP_STATE > SW_STANDBY_SNOOZE_STATE > SW_STANDBY_STATE > DEEP_SW_STANDBY_STATE
  70. */
  71. enum
  72. {
  73. SLEEP_STATE = 0, /* Sleep mode */
  74. SW_STANDBY_STATE, /* SW Standby mode */
  75. SW_STANDBY_SNOOZE_STATE, /* SW Standby mode with Snooze enabled */
  76. DEEP_SW_STANDBY_STATE, /* Deep SW Standby mode */
  77. NORMAL_STATE /* Normal mode */
  78. };
  79. #ifdef DRV_DEBUG
  80. static char *lpmstate_to_string(rt_uint8_t state)
  81. {
  82. switch (state)
  83. {
  84. case SLEEP_STATE:
  85. return "SLEEP";
  86. case SW_STANDBY_STATE:
  87. return "SW STANDBY";
  88. case SW_STANDBY_SNOOZE_STATE:
  89. return "SW STANDBY SNOOZE";
  90. case DEEP_SW_STANDBY_STATE:
  91. return "DEEP SW STANDBY";
  92. case NORMAL_STATE:
  93. return "NORMAL";
  94. default:
  95. return "UNKNOWN";
  96. }
  97. return "UNKNOWN";
  98. }
  99. static char *clk_to_string(cgc_clock_t cstate)
  100. {
  101. switch (cstate)
  102. {
  103. case CGC_CLOCK_HOCO:
  104. return "HOCO CLOCK";
  105. case CGC_CLOCK_MOCO:
  106. return "MOCO CLOCK";
  107. case CGC_CLOCK_LOCO:
  108. return "LOCO CLOCK";
  109. case CGC_CLOCK_MAIN_OSC:
  110. return "MAIN OSC CLOCK";
  111. case CGC_CLOCK_SUBCLOCK:
  112. return "SUB OSC CLOCK";
  113. case CGC_CLOCK_PLL:
  114. return "PLL OSC CLOCK";
  115. default:
  116. return "UNKNOWN";
  117. }
  118. return "UNKNOWN";
  119. }
  120. #endif
  121. /**
  122. * @brief This function enables and puts the MCU in sleep mode.
  123. * @param[IN] Requested LPM Mode and the pointer to it's instance
  124. * @retval FSP_SUCCESS: Upon successful entering sleep mode
  125. * @retval Any Other Error code apart from FSP_SUCCESS
  126. */
  127. static fsp_err_t lpm_mode_enter(uint8_t lpm_mode, lpm_instance_ctrl_t *const p_current_ctrl)
  128. {
  129. fsp_err_t err = FSP_SUCCESS;
  130. switch (lpm_mode)
  131. {
  132. case SW_STANDBY_STATE:
  133. /* Enter SW Standby mode */
  134. err = R_LPM_LowPowerModeEnter(p_current_ctrl);
  135. break;
  136. case SLEEP_STATE:
  137. /* Enter Sleep mode */
  138. err = R_LPM_LowPowerModeEnter(p_current_ctrl);
  139. break;
  140. case SW_STANDBY_SNOOZE_STATE:
  141. /* Enter SW Standby with Snooze enabled mode */
  142. err = R_LPM_LowPowerModeEnter(p_current_ctrl);
  143. break;
  144. default:
  145. /* return error */
  146. err = FSP_ERR_INVALID_MODE;
  147. break;
  148. }
  149. return err;
  150. }
  151. /**
  152. * @brief Start the LPM mode based on the incoming state
  153. * @param[IN] state: This is requested LPM state
  154. * @retval None.
  155. */
  156. static void entry_lpm(uint8_t state)
  157. {
  158. if (RT_NULL == g_lpm_ctrl_instance_ctrls[state])
  159. {
  160. return;
  161. }
  162. fsp_err_t err = FSP_SUCCESS;
  163. /* Disable IO port if it's not in Deep SW Standby mode */
  164. if (DEEP_SW_STANDBY_STATE != state)
  165. {
  166. /* Disable IO port before going to LPM mode*/
  167. err = R_IOPORT_PinsCfg(&g_ioport_ctrl, &g_bsp_pin_cfg);
  168. /* Handle error */
  169. if (FSP_SUCCESS != err)
  170. {
  171. LOG_E("Returned Error Code: 0x%x", err);
  172. }
  173. }
  174. /* Open LPM instance*/
  175. err = R_LPM_Open(g_lpm_ctrl_instance_ctrls[state], g_lpm_ctrl_instance_cfgs[state]);
  176. /* Handle error */
  177. if (FSP_SUCCESS != err)
  178. {
  179. LOG_E("Returned Error Code: 0x%x", err);
  180. }
  181. /* Enter LPM mode. Function will return after waking from low power mode. */
  182. err = lpm_mode_enter(state, g_lpm_ctrl_instance_ctrls[state]);
  183. /* Handle error */
  184. if (FSP_SUCCESS == err)
  185. {
  186. /* Close LPM instance.*/
  187. err = R_LPM_Close(g_lpm_ctrl_instance_ctrls[state]);
  188. /* Handle error */
  189. if (FSP_SUCCESS != err)
  190. {
  191. LOG_E("Returned Error Code: 0x%x", err);
  192. }
  193. /* Put IO port configuration back to user's selections */
  194. err = R_IOPORT_PinsCfg(&g_ioport_ctrl, &g_bsp_pin_cfg);
  195. /* Handle error */
  196. if (FSP_SUCCESS != err)
  197. {
  198. LOG_E("Returned Error Code: 0x%x", err);
  199. }
  200. }
  201. else
  202. {
  203. LOG_E("Returned Error Code: 0x%x", err);
  204. }
  205. }
  206. /**********************************************************************************************************************
  207. * @brief This function does necessary setups before entering SW Standby with Snooze enabled.
  208. * @retval FSP_SUCCESS Upon successful checking and starting LOCO clock, AGT1 timer
  209. * @retval Any Other Error code apart from FSP_SUCCESS
  210. **********************************************************************************************************************/
  211. static fsp_err_t standby_snooze_set(void)
  212. {
  213. fsp_err_t err = FSP_SUCCESS;
  214. agt_extended_cfg_t const *p_agt0_extend = agt1_timer_cascade_trigger_cfg.p_extend;
  215. /* Turn off part of the clock before entering Snooze */
  216. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
  217. if (FSP_SUCCESS != err)
  218. {
  219. LOG_E("Returned Error Code: 0x%x", err);
  220. }
  221. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MAIN_OSC);
  222. if (FSP_SUCCESS != err)
  223. {
  224. LOG_E("Returned Error Code: 0x%x", err);
  225. }
  226. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_SUBCLOCK);
  227. if (FSP_SUCCESS != err)
  228. {
  229. LOG_E("Returned Error Code: 0x%x", err);
  230. }
  231. /*
  232. * Check and start LOCO clock. LOCO is needed since it is selected as AGT1 timer counter source
  233. * CGC module is opened in user_clocks_set function
  234. */
  235. if (AGT_CLOCK_LOCO == p_agt0_extend->count_source)
  236. {
  237. if (CLOCK_STOP == R_SYSTEM->LOCOCR_b.LCSTP)
  238. {
  239. /* Start LOCO clock */
  240. err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_LOCO, NULL);
  241. /* Handle error */
  242. if (FSP_SUCCESS != err)
  243. {
  244. return err;
  245. }
  246. /* LOCO does not have Oscillation Stabilization Flag, wait for its stabilization by adding delay */
  247. R_BSP_SoftwareDelay(BSP_FEATURE_CGC_LOCO_STABILIZATION_MAX_US, BSP_DELAY_UNITS_MICROSECONDS);
  248. }
  249. }
  250. return err;
  251. }
  252. static void ra_sleep(struct rt_pm *pm, rt_uint8_t mode)
  253. {
  254. switch (mode)
  255. {
  256. case PM_SLEEP_MODE_NONE:
  257. break;
  258. case PM_SLEEP_MODE_IDLE:
  259. #ifdef BSP_LPM_SLEEP
  260. /* enrty sleep mode */
  261. entry_lpm(SLEEP_STATE);
  262. #else
  263. LOG_W("Disable mode:%s", lpmstate_to_string(SLEEP_STATE));
  264. #endif
  265. break;
  266. case PM_SLEEP_MODE_LIGHT:
  267. LOG_W("PM_SLEEP_MODE_LIGHT:This mode is not supported!");
  268. break;
  269. case PM_SLEEP_MODE_DEEP:
  270. #ifdef BSP_LPM_SNOOZE
  271. /* enrty standby snooze mode */
  272. standby_snooze_set();
  273. entry_lpm(SW_STANDBY_SNOOZE_STATE);
  274. #else
  275. LOG_W("Disable mode:%s", lpmstate_to_string(SW_STANDBY_SNOOZE_STATE));
  276. #endif
  277. break;
  278. case PM_SLEEP_MODE_STANDBY:
  279. #ifdef BSP_LPM_STANDBY
  280. /* enrty standby mode */
  281. entry_lpm(SW_STANDBY_STATE);
  282. #else
  283. LOG_W("Disable mode:%s", lpmstate_to_string(SW_STANDBY_STATE));
  284. #endif
  285. break;
  286. case PM_SLEEP_MODE_SHUTDOWN:
  287. LOG_W("PM_SLEEP_MODE_SHUTDOWN:This mode is not supported!");
  288. break;
  289. default:
  290. RT_ASSERT(0);
  291. break;
  292. }
  293. }
  294. /**
  295. * @brief This function changes the System Clock. Currently MOSC and SOSC are not connected on RA2L1 board.
  296. * So these needs to be turned OFF
  297. */
  298. static void preffered_ra_clock_setting(void)
  299. {
  300. fsp_err_t err = FSP_SUCCESS;
  301. /* Stop the Main Oscillator as it is not available on RA2L1-EK Board */
  302. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MAIN_OSC);
  303. if (FSP_SUCCESS != err)
  304. {
  305. LOG_E("Returned Error Code: 0x%x", err);
  306. }
  307. /* Stop the Sub Oscillator as it is not available on RA2L1-EK Board */
  308. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_SUBCLOCK);
  309. if (FSP_SUCCESS != err)
  310. {
  311. LOG_E("Returned Error Code: 0x%x", err);
  312. }
  313. }
  314. #ifdef R_CGC_H
  315. void uart_update(rt_uint8_t clockmode)
  316. {
  317. baud_setting_t baud_setting;
  318. uint32_t baud_rate = BAUD_RATE_115200;
  319. bool enable_bitrate_modulation = false;
  320. uint32_t error_rate_x_1000 = 5000;
  321. switch (clockmode)
  322. {
  323. case CGC_CLOCK_HOCO:
  324. baud_rate = BAUD_RATE_115200;
  325. break;
  326. case CGC_CLOCK_MOCO:
  327. baud_rate = BAUD_RATE_38400;
  328. break;
  329. case CGC_CLOCK_LOCO:
  330. case CGC_CLOCK_SUBCLOCK:
  331. baud_rate = 600;
  332. break;
  333. default:
  334. baud_rate = BAUD_RATE_115200;
  335. break;
  336. }
  337. fsp_err_t err = R_SCI_UART_BaudCalculate(baud_rate,
  338. enable_bitrate_modulation,
  339. error_rate_x_1000,
  340. &baud_setting);
  341. err = R_SCI_UART_BaudSet(&g_uart9_ctrl, (void *) &baud_setting);
  342. assert(FSP_SUCCESS == err);
  343. }
  344. /**
  345. * @brief This function is used to changes the System Clock.
  346. */
  347. static void change_system_clock(rt_uint8_t clockmode)
  348. {
  349. fsp_err_t err = FSP_SUCCESS;
  350. cgc_divider_cfg_t sys_divider_cf = { RESET_VALUE };
  351. cgc_clock_t sys_clock_source = { RESET_VALUE };
  352. cgc_clocks_cfg_t sys_clk_cfg = { RESET_VALUE };
  353. cgc_pll_cfg_t new_clk = { RESET_VALUE };
  354. #if defined (CPK_R7FA2L1AB)
  355. preffered_ra_clock_setting();
  356. sys_clk_cfg.mainosc_state = CGC_CLOCK_CHANGE_STOP;
  357. #endif
  358. err = R_CGC_SystemClockGet(&g_cgc0_ctrl, &sys_clock_source, &sys_divider_cf);
  359. if (FSP_SUCCESS != err)
  360. {
  361. LOG_E("Returned Error Code: 0x%x", err);
  362. }
  363. LOG_D("MCU Running with Clock Source = %s.", clk_to_string(sys_clock_source));
  364. switch (clockmode)
  365. {
  366. case CGC_CLOCK_HOCO:
  367. case CGC_CLOCK_MOCO:
  368. {
  369. sys_clock_source = clockmode;
  370. sys_clk_cfg.hoco_state = CGC_CLOCK_CHANGE_START;
  371. sys_clk_cfg.pll_cfg.source_clock = sys_clock_source;
  372. sys_clk_cfg.pll_cfg.divider = CGC_PLL_DIV_1;
  373. sys_clk_cfg.pll_cfg.multiplier = 0;
  374. sys_clk_cfg.pll2_cfg.source_clock = sys_clock_source;
  375. sys_clk_cfg.pll2_cfg.divider = CGC_PLL_DIV_1;
  376. sys_clk_cfg.pll2_cfg.multiplier = 0;
  377. sys_clk_cfg.divider_cfg.pclka_div = CGC_SYS_CLOCK_DIV_1;
  378. sys_clk_cfg.divider_cfg.pclkb_div = CGC_SYS_CLOCK_DIV_2;
  379. sys_clk_cfg.divider_cfg.pclkc_div = CGC_SYS_CLOCK_DIV_1;
  380. sys_clk_cfg.divider_cfg.pclkd_div = CGC_SYS_CLOCK_DIV_1;
  381. sys_clk_cfg.divider_cfg.iclk_div = CGC_SYS_CLOCK_DIV_1;
  382. sys_clk_cfg.divider_cfg.bclk_div = CGC_SYS_CLOCK_DIV_1;
  383. sys_clk_cfg.divider_cfg.fclk_div = CGC_SYS_CLOCK_DIV_1;
  384. break;
  385. }
  386. case CGC_CLOCK_LOCO:
  387. case CGC_CLOCK_SUBCLOCK:
  388. {
  389. sys_clock_source = clockmode;
  390. sys_clk_cfg.hoco_state = CGC_CLOCK_CHANGE_START;
  391. sys_clk_cfg.pll_cfg.source_clock = sys_clock_source;
  392. sys_clk_cfg.pll_cfg.divider = CGC_PLL_DIV_1;
  393. sys_clk_cfg.pll_cfg.multiplier = 0;
  394. sys_clk_cfg.pll2_cfg.source_clock = sys_clock_source;
  395. sys_clk_cfg.pll2_cfg.divider = CGC_PLL_DIV_1;
  396. sys_clk_cfg.pll2_cfg.multiplier = 0;
  397. sys_clk_cfg.divider_cfg.pclka_div = CGC_SYS_CLOCK_DIV_1;
  398. sys_clk_cfg.divider_cfg.pclkb_div = CGC_SYS_CLOCK_DIV_1;
  399. sys_clk_cfg.divider_cfg.pclkc_div = CGC_SYS_CLOCK_DIV_1;
  400. sys_clk_cfg.divider_cfg.pclkd_div = CGC_SYS_CLOCK_DIV_1;
  401. sys_clk_cfg.divider_cfg.iclk_div = CGC_SYS_CLOCK_DIV_1;
  402. sys_clk_cfg.divider_cfg.bclk_div = CGC_SYS_CLOCK_DIV_1;
  403. sys_clk_cfg.divider_cfg.fclk_div = CGC_SYS_CLOCK_DIV_1;
  404. break;
  405. }
  406. default:
  407. {
  408. sys_clock_source = CGC_CLOCK_PLL;
  409. sys_clk_cfg.pll_state = CGC_CLOCK_CHANGE_NONE;
  410. break;
  411. }
  412. }
  413. sys_clk_cfg.system_clock = sys_clock_source;
  414. err = R_CGC_ClocksCfg(&g_cgc0_ctrl, &sys_clk_cfg);
  415. if (FSP_SUCCESS != err)
  416. {
  417. LOG_E("Returned Error Code: 0x%x", err);
  418. }
  419. err = R_CGC_SystemClockSet(&g_cgc0_ctrl, sys_clock_source, &sys_clk_cfg.divider_cfg);
  420. if (FSP_SUCCESS != err)
  421. {
  422. LOG_E("Returned Error Code: 0x%x", err);
  423. }
  424. LOG_D("Requested Clock Source for MCU = %s.", clk_to_string(sys_clock_source));
  425. if (CGC_CLOCK_SUBCLOCK == sys_clock_source)
  426. {
  427. new_clk.source_clock = CGC_CLOCK_SUBCLOCK;
  428. err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_SUBCLOCK, &new_clk);
  429. if (FSP_SUCCESS != err)
  430. {
  431. LOG_E("Returned Error Code: 0x%x", err);
  432. }
  433. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_HOCO);
  434. if (FSP_SUCCESS != err)
  435. {
  436. LOG_E("Returned Error Code: 0x%x", err);
  437. }
  438. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
  439. if (FSP_SUCCESS != err)
  440. {
  441. LOG_E("Returned Error Code: 0x%x", err);
  442. }
  443. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_LOCO);
  444. if (FSP_SUCCESS != err)
  445. {
  446. LOG_E("Returned Error Code: 0x%x", err);
  447. }
  448. }
  449. else if (CGC_CLOCK_LOCO == sys_clock_source)
  450. {
  451. new_clk.source_clock = CGC_CLOCK_LOCO;
  452. err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_LOCO, &new_clk);
  453. if (FSP_SUCCESS != err)
  454. {
  455. LOG_E("Returned Error Code: 0x%x", err);
  456. }
  457. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_HOCO);
  458. if (FSP_SUCCESS != err)
  459. {
  460. LOG_E("Returned Error Code: 0x%x", err);
  461. }
  462. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
  463. if (FSP_SUCCESS != err)
  464. {
  465. LOG_E("Returned Error Code: 0x%x", err);
  466. }
  467. }
  468. else if (CGC_CLOCK_MOCO == sys_clock_source)
  469. {
  470. new_clk.source_clock = CGC_CLOCK_MOCO;
  471. err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_MOCO, &new_clk);
  472. if (FSP_SUCCESS != err)
  473. {
  474. LOG_E("Returned Error Code: 0x%x", err);
  475. }
  476. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_HOCO);
  477. if (FSP_SUCCESS != err)
  478. {
  479. LOG_E("Returned Error Code: 0x%x", err);
  480. }
  481. }
  482. else if (CGC_CLOCK_HOCO == sys_clock_source)
  483. {
  484. new_clk.source_clock = CGC_CLOCK_HOCO;
  485. err = R_CGC_ClockStart(&g_cgc0_ctrl, CGC_CLOCK_HOCO, &new_clk);
  486. if (FSP_SUCCESS != err)
  487. {
  488. LOG_E("Returned Error Code: 0x%x", err);
  489. }
  490. err = R_CGC_ClockStop(&g_cgc0_ctrl, CGC_CLOCK_MOCO);
  491. if (FSP_SUCCESS != err)
  492. {
  493. LOG_E("Returned Error Code: 0x%x", err);
  494. }
  495. }
  496. /* Clock Oscillation Stabilization, wait for its stabilization by adding delay */
  497. R_BSP_SoftwareDelay(BSP_FEATURE_CGC_LOCO_STABILIZATION_MAX_US, BSP_DELAY_UNITS_MICROSECONDS);
  498. extern void rt_hw_systick_init(void);
  499. rt_hw_systick_init();
  500. uart_update(clockmode);
  501. }
  502. static void ra_run(struct rt_pm *pm, rt_uint8_t mode)
  503. {
  504. switch (mode)
  505. {
  506. case PM_RUN_MODE_HIGH_SPEED:
  507. case PM_RUN_MODE_NORMAL_SPEED:
  508. change_system_clock(CGC_CLOCK_HOCO);
  509. break;
  510. case PM_RUN_MODE_MEDIUM_SPEED:
  511. change_system_clock(CGC_CLOCK_MOCO);
  512. break;
  513. case PM_RUN_MODE_LOW_SPEED:
  514. change_system_clock(CGC_CLOCK_LOCO);
  515. break;
  516. default:
  517. break;
  518. }
  519. }
  520. #endif
  521. /* Agt1 serves as a low-power timer */
  522. /**
  523. * @brief This function opens AGT modules
  524. */
  525. static fsp_err_t agt_timer_init(void)
  526. {
  527. fsp_err_t err = FSP_SUCCESS;
  528. /* Open AGT1 Timer in Periodic mode */
  529. err = R_AGT_Open(&agt1_timer_cascade_trigger_ctrl, &agt1_timer_cascade_trigger_cfg);
  530. return err;
  531. }
  532. /**
  533. * @brief This function starts AGT modules
  534. */
  535. #define AGT_SECOND_COUNT 512 /* clock_frequency / clock_divider */
  536. #define PERIOD_MAX 0xFFFF
  537. static fsp_err_t agt_timer_start(rt_uint32_t timeout)
  538. {
  539. fsp_err_t err = FSP_SUCCESS;
  540. rt_uint32_t tick = timeout * AGT_SECOND_COUNT / RT_TICK_PER_SECOND;
  541. rt_uint32_t period1 = tick > PERIOD_MAX ? PERIOD_MAX : tick;
  542. if (period1)
  543. {
  544. /* PeriodSet AGT1 timer */
  545. err = R_AGT_PeriodSet(&agt1_timer_cascade_trigger_ctrl, period1);
  546. if (FSP_SUCCESS == err)
  547. {
  548. /* Start AGT1 timer */
  549. err = R_AGT_Start(&agt1_timer_cascade_trigger_ctrl);
  550. }
  551. }
  552. return err;
  553. }
  554. /**
  555. * @brief This function stops AGT modules
  556. */
  557. static fsp_err_t agt_timer_stop(void)
  558. {
  559. fsp_err_t err = FSP_SUCCESS;
  560. timer_status_t agt_status = {0};
  561. err = R_AGT_StatusGet(&agt1_timer_cascade_trigger_ctrl, &agt_status);
  562. if (FSP_SUCCESS == err)
  563. {
  564. if (agt_status.state)
  565. {
  566. /* Stop Timer */
  567. err = R_AGT_Stop(&agt1_timer_cascade_trigger_ctrl);
  568. if (FSP_SUCCESS == err)
  569. {
  570. /* Reset counter */
  571. err = R_AGT_PeriodSet(&agt1_timer_cascade_trigger_ctrl, 0);
  572. err = R_AGT_Reset(&agt1_timer_cascade_trigger_ctrl);
  573. }
  574. }
  575. }
  576. return err;
  577. }
  578. static rt_uint32_t agt_timer_get(void)
  579. {
  580. rt_uint32_t tick = 0;
  581. rt_uint32_t counter = 0;
  582. timer_status_t agt1_status = {0};
  583. timer_info_t agt1_info = {RESET_VALUE};
  584. /* Stop AGT timers if they are counting */
  585. R_AGT_InfoGet(&agt1_timer_cascade_trigger_ctrl, &agt1_info);
  586. R_AGT_StatusGet(&agt1_timer_cascade_trigger_ctrl, &agt1_status);
  587. counter = agt1_status.counter < agt1_info.period_counts ?
  588. agt1_info.period_counts : (agt1_info.period_counts - agt1_status.counter);
  589. tick = counter * RT_TICK_PER_SECOND / AGT_SECOND_COUNT;
  590. LOG_D("get tick %u counter %u", tick, counter);
  591. return tick;
  592. }
  593. static void ra_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
  594. {
  595. agt_timer_start(timeout);
  596. }
  597. static void ra_timer_stop(struct rt_pm *pm)
  598. {
  599. agt_timer_stop();
  600. }
  601. static rt_tick_t ra_timer_get_tick(struct rt_pm *pm)
  602. {
  603. return agt_timer_get();
  604. }
  605. static const struct rt_pm_ops _ops =
  606. {
  607. ra_sleep,
  608. #ifdef R_CGC_H
  609. ra_run,
  610. #else
  611. RT_NULL,
  612. #endif
  613. ra_timer_start,
  614. ra_timer_stop,
  615. ra_timer_get_tick
  616. };
  617. /**
  618. * @brief This function initializes clock module by opening the CGC Module and Changes the System Clock to MOSC
  619. * @param[IN] None
  620. * @retval FSP_SUCCESS: Upon successful initialization.
  621. * @retval Any Other Error code apart from FSP_SUCCESS
  622. */
  623. static fsp_err_t init_cgc(void)
  624. {
  625. fsp_err_t err = FSP_SUCCESS;
  626. cgc_clock_t lsys_clock_source = {RESET_VALUE};
  627. cgc_divider_cfg_t sys_divider_cf = {RESET_VALUE};
  628. /* Open CGC module */
  629. err = R_CGC_Open(&g_cgc0_ctrl, &g_cgc0_cfg);
  630. /* Handle error */
  631. if (FSP_SUCCESS == err)
  632. {
  633. /* Get system clock source */
  634. err = R_CGC_SystemClockGet(&g_cgc0_ctrl, &lsys_clock_source, &sys_divider_cf);
  635. /* Handle error */
  636. if (FSP_SUCCESS == err)
  637. {
  638. LOG_D("MCU Running with Clock Source = %s.", clk_to_string(lsys_clock_source));
  639. }
  640. }
  641. return err;
  642. }
  643. /**
  644. * @brief This function initialize the power manager
  645. */
  646. int drv_pm_hw_init(void)
  647. {
  648. rt_uint8_t timer_mask = 0;
  649. fsp_err_t err = FSP_SUCCESS;
  650. /* Initialize the CGC(Clock Generation Circuit) module.
  651. * The CGC module API is used to dynamically change the required clock source */
  652. err = init_cgc();
  653. if (FSP_SUCCESS != err)
  654. {
  655. LOG_D("CGC Initialization Failed \r\n");
  656. LOG_E("Returned Error Code: 0x%x", err);
  657. return -1;
  658. }
  659. err = agt_timer_init();
  660. if (FSP_SUCCESS != err)
  661. {
  662. LOG_D("AGT Initialization Failed \r\n");
  663. LOG_E("Returned Error Code: 0x%x", err);
  664. return -1;
  665. }
  666. /* initialize timer mask */
  667. timer_mask = (1UL << PM_SLEEP_MODE_DEEP) | (1UL << PM_SLEEP_MODE_STANDBY);
  668. /* initialize system pm module */
  669. rt_system_pm_init(&_ops, timer_mask, RT_NULL);
  670. return 0;
  671. }
  672. INIT_BOARD_EXPORT(drv_pm_hw_init);