1 /*
2 * Copyright (c) 2019 - 2024, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifndef NRF_OSCILLATORS_H__
35 #define NRF_OSCILLATORS_H__
36
37 #include <nrfx.h>
38
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42
43 /**
44 * @defgroup nrf_oscillators_hal OSCILLATORS HAL
45 * @{
46 * @ingroup nrf_clock
47 * @brief Hardware access layer for managing the OSCILLATORS peripheral.
48 */
49
50 #if defined(OSCILLATORS_PLL_FREQ_FREQ_Msk) || defined(__NRFX_DOXYGEN__)
51 /** @brief Symbol indicating whether PLL is present. */
52 #define NRF_OSCILLATORS_HAS_PLL 1
53 #else
54 #define NRF_OSCILLATORS_HAS_PLL 0
55 #endif
56
57 #if defined(OSCILLATORS_XOSC32M_CLOCKQUALITY_INDICATOR_Msk) || defined(__NRFX_DOXYGEN__)
58 /** @brief Symbol indicating whether clock quality indicator is present. */
59 #define NRF_OSCILLATORS_HAS_CLOCK_QUALITY_IND 1
60 #else
61 #define NRF_OSCILLATORS_HAS_CLOCK_QUALITY_IND 0
62 #endif
63
64 #if defined(OSCILLATORS_XOSC32KI_INTCAP_VAL_Msk) || defined(__NRFX_DOXYGEN__)
65 /** @brief Symbol indicating whether configuration of internal capacitor using integer value is present. */
66 #define NRF_OSCILLATORS_HAS_LFXO_CAP_AS_INT_VALUE 1
67 #else
68 #define NRF_OSCILLATORS_HAS_LFXO_CAP_AS_INT_VALUE 0
69 #endif
70
71 #if defined(OSCILLATORS_XOSC32KI_Type) || defined(__NRFX_DOXYGEN__)
72 /** @brief Symbol indicating whether LFXO bypass is present. */
73 #define NRF_OSCILLATORS_HAS_LFXO_BYPASS 1
74 #else
75 #define NRF_OSCILLATORS_HAS_LFXO_BYPASS 0
76 #endif
77
78 #if defined(NRF5340_XXAA_APPLICATION) || defined(__NRFX_DOXYGEN__)
79 /**
80 * @brief Macro for calculating HFXO internal capacitor value.
81 *
82 * Depending on the SoC used, a range of capacitance of internal capacitors is as follows:
83 * - From 7 pF to 20 pF in 0.5 pF steps for nRF5340.
84 * - From 4 pF to 17 pF in 0.25 pF steps for other SoCs.
85 * This macro should be used to calculate argument's value for @ref nrf_oscillators_hfxo_cap_set function.
86 */
87 #define OSCILLATORS_HFXO_CAP_CALCULATE(p_ficr_reg, cap_val) \
88 ((((p_ficr_reg->XOSC32MTRIM & FICR_XOSC32MTRIM_SLOPE_Msk) \
89 << FICR_XOSC32MTRIM_SLOPE_Pos) / 16 + 1) * \
90 (cap_val * 2 - 14) + \
91 ((p_ficr_reg->XOSC32MTRIM & FICR_XOSC32MTRIM_OFFSET_Msk) \
92 << FICR_XOSC32MTRIM_OFFSET_Pos))
93 #else
94 #define OSCILLATORS_HFXO_CAP_CALCULATE(p_ficr_reg, cap_val) \
95 (((cap_val - 5.5) * \
96 (((p_ficr_reg->XOSC32MTRIM & FICR_XOSC32MTRIM_SLOPE_Msk) \
97 << FICR_XOSC32MTRIM_SLOPE_Pos) + 791) + \
98 (((p_ficr_reg->XOSC32MTRIM & FICR_XOSC32MTRIM_OFFSET_Msk) \
99 << FICR_XOSC32MTRIM_OFFSET_Pos) << 2)) >> 8)
100 #endif
101
102 #if NRF_OSCILLATORS_HAS_LFXO_CAP_AS_INT_VALUE
103 /**
104 * @brief Macro for calculating LFXO internal capacitor value.
105 *
106 * The capacitance of internal capacitors ranges from 4 pF to 18 pF in 0.5 pF steps.
107 * This macro should be used to calculate argument's value for @ref nrf_oscillators_lfxo_cap_set function.
108 */
109 #define OSCILLATORS_LFXO_CAP_CALCULATE(p_ficr_reg, cap_val) \
110 ((((cap_val - 4) * (((p_ficr_reg->XOSC32KTRIM & FICR_XOSC32KTRIM_SLOPE_Msk) \
111 << FICR_XOSC32KTRIM_SLOPE_Pos)) + 392) >> 3 + \
112 ((p_ficr_reg->XOSC32KTRIM & FICR_XOSC32KTRIM_OFFSET_Msk) \
113 << FICR_XOSC32KTRIM_OFFSET_Pos)) >> 6)
114 #endif
115
116 #if NRF_OSCILLATORS_HAS_CLOCK_QUALITY_IND
117 /** @brief HFXO clock quality indicator. */
118 typedef enum
119 {
120 NRF_OSCILLATORS_HFXO_CLOCK_QUALITY_NONE = OSCILLATORS_XOSC32M_CLOCKQUALITY_INDICATOR_NoStatus, ///< Clock XOSC32M status is not defined.
121 NRF_OSCILLATORS_HFXO_CLOCK_QUALITY_STARTING = OSCILLATORS_XOSC32M_CLOCKQUALITY_INDICATOR_Starting, ///< Clock XOSC32M has started but has not yet reached the specified frequency tolerance requirement fTOL_HFXO.
122 NRF_OSCILLATORS_HFXO_CLOCK_QUALITY_STARTED = OSCILLATORS_XOSC32M_CLOCKQUALITY_INDICATOR_Started ///< Clock XOSC32M has started and is operating with the specified frequency tolerance requirement fTOL_HFXO.
123 } nrf_oscillators_hfxo_clock_quality_t;
124 #endif
125
126 #if NRF_OSCILLATORS_HAS_PLL
127 /** @brief PLL frequencies. */
128 typedef enum
129 {
130 NRF_OSCILLATORS_PLL_FREQ_64M = OSCILLATORS_PLL_FREQ_FREQ_CK64M, ///< PLL 64 MHz frequency.
131 NRF_OSCILLATORS_PLL_FREQ_128M = OSCILLATORS_PLL_FREQ_FREQ_CK128M, ///< PLL 128 MHz frequency.
132 } nrf_oscillators_pll_freq_t;
133 #endif
134
135 #if NRF_OSCILLATORS_HAS_LFXO_CAP_AS_INT_VALUE
136 /** @brief LFXO capacitance type. */
137 typedef uint32_t nrf_oscillators_lfxo_cap_t;
138
139 /** @brief Symbol specifying usage of external capacitors. */
140 #define NRF_OSCILLATORS_LFXO_CAP_EXTERNAL ((nrf_oscillators_lfxo_cap_t)0)
141 #else
142 /** @brief Capacitors configuration for LFXO. */
143 typedef enum
144 {
145 NRF_OSCILLATORS_LFXO_CAP_EXTERNAL = OSCILLATORS_XOSC32KI_INTCAP_INTCAP_External, ///< Use external capacitors.
146 NRF_OSCILLATORS_LFXO_CAP_6PF = OSCILLATORS_XOSC32KI_INTCAP_INTCAP_C6PF, ///< Use 6 pF internal capacitors.
147 NRF_OSCILLATORS_LFXO_CAP_7PF = OSCILLATORS_XOSC32KI_INTCAP_INTCAP_C7PF, ///< Use 7 pF internal capacitors.
148 NRF_OSCILLATORS_LFXO_CAP_9PF = OSCILLATORS_XOSC32KI_INTCAP_INTCAP_C9PF, ///< Use 9 pF internal capacitors.
149 #if defined(OSCILLATORS_XOSC32KI_INTCAP_INTCAP_C11PF) || defined(__NRFX_DOXYGEN__)
150 NRF_OSCILLATORS_LFXO_CAP_11PF = OSCILLATORS_XOSC32KI_INTCAP_INTCAP_C11PF, ///< Use 11 pF internal capacitors.
151 #endif
152 } nrf_oscillators_lfxo_cap_t;
153 #endif
154
155 #if NRF_OSCILLATORS_HAS_CLOCK_QUALITY_IND
156 /**
157 * @brief Function for reading HFXO clock quality indicator.
158 *
159 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
160 *
161 * @return Clock quality indicator value.
162 */
163 NRF_STATIC_INLINE nrf_oscillators_hfxo_clock_quality_t
164 nrf_oscillators_hfxo_clock_quality_get(NRF_OSCILLATORS_Type * p_reg);
165 #endif
166
167 #if NRF_OSCILLATORS_HAS_PLL
168 /**
169 * @brief Function for setting PLL frequency.
170 *
171 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
172 * @param[in] freq New PLL frequency.
173 */
174 NRF_STATIC_INLINE void nrf_oscillators_pll_freq_set(NRF_OSCILLATORS_Type * p_reg,
175 nrf_oscillators_pll_freq_t freq);
176
177 /**
178 * @brief Function for getting PLL frequency.
179 *
180 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
181 *
182 * @return Current PLL frequency value.
183 */
184 NRF_STATIC_INLINE
185 nrf_oscillators_pll_freq_t nrf_oscillators_pll_freq_get(NRF_OSCILLATORS_Type * p_reg);
186 #endif
187
188 #if NRF_OSCILLATORS_HAS_LFXO_BYPASS
189 /**
190 * @brief Function for enabling or disabling the bypass of LFXO with external clock source.
191 *
192 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
193 * @param[in] enable True if bypass is to be enabled (use with rail-to-rail external source).
194 * False if bypass is to be disabled (use with xtal or low-swing external source).
195 */
196 NRF_STATIC_INLINE void nrf_oscillators_lfxo_bypass_set(NRF_OSCILLATORS_Type * p_reg, bool enable);
197 #endif
198
199 /**
200 * @brief Function for configuring the internal capacitors of LFXO.
201 *
202 * For SoCs other than nRF5340, to calculate the correct @p cap_value, use @ref OSCILLATORS_LFXO_CAP_CALCULATE macro.
203 *
204 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
205 * @param[in] cap Capacitors configuration.
206 */
207 NRF_STATIC_INLINE void nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS_Type * p_reg,
208 nrf_oscillators_lfxo_cap_t cap);
209
210 /**
211 * @brief Function for configuring the internal capacitors of HFXO.
212 *
213 * To calculate the correct @p cap_value, use @ref OSCILLATORS_HFXO_CAP_CALCULATE macro.
214 *
215 * @param[in] p_reg Pointer to the structure of registers of the peripheral.
216 * @param[in] enable True if internal capacitors are to be enabled, false otherwise.
217 * @param[in] cap_value Value representing capacitance, calculated using provided equation.
218 * Ignored when internal capacitors are disabled.
219 */
220 NRF_STATIC_INLINE void nrf_oscillators_hfxo_cap_set(NRF_OSCILLATORS_Type * p_reg,
221 bool enable,
222 uint32_t cap_value);
223
224 #ifndef NRF_DECLARE_ONLY
225
226 #if NRF_OSCILLATORS_HAS_CLOCK_QUALITY_IND
227 NRF_STATIC_INLINE nrf_oscillators_hfxo_clock_quality_t
nrf_oscillators_hfxo_clock_quality_get(NRF_OSCILLATORS_Type * p_reg)228 nrf_oscillators_hfxo_clock_quality_get(NRF_OSCILLATORS_Type * p_reg)
229 {
230 return (nrf_oscillators_hfxo_clock_quality_t)(p_reg->XOSC32M.CLOCKQUALITY);
231 }
232 #endif
233
234 #if NRF_OSCILLATORS_HAS_PLL
nrf_oscillators_pll_freq_set(NRF_OSCILLATORS_Type * p_reg,nrf_oscillators_pll_freq_t freq)235 NRF_STATIC_INLINE void nrf_oscillators_pll_freq_set(NRF_OSCILLATORS_Type * p_reg,
236 nrf_oscillators_pll_freq_t freq)
237 {
238 p_reg->PLL.FREQ = (uint32_t)freq;
239 }
240
241 NRF_STATIC_INLINE
nrf_oscillators_pll_freq_get(NRF_OSCILLATORS_Type * p_reg)242 nrf_oscillators_pll_freq_t nrf_oscillators_pll_freq_get(NRF_OSCILLATORS_Type * p_reg)
243 {
244 return (nrf_oscillators_pll_freq_t)(p_reg->PLL.CURRENTFREQ);
245 }
246 #endif
247
248 #if NRF_OSCILLATORS_HAS_LFXO_BYPASS
nrf_oscillators_lfxo_bypass_set(NRF_OSCILLATORS_Type * p_reg,bool enable)249 NRF_STATIC_INLINE void nrf_oscillators_lfxo_bypass_set(NRF_OSCILLATORS_Type * p_reg, bool enable)
250 {
251 p_reg->XOSC32KI.BYPASS = (enable ? OSCILLATORS_XOSC32KI_BYPASS_BYPASS_Enabled :
252 OSCILLATORS_XOSC32KI_BYPASS_BYPASS_Disabled);
253 }
254 #endif
255
nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS_Type * p_reg,nrf_oscillators_lfxo_cap_t cap)256 NRF_STATIC_INLINE void nrf_oscillators_lfxo_cap_set(NRF_OSCILLATORS_Type * p_reg,
257 nrf_oscillators_lfxo_cap_t cap)
258 {
259 p_reg->XOSC32KI.INTCAP = (uint32_t)cap;
260 }
261
nrf_oscillators_hfxo_cap_set(NRF_OSCILLATORS_Type * p_reg,bool enable,uint32_t cap_value)262 NRF_STATIC_INLINE void nrf_oscillators_hfxo_cap_set(NRF_OSCILLATORS_Type * p_reg,
263 bool enable,
264 uint32_t cap_value)
265 {
266 #if defined(OSCILLATORS_XOSC32MCAPS_CAPVALUE_Msk)
267 p_reg->XOSC32MCAPS =
268 (enable ? ((OSCILLATORS_XOSC32MCAPS_ENABLE_Enabled << OSCILLATORS_XOSC32MCAPS_ENABLE_Pos) |
269 (cap_value << OSCILLATORS_XOSC32MCAPS_CAPVALUE_Pos))
270 : (OSCILLATORS_XOSC32MCAPS_ENABLE_Disabled << OSCILLATORS_XOSC32MCAPS_ENABLE_Pos));
271 #else
272 p_reg->XOSC32M.CONFIG.INTCAP = enable ? cap_value : 0;
273 #endif
274 }
275 #endif // NRF_DECLARE_ONLY
276
277 /** @} */
278
279 #ifdef __cplusplus
280 }
281 #endif
282
283 #endif // NRF_OSCILLATORS_H__
284