nrf_drv_power.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /**
  2. * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA 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. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(POWER)
  42. #include "nrf_drv_power.h"
  43. #include <nrf_drv_clock.h>
  44. #ifdef SOFTDEVICE_PRESENT
  45. #include "nrf_sdh.h"
  46. #include "nrf_sdh_soc.h"
  47. #endif
  48. #include <app_util.h>
  49. // The structure with default configuration data.
  50. static const nrfx_power_config_t m_drv_power_config_default =
  51. {
  52. .dcdcen = NRFX_POWER_CONFIG_DEFAULT_DCDCEN,
  53. #if NRF_POWER_HAS_VDDH
  54. .dcdcenhv = NRFX_POWER_CONFIG_DEFAULT_DCDCENHV,
  55. #endif
  56. };
  57. static bool m_initialized;
  58. bool nrf_drv_power_init_check(void)
  59. {
  60. return m_initialized;
  61. }
  62. ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config)
  63. {
  64. #ifdef SOFTDEVICE_PRESENT
  65. if (m_initialized)
  66. {
  67. return NRF_ERROR_MODULE_ALREADY_INITIALIZED;
  68. }
  69. if (nrf_sdh_is_enabled())
  70. {
  71. return NRF_ERROR_INVALID_STATE;
  72. }
  73. #endif
  74. if (p_config == NULL)
  75. {
  76. p_config = &m_drv_power_config_default;
  77. }
  78. ret_code_t err_code = nrfx_power_init(p_config);
  79. if (err_code == NRFX_SUCCESS)
  80. {
  81. m_initialized = true;
  82. }
  83. return err_code;
  84. }
  85. void nrf_drv_power_uninit()
  86. {
  87. nrfx_power_uninit();
  88. nrf_drv_power_pof_uninit();
  89. #if NRF_POWER_HAS_SLEEPEVT
  90. nrf_drv_power_sleepevt_uninit();
  91. #endif
  92. #if NRF_POWER_HAS_USBREG
  93. nrf_drv_power_usbevt_uninit();
  94. #endif
  95. m_initialized = false;
  96. }
  97. ret_code_t nrf_drv_power_pof_init(nrf_drv_power_pofwarn_config_t const * p_config)
  98. {
  99. ret_code_t err_code = NRF_SUCCESS;
  100. nrfx_power_pof_init(p_config);
  101. #ifdef SOFTDEVICE_PRESENT
  102. if (nrf_sdh_is_enabled())
  103. {
  104. /* Currently when SD is enabled - the configuration can be changed
  105. * in very limited range.
  106. * It is the SoftDevice limitation.
  107. */
  108. #if NRF_POWER_HAS_VDDH
  109. if (p_config->thrvddh != nrf_power_pofcon_vddh_get())
  110. {
  111. /* Cannot change THRVDDH with current SD API */
  112. return NRF_ERROR_INVALID_STATE;
  113. }
  114. #endif
  115. if (p_config->thr != nrf_power_pofcon_get(NULL))
  116. {
  117. /* Only limited number of THR values are supported and
  118. * the values taken by SD is different than the one in hardware
  119. */
  120. uint8_t thr;
  121. switch(p_config->thr)
  122. {
  123. case NRF_POWER_POFTHR_V21:
  124. thr = NRF_POWER_THRESHOLD_V21;
  125. break;
  126. case NRF_POWER_POFTHR_V23:
  127. thr = NRF_POWER_THRESHOLD_V23;
  128. break;
  129. case NRF_POWER_POFTHR_V25:
  130. thr = NRF_POWER_THRESHOLD_V25;
  131. break;
  132. case NRF_POWER_POFTHR_V27:
  133. thr = NRF_POWER_THRESHOLD_V27;
  134. break;
  135. default:
  136. /* Cannot configure */
  137. nrfx_power_pof_uninit();
  138. return NRF_ERROR_INVALID_STATE;
  139. }
  140. err_code = sd_power_pof_threshold_set(thr);
  141. if (err_code != NRF_SUCCESS)
  142. {
  143. return err_code;
  144. }
  145. }
  146. err_code = sd_power_pof_enable(true);
  147. }
  148. else
  149. #endif /* SOFTDEVICE_PRESENT */
  150. {
  151. nrfx_power_pof_enable(p_config);
  152. }
  153. return err_code;
  154. }
  155. void nrf_drv_power_pof_uninit()
  156. {
  157. #ifdef SOFTDEVICE_PRESENT
  158. if (nrf_sdh_is_enabled())
  159. {
  160. ret_code_t err_code = sd_power_pof_enable(false);
  161. ASSERT(err_code == NRF_SUCCESS);
  162. UNUSED_VARIABLE(err_code); //handle no-debug case
  163. }
  164. else
  165. #endif
  166. {
  167. nrfx_power_pof_disable();
  168. }
  169. nrfx_power_pof_uninit();
  170. }
  171. #if NRF_POWER_HAS_SLEEPEVT
  172. ret_code_t nrf_drv_power_sleepevt_init(nrf_drv_power_sleepevt_config_t const * p_config)
  173. {
  174. if (p_config->handler != NULL)
  175. {
  176. #ifdef SOFTDEVICE_PRESENT
  177. if (nrf_sdh_is_enabled())
  178. {
  179. if ((p_config->en_enter) || (p_config->en_exit))
  180. {
  181. return NRF_ERROR_INVALID_STATE;
  182. }
  183. }
  184. else
  185. #endif
  186. {
  187. nrfx_power_sleepevt_enable(p_config);
  188. }
  189. }
  190. return NRF_SUCCESS;
  191. }
  192. void nrf_drv_power_sleepevt_uninit(void)
  193. {
  194. #ifdef SOFTDEVICE_PRESENT
  195. if (nrf_sdh_is_enabled())
  196. {
  197. /* Nothing to do */
  198. }
  199. else
  200. #endif
  201. {
  202. nrfx_power_sleepevt_disable();
  203. }
  204. nrfx_power_sleepevt_uninit();
  205. }
  206. #endif /* NRF_POWER_HAS_SLEEPEVT */
  207. #if NRF_POWER_HAS_USBREG
  208. #ifdef SOFTDEVICE_PRESENT
  209. static ret_code_t nrf_drv_power_sd_usbevt_enable(bool enable)
  210. {
  211. ret_code_t err_code;
  212. err_code = sd_power_usbdetected_enable(enable);
  213. ASSERT(err_code == NRF_SUCCESS);
  214. if (err_code != NRF_SUCCESS)
  215. {
  216. return err_code;
  217. }
  218. err_code = sd_power_usbpwrrdy_enable(enable);
  219. ASSERT(err_code == NRF_SUCCESS);
  220. if (err_code != NRF_SUCCESS)
  221. {
  222. return err_code;
  223. }
  224. err_code = sd_power_usbremoved_enable(enable);
  225. ASSERT(err_code == NRF_SUCCESS);
  226. return err_code;
  227. }
  228. #endif // SOFTDEVICE_PRESENT
  229. ret_code_t nrf_drv_power_usbevt_init(nrf_drv_power_usbevt_config_t const * p_config)
  230. {
  231. nrf_drv_power_usbevt_uninit();
  232. nrfx_power_usbevt_init(p_config);
  233. #ifdef SOFTDEVICE_PRESENT
  234. if (nrf_sdh_is_enabled())
  235. {
  236. ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true);
  237. ASSERT(err_code == NRF_SUCCESS);
  238. if (err_code != NRF_SUCCESS)
  239. {
  240. return err_code;
  241. }
  242. uint32_t regstatus;
  243. err_code = sd_power_usbregstatus_get(&regstatus);
  244. ASSERT(err_code == NRF_SUCCESS);
  245. if (err_code != NRF_SUCCESS)
  246. {
  247. return err_code;
  248. }
  249. if (regstatus & POWER_USBREGSTATUS_VBUSDETECT_Msk)
  250. {
  251. nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get();
  252. ASSERT(usbevt_handler != NULL);
  253. usbevt_handler(NRFX_POWER_USB_EVT_DETECTED);
  254. }
  255. }
  256. else
  257. #endif
  258. {
  259. nrfx_power_usbevt_enable();
  260. }
  261. return NRF_SUCCESS;
  262. }
  263. void nrf_drv_power_usbevt_uninit(void)
  264. {
  265. #ifdef SOFTDEVICE_PRESENT
  266. CRITICAL_REGION_ENTER();
  267. if (nrf_sdh_is_enabled())
  268. {
  269. ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(false);
  270. ASSERT(err_code == NRF_SUCCESS);
  271. UNUSED_VARIABLE(err_code);
  272. }
  273. else
  274. #endif
  275. {
  276. nrfx_power_usbevt_disable();
  277. }
  278. #ifdef SOFTDEVICE_PRESENT
  279. CRITICAL_REGION_EXIT();
  280. #endif
  281. nrfx_power_usbevt_uninit();
  282. }
  283. #endif /* NRF_POWER_HAS_USBREG */
  284. #ifdef SOFTDEVICE_PRESENT
  285. static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context);
  286. static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context);
  287. NRF_SDH_SOC_OBSERVER(m_soc_observer, POWER_CONFIG_SOC_OBSERVER_PRIO,
  288. nrf_drv_power_sdh_soc_evt_handler, NULL);
  289. NRF_SDH_STATE_OBSERVER(m_sd_observer, POWER_CONFIG_STATE_OBSERVER_PRIO) =
  290. {
  291. .handler = nrf_drv_power_sdh_state_evt_handler,
  292. .p_context = NULL
  293. };
  294. static void nrf_drv_power_sdh_soc_evt_handler(uint32_t evt_id, void * p_context)
  295. {
  296. if (evt_id == NRF_EVT_POWER_FAILURE_WARNING)
  297. {
  298. nrfx_power_pofwarn_event_handler_t pofwarn_handler = nrfx_power_pof_handler_get();
  299. /* Cannot be null if event is enabled */
  300. ASSERT(pofwarn_handler != NULL);
  301. pofwarn_handler();
  302. }
  303. #if NRF_POWER_HAS_USBREG
  304. nrfx_power_usb_event_handler_t usbevt_handler = nrfx_power_usb_handler_get();
  305. if (usbevt_handler != NULL)
  306. {
  307. switch (evt_id)
  308. {
  309. case NRF_EVT_POWER_USB_POWER_READY:
  310. usbevt_handler(NRFX_POWER_USB_EVT_READY);
  311. break;
  312. case NRF_EVT_POWER_USB_DETECTED:
  313. usbevt_handler(NRFX_POWER_USB_EVT_DETECTED);
  314. break;
  315. case NRF_EVT_POWER_USB_REMOVED:
  316. usbevt_handler(NRFX_POWER_USB_EVT_REMOVED);
  317. break;
  318. default:
  319. break;
  320. }
  321. }
  322. #endif
  323. }
  324. static void nrf_drv_power_on_sd_enable(void)
  325. {
  326. ASSERT(m_initialized); /* This module has to be enabled first */
  327. CRITICAL_REGION_ENTER();
  328. if (nrfx_power_pof_handler_get() != NULL)
  329. {
  330. ret_code_t err_code = sd_power_pof_enable(true);
  331. ASSERT(err_code == NRF_SUCCESS);
  332. UNUSED_VARIABLE(err_code); //handle no-debug case
  333. }
  334. CRITICAL_REGION_EXIT();
  335. #if NRF_POWER_HAS_USBREG
  336. if (nrfx_power_usb_handler_get() != NULL)
  337. {
  338. ret_code_t err_code = nrf_drv_power_sd_usbevt_enable(true);
  339. ASSERT(err_code == NRF_SUCCESS);
  340. UNUSED_VARIABLE(err_code); //handle no-debug case
  341. }
  342. #endif
  343. }
  344. static void nrf_drv_power_on_sd_disable(void)
  345. {
  346. /* Reinit interrupts */
  347. ASSERT(m_initialized);
  348. NRFX_IRQ_PRIORITY_SET(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY);
  349. NRFX_IRQ_ENABLE(POWER_CLOCK_IRQn);
  350. if (nrfx_power_pof_handler_get() != NULL)
  351. {
  352. nrf_power_int_enable(NRF_POWER_INT_POFWARN_MASK);
  353. }
  354. #if NRF_POWER_HAS_USBREG
  355. if (nrfx_power_usb_handler_get() != NULL)
  356. {
  357. nrf_power_int_enable(
  358. NRF_POWER_INT_USBDETECTED_MASK |
  359. NRF_POWER_INT_USBREMOVED_MASK |
  360. NRF_POWER_INT_USBPWRRDY_MASK);
  361. }
  362. #endif
  363. }
  364. static void nrf_drv_power_sdh_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context)
  365. {
  366. switch (state)
  367. {
  368. case NRF_SDH_EVT_STATE_ENABLED:
  369. nrf_drv_power_on_sd_enable();
  370. break;
  371. case NRF_SDH_EVT_STATE_DISABLED:
  372. nrf_drv_power_on_sd_disable();
  373. break;
  374. default:
  375. break;
  376. }
  377. }
  378. #endif // SOFTDEVICE_PRESENT
  379. #endif //POWER_ENABLED