1616
1717#include "pico/binary_info.h"
1818
19+ #include "hardware/clocks.h"
20+ #include "hardware/xosc.h"
21+ #include "hardware/structs/rosc.h"
22+
1923#include "config.h"
2024
2125extern uint32_t rstate_sha [4 ];
@@ -145,6 +149,125 @@ void init_rstate() {
145149 // No need to wait for SHA, as we polled the EHR one extra time, which
146150 // takes longer than the SHA.
147151 for (i = 0 ;i < 4 ;i ++ ) rstate_sha [i ]= sha256 -> sum [i ];
152+
153+ rosc_hw -> random = rstate_sha [0 ];
154+ }
155+
156+ // These just have to be higher than the actual frequency, to prevent overclocking unused peripherals
157+ #define ROSC_HZ 300*MHZ
158+ #define OTHER_CLK_DIV 30
159+
160+ void runtime_init_clocks (void ) {
161+ // Disable resus that may be enabled from previous software
162+ clocks_hw -> resus .ctrl = 0 ;
163+
164+ bi_decl (bi_ptr_int32 (0 , 0 , rosc_div , 2 )); // default divider 2
165+ bi_decl (bi_ptr_int32 (0 , 0 , rosc_drive , 0x0000 )); // default drives of 0
166+ bi_decl (bi_ptr_int32 (0 , 0 , xosc_mhz , 12 )); // xosc freq in MHz
167+ bi_decl (bi_ptr_int32 (0 , 0 , clk_mhz , 150 )); // xosc freq in MHz
168+
169+ // Bump up ROSC speed to ~90MHz
170+ rosc_hw -> freqa = 0 ; // reset the drive strengths
171+ rosc_hw -> div = rosc_div | ROSC_DIV_VALUE_PASS ; // set divider
172+ // Increment the freqency range one step at a time - this is safe provided the current config is not TOOHIGH
173+ // because ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM | ROSC_CTRL_FREQ_RANGE_VALUE_HIGH == ROSC_CTRL_FREQ_RANGE_VALUE_HIGH
174+ static_assert (ROSC_CTRL_FREQ_RANGE_VALUE_LOW | ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM == ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM );
175+ static_assert (ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM | ROSC_CTRL_FREQ_RANGE_VALUE_HIGH == ROSC_CTRL_FREQ_RANGE_VALUE_HIGH );
176+ hw_set_bits (& rosc_hw -> ctrl , ROSC_CTRL_FREQ_RANGE_VALUE_MEDIUM );
177+ hw_set_bits (& rosc_hw -> ctrl , ROSC_CTRL_FREQ_RANGE_VALUE_HIGH );
178+
179+ // Enable rosc randomisation
180+ rosc_hw -> freqa = (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB ) |
181+ rosc_drive | ROSC_FREQA_DS1_RANDOM_BITS | ROSC_FREQA_DS0_RANDOM_BITS ; // enable randomisation
182+
183+ // Not used with FREQ_RANGE_VALUE_HIGH, but should still be set
184+ rosc_hw -> freqb = (ROSC_FREQB_PASSWD_VALUE_PASS << ROSC_FREQB_PASSWD_LSB ) |
185+ rosc_drive ;
186+
187+ // Calibrate ROSC frequency if XOSC present - otherwise just configure
188+ uint32_t rosc_freq_mhz = 0 ;
189+ if (xosc_mhz ) {
190+ xosc_init ();
191+ // CLK_REF = XOSC
192+ clock_configure_int_divider (clk_ref ,
193+ CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC ,
194+ 0 ,
195+ xosc_mhz * MHZ ,
196+ 1 );
197+ // CLK_SYS = CLK_REF
198+ clock_configure_int_divider (clk_sys ,
199+ CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF ,
200+ CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC , // leave the aux source on ROSC
201+ xosc_mhz * MHZ ,
202+ 1 );
203+
204+ // Max out rosc
205+ rosc_hw -> div = 1 | ROSC_DIV_VALUE_PASS ;
206+ rosc_hw -> freqa = (ROSC_FREQA_PASSWD_VALUE_PASS << ROSC_FREQA_PASSWD_LSB ) |
207+ ROSC_FREQA_DS3_BITS | ROSC_FREQA_DS2_BITS |
208+ ROSC_FREQA_DS1_RANDOM_BITS | ROSC_FREQA_DS0_RANDOM_BITS ; // enable randomisation
209+ rosc_hw -> freqb = (ROSC_FREQB_PASSWD_VALUE_PASS << ROSC_FREQB_PASSWD_LSB ) |
210+ ROSC_FREQB_DS7_LSB | ROSC_FREQB_DS6_LSB | ROSC_FREQB_DS5_LSB | ROSC_FREQB_DS4_LSB ;
211+
212+ // Wait for ROSC to be stable
213+ while (!(rosc_hw -> status & ROSC_STATUS_STABLE_BITS )) {
214+ tight_loop_contents ();
215+ }
216+
217+ rosc_freq_mhz = frequency_count_khz (CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC_PH ) / KHZ ;
218+ }
219+ if (rosc_freq_mhz > clk_mhz ) {
220+ // CLK SYS = ROSC divided down to clk_mhz, according to XOSC calibration
221+ clock_configure_mhz (clk_sys ,
222+ CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX ,
223+ CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC ,
224+ rosc_freq_mhz ,
225+ clk_mhz );
226+ } else { // Either ROSC is running too slowly, or there was no XOSC to calibrate it against
227+ // CLK SYS = ROSC directly, as it's running slowly enough
228+ clock_configure_int_divider (clk_sys ,
229+ CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX ,
230+ CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC ,
231+ ROSC_HZ , // this doesn't have to be accurate
232+ 1 );
233+ }
234+
235+ // Configure other clocks - none of these need to be accurate
236+
237+ // CLK_REF = ROSC / OTHER_CLK_DIV - this and other clocks aren't really used, so just need to be set to a low enough frequency
238+ clock_configure_int_divider (clk_ref ,
239+ CLOCKS_CLK_REF_CTRL_SRC_VALUE_ROSC_CLKSRC_PH ,
240+ 0 ,
241+ ROSC_HZ ,
242+ OTHER_CLK_DIV );
243+
244+ // CLK USB (not used)
245+ clock_configure_int_divider (clk_usb ,
246+ 0 , // No GLMUX
247+ CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH ,
248+ ROSC_HZ ,
249+ OTHER_CLK_DIV );
250+
251+ // CLK ADC (not used)
252+ clock_configure_int_divider (clk_adc ,
253+ 0 , // No GLMUX
254+ CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_ROSC_CLKSRC_PH ,
255+ ROSC_HZ ,
256+ OTHER_CLK_DIV );
257+
258+ // CLK PERI Used as reference clock for UART and SPI serial. (not used)
259+ clock_configure_int_divider (clk_peri ,
260+ 0 ,
261+ CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS ,
262+ ROSC_HZ ,
263+ OTHER_CLK_DIV );
264+
265+ // CLK_HSTX Transmit bit clock for the HSTX peripheral. (not used)
266+ clock_configure_int_divider (clk_hstx ,
267+ 0 ,
268+ CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLK_SYS ,
269+ ROSC_HZ ,
270+ OTHER_CLK_DIV );
148271}
149272
150273
@@ -158,14 +281,13 @@ int main() {
158281 otp_hw -> crt_key_w [i ] = key_i ;
159282 }
160283
161- bi_decl (bi_program_feature_group (0x1111 , 0x2222 , "encryption_config" ));
162- bi_decl (bi_ptr_int32 (0x1111 , 0x2222 , data_start_addr , 0x20000000 ));
163- bi_decl (bi_ptr_int32 (0x1111 , 0x2222 , data_size , 0x78000 ));
164- bi_decl (bi_ptr_int32 (0x1111 , 0x2222 , iv0 , 0 ));
165- bi_decl (bi_ptr_int32 (0x1111 , 0x2222 , iv1 , 1 ));
166- bi_decl (bi_ptr_int32 (0x1111 , 0x2222 , iv2 , 2 ));
167- bi_decl (bi_ptr_int32 (0x1111 , 0x2222 , iv3 , 3 ));
168- bi_decl (bi_ptr_int32 (0x1111 , 0x2222 , otp_key_page , 30 ));
284+ bi_decl (bi_ptr_int32 (0 , 0 , data_start_addr , 0x20000000 ));
285+ bi_decl (bi_ptr_int32 (0 , 0 , data_size , 0x78000 ));
286+ bi_decl (bi_ptr_int32 (0 , 0 , iv0 , 0 ));
287+ bi_decl (bi_ptr_int32 (0 , 0 , iv1 , 1 ));
288+ bi_decl (bi_ptr_int32 (0 , 0 , iv2 , 2 ));
289+ bi_decl (bi_ptr_int32 (0 , 0 , iv3 , 3 ));
290+ bi_decl (bi_ptr_int32 (0 , 0 , otp_key_page , 30 ));
169291
170292 // Initialise IV from binary info words
171293 uint8_t iv [16 ];
0 commit comments