fsl_dcdc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Copyright (c) 2017, NXP
  3. * All rights reserved.
  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 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_dcdc.h"
  31. /*******************************************************************************
  32. * Prototypes
  33. ******************************************************************************/
  34. /*!
  35. * @brief Get instance number for DCDC module.
  36. *
  37. * @param base DCDC peripheral base address
  38. */
  39. static uint32_t DCDC_GetInstance(DCDC_Type *base);
  40. /*******************************************************************************
  41. * Variables
  42. ******************************************************************************/
  43. /*! @brief Pointers to DCDC bases for each instance. */
  44. static DCDC_Type *const s_dcdcBases[] = DCDC_BASE_PTRS;
  45. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  46. /*! @brief Pointers to DCDC clocks for each instance. */
  47. static const clock_ip_name_t s_dcdcClocks[] = DCDC_CLOCKS;
  48. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  49. /*******************************************************************************
  50. * Code
  51. ******************************************************************************/
  52. static uint32_t DCDC_GetInstance(DCDC_Type *base)
  53. {
  54. uint32_t instance;
  55. /* Find the instance index from base address mappings. */
  56. for (instance = 0; instance < ARRAY_SIZE(s_dcdcBases); instance++)
  57. {
  58. if (s_dcdcBases[instance] == base)
  59. {
  60. break;
  61. }
  62. }
  63. assert(instance < ARRAY_SIZE(s_dcdcBases));
  64. return instance;
  65. }
  66. void DCDC_Init(DCDC_Type *base)
  67. {
  68. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  69. /* Enable the clock. */
  70. CLOCK_EnableClock(s_dcdcClocks[DCDC_GetInstance(base)]);
  71. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  72. }
  73. void DCDC_Deinit(DCDC_Type *base)
  74. {
  75. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  76. /* Disable the clock. */
  77. CLOCK_DisableClock(s_dcdcClocks[DCDC_GetInstance(base)]);
  78. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  79. }
  80. void DCDC_SetClockSource(DCDC_Type *base, dcdc_clock_source_t clockSource)
  81. {
  82. uint32_t tmp32;
  83. /* Configure the DCDC_REG0 register. */
  84. tmp32 = base->REG0 &
  85. ~(DCDC_REG0_XTAL_24M_OK_MASK | DCDC_REG0_DISABLE_AUTO_CLK_SWITCH_MASK | DCDC_REG0_SEL_CLK_MASK |
  86. DCDC_REG0_PWD_OSC_INT_MASK);
  87. switch (clockSource)
  88. {
  89. case kDCDC_ClockInternalOsc:
  90. tmp32 |= DCDC_REG0_DISABLE_AUTO_CLK_SWITCH_MASK;
  91. break;
  92. case kDCDC_ClockExternalOsc:
  93. /* Choose the external clock and disable the internal clock. */
  94. tmp32 |= DCDC_REG0_DISABLE_AUTO_CLK_SWITCH_MASK | DCDC_REG0_SEL_CLK_MASK | DCDC_REG0_PWD_OSC_INT_MASK;
  95. break;
  96. case kDCDC_ClockAutoSwitch:
  97. /* Set to switch from internal ring osc to xtal 24M if auto mode is enabled. */
  98. tmp32 |= DCDC_REG0_XTAL_24M_OK_MASK;
  99. break;
  100. default:
  101. break;
  102. }
  103. base->REG0 = tmp32;
  104. }
  105. void DCDC_GetDefaultDetectionConfig(dcdc_detection_config_t *config)
  106. {
  107. assert(NULL != config);
  108. config->enableXtalokDetection = false;
  109. config->powerDownOverVoltageDetection = true;
  110. config->powerDownLowVlotageDetection = false;
  111. config->powerDownOverCurrentDetection = true;
  112. config->powerDownPeakCurrentDetection = true;
  113. config->powerDownZeroCrossDetection = true;
  114. config->OverCurrentThreshold = kDCDC_OverCurrentThresholdAlt0;
  115. config->PeakCurrentThreshold = kDCDC_PeakCurrentThresholdAlt0;
  116. }
  117. void DCDC_SetDetectionConfig(DCDC_Type *base, const dcdc_detection_config_t *config)
  118. {
  119. assert(NULL != config);
  120. uint32_t tmp32;
  121. /* Configure the DCDC_REG0 register. */
  122. tmp32 = base->REG0 &
  123. ~(DCDC_REG0_XTALOK_DISABLE_MASK | DCDC_REG0_PWD_HIGH_VOLT_DET_MASK | DCDC_REG0_PWD_CMP_BATT_DET_MASK |
  124. DCDC_REG0_PWD_OVERCUR_DET_MASK | DCDC_REG0_PWD_CUR_SNS_CMP_MASK | DCDC_REG0_PWD_ZCD_MASK |
  125. DCDC_REG0_CUR_SNS_THRSH_MASK | DCDC_REG0_OVERCUR_TRIG_ADJ_MASK);
  126. tmp32 |= DCDC_REG0_CUR_SNS_THRSH(config->PeakCurrentThreshold) |
  127. DCDC_REG0_OVERCUR_TRIG_ADJ(config->OverCurrentThreshold);
  128. if (false == config->enableXtalokDetection)
  129. {
  130. tmp32 |= DCDC_REG0_XTALOK_DISABLE_MASK;
  131. }
  132. if (config->powerDownOverVoltageDetection)
  133. {
  134. tmp32 |= DCDC_REG0_PWD_HIGH_VOLT_DET_MASK;
  135. }
  136. if (config->powerDownLowVlotageDetection)
  137. {
  138. tmp32 |= DCDC_REG0_PWD_CMP_BATT_DET_MASK;
  139. }
  140. if (config->powerDownOverCurrentDetection)
  141. {
  142. tmp32 |= DCDC_REG0_PWD_OVERCUR_DET_MASK;
  143. }
  144. if (config->powerDownPeakCurrentDetection)
  145. {
  146. tmp32 |= DCDC_REG0_PWD_CUR_SNS_CMP_MASK;
  147. }
  148. if (config->powerDownZeroCrossDetection)
  149. {
  150. tmp32 |= DCDC_REG0_PWD_ZCD_MASK;
  151. }
  152. base->REG0 = tmp32;
  153. }
  154. void DCDC_GetDefaultLowPowerConfig(dcdc_low_power_config_t *config)
  155. {
  156. assert(NULL != config);
  157. config->enableOverloadDetection = true;
  158. config->enableAdjustHystereticValue = false;
  159. config->countChargingTimePeriod = kDCDC_CountChargingTimePeriod8Cycle;
  160. config->countChargingTimeThreshold = kDCDC_CountChargingTimeThreshold32;
  161. }
  162. void DCDC_SetLowPowerConfig(DCDC_Type *base, const dcdc_low_power_config_t *config)
  163. {
  164. assert(NULL != config);
  165. uint32_t tmp32;
  166. /* Configure the DCDC_REG0 register. */
  167. tmp32 = base->REG0 &
  168. ~(DCDC_REG0_EN_LP_OVERLOAD_SNS_MASK | DCDC_REG0_LP_HIGH_HYS_MASK | DCDC_REG0_LP_OVERLOAD_FREQ_SEL_MASK |
  169. DCDC_REG0_LP_OVERLOAD_THRSH_MASK);
  170. tmp32 |= DCDC_REG0_LP_OVERLOAD_FREQ_SEL(config->countChargingTimePeriod) |
  171. DCDC_REG0_LP_OVERLOAD_THRSH(config->countChargingTimeThreshold);
  172. if (config->enableOverloadDetection)
  173. {
  174. tmp32 |= DCDC_REG0_EN_LP_OVERLOAD_SNS_MASK;
  175. }
  176. if (config->enableAdjustHystereticValue)
  177. {
  178. tmp32 |= DCDC_REG0_LP_HIGH_HYS_MASK;
  179. }
  180. base->REG0 = tmp32;
  181. }
  182. uint32_t DCDC_GetstatusFlags(DCDC_Type *base)
  183. {
  184. uint32_t tmp32 = 0U;
  185. if (DCDC_REG0_STS_DC_OK_MASK == (DCDC_REG0_STS_DC_OK_MASK & base->REG0))
  186. {
  187. tmp32 |= kDCDC_LockedOKStatus;
  188. }
  189. return tmp32;
  190. }
  191. void DCDC_ResetCurrentAlertSignal(DCDC_Type *base, bool enable)
  192. {
  193. if (enable)
  194. {
  195. base->REG0 |= DCDC_REG0_CURRENT_ALERT_RESET_MASK;
  196. }
  197. else
  198. {
  199. base->REG0 &= ~DCDC_REG0_CURRENT_ALERT_RESET_MASK;
  200. }
  201. }
  202. void DCDC_GetDefaultLoopControlConfig(dcdc_loop_control_config_t *config)
  203. {
  204. assert(NULL != config);
  205. config->enableCommonHysteresis = false;
  206. config->enableCommonThresholdDetection = false;
  207. config->enableInvertHysteresisSign = false;
  208. config->enableRCThresholdDetection = false;
  209. config->enableRCScaleCircuit = 0U;
  210. config->complementFeedForwardStep = 0U;
  211. config->controlParameterMagnitude = 2U;
  212. config->integralProportionalRatio = 2U;
  213. }
  214. void DCDC_SetLoopControlConfig(DCDC_Type *base, const dcdc_loop_control_config_t *config)
  215. {
  216. assert(NULL != config);
  217. uint32_t tmp32;
  218. /* Configure the DCDC_REG1 register. */
  219. tmp32 = base->REG1 & ~(DCDC_REG1_LOOPCTRL_EN_HYST_MASK | DCDC_REG1_LOOPCTRL_HST_THRESH_MASK);
  220. if (config->enableCommonHysteresis)
  221. {
  222. tmp32 |= DCDC_REG1_LOOPCTRL_EN_HYST_MASK;
  223. }
  224. if (config->enableCommonThresholdDetection)
  225. {
  226. tmp32 |= DCDC_REG1_LOOPCTRL_HST_THRESH_MASK;
  227. }
  228. base->REG1 = tmp32;
  229. /* configure the DCDC_REG2 register. */
  230. tmp32 = base->REG2 &
  231. ~(DCDC_REG2_LOOPCTRL_HYST_SIGN_MASK | DCDC_REG2_LOOPCTRL_RCSCALE_THRSH_MASK |
  232. DCDC_REG2_LOOPCTRL_EN_RCSCALE_MASK | DCDC_REG2_LOOPCTRL_DC_FF_MASK | DCDC_REG2_LOOPCTRL_DC_R_MASK |
  233. DCDC_REG2_LOOPCTRL_DC_C_MASK);
  234. tmp32 |= DCDC_REG2_LOOPCTRL_DC_FF(config->complementFeedForwardStep) |
  235. DCDC_REG2_LOOPCTRL_DC_R(config->controlParameterMagnitude) |
  236. DCDC_REG2_LOOPCTRL_DC_C(config->integralProportionalRatio) |
  237. DCDC_REG2_LOOPCTRL_EN_RCSCALE(config->enableRCScaleCircuit);
  238. if (config->enableInvertHysteresisSign)
  239. {
  240. tmp32 |= DCDC_REG2_LOOPCTRL_HYST_SIGN_MASK;
  241. }
  242. if (config->enableRCThresholdDetection)
  243. {
  244. tmp32 |= DCDC_REG2_LOOPCTRL_RCSCALE_THRSH_MASK;
  245. }
  246. base->REG2 = tmp32;
  247. }
  248. void DCDC_SetMinPowerConfig(DCDC_Type *base, const dcdc_min_power_config_t *config)
  249. {
  250. assert(NULL != config);
  251. uint32_t tmp32;
  252. tmp32 = base->REG3 & ~DCDC_REG3_MINPWR_DC_HALFCLK_MASK;
  253. if (config->enableUseHalfFreqForContinuous)
  254. {
  255. tmp32 |= DCDC_REG3_MINPWR_DC_HALFCLK_MASK;
  256. }
  257. base->REG3 = tmp32;
  258. }
  259. void DCDC_AdjustTargetVoltage(DCDC_Type *base, uint32_t VDDRun, uint32_t VDDStandby)
  260. {
  261. uint32_t tmp32;
  262. /* Unlock the step for the output. */
  263. base->REG3 &= ~DCDC_REG3_DISABLE_STEP_MASK;
  264. /* Configure the DCDC_REG3 register. */
  265. tmp32 = base->REG3 & ~(DCDC_REG3_TARGET_LP_MASK | DCDC_REG3_TRG_MASK);
  266. tmp32 |= DCDC_REG3_TARGET_LP(VDDStandby) | DCDC_REG3_TRG(VDDRun);
  267. base->REG3 = tmp32;
  268. /* DCDC_STS_DC_OK bit will be de-asserted after target register changes. After output voltage settling to new
  269. * target value, DCDC_STS_DC_OK will be asserted. */
  270. while (DCDC_REG0_STS_DC_OK_MASK != (DCDC_REG0_STS_DC_OK_MASK & base->REG0))
  271. {
  272. }
  273. }
  274. void DCDC_SetInternalRegulatorConfig(DCDC_Type *base, const dcdc_internal_regulator_config_t *config)
  275. {
  276. assert(NULL != config);
  277. uint32_t tmp32;
  278. /* Configure the DCDC_REG1 register. */
  279. tmp32 = base->REG1 & ~(DCDC_REG1_REG_FBK_SEL_MASK | DCDC_REG1_REG_RLOAD_SW_MASK);
  280. tmp32 |= DCDC_REG1_REG_FBK_SEL(config->feedbackPoint);
  281. if (config->enableLoadResistor)
  282. {
  283. tmp32 |= DCDC_REG1_REG_RLOAD_SW_MASK;
  284. }
  285. base->REG1 = tmp32;
  286. }
  287. void DCDC_BootIntoDCM(DCDC_Type *base)
  288. {
  289. base->REG0 &= ~(DCDC_REG0_PWD_ZCD_MASK | DCDC_REG0_PWD_CMP_OFFSET_MASK);
  290. base->REG2 = (~DCDC_REG2_LOOPCTRL_EN_RCSCALE_MASK & base->REG2) | DCDC_REG2_LOOPCTRL_EN_RCSCALE(0x3U) |
  291. DCDC_REG2_DCM_SET_CTRL_MASK;
  292. }
  293. void DCDC_BootIntoCCM(DCDC_Type *base)
  294. {
  295. base->REG0 = (~DCDC_REG0_PWD_CMP_OFFSET_MASK & base->REG0) | DCDC_REG0_PWD_ZCD_MASK;
  296. base->REG2 = (~DCDC_REG2_LOOPCTRL_EN_RCSCALE_MASK & base->REG2) | DCDC_REG2_LOOPCTRL_EN_RCSCALE(0x3U) |
  297. DCDC_REG2_DCM_SET_CTRL_MASK;
  298. }