1 /*
2  * Copyright 2019-2022 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_vref.h"
9 
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.vref_1"
13 #endif
14 
15 /*******************************************************************************
16  * Prototypes
17  ******************************************************************************/
18 
19 /*!
20  * @brief Gets the instance from the base address
21  *
22  * @param base VREF peripheral base address
23  *
24  * @return The VREF instance
25  */
26 static uint32_t VREF_GetInstance(VREF_Type *base);
27 
28 /*******************************************************************************
29  * Variables
30  ******************************************************************************/
31 
32 /*! @brief Pointers to VREF bases for each instance. */
33 static VREF_Type *const s_vrefBases[] = VREF_BASE_PTRS;
34 
35 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
36 /*! @brief Pointers to VREF clocks for each instance. */
37 static const clock_ip_name_t s_vrefClocks[] = VREF_CLOCKS;
38 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
39 
40 /*******************************************************************************
41  * Code
42  ******************************************************************************/
43 
VREF_GetInstance(VREF_Type * base)44 static uint32_t VREF_GetInstance(VREF_Type *base)
45 {
46     uint32_t instance;
47 
48     /* Find the instance index from base address mappings. */
49     for (instance = 0; instance < ARRAY_SIZE(s_vrefBases); instance++)
50     {
51         if (s_vrefBases[instance] == base)
52         {
53             break;
54         }
55     }
56 
57     assert(instance < ARRAY_SIZE(s_vrefBases));
58 
59     return instance;
60 }
61 
62 /*!
63  * brief Enables the clock gate and configures the VREF module according to the configuration structure.
64  *
65  * This function must be called before calling all other VREF driver functions, read/write registers, and
66  * configurations with user-defined settings. The example below shows how to set up vref_config_t parameters
67  * and how to call the VREF_Init function by passing in these parameters.
68  * code
69  *    vref_config_t vrefConfig;
70  *    VREF_GetDefaultConfig(VREF, &vrefConfig);
71  *    vrefConfig.bufferMode = kVREF_ModeHighPowerBuffer;
72  *    VREF_Init(VREF, &vrefConfig);
73  * endcode
74  *
75  * param base VREF peripheral address.
76  * param config Pointer to the configuration structure.
77  */
VREF_Init(VREF_Type * base,const vref_config_t * config)78 void VREF_Init(VREF_Type *base, const vref_config_t *config)
79 {
80     assert(config != NULL);
81 
82     uint32_t tmp32 = 0UL;
83 
84 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
85     /* Ungate clock for VREF */
86     CLOCK_EnableClock(s_vrefClocks[VREF_GetInstance(base)]);
87 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
88 
89     /* Enable low power bandgap at first. */
90     tmp32 = VREF_CSR_LPBGEN_MASK | VREF_CSR_LPBG_BUF_EN_MASK | VREF_CSR_VRSEL(config->vrefSel);
91 
92     /* Configure buffer mode. */
93     switch (config->bufferMode)
94     {
95         case kVREF_ModeBandgapOnly:
96             break;
97         case kVREF_ModeLowPowerBuffer:
98             tmp32 |= VREF_CSR_BUF21EN_MASK;
99             break;
100         case kVREF_ModeHighPowerBuffer:
101             tmp32 |= (VREF_CSR_BUF21EN_MASK | VREF_CSR_HI_PWR_LV_MASK);
102             break;
103         default:
104             assert(false);
105             break;
106     }
107 
108     /* Enable internal voltage regulator */
109     if (config->enableInternalVoltageRegulator)
110     {
111         /* Enable internal voltage regulator to provide the optimum VREF performance. */
112         tmp32 |= VREF_CSR_REGEN_MASK | VREF_CSR_CHOPEN_MASK | VREF_CSR_ICOMPEN_MASK;
113         base->CSR = tmp32;
114         /* After enabling low power bandgap, delay 20 us. */
115         SDK_DelayAtLeastUs(20U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
116         /* Enable high accurancy bandgap for vref output. */
117         if (config->enableVrefOut)
118         {
119             base->CSR |= VREF_CSR_HCBGEN_MASK;
120         }
121         /* After enabling high accurancy bandgap, delay 400 us. */
122         SDK_DelayAtLeastUs(400U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
123     }
124     else
125     {
126         /* Enable high accurancy bandgap for vref output. */
127         if (config->enableVrefOut)
128         {
129             tmp32 |= VREF_CSR_HCBGEN_MASK;
130             base->CSR = tmp32;
131             /* Wait until internal voltage stable */
132             while ((base->CSR & VREF_CSR_VREFST_MASK) == 0U)
133             {
134             }
135         }
136         else
137         {
138             base->CSR = tmp32;
139         }
140     }
141 }
142 
143 /*!
144  * brief Stops and disables the clock for the VREF module.
145  *
146  * This function should be called to shut down the module.
147  * This is an example.
148  * code
149  *    vref_config_t vrefUserConfig;
150  *    VREF_GetDefaultConfig(VREF, &vrefUserConfig);
151  *    VREF_Init(VREF, &vrefUserConfig);
152  *    ...
153  *    VREF_Deinit(VREF);
154  * endcode
155  *
156  * param base VREF peripheral address.
157  */
VREF_Deinit(VREF_Type * base)158 void VREF_Deinit(VREF_Type *base)
159 {
160 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
161     /* Gate clock for VREF */
162     CLOCK_DisableClock(s_vrefClocks[VREF_GetInstance(base)]);
163 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
164 }
165 
166 /*!
167  * brief Initializes the VREF configuration structure.
168  *
169  * This function initializes the VREF configuration structure to default values.
170  * This is an example.
171  * code
172  *    config->bufferMode = kVREF_ModeHighPowerBuffer;
173  *    config->enableInternalVoltageRegulator = true;
174  *    config->enableVrefOut = true;
175  *    config->vrefSel = kVREF_InternalBandgap;
176  * endcode
177  *
178  * param config Pointer to the initialization structure.
179  */
VREF_GetDefaultConfig(vref_config_t * config)180 void VREF_GetDefaultConfig(vref_config_t *config)
181 {
182     assert(NULL != config);
183 
184     /* Initializes the configure structure to zero. */
185     (void)memset(config, 0, sizeof(*config));
186 
187     config->bufferMode                     = kVREF_ModeHighPowerBuffer;
188     config->enableInternalVoltageRegulator = true;
189     config->enableVrefOut                  = true;
190     config->vrefSel                        = kVREF_InternalBandgap;
191 }
192 
193 /*!
194  * brief Sets a TRIM value for the accurate 1.0V bandgap output.
195  *
196  * This function sets a TRIM value for the reference voltage. It will trim the accurate 1.0V bandgap by 0.5mV each step.
197  *
198  * param base VREF peripheral address.
199  * param trimValue Value of the trim register to set the output reference voltage (maximum 0x3F (6-bit)).
200  */
VREF_SetVrefTrimVal(VREF_Type * base,uint8_t trimValue)201 void VREF_SetVrefTrimVal(VREF_Type *base, uint8_t trimValue)
202 {
203     uint32_t tmp32 = base->UTRIM;
204 
205     tmp32 &= (~VREF_UTRIM_VREFTRIM_MASK);
206     tmp32 |= VREF_UTRIM_VREFTRIM(trimValue);
207 
208     base->UTRIM = tmp32;
209 
210     if (VREF_CSR_CHOPEN_MASK == (base->CSR & VREF_CSR_CHOPEN_MASK))
211     {
212         /* After enabling high accurancy bandgap, delay 400 us. */
213         SDK_DelayAtLeastUs(400U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
214     }
215     else
216     {
217         while ((base->CSR & VREF_CSR_VREFST_MASK) == 0U)
218         {
219         }
220     }
221 }
222 
223 /*!
224  * brief Sets a TRIM value for the accurate buffered VREF output.
225  *
226  * This function sets a TRIM value for the reference voltage. If buffer mode be set to other values (Buf21
227  * enabled), it will trim the VREF_OUT by 0.1V each step from 1.0V to 2.1V.
228  *
229  * note When Buf21 is enabled, the value of UTRIM[TRIM2V1] should be ranged from 0b0000 to 0b1011 in order to trim the
230  * output voltage from 1.0V to 2.1V, other values will make the VREF_OUT to default value, 1.0V.
231  *
232  * param base VREF peripheral address.
233  * param trimValue Value of the trim register to set the output reference voltage (maximum 0xF (4-bit)).
234  */
VREF_SetTrim21Val(VREF_Type * base,uint8_t trim21Value)235 void VREF_SetTrim21Val(VREF_Type *base, uint8_t trim21Value)
236 {
237     uint32_t tmp32 = base->UTRIM;
238 
239     if (VREF_CSR_BUF21EN_MASK == (base->CSR & VREF_CSR_BUF21EN_MASK))
240     {
241         tmp32 &= (~VREF_UTRIM_TRIM2V1_MASK);
242         tmp32 |= VREF_UTRIM_TRIM2V1(trim21Value);
243     }
244 
245     base->UTRIM = tmp32;
246 
247     if (VREF_CSR_CHOPEN_MASK == (base->CSR & VREF_CSR_CHOPEN_MASK))
248     {
249         /* After enabling high accurancy bandgap, delay 400 us. */
250         SDK_DelayAtLeastUs(400U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
251     }
252     else
253     {
254         while ((base->CSR & VREF_CSR_VREFST_MASK) == 0U)
255         {
256         }
257     }
258 }
259 
260 /*!
261  * brief Reads the VREF trim value..
262  *
263  * This function gets the TRIM value from the UTRIM register. It reads UTRIM[VREFTRIM] (13:8)
264  *
265  * param base VREF peripheral address.
266  * return 6-bit value of trim setting.
267  */
VREF_GetVrefTrimVal(VREF_Type * base)268 uint8_t VREF_GetVrefTrimVal(VREF_Type *base)
269 {
270     uint8_t trimValue;
271 
272     trimValue = (uint8_t)((base->UTRIM & VREF_UTRIM_VREFTRIM_MASK) >> VREF_UTRIM_VREFTRIM_SHIFT);
273 
274     return trimValue;
275 }
276 
277 /*!
278  * brief Reads the VREF 2.1V trim value..
279  *
280  * This function gets the TRIM value from the UTRIM register. It reads UTRIM[TRIM2V1] (3:0),
281  *
282  * param base VREF peripheral address.
283  * return 4-bit value of trim setting.
284  */
VREF_GetTrim21Val(VREF_Type * base)285 uint8_t VREF_GetTrim21Val(VREF_Type *base)
286 {
287     uint8_t trimValue;
288 
289     trimValue = (uint8_t)((base->UTRIM & VREF_UTRIM_TRIM2V1_MASK) >> VREF_UTRIM_TRIM2V1_SHIFT);
290 
291     return trimValue;
292 }
293