1 /*
2  * Copyright 2018-2020, NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 #include "fsl_anactrl.h"
9 
10 /* Component ID definition, used by tools. */
11 #ifndef FSL_COMPONENT_ID
12 #define FSL_COMPONENT_ID "platform.drivers.anactrl"
13 #endif
14 
15 /*******************************************************************************
16  * Prototypes
17  ******************************************************************************/
18 /*!
19  * @brief Get instance number for ANACTRL module.
20  *
21  * @param base ANACTRL peripheral base address
22  */
23 static uint32_t ANACTRL_GetInstance(ANACTRL_Type *base);
24 
25 /*******************************************************************************
26  * Variables
27  ******************************************************************************/
28 /*! @brief Pointers to ANACTRL bases for each instance. */
29 static ANACTRL_Type *const s_anactrlBases[] = ANACTRL_BASE_PTRS;
30 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
31 /*! @brief Pointers to ANACTRL clocks for each instance. */
32 static const clock_ip_name_t s_anactrlClocks[] = ANALOGCTRL_CLOCKS;
33 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
34 
35 /*******************************************************************************
36  * Code
37  ******************************************************************************/
38 /*!
39  * brief Get the ANACTRL instance from peripheral base address.
40  *
41  * param base ANACTRL peripheral base address.
42  * return ANACTRL instance.
43  */
ANACTRL_GetInstance(ANACTRL_Type * base)44 static uint32_t ANACTRL_GetInstance(ANACTRL_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_anactrlBases); instance++)
50     {
51         if (s_anactrlBases[instance] == base)
52         {
53             break;
54         }
55     }
56 
57     assert(instance < ARRAY_SIZE(s_anactrlBases));
58 
59     return instance;
60 }
61 
62 /*!
63  * brief Initializes the ANACTRL mode, the module's clock will be enabled by invoking this function.
64  *
65  * param base ANACTRL peripheral base address.
66  */
ANACTRL_Init(ANACTRL_Type * base)67 void ANACTRL_Init(ANACTRL_Type *base)
68 {
69     assert(NULL != base);
70 
71 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
72     /* Enable the clock for ANACTRL instance. */
73     CLOCK_EnableClock(s_anactrlClocks[ANACTRL_GetInstance(base)]);
74 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
75 }
76 
77 /*!
78  * brief De-initializes ANACTRL module, the module's clock will be disabled by invoking this function.
79  *
80  * param base ANACTRL peripheral base address.
81  */
ANACTRL_Deinit(ANACTRL_Type * base)82 void ANACTRL_Deinit(ANACTRL_Type *base)
83 {
84     assert(NULL != base);
85 
86 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
87     /* Disable the clock for ANACTRL instance. */
88     CLOCK_DisableClock(s_anactrlClocks[ANACTRL_GetInstance(base)]);
89 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
90 }
91 
92 /*!
93  * brief Configs the on-chip high-speed Free Running Oscillator(FRO192M), such as enabling/disabling 12 MHZ clock output
94  * and enable/disable 96MHZ clock output.
95  *
96  * param base ANACTRL peripheral base address.
97  * param config Pointer to FRO192M configuration structure. Refer to anactrl_fro192M_config_t structure.
98  */
ANACTRL_SetFro192M(ANACTRL_Type * base,const anactrl_fro192M_config_t * config)99 void ANACTRL_SetFro192M(ANACTRL_Type *base, const anactrl_fro192M_config_t *config)
100 {
101     assert(NULL != config);
102 
103     uint32_t tmp32 = base->FRO192M_CTRL;
104 
105     tmp32 &= ~(ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK | ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK);
106 
107     if (config->enable12MHzClk)
108     {
109         tmp32 |= ANACTRL_FRO192M_CTRL_ENA_12MHZCLK_MASK;
110     }
111     if (config->enable96MHzClk)
112     {
113         tmp32 |= ANACTRL_FRO192M_CTRL_ENA_96MHZCLK_MASK;
114     }
115 
116     base->FRO192M_CTRL |= tmp32;
117 }
118 
119 /*!
120  * brief Gets the default configuration of FRO192M.
121  * The default values are:
122  * code
123     config->enable12MHzClk = true;
124     config->enable96MHzClk = false;
125     endcode
126  * param config Pointer to FRO192M configuration structure. Refer to anactrl_fro192M_config_t structure.
127  */
ANACTRL_GetDefaultFro192MConfig(anactrl_fro192M_config_t * config)128 void ANACTRL_GetDefaultFro192MConfig(anactrl_fro192M_config_t *config)
129 {
130     assert(NULL != config);
131 
132     /* Initializes the configure structure to zero. */
133     (void)memset(config, 0, sizeof(*config));
134 
135     config->enable12MHzClk = true;
136     config->enable96MHzClk = false;
137 }
138 
139 /*!
140  * brief Configs the 32 MHz Crystal oscillator(High-speed crystal oscillator), such as enable/disable output to CPU
141  * system, and so on.
142  *
143  * param base ANACTRL peripheral base address.
144  * param config Pointer to XO32M configuration structure. Refer to anactrl_xo32M_config_t structure.
145  */
ANACTRL_SetXo32M(ANACTRL_Type * base,const anactrl_xo32M_config_t * config)146 void ANACTRL_SetXo32M(ANACTRL_Type *base, const anactrl_xo32M_config_t *config)
147 {
148     assert(NULL != config);
149 
150     uint32_t tmp32 = base->XO32M_CTRL;
151 
152     tmp32 &= ~(ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK | ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK);
153 
154     /* Set XO32M CTRL. */
155 #if !(defined(FSL_FEATURE_ANACTRL_HAS_NO_ENABLE_PLL_USB_OUT_BIT_FIELD) && \
156       FSL_FEATURE_ANACTRL_HAS_NO_ENABLE_PLL_USB_OUT_BIT_FIELD)
157     tmp32 &= ~ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT_MASK;
158     if (config->enablePllUsbOutput)
159     {
160         tmp32 |= ANACTRL_XO32M_CTRL_ENABLE_PLL_USB_OUT_MASK;
161     }
162 #endif /* FSL_FEATURE_ANACTRL_HAS_NO_ENABLE_PLL_USB_OUT_BIT_FIELD */
163 
164     if (config->enableACBufferBypass)
165     {
166         tmp32 |= ANACTRL_XO32M_CTRL_ACBUF_PASS_ENABLE_MASK;
167     }
168 
169     if (config->enableSysCLkOutput)
170     {
171         tmp32 |= ANACTRL_XO32M_CTRL_ENABLE_SYSTEM_CLK_OUT_MASK;
172     }
173     base->XO32M_CTRL = tmp32;
174 
175 #if (defined(FSL_FEATURE_ANACTRL_HAS_XO32M_ADC_CLK_MODE_BIF_FIELD) && \
176      FSL_FEATURE_ANACTRL_HAS_XO32M_ADC_CLK_MODE_BIF_FIELD)
177     if (config->enableADCOutput)
178     {
179         base->DUMMY_CTRL |= ANACTRL_DUMMY_CTRL_XO32M_ADC_CLK_MODE_MASK;
180     }
181     else
182     {
183         base->DUMMY_CTRL &= ~ANACTRL_DUMMY_CTRL_XO32M_ADC_CLK_MODE_MASK;
184     }
185 #endif /* FSL_FEATURE_ANACTRL_HAS_XO32M_ADC_CLK_MODE_BIF_FIELD */
186 }
187 
188 /*!
189  * brief Gets the default configuration of XO32M.
190  * The default values are:
191  * code
192     config->enableSysCLkOutput = false;
193     config->enableACBufferBypass = false;
194     endcode
195  * param config Pointer to XO32M configuration structure. Refer to anactrl_xo32M_config_t structure.
196  */
ANACTRL_GetDefaultXo32MConfig(anactrl_xo32M_config_t * config)197 void ANACTRL_GetDefaultXo32MConfig(anactrl_xo32M_config_t *config)
198 {
199     assert(NULL != config);
200 
201     /* Initializes the configure structure to zero. */
202     (void)memset(config, 0, sizeof(*config));
203 
204 #if !(defined(FSL_FEATURE_ANACTRL_HAS_NO_ENABLE_PLL_USB_OUT_BIT_FIELD) && \
205       FSL_FEATURE_ANACTRL_HAS_NO_ENABLE_PLL_USB_OUT_BIT_FIELD)
206     config->enablePllUsbOutput = false;
207 #endif /* FSL_FEATURE_ANACTRL_HAS_NO_ENABLE_PLL_USB_OUT_BIT_FIELD */
208     config->enableSysCLkOutput   = false;
209     config->enableACBufferBypass = false;
210 #if (defined(FSL_FEATURE_ANACTRL_HAS_XO32M_ADC_CLK_MODE_BIF_FIELD) && \
211      FSL_FEATURE_ANACTRL_HAS_XO32M_ADC_CLK_MODE_BIF_FIELD)
212     config->enableADCOutput = true;
213 #endif /* FSL_FEATURE_ANACTRL_HAS_XO32M_ADC_CLK_MODE_BIF_FIELD */
214 }
215 
216 /*!
217  * brief Measures the frequency of the target clock source.
218  *
219  * This function measures target frequency according to a accurate reference frequency.The formula is:
220  * Ftarget = (CAPVAL * Freference) / ((1<<SCALE)-1)
221  *
222  * note Both tartget and reference clocks are selectable by programming the target clock select FREQMEAS_TARGET register
223  * in INPUTMUX and reference clock select FREQMEAS_REF register in INPUTMUX.
224  *
225  * param base ANACTRL peripheral base address.
226  * param scale Define the power of 2 count that ref counter counts to during measurement, ranges from 2 to 31.
227  * param refClkFreq frequency of the reference clock.
228  *
229  * return frequency of the target clock.
230  */
ANACTRL_MeasureFrequency(ANACTRL_Type * base,uint8_t scale,uint32_t refClkFreq)231 uint32_t ANACTRL_MeasureFrequency(ANACTRL_Type *base, uint8_t scale, uint32_t refClkFreq)
232 {
233     assert(scale >= 2U);
234 
235     uint32_t targetClkFreq = 0U;
236     uint32_t capval        = 0U;
237 
238     /* Init a measurement cycle. */
239     base->FREQ_ME_CTRL = ANACTRL_FREQ_ME_CTRL_PROG_MASK + ANACTRL_FREQ_ME_CTRL_CAPVAL_SCALE(scale);
240     while (ANACTRL_FREQ_ME_CTRL_PROG_MASK == (base->FREQ_ME_CTRL & ANACTRL_FREQ_ME_CTRL_PROG_MASK))
241     {
242     }
243 
244     /* Calculate the target clock frequency. */
245     capval        = (base->FREQ_ME_CTRL & ANACTRL_FREQ_ME_CTRL_CAPVAL_SCALE_MASK);
246     targetClkFreq = (capval * refClkFreq) / ((1UL << scale) - 1UL);
247 
248     return targetClkFreq;
249 }
250