1 /*
2  * Copyright 2021 ~ 2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_vbat.h"
9 
10 /*******************************************************************************
11  * Definitions
12  ******************************************************************************/
13 
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.vbat"
17 #endif
18 
19 /*******************************************************************************
20  * Prototypes
21  ******************************************************************************/
22 
23 /*******************************************************************************
24  * Variables
25  ******************************************************************************/
26 
27 /*******************************************************************************
28  * Code
29  ******************************************************************************/
30 
31 /*!
32  * brief Configure internal 16kHz free running oscillator, including enabel FRO16k, gate FRO16k output.
33  *
34  * param base VBAT peripheral base address.
35  * param config Pointer to vbat_fro16k_config_t structure.
36  */
VBAT_ConfigFRO16k(VBAT_Type * base,const vbat_fro16k_config_t * config)37 void VBAT_ConfigFRO16k(VBAT_Type *base, const vbat_fro16k_config_t *config)
38 {
39     assert(config != NULL);
40 
41     VBAT_EnableFRO16k(base, config->enableFRO16k);
42 
43     if (config->enableFRO16k)
44     {
45         VBAT_UngateFRO16k(base, true);
46     }
47     else
48     {
49         VBAT_UngateFRO16k(base, false);
50     }
51 }
52 
53 /*!
54  * brief Enable/disable Bandgap.
55  *
56  * note The FRO16K must be enabled before enableing the bandgap.
57  * note This setting can be locked by VBAT_LockLdoRamSettings() function.
58  *
59  * param base VBAT peripheral base address.
60  * param enable Used to enable/disable bandgap.
61  *      - \b true Enable the bandgap.
62  *      - \b false Disable the bandgap.
63  *
64  * retval kStatus_Success Success to enable/disable the bandgap.
65  * retval kStatus_VBAT_Fro16kNotEnabled Fail to enable the bandgap due to FRO16k is not enabled previously.
66  */
VBAT_EnableBandgap(VBAT_Type * base,bool enable)67 status_t VBAT_EnableBandgap(VBAT_Type *base, bool enable)
68 {
69     status_t status = kStatus_Success;
70 
71     if (enable)
72     {
73         if (VBAT_CheckFRO16kEnabled(base))
74         {
75             base->LDOCTLA |= VBAT_LDOCTLA_BG_EN_MASK;
76         }
77         else
78         {
79             /* FRO16K must be enabled before enabling the Bandgap. */
80             status = kStatus_VBAT_Fro16kNotEnabled;
81         }
82     }
83     else
84     {
85         base->LDOCTLA &= ~VBAT_LDOCTLA_BG_EN_MASK;
86     }
87 
88     return status;
89 }
90 
91 /*!
92  * brief Enable/disable Backup RAM Regulator(RAM_LDO).
93  *
94  * note This setting can be locked by VBAT_LockLdoRamSettings() function.
95  *
96  * param base VBAT peripheral base address.
97  * param enable Used to enable/disable RAM_LDO.
98  *          - \b true Enable backup SRAM regulator.
99  *          - \b false Disable backup SRAM regulator.
100  *
101  * retval kStatusSuccess Success to enable/disable backup SRAM regulator.
102  * retval kStatus_VBAT_Fro16kNotEnabled Fail to enable backup SRAM regulator due to FRO16k is not enabled previously.
103  * retval kStatus_VBAT_BandgapNotEnabled Fail to enable backup SRAM regulator due to the bandgap is not enabled
104  * previously.
105  */
VBAT_EnableBackupSRAMRegulator(VBAT_Type * base,bool enable)106 status_t VBAT_EnableBackupSRAMRegulator(VBAT_Type *base, bool enable)
107 {
108     status_t status = kStatus_Success;
109 
110     if (enable)
111     {
112         if (VBAT_CheckFRO16kEnabled(base))
113         {
114             if (VBAT_CheckBandgapEnabled(base))
115             {
116                 base->LDOCTLA |= VBAT_LDOCTLA_LDO_EN_MASK;
117                 while ((base->STATUSA & VBAT_STATUSA_LDO_RDY_MASK) == 0UL)
118                 {
119                 }
120             }
121             else
122             {
123                 /* The bandgap must be enabled previously. */
124                 status = kStatus_VBAT_BandgapNotEnabled;
125             }
126         }
127         else
128         {
129             /* FRO16k must be enabled previously. */
130             status = kStatus_VBAT_Fro16kNotEnabled;
131         }
132     }
133     else
134     {
135         base->LDOCTLA &= ~VBAT_LDOCTLA_LDO_EN_MASK;
136     }
137 
138     return status;
139 }
140 
141 /*!
142  * brief Switch the SRAM to be powered by VBAT.
143  *
144  * param base VBAT peripheral base address.
145  *
146  * retval kStatusSuccess Success to Switch SRAM powered by VBAT.
147  * retval kStatus_VBAT_Fro16kNotEnabled Fail to switch SRAM powered by VBAT due to FRO16K not enabled previously.
148  */
VBAT_SwitchSRAMPowerByVBAT(VBAT_Type * base)149 status_t VBAT_SwitchSRAMPowerByVBAT(VBAT_Type *base)
150 {
151     status_t status = kStatus_Success;
152 
153     status = VBAT_EnableBandgap(base, true);
154 
155     if (status == kStatus_Success)
156     {
157         VBAT_EnableBandgapRefreshMode(base, true);
158         (void)VBAT_EnableBackupSRAMRegulator(base, true);
159 
160         /* Isolate the SRAM array */
161         base->LDORAMC |= VBAT_LDORAMC_ISO_MASK;
162         /* Switch the supply to VBAT LDO. */
163         base->LDORAMC |= VBAT_LDORAMC_SWI_MASK;
164     }
165 
166     return status;
167 }
168 
169 /*!
170  * brief Enable/disable Bandgap timer.
171  *
172  * note The bandgap timer is available when the bandgap is enabled and are clocked by the FRO16k.
173  *
174  * param base VBAT peripheral base address.
175  * param enable Used to enable/disable bandgap timer.
176  * param timerIdMask The mask of bandgap timer Id, should be the OR'ed value of vbat_bandgap_timer_id_t.
177  *
178  * retval kStatus_Success Success to enable/disable selected bandgap timer.
179  * retval kStatus_VBAT_Fro16kNotEnabled Fail to enable/disable selected bandgap timer due to FRO16k not enabled
180  * previously. retval kStatus_VBAT_BandgapNotEnabled Fail to enable/disable selected bandgap timer due to bandgap not
181  * enabled previously.
182  */
VBAT_EnableBandgapTimer(VBAT_Type * base,bool enable,uint8_t timerIdMask)183 status_t VBAT_EnableBandgapTimer(VBAT_Type *base, bool enable, uint8_t timerIdMask)
184 {
185     status_t status = kStatus_Success;
186 
187     if (enable)
188     {
189         if (VBAT_CheckFRO16kEnabled(base))
190         {
191             if (VBAT_CheckBandgapEnabled(base))
192             {
193                 if ((timerIdMask & (uint8_t)kVBAT_BandgapTimer0) != 0U)
194                 {
195                     base->LDOTIMER0 |= VBAT_LDOTIMER0_TIMEN_MASK;
196                 }
197 
198                 if ((timerIdMask & (uint8_t)kVBAT_BandgapTimer1) != 0U)
199                 {
200                     base->LDOTIMER1 |= VBAT_LDOTIMER1_TIMEN_MASK;
201                 }
202             }
203             else
204             {
205                 /* Bandgap must be enabled previously. */
206                 status = kStatus_VBAT_BandgapNotEnabled;
207             }
208         }
209         else
210         {
211             /* FRO16K must be enabled previously. */
212             status = kStatus_VBAT_Fro16kNotEnabled;
213         }
214     }
215     else
216     {
217         if ((timerIdMask & (uint8_t)kVBAT_BandgapTimer0) != 0U)
218         {
219             base->LDOTIMER0 &= ~VBAT_LDOTIMER0_TIMEN_MASK;
220         }
221 
222         if ((timerIdMask & (uint8_t)kVBAT_BandgapTimer1) != 0U)
223         {
224             base->LDOTIMER1 &= ~VBAT_LDOTIMER1_TIMEN_MASK;
225         }
226     }
227 
228     return status;
229 }
230 
231 /*!
232  * brief Set bandgap timer timeout value.
233  *
234  * param base VBAT peripheral base address.
235  * param timeoutPeriod Bandgap timer timeout value, please refer to vbat_bandgap_timer_timeout_period_t.
236  * param timerIdMask The mask of bandgap timer Id, should be the OR'ed value of vbat_bandgap_timer_id_t.
237  */
VBAT_SetBandgapTimerTimeoutValue(VBAT_Type * base,vbat_bandgap_timer_timeout_period_t timeoutPeriod,uint8_t timerIdMask)238 void VBAT_SetBandgapTimerTimeoutValue(VBAT_Type *base,
239                                       vbat_bandgap_timer_timeout_period_t timeoutPeriod,
240                                       uint8_t timerIdMask)
241 {
242     bool timerEnabled = false;
243 
244     if ((timerIdMask & (uint8_t)kVBAT_BandgapTimer0) != 0U)
245     {
246         timerEnabled = ((base->LDOTIMER0 & VBAT_LDOTIMER0_TIMEN_MASK) != 0UL) ? true : false;
247 
248         if (timerEnabled)
249         {
250             base->LDOTIMER0 &= ~VBAT_LDOTIMER0_TIMEN_MASK;
251         }
252 
253         base->LDOTIMER0 = ((base->LDOTIMER0 & (~VBAT_LDOTIMER0_TIMCFG_MASK)) | VBAT_LDOTIMER0_TIMCFG(timeoutPeriod));
254 
255         if (timerEnabled)
256         {
257             base->LDOTIMER0 |= VBAT_LDOTIMER0_TIMEN_MASK;
258         }
259     }
260 
261     if ((timerIdMask & (uint8_t)kVBAT_BandgapTimer1) != 0U)
262     {
263         timerEnabled = ((base->LDOTIMER1 & VBAT_LDOTIMER1_TIMEN_MASK) != 0UL) ? true : false;
264 
265         if (timerEnabled)
266         {
267             base->LDOTIMER1 &= ~VBAT_LDOTIMER1_TIMEN_MASK;
268         }
269 
270         base->LDOTIMER1 = ((base->LDOTIMER1 & (~VBAT_LDOTIMER1_TIMCFG_MASK)) | VBAT_LDOTIMER1_TIMCFG(timeoutPeriod));
271 
272         if (timerEnabled)
273         {
274             base->LDOTIMER1 |= VBAT_LDOTIMER1_TIMEN_MASK;
275         }
276     }
277 }
278