1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_vref.h"
10 
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.vref"
14 #endif
15 
16 /*******************************************************************************
17  * Prototypes
18  ******************************************************************************/
19 
20 /*!
21  * @brief Gets the instance from the base address
22  *
23  * @param base VREF peripheral base address
24  *
25  * @return The VREF instance
26  */
27 static uint32_t VREF_GetInstance(VREF_Type *base);
28 
29 /*******************************************************************************
30  * Variables
31  ******************************************************************************/
32 
33 /*! @brief Pointers to VREF bases for each instance. */
34 static VREF_Type *const s_vrefBases[] = VREF_BASE_PTRS;
35 
36 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
37 /*! @brief Pointers to VREF clocks for each instance. */
38 static const clock_ip_name_t s_vrefClocks[] = VREF_CLOCKS;
39 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
40 
41 /*******************************************************************************
42  * Code
43  ******************************************************************************/
44 
VREF_GetInstance(VREF_Type * base)45 static uint32_t VREF_GetInstance(VREF_Type *base)
46 {
47     uint32_t instance;
48 
49     /* Find the instance index from base address mappings. */
50     for (instance = 0; instance < ARRAY_SIZE(s_vrefBases); instance++)
51     {
52         if (s_vrefBases[instance] == base)
53         {
54             break;
55         }
56     }
57 
58     assert(instance < ARRAY_SIZE(s_vrefBases));
59 
60     return instance;
61 }
62 
63 /*!
64  * brief Enables the clock gate and configures the VREF module according to the configuration structure.
65  *
66  * This function must be called before calling all other VREF driver functions,
67  * read/write registers, and configurations with user-defined settings.
68  * The example below shows how to set up  vref_config_t parameters and
69  * how to call the VREF_Init function by passing in these parameters.
70  * This is an example.
71  * code
72  *   vref_config_t vrefConfig;
73  *   vrefConfig.bufferMode = kVREF_ModeHighPowerBuffer;
74  *   vrefConfig.enableExternalVoltRef = false;
75  *   vrefConfig.enableLowRef = false;
76  *   VREF_Init(VREF, &vrefConfig);
77  * endcode
78  *
79  * param base VREF peripheral address.
80  * param config Pointer to the configuration structure.
81  */
VREF_Init(VREF_Type * base,const vref_config_t * config)82 void VREF_Init(VREF_Type *base, const vref_config_t *config)
83 {
84     assert(config != NULL);
85 
86     uint8_t reg = 0U;
87 
88 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
89     /* Ungate clock for VREF */
90     CLOCK_EnableClock(s_vrefClocks[VREF_GetInstance(base)]);
91 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
92 
93 /* Configure VREF to a known state */
94 #if defined(FSL_FEATURE_VREF_HAS_CHOP_OSC) && FSL_FEATURE_VREF_HAS_CHOP_OSC
95     /* Set chop oscillator bit */
96     base->TRM |= VREF_TRM_CHOPEN_MASK;
97 #endif /* FSL_FEATURE_VREF_HAS_CHOP_OSC */
98 /* Get current SC register */
99 #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE
100     reg = base->VREFH_SC;
101 #else
102     reg      = base->SC;
103 #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */
104     /* Clear old buffer mode selection bits */
105     reg &= ~(uint8_t)VREF_SC_MODE_LV_MASK;
106     /* Set buffer Mode selection and Regulator enable bit */
107     reg |= VREF_SC_MODE_LV(config->bufferMode) | VREF_SC_REGEN(1U);
108 #if defined(FSL_FEATURE_VREF_HAS_COMPENSATION) && FSL_FEATURE_VREF_HAS_COMPENSATION
109     /* Set second order curvature compensation enable bit */
110     reg |= VREF_SC_ICOMPEN(1U);
111 #endif /* FSL_FEATURE_VREF_HAS_COMPENSATION */
112     /* Enable VREF module */
113     reg |= VREF_SC_VREFEN(1U);
114 /* Update bit-field from value to Status and Control register */
115 #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE
116     base->VREFH_SC = reg;
117 #else
118     base->SC = reg;
119 #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */
120 #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE
121     reg = base->VREFL_TRM;
122     /* Clear old select external voltage reference and VREFL (0.4 V) reference buffer enable bits */
123     reg &= (uint8_t)(~(VREF_VREFL_TRM_VREFL_EN_MASK | VREF_VREFL_TRM_VREFL_SEL_MASK));
124     /* Select external voltage reference and set VREFL (0.4 V) reference buffer enable */
125     reg |= VREF_VREFL_TRM_VREFL_SEL(config->enableExternalVoltRef) | VREF_VREFL_TRM_VREFL_EN(config->enableLowRef);
126     base->VREFL_TRM = reg;
127 #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */
128 
129 #if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4
130     reg = base->TRM4;
131     /* Clear old select internal voltage reference bit (2.1V) */
132     reg &= ~(uint8_t)VREF_TRM4_VREF2V1_EN_MASK;
133     /* Select internal voltage reference (2.1V) */
134     reg |= VREF_TRM4_VREF2V1_EN(config->enable2V1VoltRef);
135     base->TRM4 = reg;
136 #endif /* FSL_FEATURE_VREF_HAS_TRM4 */
137 
138 /* Wait until internal voltage stable */
139 #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE
140     while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0U)
141 #else
142     while ((base->SC & VREF_SC_VREFST_MASK) == 0U)
143 #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */
144     {
145     }
146 }
147 
148 /*!
149  * brief Stops and disables the clock for the VREF module.
150  *
151  * This function should be called to shut down the module.
152  * This is an example.
153  * code
154  *   vref_config_t vrefUserConfig;
155  *   VREF_Init(VREF);
156  *   VREF_GetDefaultConfig(&vrefUserConfig);
157  *   ...
158  *   VREF_Deinit(VREF);
159  * endcode
160  *
161  * param base VREF peripheral address.
162  */
VREF_Deinit(VREF_Type * base)163 void VREF_Deinit(VREF_Type *base)
164 {
165 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
166     /* Gate clock for VREF */
167     CLOCK_DisableClock(s_vrefClocks[VREF_GetInstance(base)]);
168 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
169 }
170 
171 /*!
172  * brief Initializes the VREF configuration structure.
173  *
174  * This function initializes the VREF configuration structure to default values.
175  * This is an example.
176  * code
177  *   vrefConfig->bufferMode = kVREF_ModeHighPowerBuffer;
178  *   vrefConfig->enableExternalVoltRef = false;
179  *   vrefConfig->enableLowRef = false;
180  * endcode
181  *
182  * param config Pointer to the initialization structure.
183  */
VREF_GetDefaultConfig(vref_config_t * config)184 void VREF_GetDefaultConfig(vref_config_t *config)
185 {
186     assert(NULL != config);
187 
188     /* Initializes the configure structure to zero. */
189     (void)memset(config, 0, sizeof(*config));
190 
191 /* Set High power buffer mode in */
192 #if defined(FSL_FEATURE_VREF_MODE_LV_TYPE) && FSL_FEATURE_VREF_MODE_LV_TYPE
193     config->bufferMode = kVREF_ModeHighPowerBuffer;
194 #else
195     config->bufferMode = kVREF_ModeTightRegulationBuffer;
196 #endif /* FSL_FEATURE_VREF_MODE_LV_TYPE */
197 
198 #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE
199     /* Select internal voltage reference */
200     config->enableExternalVoltRef = false;
201     /* Set VREFL (0.4 V) reference buffer disable */
202     config->enableLowRef = false;
203 #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */
204 
205 #if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4
206     /* Disable internal voltage reference (2.1V) */
207     config->enable2V1VoltRef = false;
208 #endif /* FSL_FEATURE_VREF_HAS_TRM4 */
209 }
210 
211 /*!
212  * brief Sets a TRIM value for the reference voltage.
213  *
214  * This function sets a TRIM value for the reference voltage.
215  * Note that the TRIM value maximum is 0x3F.
216  *
217  * param base VREF peripheral address.
218  * param trimValue Value of the trim register to set the output reference voltage (maximum 0x3F (6-bit)).
219  */
VREF_SetTrimVal(VREF_Type * base,uint8_t trimValue)220 void VREF_SetTrimVal(VREF_Type *base, uint8_t trimValue)
221 {
222     uint8_t reg = 0U;
223 
224     /* Set TRIM bits value in voltage reference */
225     reg       = base->TRM;
226     reg       = (uint8_t)((reg & ~VREF_TRM_TRIM_MASK) | VREF_TRM_TRIM(trimValue));
227     base->TRM = reg;
228 /* Wait until internal voltage stable */
229 #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE
230     while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0U)
231 #else
232     while ((base->SC & VREF_SC_VREFST_MASK) == 0U)
233 #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */
234     {
235     }
236 }
237 
238 #if defined(FSL_FEATURE_VREF_HAS_TRM4) && FSL_FEATURE_VREF_HAS_TRM4
239 /*!
240  * brief Sets a TRIM value for the reference voltage (2V1).
241  *
242  * This function sets a TRIM value for the reference voltage (2V1).
243  * Note that the TRIM value maximum is 0x3F.
244  *
245  * param base VREF peripheral address.
246  * param trimValue Value of the trim register to set the output reference voltage (maximum 0x3F (6-bit)).
247  */
VREF_SetTrim2V1Val(VREF_Type * base,uint8_t trimValue)248 void VREF_SetTrim2V1Val(VREF_Type *base, uint8_t trimValue)
249 {
250     uint8_t reg = 0U;
251 
252     /* Set TRIM bits value in voltage reference (2V1) */
253     reg        = base->TRM4;
254     reg        = (uint8_t)((reg & ~VREF_TRM4_TRIM2V1_MASK) | VREF_TRM4_TRIM2V1(trimValue));
255     base->TRM4 = reg;
256     /* Wait until internal voltage stable */
257     while ((base->SC & VREF_SC_VREFST_MASK) == 0U)
258     {
259     }
260 }
261 #endif /* FSL_FEATURE_VREF_HAS_TRM4 */
262 
263 #if defined(FSL_FEATURE_VREF_HAS_LOW_REFERENCE) && FSL_FEATURE_VREF_HAS_LOW_REFERENCE
264 /*!
265  * brief Sets the TRIM value for the low voltage reference.
266  *
267  * This function sets the TRIM value for low reference voltage.
268  * Note the following.
269  *      - The TRIM value maximum is 0x05U
270  *      - The values 111b and 110b are not valid/allowed.
271  *
272  * param base VREF peripheral address.
273  * param trimValue Value of the trim register to set output low reference voltage (maximum 0x05U (3-bit)).
274  */
VREF_SetLowReferenceTrimVal(VREF_Type * base,uint8_t trimValue)275 void VREF_SetLowReferenceTrimVal(VREF_Type *base, uint8_t trimValue)
276 {
277     /* The values 111b and 110b are NOT valid/allowed */
278     assert((trimValue != 0x7U) && (trimValue != 0x6U));
279 
280     uint8_t reg = 0U;
281 
282     /* Set TRIM bits value in low voltage reference */
283     reg             = base->VREFL_TRM;
284     reg             = ((reg & (uint8_t)(~VREF_VREFL_TRM_VREFL_TRIM_MASK)) | VREF_VREFL_TRM_VREFL_TRIM(trimValue));
285     base->VREFL_TRM = reg;
286     /* Wait until internal voltage stable */
287 
288     while ((base->VREFH_SC & VREF_SC_VREFST_MASK) == 0U)
289     {
290     }
291 }
292 #endif /* FSL_FEATURE_VREF_HAS_LOW_REFERENCE */
293