fsl_smc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  4. * Copyright 2016-2017 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_smc.h"
  35. #include "fsl_flash.h"
  36. #include "fsl_common.h"
  37. static uint32_t g_savedPrimask;
  38. #if (defined(FSL_FEATURE_SMC_HAS_PARAM) && FSL_FEATURE_SMC_HAS_PARAM)
  39. void SMC_GetParam(SMC_Type *base, smc_param_t *param)
  40. {
  41. uint32_t reg = base->PARAM;
  42. param->hsrunEnable = (bool)(reg & SMC_PARAM_EHSRUN_MASK);
  43. param->llsEnable = (bool)(reg & SMC_PARAM_ELLS_MASK);
  44. param->lls2Enable = (bool)(reg & SMC_PARAM_ELLS2_MASK);
  45. param->vlls0Enable = (bool)(reg & SMC_PARAM_EVLLS0_MASK);
  46. }
  47. #endif /* FSL_FEATURE_SMC_HAS_PARAM */
  48. void SMC_PreEnterStopModes(void)
  49. {
  50. flash_prefetch_speculation_status_t speculationStatus = {
  51. kFLASH_prefetchSpeculationOptionDisable, /* Disable instruction speculation.*/
  52. kFLASH_prefetchSpeculationOptionDisable, /* Disable data speculation.*/
  53. };
  54. g_savedPrimask = DisableGlobalIRQ();
  55. __ISB();
  56. /*
  57. * Before enter stop modes, the flash cache prefetch should be disabled.
  58. * Otherwise the prefetch might be interrupted by stop, then the data and
  59. * and instruction from flash are wrong.
  60. */
  61. FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
  62. }
  63. void SMC_PostExitStopModes(void)
  64. {
  65. flash_prefetch_speculation_status_t speculationStatus = {
  66. kFLASH_prefetchSpeculationOptionEnable, /* Enable instruction speculation.*/
  67. kFLASH_prefetchSpeculationOptionEnable, /* Enable data speculation.*/
  68. };
  69. FLASH_PflashSetPrefetchSpeculation(&speculationStatus);
  70. EnableGlobalIRQ(g_savedPrimask);
  71. __ISB();
  72. }
  73. void SMC_PreEnterWaitModes(void)
  74. {
  75. g_savedPrimask = DisableGlobalIRQ();
  76. __ISB();
  77. }
  78. void SMC_PostExitWaitModes(void)
  79. {
  80. EnableGlobalIRQ(g_savedPrimask);
  81. __ISB();
  82. }
  83. status_t SMC_SetPowerModeRun(SMC_Type *base)
  84. {
  85. uint8_t reg;
  86. reg = base->PMCTRL;
  87. /* configure Normal RUN mode */
  88. reg &= ~SMC_PMCTRL_RUNM_MASK;
  89. reg |= (kSMC_RunNormal << SMC_PMCTRL_RUNM_SHIFT);
  90. base->PMCTRL = reg;
  91. return kStatus_Success;
  92. }
  93. #if (defined(FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE) && FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE)
  94. status_t SMC_SetPowerModeHsrun(SMC_Type *base)
  95. {
  96. uint8_t reg;
  97. reg = base->PMCTRL;
  98. /* configure High Speed RUN mode */
  99. reg &= ~SMC_PMCTRL_RUNM_MASK;
  100. reg |= (kSMC_Hsrun << SMC_PMCTRL_RUNM_SHIFT);
  101. base->PMCTRL = reg;
  102. return kStatus_Success;
  103. }
  104. #endif /* FSL_FEATURE_SMC_HAS_HIGH_SPEED_RUN_MODE */
  105. status_t SMC_SetPowerModeWait(SMC_Type *base)
  106. {
  107. /* configure Normal Wait mode */
  108. SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
  109. __DSB();
  110. __WFI();
  111. __ISB();
  112. return kStatus_Success;
  113. }
  114. status_t SMC_SetPowerModeStop(SMC_Type *base, smc_partial_stop_option_t option)
  115. {
  116. uint8_t reg;
  117. #if (defined(FSL_FEATURE_SMC_HAS_PSTOPO) && FSL_FEATURE_SMC_HAS_PSTOPO)
  118. /* configure the Partial Stop mode in Noraml Stop mode */
  119. reg = base->STOPCTRL;
  120. reg &= ~SMC_STOPCTRL_PSTOPO_MASK;
  121. reg |= ((uint32_t)option << SMC_STOPCTRL_PSTOPO_SHIFT);
  122. base->STOPCTRL = reg;
  123. #endif
  124. /* configure Normal Stop mode */
  125. reg = base->PMCTRL;
  126. reg &= ~SMC_PMCTRL_STOPM_MASK;
  127. reg |= (kSMC_StopNormal << SMC_PMCTRL_STOPM_SHIFT);
  128. base->PMCTRL = reg;
  129. /* Set the SLEEPDEEP bit to enable deep sleep mode (stop mode) */
  130. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  131. /* read back to make sure the configuration valid before enter stop mode */
  132. (void)base->PMCTRL;
  133. __DSB();
  134. __WFI();
  135. __ISB();
  136. /* check whether the power mode enter Stop mode succeed */
  137. if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
  138. {
  139. return kStatus_SMC_StopAbort;
  140. }
  141. else
  142. {
  143. return kStatus_Success;
  144. }
  145. }
  146. status_t SMC_SetPowerModeVlpr(SMC_Type *base
  147. #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
  148. ,
  149. bool wakeupMode
  150. #endif
  151. )
  152. {
  153. uint8_t reg;
  154. reg = base->PMCTRL;
  155. #if (defined(FSL_FEATURE_SMC_HAS_LPWUI) && FSL_FEATURE_SMC_HAS_LPWUI)
  156. /* configure whether the system remains in VLP mode on an interrupt */
  157. if (wakeupMode)
  158. {
  159. /* exits to RUN mode on an interrupt */
  160. reg |= SMC_PMCTRL_LPWUI_MASK;
  161. }
  162. else
  163. {
  164. /* remains in VLP mode on an interrupt */
  165. reg &= ~SMC_PMCTRL_LPWUI_MASK;
  166. }
  167. #endif /* FSL_FEATURE_SMC_HAS_LPWUI */
  168. /* configure VLPR mode */
  169. reg &= ~SMC_PMCTRL_RUNM_MASK;
  170. reg |= (kSMC_RunVlpr << SMC_PMCTRL_RUNM_SHIFT);
  171. base->PMCTRL = reg;
  172. return kStatus_Success;
  173. }
  174. status_t SMC_SetPowerModeVlpw(SMC_Type *base)
  175. {
  176. /* configure VLPW mode */
  177. /* Set the SLEEPDEEP bit to enable deep sleep mode */
  178. SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
  179. __DSB();
  180. __WFI();
  181. __ISB();
  182. return kStatus_Success;
  183. }
  184. status_t SMC_SetPowerModeVlps(SMC_Type *base)
  185. {
  186. uint8_t reg;
  187. /* configure VLPS mode */
  188. reg = base->PMCTRL;
  189. reg &= ~SMC_PMCTRL_STOPM_MASK;
  190. reg |= (kSMC_StopVlps << SMC_PMCTRL_STOPM_SHIFT);
  191. base->PMCTRL = reg;
  192. /* Set the SLEEPDEEP bit to enable deep sleep mode */
  193. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  194. /* read back to make sure the configuration valid before enter stop mode */
  195. (void)base->PMCTRL;
  196. __DSB();
  197. __WFI();
  198. __ISB();
  199. /* check whether the power mode enter VLPS mode succeed */
  200. if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
  201. {
  202. return kStatus_SMC_StopAbort;
  203. }
  204. else
  205. {
  206. return kStatus_Success;
  207. }
  208. }
  209. #if (defined(FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE)
  210. status_t SMC_SetPowerModeLls(SMC_Type *base
  211. #if ((defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE) || \
  212. (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO))
  213. ,
  214. const smc_power_mode_lls_config_t *config
  215. #endif
  216. )
  217. {
  218. uint8_t reg;
  219. /* configure to LLS mode */
  220. reg = base->PMCTRL;
  221. reg &= ~SMC_PMCTRL_STOPM_MASK;
  222. reg |= (kSMC_StopLls << SMC_PMCTRL_STOPM_SHIFT);
  223. base->PMCTRL = reg;
  224. /* configure LLS sub-mode*/
  225. #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
  226. reg = base->STOPCTRL;
  227. reg &= ~SMC_STOPCTRL_LLSM_MASK;
  228. reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
  229. base->STOPCTRL = reg;
  230. #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
  231. #if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
  232. if (config->enableLpoClock)
  233. {
  234. base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK;
  235. }
  236. else
  237. {
  238. base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK;
  239. }
  240. #endif /* FSL_FEATURE_SMC_HAS_LPOPO */
  241. /* Set the SLEEPDEEP bit to enable deep sleep mode */
  242. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  243. /* read back to make sure the configuration valid before enter stop mode */
  244. (void)base->PMCTRL;
  245. __DSB();
  246. __WFI();
  247. __ISB();
  248. /* check whether the power mode enter LLS mode succeed */
  249. if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
  250. {
  251. return kStatus_SMC_StopAbort;
  252. }
  253. else
  254. {
  255. return kStatus_Success;
  256. }
  257. }
  258. #endif /* FSL_FEATURE_SMC_HAS_LOW_LEAKAGE_STOP_MODE */
  259. #if (defined(FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE) && FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE)
  260. status_t SMC_SetPowerModeVlls(SMC_Type *base, const smc_power_mode_vlls_config_t *config)
  261. {
  262. uint8_t reg;
  263. #if (defined(FSL_FEATURE_SMC_HAS_PORPO) && FSL_FEATURE_SMC_HAS_PORPO)
  264. #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG) || \
  265. (defined(FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) && FSL_FEATURE_SMC_USE_STOPCTRL_VLLSM) || \
  266. (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
  267. if (config->subMode == kSMC_StopSub0)
  268. #endif
  269. {
  270. /* configure whether the Por Detect work in Vlls0 mode */
  271. if (config->enablePorDetectInVlls0)
  272. {
  273. #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
  274. base->VLLSCTRL &= ~SMC_VLLSCTRL_PORPO_MASK;
  275. #else
  276. base->STOPCTRL &= ~SMC_STOPCTRL_PORPO_MASK;
  277. #endif
  278. }
  279. else
  280. {
  281. #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
  282. base->VLLSCTRL |= SMC_VLLSCTRL_PORPO_MASK;
  283. #else
  284. base->STOPCTRL |= SMC_STOPCTRL_PORPO_MASK;
  285. #endif
  286. }
  287. }
  288. #endif /* FSL_FEATURE_SMC_HAS_PORPO */
  289. #if (defined(FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION) && FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION)
  290. else if (config->subMode == kSMC_StopSub2)
  291. {
  292. /* configure whether the Por Detect work in Vlls0 mode */
  293. if (config->enableRam2InVlls2)
  294. {
  295. #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
  296. base->VLLSCTRL |= SMC_VLLSCTRL_RAM2PO_MASK;
  297. #else
  298. base->STOPCTRL |= SMC_STOPCTRL_RAM2PO_MASK;
  299. #endif
  300. }
  301. else
  302. {
  303. #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
  304. base->VLLSCTRL &= ~SMC_VLLSCTRL_RAM2PO_MASK;
  305. #else
  306. base->STOPCTRL &= ~SMC_STOPCTRL_RAM2PO_MASK;
  307. #endif
  308. }
  309. }
  310. else
  311. {
  312. }
  313. #endif /* FSL_FEATURE_SMC_HAS_RAM2_POWER_OPTION */
  314. /* configure to VLLS mode */
  315. reg = base->PMCTRL;
  316. reg &= ~SMC_PMCTRL_STOPM_MASK;
  317. reg |= (kSMC_StopVlls << SMC_PMCTRL_STOPM_SHIFT);
  318. base->PMCTRL = reg;
  319. /* configure the VLLS sub-mode */
  320. #if (defined(FSL_FEATURE_SMC_USE_VLLSCTRL_REG) && FSL_FEATURE_SMC_USE_VLLSCTRL_REG)
  321. reg = base->VLLSCTRL;
  322. reg &= ~SMC_VLLSCTRL_VLLSM_MASK;
  323. reg |= ((uint32_t)config->subMode << SMC_VLLSCTRL_VLLSM_SHIFT);
  324. base->VLLSCTRL = reg;
  325. #else
  326. #if (defined(FSL_FEATURE_SMC_HAS_LLS_SUBMODE) && FSL_FEATURE_SMC_HAS_LLS_SUBMODE)
  327. reg = base->STOPCTRL;
  328. reg &= ~SMC_STOPCTRL_LLSM_MASK;
  329. reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_LLSM_SHIFT);
  330. base->STOPCTRL = reg;
  331. #else
  332. reg = base->STOPCTRL;
  333. reg &= ~SMC_STOPCTRL_VLLSM_MASK;
  334. reg |= ((uint32_t)config->subMode << SMC_STOPCTRL_VLLSM_SHIFT);
  335. base->STOPCTRL = reg;
  336. #endif /* FSL_FEATURE_SMC_HAS_LLS_SUBMODE */
  337. #endif
  338. #if (defined(FSL_FEATURE_SMC_HAS_LPOPO) && FSL_FEATURE_SMC_HAS_LPOPO)
  339. if (config->enableLpoClock)
  340. {
  341. base->STOPCTRL &= ~SMC_STOPCTRL_LPOPO_MASK;
  342. }
  343. else
  344. {
  345. base->STOPCTRL |= SMC_STOPCTRL_LPOPO_MASK;
  346. }
  347. #endif /* FSL_FEATURE_SMC_HAS_LPOPO */
  348. /* Set the SLEEPDEEP bit to enable deep sleep mode */
  349. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  350. /* read back to make sure the configuration valid before enter stop mode */
  351. (void)base->PMCTRL;
  352. __DSB();
  353. __WFI();
  354. __ISB();
  355. /* check whether the power mode enter LLS mode succeed */
  356. if (base->PMCTRL & SMC_PMCTRL_STOPA_MASK)
  357. {
  358. return kStatus_SMC_StopAbort;
  359. }
  360. else
  361. {
  362. return kStatus_Success;
  363. }
  364. }
  365. #endif /* FSL_FEATURE_SMC_HAS_VERY_LOW_LEAKAGE_STOP_MODE */