@@ -50,6 +50,23 @@ void board_init(void)
5050 /* Turn on the digital interface clock */
5151 PM -> APBAMASK .reg |= PM_APBAMASK_GCLK ;
5252
53+ #if defined(CRYSTALLESS )
54+
55+ /* ----------------------------------------------------------------------------------------------
56+ * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
57+ */
58+
59+ uint32_t calib = (* ((uint32_t * ) FUSES_OSC32K_CAL_ADDR ) & FUSES_OSC32K_CAL_Msk ) >> FUSES_OSC32K_CAL_Pos ;
60+
61+ SYSCTRL -> OSC32K .reg = SYSCTRL_OSC32K_CALIB (calib ) |
62+ SYSCTRL_OSC32K_STARTUP ( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
63+ SYSCTRL_OSC32K_EN32K |
64+ SYSCTRL_OSC32K_ENABLE ;
65+
66+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_OSC32KRDY ) == 0 ); // Wait for oscillator stabilization
67+
68+ #else
69+
5370 /* ----------------------------------------------------------------------------------------------
5471 * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
5572 */
@@ -62,6 +79,8 @@ void board_init(void)
6279 /* Wait for oscillator stabilization */
6380 }
6481
82+ #endif
83+
6584 /* Software reset the module to ensure it is re-initialized correctly */
6685 /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
6786 * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
@@ -85,7 +104,11 @@ void board_init(void)
85104
86105 /* Write Generic Clock Generator 1 configuration */
87106 GCLK -> GENCTRL .reg = GCLK_GENCTRL_ID ( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
107+ #if defined(CRYSTALLESS )
108+ GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
109+ #else
88110 GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
111+ #endif
89112// GCLK_GENCTRL_OE | // Output clock to a pin for tests
90113 GCLK_GENCTRL_GENEN ;
91114
@@ -129,6 +152,49 @@ void board_init(void)
129152 /* Wait for synchronization */
130153 }
131154
155+ #if defined(CRYSTALLESS )
156+
157+ #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
158+
159+ // Turn on DFLL
160+ uint32_t coarse = ( * ((uint32_t * )(NVMCTRL_OTP4 ) + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32 )) >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32 ) )
161+ & ((1 << 6 ) - 1 );
162+ if (coarse == 0x3f ) {
163+ coarse = 0x1f ;
164+ }
165+ // TODO(tannewt): Load this value from memory we've written previously. There
166+ // isn't a value from the Atmel factory.
167+ uint32_t fine = 0x1ff ;
168+
169+ SYSCTRL -> DFLLVAL .bit .COARSE = coarse ;
170+ SYSCTRL -> DFLLVAL .bit .FINE = fine ;
171+ /* Write full configuration to DFLL control register */
172+ SYSCTRL -> DFLLMUL .reg = SYSCTRL_DFLLMUL_CSTEP ( 0x1f / 4 ) | // Coarse step is 31, half of the max value
173+ SYSCTRL_DFLLMUL_FSTEP ( 10 ) |
174+ SYSCTRL_DFLLMUL_MUL ( (48000 ) ) ;
175+
176+ SYSCTRL -> DFLLCTRL .reg = 0 ;
177+
178+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
179+ {
180+ /* Wait for synchronization */
181+ }
182+
183+ SYSCTRL -> DFLLCTRL .reg = SYSCTRL_DFLLCTRL_MODE |
184+ SYSCTRL_DFLLCTRL_CCDIS |
185+ SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
186+ SYSCTRL_DFLLCTRL_BPLCKC ;
187+
188+ while ( (SYSCTRL -> PCLKSR .reg & SYSCTRL_PCLKSR_DFLLRDY ) == 0 )
189+ {
190+ /* Wait for synchronization */
191+ }
192+
193+ /* Enable the DFLL */
194+ SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_ENABLE ;
195+
196+ #else // has crystal
197+
132198 /* Write full configuration to DFLL control register */
133199 SYSCTRL -> DFLLCTRL .reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
134200 SYSCTRL_DFLLCTRL_WAITLOCK |
@@ -153,6 +219,8 @@ void board_init(void)
153219 /* Wait for synchronization */
154220 }
155221
222+ #endif
223+
156224 /* ----------------------------------------------------------------------------------------------
157225 * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
158226 */
0 commit comments