@@ -57,6 +57,11 @@ static frequencyio_frequencyin_obj_t *active_frequencyins[TC_INST_NUM];
57
57
volatile uint8_t reference_tc ;
58
58
#ifdef SAM_D5X_E5X
59
59
static uint8_t dpll_gclk ;
60
+
61
+ #if !BOARD_HAS_CRYSTAL
62
+ static uint8_t osculp32k_gclk ;
63
+ #endif
64
+
60
65
#endif
61
66
62
67
void frequencyin_reset (void ) {
@@ -67,6 +72,11 @@ void frequencyin_reset(void) {
67
72
reference_tc = 0xff ;
68
73
#ifdef SAM_D5X_E5X
69
74
dpll_gclk = 0xff ;
75
+
76
+ #if !BOARD_HAS_CRYSTAL
77
+ osculp32k_gclk = 0xff ;
78
+ #endif
79
+
70
80
#endif
71
81
}
72
82
@@ -208,34 +218,38 @@ static bool frequencyin_samd51_start_dpll(void) {
208
218
return true;
209
219
}
210
220
211
- uint8_t free_gclk = find_free_gclk (1 );
212
- if (free_gclk == 0xff ) {
213
- dpll_gclk = 0xff ;
221
+ dpll_gclk = find_free_gclk (1 );
222
+ if (dpll_gclk == 0xff ) {
214
223
return false;
215
224
}
216
225
217
- GCLK -> PCHCTRL [OSCCTRL_GCLK_ID_FDPLL1 ].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN (free_gclk );
218
226
// TC4-7 can only have a max of 100MHz source
219
227
// DPLL1 frequency equation with [X]OSC32K as source: 98.304MHz = 32768(2999 + 1 + 0/32)
220
228
// Will also enable the Lock Bypass due to low-frequency sources causing DPLL unlocks
221
229
// as outlined in the Errata (1.12.1)
222
230
OSCCTRL -> Dpll [1 ].DPLLRATIO .reg = OSCCTRL_DPLLRATIO_LDRFRAC (0 ) | OSCCTRL_DPLLRATIO_LDR (2999 );
231
+
223
232
#if BOARD_HAS_CRYSTAL
224
- // we can use XOSC32K directly as the source
225
- OSC32KCTRL -> XOSC32K . bit . EN32K = 1 ;
226
- OSCCTRL -> Dpll [ 1 ]. DPLLCTRLB . reg = OSCCTRL_DPLLCTRLB_REFCLK (1 ) | OSCCTRL_DPLLCTRLB_LBYPASS ;
233
+ // we can use XOSC32K directly as the source. It has already been initialized in clocks.c
234
+ OSCCTRL -> Dpll [ 1 ]. DPLLCTRLB . reg =
235
+ OSCCTRL_DPLLCTRLB_REFCLK (OSCCTRL_DPLLCTRLB_REFCLK_XOSC32_Val ) | OSCCTRL_DPLLCTRLB_LBYPASS ;
227
236
#else
228
- // can't use OSCULP32K directly; need to setup a GCLK as a reference,
229
- // which must be done in samd/clocks.c to avoid waiting for sync
230
- return ;
231
- //OSC32KCTRL->OSCULP32K.bit.EN32K = 1;
232
- //OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0);
237
+ // We can't use OSCULP32K directly. Set up a GCLK controlled by it
238
+ // Then use that GCLK as the reference oscillator for the DPLL.
239
+ osculp32k_gclk = find_free_gclk (1 );
240
+ if (osculp32k_gclk == 0xff ) {
241
+ return false;
242
+ }
243
+ enable_clock_generator (osculp32k_gclk , GCLK_GENCTRL_SRC_OSCULP32K_Val , 1 );
244
+ GCLK -> PCHCTRL [OSCCTRL_GCLK_ID_FDPLL1 ].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN (OSCCTRL_GCLK_ID_FDPLL1 );
245
+ OSCCTRL -> Dpll [1 ].DPLLCTRLB .reg =
246
+ OSCCTRL_DPLLCTRLB_REFCLK (OSCCTRL_DPLLCTRLB_REFCLK_GCLK_Val ) | OSCCTRL_DPLLCTRLB_LBYPASS ;
233
247
#endif
234
- OSCCTRL -> Dpll [1 ].DPLLCTRLA .reg = OSCCTRL_DPLLCTRLA_ENABLE ;
235
248
249
+ OSCCTRL -> Dpll [1 ].DPLLCTRLA .reg = OSCCTRL_DPLLCTRLA_ENABLE ;
236
250
while (!(OSCCTRL -> Dpll [1 ].DPLLSTATUS .bit .LOCK || OSCCTRL -> Dpll [1 ].DPLLSTATUS .bit .CLKRDY )) {}
237
- enable_clock_generator ( free_gclk , GCLK_GENCTRL_SRC_DPLL1_Val , 1 );
238
- dpll_gclk = free_gclk ;
251
+
252
+ enable_clock_generator ( dpll_gclk , GCLK_GENCTRL_SRC_DPLL1_Val , 1 ) ;
239
253
return true;
240
254
}
241
255
@@ -249,6 +263,11 @@ static void frequencyin_samd51_stop_dpll(void) {
249
263
dpll_gclk = 0xff ;
250
264
}
251
265
266
+ if (osculp32k_gclk != 0xff ) {
267
+ disable_clock_generator (osculp32k_gclk );
268
+ osculp32k_gclk = 0xff ;
269
+ }
270
+
252
271
GCLK -> PCHCTRL [OSCCTRL_GCLK_ID_FDPLL1 ].reg = 0 ;
253
272
OSCCTRL -> Dpll [1 ].DPLLCTRLA .reg = 0 ;
254
273
OSCCTRL -> Dpll [1 ].DPLLRATIO .reg = 0 ;
0 commit comments