3333#include "modrp2.h"
3434#include "hardware/flash.h"
3535#include "pico/binary_info.h"
36+ #ifdef PICO_RP2350
37+ #include "hardware/structs/ioqspi.h"
38+ #include "hardware/structs/qmi.h"
39+ #else
40+ #include "hardware/structs/ssi.h"
41+ #endif
3642
3743#define BLOCK_SIZE_BYTES (FLASH_SECTOR_SIZE)
3844
@@ -81,6 +87,48 @@ static bool use_multicore_lockout(void) {
8187 ;
8288}
8389
90+ // Function to set the flash divisor to the correct divisor, assumes interrupts disabled
91+ // and core1 locked out if relevant.
92+ static void __no_inline_not_in_flash_func (rp2_flash_set_timing_internal )(int clock_hz ) {
93+
94+ // Use the minimum divisor assuming a 133MHz flash.
95+ const int max_flash_freq = 133000000 ;
96+ int divisor = (clock_hz + max_flash_freq - 1 ) / max_flash_freq ;
97+
98+ #if PICO_RP2350
99+ // Make sure flash is deselected - QMI doesn't appear to have a busy flag(!)
100+ while ((ioqspi_hw -> io [1 ].status & IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS ) != IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS ) {
101+ ;
102+ }
103+
104+ // RX delay equal to the divisor means sampling at the same time as the next falling edge of SCK after the
105+ // falling edge that generated the data. This is pretty tight at 133MHz but seems to work with the Winbond flash chips.
106+ const int rxdelay = divisor ;
107+ qmi_hw -> m [0 ].timing = (1 << QMI_M0_TIMING_COOLDOWN_LSB ) |
108+ rxdelay << QMI_M1_TIMING_RXDELAY_LSB |
109+ divisor << QMI_M1_TIMING_CLKDIV_LSB ;
110+
111+ // Force a read through XIP to ensure the timing is applied
112+ volatile uint32_t * ptr = (volatile uint32_t * )0x14000000 ;
113+ (void )* ptr ;
114+ #else
115+ // RP2040 SSI hardware only supports even divisors
116+ if (divisor & 1 ) {
117+ divisor += 1 ;
118+ }
119+
120+ // Wait for SSI not busy
121+ while (ssi_hw -> sr & SSI_SR_BUSY_BITS ) {
122+ ;
123+ }
124+
125+ // Disable, set the new divisor, and re-enable
126+ hw_clear_bits (& ssi_hw -> ssienr , SSI_SSIENR_SSI_EN_BITS );
127+ ssi_hw -> baudr = divisor ;
128+ hw_set_bits (& ssi_hw -> ssienr , SSI_SSIENR_SSI_EN_BITS );
129+ #endif
130+ }
131+
84132// Flash erase and write must run with interrupts disabled and the other core suspended,
85133// because the XIP bit gets disabled.
86134static uint32_t begin_critical_flash_section (void ) {
@@ -104,6 +152,7 @@ static void end_critical_flash_section(uint32_t state) {
104152 #if defined(MICROPY_HW_PSRAM_CS_PIN ) && MICROPY_HW_ENABLE_PSRAM
105153 psram_init (MICROPY_HW_PSRAM_CS_PIN );
106154 #endif
155+ rp2_flash_set_timing_internal (clock_get_hz (clk_sys ));
107156 restore_interrupts (state );
108157 if (use_multicore_lockout ()) {
109158 multicore_lockout_end_blocking ();
@@ -260,3 +309,23 @@ MP_DEFINE_CONST_OBJ_TYPE(
260309 make_new , rp2_flash_make_new ,
261310 locals_dict , & rp2_flash_locals_dict
262311 );
312+
313+ // Modify the flash timing. Ensure flash access is suspended while
314+ // the timings are altered.
315+ void rp2_flash_set_timing_for_freq (int clock_hz ) {
316+ if (multicore_lockout_victim_is_initialized (1 - get_core_num ())) {
317+ multicore_lockout_start_blocking ();
318+ }
319+ uint32_t state = save_and_disable_interrupts ();
320+
321+ rp2_flash_set_timing_internal (clock_hz );
322+
323+ restore_interrupts (state );
324+ if (multicore_lockout_victim_is_initialized (1 - get_core_num ())) {
325+ multicore_lockout_end_blocking ();
326+ }
327+ }
328+
329+ void rp2_flash_set_timing () {
330+ rp2_flash_set_timing_for_freq (clock_get_hz (clk_sys ));
331+ }
0 commit comments