1 /*
2 * Copyright (c) 2016 - 2025, 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 NRFX_CLOCK_H__
35 #define NRFX_CLOCK_H__
36
37 #include <nrfx.h>
38 #include <hal/nrf_clock.h>
39 #include <nrfx_power_clock.h>
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 /**
46 * @defgroup nrfx_clock CLOCK driver
47 * @{
48 * @ingroup nrf_clock
49 * @brief CLOCK peripheral driver.
50 */
51
52 /** @brief Clock events. */
53 typedef enum
54 {
55 NRFX_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started.
56 NRFX_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started.
57 NRFX_CLOCK_EVT_PLL_STARTED, ///< PLL has been started.
58 NRFX_CLOCK_EVT_CTTO, ///< Calibration timeout.
59 NRFX_CLOCK_EVT_CAL_DONE, ///< Calibration has been done.
60 NRFX_CLOCK_EVT_HFCLKAUDIO_STARTED, ///< HFCLKAUDIO has been started.
61 NRFX_CLOCK_EVT_HFCLK192M_STARTED, ///< HFCLK192M has been started.
62 #if NRF_CLOCK_HAS_XO_TUNE
63 NRFX_CLOCK_EVT_XO_TUNED, ///< XO tune has been done.
64 NRFX_CLOCK_EVT_XO_TUNE_ERROR, ///< XO is not tuned.
65 NRFX_CLOCK_EVT_XO_TUNE_FAILED, ///< XO tune operation failed.
66 #endif
67 } nrfx_clock_evt_type_t;
68
69 /**
70 * @brief Clock event handler.
71 *
72 * @param[in] event Event.
73 */
74 typedef void (*nrfx_clock_event_handler_t)(nrfx_clock_evt_type_t event);
75
76 /**
77 * @brief Function for initializing internal structures in the nrfx_clock module.
78 *
79 * After initialization, the module is in power off state (clocks are not started).
80 *
81 * @param[in] event_handler Event handler provided by the user.
82 * If not provided, driver works in blocking mode.
83 *
84 * @retval NRFX_SUCCESS The procedure is successful.
85 * @retval NRFX_ERROR_ALREADY The driver is already initialized.
86 */
87 nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler);
88
89 /** @brief Function for enabling interrupts in the clock module. */
90 void nrfx_clock_enable(void);
91
92 /** @brief Function for disabling interrupts in the clock module. */
93 void nrfx_clock_disable(void);
94
95 /** @brief Function for uninitializing the clock module. */
96 void nrfx_clock_uninit(void);
97
98 /**
99 * @brief Function for checking if the clock driver is initialized.
100 *
101 * @retval true Driver is already initialized.
102 * @retval false Driver is not initialized.
103 */
104 bool nrfx_clock_init_check(void);
105
106 /**
107 * @brief Function for starting the specified clock domain.
108 *
109 * @param[in] domain Clock domain.
110 */
111 void nrfx_clock_start(nrf_clock_domain_t domain);
112
113 /**
114 * @brief Function for stopping the specified clock domain.
115 *
116 * @param[in] domain Clock domain.
117 */
118 void nrfx_clock_stop(nrf_clock_domain_t domain);
119
120 /**
121 * @brief Function for checking the specified clock domain state.
122 *
123 * XTAL source is assumed for domains with multiple sources.
124 *
125 * @param[in] domain Clock domain.
126 * @param[out] p_clk_src Pointer to a clock source that is running. Set to NULL if not needed.
127 * Ignored for HFCLKAUDIO domain. Variable pointed by @p p_clk_src
128 * must be of either @ref nrf_clock_lfclk_t type for LFCLK
129 * or @ref nrf_clock_hfclk_t type for HFCLK and HFCLK192M.
130 *
131 * @retval true The clock domain is running.
132 * @retval false The clock domain is not running.
133 */
134 NRFX_STATIC_INLINE bool nrfx_clock_is_running(nrf_clock_domain_t domain, void * p_clk_src);
135
136 #if defined(CLOCK_FEATURE_HFCLK_DIVIDE_PRESENT) || NRF_CLOCK_HAS_HFCLK192M || \
137 defined(__NRFX_DOXYGEN__)
138 /**
139 * @brief Function for setting the specified clock domain divider.
140 *
141 * @param[in] domain Clock domain.
142 * @param[in] div New divider for the clock domain.
143 *
144 * @retval NRFX_SUCCESS Divider successfully set.
145 * @retval NRFX_ERROR_NOT_SUPPORTED Domain does not support setting the divider.
146 * @retval NRFX_ERROR_INVALID_PARAM Divider not supported by the specified domain.
147 */
148 nrfx_err_t nrfx_clock_divider_set(nrf_clock_domain_t domain,
149 nrf_clock_hfclk_div_t div);
150
151 /**
152 * @brief Function for getting the specified clock domain divider.
153 *
154 * @param[in] domain Clock domain.
155 *
156 * @return Current divider for the specified clock domain.
157 */
158
159 NRFX_STATIC_INLINE nrf_clock_hfclk_div_t nrfx_clock_divider_get(nrf_clock_domain_t domain);
160 #endif
161
162 /**
163 * @brief Function for starting the LFCLK.
164 *
165 * @note This function is deprecated. Use @ref nrfx_clock_start instead.
166 */
167 NRFX_STATIC_INLINE void nrfx_clock_lfclk_start(void);
168
169 /**
170 * @brief Function for stopping the LFCLK.
171 *
172 * @note This function is deprecated. Use @ref nrfx_clock_stop instead.
173 */
174 NRFX_STATIC_INLINE void nrfx_clock_lfclk_stop(void);
175
176 /**
177 * @brief Function for checking the LFCLK state.
178 *
179 * @note This function is deprecated. Use @ref nrfx_clock_is_running instead.
180 *
181 * @retval true The LFCLK is running.
182 * @retval false The LFCLK is not running.
183 */
184 NRFX_STATIC_INLINE bool nrfx_clock_lfclk_is_running(void);
185
186 /**
187 * @brief Function for starting the high-accuracy source HFCLK.
188 *
189 * @note This function is deprecated. Use @ref nrfx_clock_start instead.
190 */
191 NRFX_STATIC_INLINE void nrfx_clock_hfclk_start(void);
192
193 /**
194 * @brief Function for stopping the external high-accuracy source HFCLK.
195 *
196 * @note This function is deprecated. Use @ref nrfx_clock_stop instead.
197 */
198 NRFX_STATIC_INLINE void nrfx_clock_hfclk_stop(void);
199
200 /**
201 * @brief Function for checking the HFCLK state.
202 *
203 * @note This function is deprecated. Use @ref nrfx_clock_is_running instead.
204 *
205 * @retval true The HFCLK is running (XTAL source).
206 * @retval false The HFCLK is not running.
207 */
208 NRFX_STATIC_INLINE bool nrfx_clock_hfclk_is_running(void);
209
210
211 #if NRF_CLOCK_HAS_HFCLKAUDIO || defined(__NRFX_DOXYGEN__)
212 /**
213 * @brief Function for setting the HFCLKAUDIO configuration.
214 *
215 * The frequency of HFCLKAUDIO ranges from 10.666 MHz to 13.333 MHz in 40.7 Hz steps.
216 * To calculate @p freq_value corresponding to the chosen frequency, use the following equation:
217 * FREQ_VALUE = 2^16 * ((12 * f_out / 32M) - 4)
218 *
219 * @warning Chosen frequency must fit in 11.176 MHz - 11.402 MHz or 12.165 MHz - 12.411 MHz
220 * frequency bands.
221 *
222 * @param[in] freq_value New FREQ_VALUE for HFCLKAUDIO.
223 */
224 NRFX_STATIC_INLINE void nrfx_clock_hfclkaudio_config_set(uint16_t freq_value);
225
226 /**
227 * @brief Function for getting the HFCLKAUDIO configuration.
228 *
229 * The frequency of HFCLKAUDIO ranges from 10.666 MHz to 13.333 MHz in 40.7 Hz steps.
230 * To calculate frequency corresponding to the returned FREQ_VALUE, use the following equation:
231 * f_out = 32M * (4 + FREQ_VALUE * 2^(-16))/12
232 *
233 * @return Current value of FREQ_VALUE for HFCLKAUDIO.
234 */
235 NRFX_STATIC_INLINE uint16_t nrfx_clock_hfclkaudio_config_get(void);
236 #endif
237
238 #if (NRF_CLOCK_HAS_CALIBRATION && NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)) || \
239 defined(__NRFX_DOXYGEN__)
240 /**
241 * @brief Function for starting the calibration of internal LFCLK.
242 *
243 * This function starts the calibration process. The process cannot be aborted. LFCLK and HFCLK
244 * must be running before this function is called.
245 *
246 * @retval NRFX_SUCCESS The procedure is successful.
247 * @retval NRFX_ERROR_INVALID_STATE The low-frequency of high-frequency clock is off.
248 * @retval NRFX_ERROR_BUSY Clock is in the calibration phase.
249 */
250 nrfx_err_t nrfx_clock_calibration_start(void);
251
252 #if NRF_CLOCK_HAS_XO_TUNE
253
254 /**
255 * @brief Function for starting tune of crystal HFCLK.
256 *
257 * This function starts tuning process of the HFCLK.
258 *
259 * @retval NRFX_SUCCESS The procedure is successful.
260 * @retval NRFX_ERROR_INVALID_STATE The high-frequency XO clock is off or operation is in progress.
261 * @retval NRFX_ERROR_INTERNAL XO tune operation failed.
262 */
263 nrfx_err_t nrfx_clock_xo_tune_start(void);
264
265 /**
266 * @brief Function for aborting tune of crystal HFCLK.
267 *
268 * This function aborts tuning process.
269 *
270 * @retval NRFX_SUCCESS The procedure is successful.
271 * @retval NRFX_ERROR_INVALID_STATE The high-frequency XO clock is off or operation is not in progress.
272 */
273 nrfx_err_t nrfx_clock_xo_tune_abort(void);
274
275 /**
276 * @brief Function for checking if XO tune error occurred.
277 *
278 * @note Must be used only if @p event_handler was not provided during driver initialization.
279 *
280 * @retval true XO tune procedure failed.
281 * @retval false No error.
282 */
283 bool nrfx_clock_xo_tune_error_check(void);
284
285 #endif
286
287 /**
288 * @brief Function for checking if calibration is in progress.
289 *
290 * This function indicates that the system is in calibration phase.
291 *
292 * @retval NRFX_SUCCESS The procedure is successful.
293 * @retval NRFX_ERROR_BUSY Clock is in the calibration phase.
294 */
295 nrfx_err_t nrfx_clock_is_calibrating(void);
296
297 #if (NRF_CLOCK_HAS_CALIBRATION_TIMER && NRFX_CHECK(NRFX_CLOCK_CONFIG_CT_ENABLED)) || \
298 defined(__NRFX_DOXYGEN__)
299 /**
300 * @brief Function for starting calibration timer.
301 *
302 * @param[in] interval Time after which the CTTO event and interrupt will be generated (in 0.25 s units).
303 */
304 void nrfx_clock_calibration_timer_start(uint8_t interval);
305
306 /** @brief Function for stopping the calibration timer. */
307 void nrfx_clock_calibration_timer_stop(void);
308 #endif
309 #endif /* (NRF_CLOCK_HAS_CALIBRATION && NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)) || \
310 defined(__NRFX_DOXYGEN__) */
311
312 /**
313 * @brief Function for returning a requested task address for the clock driver module.
314 *
315 * @param[in] task One of the peripheral tasks.
316 *
317 * @return Task address.
318 */
319 NRFX_STATIC_INLINE uint32_t nrfx_clock_task_address_get(nrf_clock_task_t task);
320
321 /**
322 * @brief Function for returning a requested event address for the clock driver module.
323 *
324 * @param[in] event One of the peripheral events.
325 *
326 * @return Event address.
327 */
328 NRFX_STATIC_INLINE uint32_t nrfx_clock_event_address_get(nrf_clock_event_t event);
329
330 #ifndef NRFX_DECLARE_ONLY
331
332 #if defined(CLOCK_FEATURE_HFCLK_DIVIDE_PRESENT) || NRF_CLOCK_HAS_HFCLK192M
nrfx_clock_divider_get(nrf_clock_domain_t domain)333 NRFX_STATIC_INLINE nrf_clock_hfclk_div_t nrfx_clock_divider_get(nrf_clock_domain_t domain)
334 {
335 switch (domain)
336 {
337 #if defined(CLOCK_FEATURE_HFCLK_DIVIDE_PRESENT)
338 case NRF_CLOCK_DOMAIN_HFCLK:
339 return nrf_clock_hfclk_div_get(NRF_CLOCK);
340 #endif
341 #if NRF_CLOCK_HAS_HFCLK192M
342 case NRF_CLOCK_DOMAIN_HFCLK192M:
343 return nrf_clock_hfclk192m_div_get(NRF_CLOCK);
344 #endif
345 default:
346 NRFX_ASSERT(0);
347 return (nrf_clock_hfclk_div_t)0;
348 }
349 }
350 #endif // defined(CLOCK_FEATURE_HFCLK_DIVIDE_PRESENT) || NRF_CLOCK_HAS_HFCLK192M
351
nrfx_clock_lfclk_start(void)352 NRFX_STATIC_INLINE void nrfx_clock_lfclk_start(void)
353 {
354 nrfx_clock_start(NRF_CLOCK_DOMAIN_LFCLK);
355 }
356
nrfx_clock_lfclk_stop(void)357 NRFX_STATIC_INLINE void nrfx_clock_lfclk_stop(void)
358 {
359 nrfx_clock_stop(NRF_CLOCK_DOMAIN_LFCLK);
360 }
361
nrfx_clock_hfclk_start(void)362 NRFX_STATIC_INLINE void nrfx_clock_hfclk_start(void)
363 {
364 nrfx_clock_start(NRF_CLOCK_DOMAIN_HFCLK);
365 }
366
nrfx_clock_hfclk_stop(void)367 NRFX_STATIC_INLINE void nrfx_clock_hfclk_stop(void)
368 {
369 nrfx_clock_stop(NRF_CLOCK_DOMAIN_HFCLK);
370 }
371
nrfx_clock_task_address_get(nrf_clock_task_t task)372 NRFX_STATIC_INLINE uint32_t nrfx_clock_task_address_get(nrf_clock_task_t task)
373 {
374 return nrf_clock_task_address_get(NRF_CLOCK, task);
375 }
376
nrfx_clock_event_address_get(nrf_clock_event_t event)377 NRFX_STATIC_INLINE uint32_t nrfx_clock_event_address_get(nrf_clock_event_t event)
378 {
379 return nrf_clock_event_address_get(NRF_CLOCK, event);
380 }
381
nrfx_clock_is_running(nrf_clock_domain_t domain,void * p_clk_src)382 NRFX_STATIC_INLINE bool nrfx_clock_is_running(nrf_clock_domain_t domain, void * p_clk_src)
383 {
384 return nrf_clock_is_running(NRF_CLOCK, domain, p_clk_src);
385 }
386
nrfx_clock_hfclk_is_running(void)387 NRFX_STATIC_INLINE bool nrfx_clock_hfclk_is_running(void)
388 {
389 nrf_clock_hfclk_t clk_src;
390 bool ret = nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &clk_src);
391 return (ret && (clk_src == NRF_CLOCK_HFCLK_HIGH_ACCURACY));
392 }
393
nrfx_clock_lfclk_is_running(void)394 NRFX_STATIC_INLINE bool nrfx_clock_lfclk_is_running(void)
395 {
396 return nrfx_clock_is_running(NRF_CLOCK_DOMAIN_LFCLK, NULL);
397 }
398
399 #if NRF_CLOCK_HAS_HFCLKAUDIO
400
nrfx_clock_hfclkaudio_config_set(uint16_t freq_value)401 NRFX_STATIC_INLINE void nrfx_clock_hfclkaudio_config_set(uint16_t freq_value)
402 {
403 nrf_clock_hfclkaudio_config_set(NRF_CLOCK, freq_value);
404 }
405
nrfx_clock_hfclkaudio_config_get(void)406 NRFX_STATIC_INLINE uint16_t nrfx_clock_hfclkaudio_config_get(void)
407 {
408 return nrf_clock_hfclkaudio_config_get(NRF_CLOCK);
409 }
410
411 #endif
412
413 #endif // NRFX_DECLARE_ONLY
414
415 /** @} */
416
417
418 void nrfx_clock_irq_handler(void);
419
420
421 #ifdef __cplusplus
422 }
423 #endif
424
425 #endif // NRFX_CLOCK_H__
426