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