1 /*
2 * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <nrfx.h>
33
34 #if NRFX_CHECK(NRFX_CLOCK_ENABLED)
35
36 #include <nrfx_clock.h>
37 #include <nrf_erratas.h>
38
39 #define NRFX_LOG_MODULE CLOCK
40 #include <nrfx_log.h>
41
42 #if NRFX_CHECK(NRFX_POWER_ENABLED)
43 extern bool nrfx_power_irq_enabled;
44 #endif
45
46 #if defined(CLOCK_LFCLKSRC_SRC_RC) || defined(__NRFX_DOXYGEN__)
47 #define LF_SRC_RC CLOCK_LFCLKSRC_SRC_RC
48 #else
49 #define LF_SRC_RC CLOCK_LFCLKSRC_SRC_LFRC
50 #endif
51
52 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
53 #if (NRF_CLOCK_HAS_CALIBRATION == 0)
54 #error "Calibration is not available in the SoC that is used."
55 #endif
56 #if (NRFX_CLOCK_CONFIG_LF_SRC != LF_SRC_RC)
57 #error "Calibration can be performed only for the RC Oscillator."
58 #endif
59 #endif
60
61 #if !defined(USE_WORKAROUND_FOR_ANOMALY_132) && \
62 (defined(NRF52832_XXAA) || defined(NRF52832_XXAB))
63 // ANOMALY 132 - LFCLK needs to avoid frame from 66us to 138us after LFCLK stop. This solution
64 // applies delay of 138us before starting LFCLK.
65 #define USE_WORKAROUND_FOR_ANOMALY_132 1
66
67 // Convert time to cycles (nRF52832 is clocked with 64 MHz, use delay of 138 us).
68 #define ANOMALY_132_DELAY_CYCLES (64UL * 138)
69 #endif
70
71 #if !defined(USE_WORKAROUND_FOR_ANOMALY_192) && \
72 (defined(NRF52810_XXAA) || \
73 defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
74 defined(NRF52840_XXAA))
75 // Enable workaround for nRF52 anomaly 192 (LFRC oscillator frequency is wrong
76 // after calibration, exceeding 500 ppm).
77 #define USE_WORKAROUND_FOR_ANOMALY_192 1
78 #endif
79
80 #if !defined(USE_WORKAROUND_FOR_ANOMALY_201) && \
81 (defined(NRF52810_XXAA) || \
82 defined(NRF52832_XXAA) || defined(NRF52832_XXAB) || \
83 defined(NRF52840_XXAA))
84 // Enable workaround for nRF52 anomaly 201 (EVENTS_HFCLKSTARTED might be generated twice).
85 #define USE_WORKAROUND_FOR_ANOMALY_201 1
86 #endif
87
88 #if defined(CLOCK_LFCLKSRC_SRC_Xtal)
89 #define LF_SRC_LFXO CLOCK_LFCLKSRC_SRC_Xtal
90 #else
91 #define LF_SRC_LFXO CLOCK_LFCLKSRC_SRC_LFXO
92 #endif
93
94 #if defined(NRF_CLOCK_USE_EXTERNAL_LFCLK_SOURCES)
95 #define LF_SRC_XTAL_LOW (CLOCK_LFCLKSRC_SRC_Xtal | \
96 (CLOCK_LFCLKSRC_EXTERNAL_Enabled << CLOCK_LFCLKSRC_EXTERNAL_Pos))
97 #define LF_SRC_XTAL_FULL (CLOCK_LFCLKSRC_SRC_Xtal | \
98 (CLOCK_LFCLKSRC_BYPASS_Enabled << CLOCK_LFCLKSRC_BYPASS_Pos) | \
99 (CLOCK_LFCLKSRC_EXTERNAL_Enabled << CLOCK_LFCLKSRC_EXTERNAL_Pos))
100 #else
101 #define LF_SRC_XTAL_LOW LF_SRC_LFXO
102 #define LF_SRC_XTAL_FULL LF_SRC_LFXO
103 #endif
104
105 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LFXO_TWO_STAGE_ENABLED) && \
106 NRFX_CLOCK_CONFIG_LF_SRC != LF_SRC_LFXO && \
107 NRFX_CLOCK_CONFIG_LF_SRC != LF_SRC_XTAL_LOW && \
108 NRFX_CLOCK_CONFIG_LF_SRC != LF_SRC_XTAL_FULL
109 #error "Two-stage LFXO start procedure enabled but LFCLK source is not set to LFXO!"
110 #endif
111
112 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
113 typedef enum
114 {
115 CAL_STATE_IDLE,
116 CAL_STATE_CAL
117 } nrfx_clock_cal_state_t;
118 #endif
119
120 /**@brief CLOCK control block. */
121 typedef struct
122 {
123 nrfx_clock_event_handler_t event_handler;
124 bool module_initialized; /*< Indicate the state of module */
125 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
126 bool hfclk_started; /*< Anomaly 201 workaround. */
127 #endif
128
129 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
130 volatile nrfx_clock_cal_state_t cal_state;
131 #endif
132 } nrfx_clock_cb_t;
133
134 static nrfx_clock_cb_t m_clock_cb;
135
136 /**
137 * This variable is used to check whether common POWER_CLOCK common interrupt
138 * should be disabled or not if @ref nrfx_power tries to disable the interrupt.
139 */
140 #if NRFX_CHECK(NRFX_POWER_ENABLED)
141 bool nrfx_clock_irq_enabled;
142 #endif
143
144 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132)
145 /**
146 * @brief Function for applying delay of 138us before starting LFCLK.
147 */
nrfx_clock_anomaly_132(void)148 static void nrfx_clock_anomaly_132(void)
149 {
150 uint32_t cyccnt_inital;
151 uint32_t core_debug;
152 uint32_t dwt_ctrl;
153
154 // Preserve DEMCR register to do not influence into its configuration. Enable the trace and
155 // debug blocks. It is required to read and write data to DWT block.
156 core_debug = CoreDebug->DEMCR;
157 CoreDebug->DEMCR = core_debug | CoreDebug_DEMCR_TRCENA_Msk;
158
159 // Preserve CTRL register in DWT block to do not influence into its configuration. Make sure
160 // that cycle counter is enabled.
161 dwt_ctrl = DWT->CTRL;
162 DWT->CTRL = dwt_ctrl | DWT_CTRL_CYCCNTENA_Msk;
163
164 // Store start value of cycle counter.
165 cyccnt_inital = DWT->CYCCNT;
166
167 // Delay required time.
168 while ((DWT->CYCCNT - cyccnt_inital) < ANOMALY_132_DELAY_CYCLES)
169 {}
170
171 // Restore preserved registers.
172 DWT->CTRL = dwt_ctrl;
173 CoreDebug->DEMCR = core_debug;
174 }
175 #endif // NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132)
176
nrfx_clock_init(nrfx_clock_event_handler_t event_handler)177 nrfx_err_t nrfx_clock_init(nrfx_clock_event_handler_t event_handler)
178 {
179 NRFX_ASSERT(event_handler);
180
181 nrfx_err_t err_code = NRFX_SUCCESS;
182 if (m_clock_cb.module_initialized)
183 {
184 err_code = NRFX_ERROR_ALREADY_INITIALIZED;
185 }
186 else
187 {
188 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
189 m_clock_cb.cal_state = CAL_STATE_IDLE;
190 #endif
191 m_clock_cb.event_handler = event_handler;
192 m_clock_cb.module_initialized = true;
193 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
194 m_clock_cb.hfclk_started = false;
195 #endif
196 }
197
198 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
199 return err_code;
200 }
201
nrfx_clock_enable(void)202 void nrfx_clock_enable(void)
203 {
204 NRFX_ASSERT(m_clock_cb.module_initialized);
205 nrfx_power_clock_irq_init();
206 #if !NRFX_CHECK(NRFX_CLOCK_CONFIG_LFXO_TWO_STAGE_ENABLED)
207 nrf_clock_lf_src_set(NRF_CLOCK, (nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC);
208 #endif
209 #if NRF_CLOCK_HAS_HFCLKSRC
210 nrf_clock_hf_src_set(NRF_CLOCK, NRF_CLOCK_HFCLK_HIGH_ACCURACY);
211 #endif
212 #if NRF_CLOCK_HAS_HFCLK192M
213 nrf_clock_hfclk192m_src_set(NRF_CLOCK, (nrf_clock_hfclk_t)NRFX_CLOCK_CONFIG_HFCLK192M_SRC);
214 #endif
215 #if NRFX_CHECK(NRFX_POWER_ENABLED)
216 nrfx_clock_irq_enabled = true;
217 #endif
218
219 NRFX_LOG_INFO("Module enabled.");
220 }
221
nrfx_clock_disable(void)222 void nrfx_clock_disable(void)
223 {
224 NRFX_ASSERT(m_clock_cb.module_initialized);
225 #if NRFX_CHECK(NRFX_POWER_ENABLED)
226 NRFX_ASSERT(nrfx_clock_irq_enabled);
227 if (!nrfx_power_irq_enabled)
228 #endif
229 {
230 NRFX_IRQ_DISABLE(nrfx_get_irq_number(NRF_CLOCK));
231 }
232 nrf_clock_int_disable(NRF_CLOCK, CLOCK_INTENSET_HFCLKSTARTED_Msk |
233 CLOCK_INTENSET_LFCLKSTARTED_Msk |
234 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
235 CLOCK_INTENSET_DONE_Msk |
236 #if NRF_HAS_CALIBRATION_TIMER
237 CLOCK_INTENSET_CTTO_Msk |
238 #endif
239 #endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
240 0);
241 #if NRFX_CHECK(NRFX_POWER_ENABLED)
242 nrfx_clock_irq_enabled = false;
243 #endif
244 NRFX_LOG_INFO("Module disabled.");
245 }
246
nrfx_clock_uninit(void)247 void nrfx_clock_uninit(void)
248 {
249 NRFX_ASSERT(m_clock_cb.module_initialized);
250 nrfx_clock_stop(NRF_CLOCK_DOMAIN_LFCLK);
251 nrfx_clock_stop(NRF_CLOCK_DOMAIN_HFCLK);
252 #if NRF_CLOCK_HAS_HFCLK192M
253 nrfx_clock_stop(NRF_CLOCK_DOMAIN_HFCLK192M);
254 #endif
255 #if NRF_CLOCK_HAS_HFCLKAUDIO
256 nrfx_clock_stop(NRF_CLOCK_DOMAIN_HFCLKAUDIO);
257 #endif
258 m_clock_cb.module_initialized = false;
259 NRFX_LOG_INFO("Uninitialized.");
260 }
261
nrfx_clock_start(nrf_clock_domain_t domain)262 void nrfx_clock_start(nrf_clock_domain_t domain)
263 {
264 NRFX_ASSERT(m_clock_cb.module_initialized);
265 switch (domain)
266 {
267 case NRF_CLOCK_DOMAIN_LFCLK:
268 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LFXO_TWO_STAGE_ENABLED)
269 {
270 nrf_clock_lfclk_t lfclksrc;
271 if (nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_LFCLK, &lfclksrc) &&
272 lfclksrc == NRFX_CLOCK_CONFIG_LF_SRC)
273 {
274 // If the two-stage LFXO procedure has finished already
275 // use the configured LF clock source.
276 nrf_clock_lf_src_set(NRF_CLOCK, (nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC);
277 }
278 else
279 {
280 // If the two-stage LFXO procedure hasn't started yet
281 // or the RC stage is in progress,
282 // use the RC oscillator as LF clock source.
283 nrf_clock_lf_src_set(NRF_CLOCK, NRF_CLOCK_LFCLK_RC);
284 }
285 }
286 #endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LFXO_TWO_STAGE_ENABLED)
287 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_LFCLKSTARTED);
288 nrf_clock_int_enable(NRF_CLOCK, NRF_CLOCK_INT_LF_STARTED_MASK);
289 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_132)
290 nrfx_clock_anomaly_132();
291 #endif
292 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART);
293 break;
294 case NRF_CLOCK_DOMAIN_HFCLK:
295 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED);
296 nrf_clock_int_enable(NRF_CLOCK, NRF_CLOCK_INT_HF_STARTED_MASK);
297 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART);
298 break;
299 #if NRF_CLOCK_HAS_HFCLK192M
300 case NRF_CLOCK_DOMAIN_HFCLK192M:
301 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLK192MSTARTED);
302 nrf_clock_int_enable(NRF_CLOCK, NRF_CLOCK_INT_HF192M_STARTED_MASK);
303 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLK192MSTART);
304 break;
305 #endif
306 #if NRF_CLOCK_HAS_HFCLKAUDIO
307 case NRF_CLOCK_DOMAIN_HFCLKAUDIO:
308 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKAUDIOSTARTED);
309 nrf_clock_int_enable(NRF_CLOCK, NRF_CLOCK_INT_HFAUDIO_STARTED_MASK);
310 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKAUDIOSTART);
311 break;
312 #endif
313 default:
314 NRFX_ASSERT(0);
315 break;
316 }
317 }
318
nrfx_clock_stop(nrf_clock_domain_t domain)319 void nrfx_clock_stop(nrf_clock_domain_t domain)
320 {
321 NRFX_ASSERT(m_clock_cb.module_initialized);
322 switch (domain)
323 {
324 case NRF_CLOCK_DOMAIN_LFCLK:
325 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_LF_STARTED_MASK);
326 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_LFCLKSTARTED);
327 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTOP);
328 break;
329 case NRF_CLOCK_DOMAIN_HFCLK:
330 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_HF_STARTED_MASK);
331 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED);
332 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP);
333 break;
334 #if NRF_CLOCK_HAS_HFCLK192M
335 case NRF_CLOCK_DOMAIN_HFCLK192M:
336 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_HF192M_STARTED_MASK);
337 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLK192MSTARTED);
338 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLK192MSTOP);
339 break;
340 #endif
341 #if NRF_CLOCK_HAS_HFCLKAUDIO
342 case NRF_CLOCK_DOMAIN_HFCLKAUDIO:
343 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_HFAUDIO_STARTED_MASK);
344 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKAUDIOSTARTED);
345 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKAUDIOSTOP);
346 break;
347 #endif
348 default:
349 NRFX_ASSERT(0);
350 return;
351 }
352
353 bool stopped;
354 if (domain == NRF_CLOCK_DOMAIN_HFCLK)
355 {
356 nrf_clock_hfclk_t clk_src = NRF_CLOCK_HFCLK_HIGH_ACCURACY;
357 NRFX_WAIT_FOR((!nrfx_clock_is_running(domain, &clk_src) ||
358 (clk_src != NRF_CLOCK_HFCLK_HIGH_ACCURACY)), 10000, 1, stopped);
359 }
360 else
361 {
362 NRFX_WAIT_FOR(!nrfx_clock_is_running(domain, NULL), 10000, 1, stopped);
363 }
364
365 if (!stopped)
366 {
367 NRFX_LOG_ERROR("Failed to stop clock domain: %d.", domain);
368 }
369
370 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
371 if (domain == NRF_CLOCK_DOMAIN_HFCLK)
372 {
373 m_clock_cb.hfclk_started = false;
374 }
375 #endif
376 }
377
nrfx_clock_calibration_start(void)378 nrfx_err_t nrfx_clock_calibration_start(void)
379 {
380 nrfx_err_t err_code = NRFX_SUCCESS;
381
382 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
383 nrf_clock_hfclk_t clk_src;
384 if (!nrfx_clock_is_running(NRF_CLOCK_DOMAIN_HFCLK, &clk_src))
385 {
386 return NRFX_ERROR_INVALID_STATE;
387 }
388
389 if (clk_src != NRF_CLOCK_HFCLK_HIGH_ACCURACY)
390 {
391 return NRFX_ERROR_INVALID_STATE;
392 }
393
394 if (!nrfx_clock_is_running(NRF_CLOCK_DOMAIN_LFCLK, NULL))
395 {
396 return NRFX_ERROR_INVALID_STATE;
397 }
398
399 if (m_clock_cb.cal_state == CAL_STATE_IDLE)
400 {
401 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_DONE);
402 nrf_clock_int_enable(NRF_CLOCK, NRF_CLOCK_INT_DONE_MASK);
403 m_clock_cb.cal_state = CAL_STATE_CAL;
404 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_192)
405 *(volatile uint32_t *)0x40000C34 = 0x00000002;
406 #endif
407 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_CAL);
408 }
409 else
410 {
411 err_code = NRFX_ERROR_BUSY;
412 }
413 #endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
414
415 NRFX_LOG_WARNING("Function: %s, error code: %s.",
416 __func__,
417 NRFX_LOG_ERROR_STRING_GET(err_code));
418 return err_code;
419 }
420
nrfx_clock_is_calibrating(void)421 nrfx_err_t nrfx_clock_is_calibrating(void)
422 {
423 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
424 if (m_clock_cb.cal_state == CAL_STATE_CAL)
425 {
426 return NRFX_ERROR_BUSY;
427 }
428 #endif
429 return NRFX_SUCCESS;
430 }
431
nrfx_clock_calibration_timer_start(uint8_t interval)432 void nrfx_clock_calibration_timer_start(uint8_t interval)
433 {
434 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) && NRF_CLOCK_HAS_CALIBRATION_TIMER
435 nrf_clock_cal_timer_timeout_set(NRF_CLOCK, interval);
436 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_CTTO);
437 nrf_clock_int_enable(NRF_CLOCK, NRF_CLOCK_INT_CTTO_MASK);
438 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_CTSTART);
439 #endif
440 }
441
nrfx_clock_calibration_timer_stop(void)442 void nrfx_clock_calibration_timer_stop(void)
443 {
444 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED) && NRF_CLOCK_HAS_CALIBRATION_TIMER
445 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_CTTO_MASK);
446 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_CTSTOP);
447 #endif
448 }
449
450 #if NRF_CLOCK_HAS_HFCLK_DIV || NRF_CLOCK_HAS_HFCLK192M
nrfx_clock_divider_set(nrf_clock_domain_t domain,nrf_clock_hfclk_div_t div)451 nrfx_err_t nrfx_clock_divider_set(nrf_clock_domain_t domain,
452 nrf_clock_hfclk_div_t div)
453 {
454 switch(domain)
455 {
456 #if NRF_CLOCK_HAS_HFCLK_DIV
457 case NRF_CLOCK_DOMAIN_HFCLK:
458 switch (div)
459 {
460 case NRF_CLOCK_HFCLK_DIV_2:
461 NRFX_CRITICAL_SECTION_ENTER();
462 if (nrf53_errata_4())
463 {
464 __DSB();
465 }
466 nrf_clock_hfclk_div_set(NRF_CLOCK, div);
467 if (nrf53_errata_4())
468 {
469 *(volatile uint32_t *)0x5084450C = 0x0;
470 *(volatile uint32_t *)0x50026548 = 0x0;
471 *(volatile uint32_t *)0x50081EE4 = 0x0D;
472 }
473 NRFX_CRITICAL_SECTION_EXIT();
474 break;
475 case NRF_CLOCK_HFCLK_DIV_1:
476 NRFX_CRITICAL_SECTION_ENTER();
477 if (nrf53_errata_4())
478 {
479 __DSB();
480 *(volatile uint32_t *)0x5084450C = 0x4040;
481 *(volatile uint32_t *)0x50026548 = 0x40;
482 *(volatile uint32_t *)0x50081EE4 = 0x4D;
483 }
484 nrf_clock_hfclk_div_set(NRF_CLOCK, div);
485 NRFX_CRITICAL_SECTION_EXIT();
486 break;
487 default:
488 return NRFX_ERROR_INVALID_PARAM;
489 }
490 SystemCoreClockUpdate();
491 return NRFX_SUCCESS;
492 #endif
493 #if NRF_CLOCK_HAS_HFCLK192M
494 case NRF_CLOCK_DOMAIN_HFCLK192M:
495 if (div > NRF_CLOCK_HFCLK_DIV_4)
496 {
497 return NRFX_ERROR_INVALID_PARAM;
498 }
499 else
500 {
501 nrf_clock_hfclk192m_div_set(NRF_CLOCK, div);
502 }
503 return NRFX_SUCCESS;
504 #endif
505 default:
506 NRFX_ASSERT(0);
507 return NRFX_ERROR_NOT_SUPPORTED;
508 }
509 }
510 #endif
511
nrfx_clock_irq_handler(void)512 void nrfx_clock_irq_handler(void)
513 {
514 if (nrf_clock_event_check(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED))
515 {
516 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKSTARTED);
517 NRFX_LOG_DEBUG("Event: NRF_CLOCK_EVENT_HFCLKSTARTED");
518 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_HF_STARTED_MASK);
519
520 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_201)
521 if (!m_clock_cb.hfclk_started)
522 {
523 m_clock_cb.hfclk_started = true;
524 m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
525 }
526 #else
527 m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK_STARTED);
528 #endif
529 }
530 if (nrf_clock_event_check(NRF_CLOCK, NRF_CLOCK_EVENT_LFCLKSTARTED))
531 {
532 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_LFCLKSTARTED);
533 NRFX_LOG_DEBUG("Event: NRF_CLOCK_EVENT_LFCLKSTARTED");
534
535 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LFXO_TWO_STAGE_ENABLED)
536 nrf_clock_lfclk_t lfclksrc;
537 (void)nrf_clock_is_running(NRF_CLOCK, NRF_CLOCK_DOMAIN_LFCLK, &lfclksrc);
538 if (lfclksrc == NRF_CLOCK_LFCLK_RC)
539 {
540 // After the LFRC oscillator start switch to external source.
541 nrf_clock_lf_src_set(NRF_CLOCK, (nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC);
542 nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_LFCLKSTART);
543 }
544 else
545 #endif
546 {
547 // After the LF clock external source start invoke user callback.
548 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_LF_STARTED_MASK);
549 m_clock_cb.event_handler(NRFX_CLOCK_EVT_LFCLK_STARTED);
550 }
551 }
552
553 #if NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
554 #if NRF_CLOCK_HAS_CALIBRATION_TIMER
555 if (nrf_clock_event_check(NRF_CLOCK, NRF_CLOCK_EVENT_CTTO))
556 {
557 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_CTTO);
558 NRFX_LOG_DEBUG("Event: NRF_CLOCK_EVENT_CTTO");
559 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_CTTO_MASK);
560
561 m_clock_cb.event_handler(NRFX_CLOCK_EVT_CTTO);
562 }
563 #endif // NRF_CLOCK_HAS_CALIBRATION_TIMER
564
565 if (nrf_clock_event_check(NRF_CLOCK, NRF_CLOCK_EVENT_DONE))
566 {
567 #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_192)
568 *(volatile uint32_t *)0x40000C34 = 0x00000000;
569 #endif
570 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_DONE);
571 NRFX_LOG_DEBUG("Event: NRF_CLOCK_EVENT_DONE");
572 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_DONE_MASK);
573 m_clock_cb.cal_state = CAL_STATE_IDLE;
574 m_clock_cb.event_handler(NRFX_CLOCK_EVT_CAL_DONE);
575 }
576 #endif // NRFX_CHECK(NRFX_CLOCK_CONFIG_LF_CAL_ENABLED)
577
578 #if NRF_CLOCK_HAS_HFCLKAUDIO
579 if (nrf_clock_event_check(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKAUDIOSTARTED))
580 {
581 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLKAUDIOSTARTED);
582 NRFX_LOG_DEBUG("Event: NRF_CLOCK_EVENT_HFCLKAUDIOSTARTED");
583 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_HFAUDIO_STARTED_MASK);
584
585 m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLKAUDIO_STARTED);
586 }
587 #endif
588
589 #if NRF_CLOCK_HAS_HFCLK192M
590 if (nrf_clock_event_check(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLK192MSTARTED))
591 {
592 nrf_clock_event_clear(NRF_CLOCK, NRF_CLOCK_EVENT_HFCLK192MSTARTED);
593 NRFX_LOG_DEBUG("Event: NRF_CLOCK_EVENT_HFCLK192MSTARTED");
594 nrf_clock_int_disable(NRF_CLOCK, NRF_CLOCK_INT_HF192M_STARTED_MASK);
595
596 m_clock_cb.event_handler(NRFX_CLOCK_EVT_HFCLK192M_STARTED);
597 }
598 #endif
599 }
600
601 #endif // NRFX_CHECK(NRFX_CLOCK_ENABLED)
602