fsl_smc.c 12 KB

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