1212#include "hardware/structs/ssi.h"
1313#else
1414#include "hardware/structs/qmi.h"
15+ #include "hardware/regs/otp_data.h"
1516#endif
1617#include "hardware/xip_cache.h"
1718
@@ -70,6 +71,43 @@ static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) {
7071
7172#endif
7273
74+ #if PICO_RP2350
75+ // This is specifically for saving/restoring the registers modified by RP2350
76+ // flash_exit_xip() ROM func, not the entirety of the QMI window state.
77+ typedef struct flash_rp2350_qmi_save_state {
78+ uint32_t timing ;
79+ uint32_t rcmd ;
80+ uint32_t rfmt ;
81+ } flash_rp2350_qmi_save_state_t ;
82+
83+ static void __no_inline_not_in_flash_func (flash_rp2350_save_qmi_cs1 )(flash_rp2350_qmi_save_state_t * state ) {
84+ state -> timing = qmi_hw -> m [1 ].timing ;
85+ state -> rcmd = qmi_hw -> m [1 ].rcmd ;
86+ state -> rfmt = qmi_hw -> m [1 ].rfmt ;
87+ }
88+
89+ static void __no_inline_not_in_flash_func (flash_rp2350_restore_qmi_cs1 )(const flash_rp2350_qmi_save_state_t * state ) {
90+ if (flash_devinfo_get_cs_size (1 ) == FLASH_DEVINFO_SIZE_NONE ) {
91+ // Case 1: The RP2350 ROM sets QMI to a clean (03h read) configuration
92+ // during flash_exit_xip(), even though when CS1 is not enabled via
93+ // FLASH_DEVINFO it does not issue an XIP exit sequence to CS1. In
94+ // this case, restore the original register config for CS1 as it is
95+ // still the correct config.
96+ qmi_hw -> m [1 ].timing = state -> timing ;
97+ qmi_hw -> m [1 ].rcmd = state -> rcmd ;
98+ qmi_hw -> m [1 ].rfmt = state -> rfmt ;
99+ } else {
100+ // Case 2: If RAM is attached to CS1, and the ROM has issued an XIP
101+ // exit sequence to it, then the ROM re-initialisation of the QMI
102+ // registers has actually not gone far enough. The old XIP write mode
103+ // is no longer valid when the QSPI RAM is returned to a serial
104+ // command state. Restore the default 02h serial write command config.
105+ qmi_hw -> m [1 ].wfmt = QMI_M1_WFMT_RESET ;
106+ qmi_hw -> m [1 ].wcmd = QMI_M1_WCMD_RESET ;
107+ }
108+ }
109+ #endif
110+
73111//-----------------------------------------------------------------------------
74112// Actual flash programming shims (work whether or not PICO_NO_FLASH==1)
75113
@@ -87,6 +125,10 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
87125 flash_init_boot2_copyout ();
88126 // Commit any pending writes to external RAM, to avoid losing them in the subsequent flush:
89127 xip_cache_clean_all ();
128+ #if PICO_RP2350
129+ flash_rp2350_qmi_save_state_t qmi_save ;
130+ flash_rp2350_save_qmi_cs1 (& qmi_save );
131+ #endif
90132
91133 // No flash accesses after this point
92134 __compiler_memory_barrier ();
@@ -96,6 +138,9 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
96138 flash_range_erase_func (flash_offs , count , FLASH_BLOCK_SIZE , FLASH_BLOCK_ERASE_CMD );
97139 flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
98140 flash_enable_xip_via_boot2 ();
141+ #if PICO_RP2350
142+ flash_rp2350_restore_qmi_cs1 (& qmi_save );
143+ #endif
99144}
100145
101146void __no_inline_not_in_flash_func (flash_flush_cache )(void ) {
@@ -116,6 +161,10 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
116161 assert (connect_internal_flash_func && flash_exit_xip_func && flash_range_program_func && flash_flush_cache_func );
117162 flash_init_boot2_copyout ();
118163 xip_cache_clean_all ();
164+ #if PICO_RP2350
165+ flash_rp2350_qmi_save_state_t qmi_save ;
166+ flash_rp2350_save_qmi_cs1 (& qmi_save );
167+ #endif
119168
120169 __compiler_memory_barrier ();
121170
@@ -124,6 +173,9 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
124173 flash_range_program_func (flash_offs , data , count );
125174 flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
126175 flash_enable_xip_via_boot2 ();
176+ #if PICO_RP2350
177+ flash_rp2350_restore_qmi_cs1 (& qmi_save );
178+ #endif
127179}
128180
129181//-----------------------------------------------------------------------------
@@ -157,6 +209,10 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
157209 assert (connect_internal_flash_func && flash_exit_xip_func && flash_flush_cache_func );
158210 flash_init_boot2_copyout ();
159211 xip_cache_clean_all ();
212+ #if PICO_RP2350
213+ flash_rp2350_qmi_save_state_t qmi_save ;
214+ flash_rp2350_save_qmi_cs1 (& qmi_save );
215+ #endif
160216
161217 __compiler_memory_barrier ();
162218 connect_internal_flash_func ();
@@ -204,6 +260,9 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
204260
205261 flash_flush_cache_func ();
206262 flash_enable_xip_via_boot2 ();
263+ #if PICO_RP2350
264+ flash_rp2350_restore_qmi_cs1 (& qmi_save );
265+ #endif
207266}
208267#endif
209268
@@ -225,3 +284,89 @@ void flash_get_unique_id(uint8_t *id_out) {
225284 id_out [i ] = rxbuf [i + 1 + FLASH_RUID_DUMMY_BYTES ];
226285#endif
227286}
287+
288+ #if !PICO_RP2040
289+ // This is a static symbol because the layout of FLASH_DEVINFO is liable to change from device to
290+ // device, so fields must have getters/setters.
291+ static io_rw_16 * flash_devinfo_ptr (void ) {
292+ // Note the lookup returns a pointer to a 32-bit pointer literal in the ROM
293+ io_rw_16 * * p = (io_rw_16 * * ) rom_data_lookup (ROM_DATA_FLASH_DEVINFO16_PTR );
294+ assert (p );
295+ return * p ;
296+ }
297+
298+ static void flash_devinfo_update_field (uint16_t wdata , uint16_t mask ) {
299+ // Boot RAM does not support exclusives, but does support RWTYPE SET/CLR/XOR (with byte
300+ // strobes). Can't use hw_write_masked because it performs a 32-bit write.
301+ io_rw_16 * devinfo = flash_devinfo_ptr ();
302+ * hw_xor_alias (devinfo ) = (* devinfo ^ wdata ) & mask ;
303+ }
304+
305+ // This is a RAM function because may be called during flash programming to enable save/restore of
306+ // QMI window 1 registers on RP2350:
307+ flash_devinfo_size_t __no_inline_not_in_flash_func (flash_devinfo_get_cs_size )(uint cs ) {
308+ invalid_params_if (HARDWARE_FLASH , cs > 1 );
309+ io_ro_16 * devinfo = (io_ro_16 * ) flash_devinfo_ptr ();
310+ if (cs == 0u ) {
311+ #ifdef PICO_FLASH_SIZE_BYTES
312+ // A flash size explicitly specified for the build (e.g. from the board header) takes
313+ // precedence over whatever was found in OTP. Not using flash_devinfo_bytes_to_size() as
314+ // the call could be outlined, and this code must be in RAM.
315+ if (PICO_FLASH_SIZE_BYTES == 0 ) {
316+ return FLASH_DEVINFO_SIZE_NONE ;
317+ } else {
318+ return (flash_devinfo_size_t ) (
319+ __builtin_ctz (PICO_FLASH_SIZE_BYTES / 8192u ) + (uint )FLASH_DEVINFO_SIZE_8K
320+ );
321+ }
322+ #else
323+ return (flash_devinfo_size_t ) (
324+ (* devinfo & OTP_DATA_FLASH_DEVINFO_CS0_SIZE_BITS ) >> OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB
325+ );
326+ #endif
327+ } else {
328+ return (flash_devinfo_size_t ) (
329+ (* devinfo & OTP_DATA_FLASH_DEVINFO_CS1_SIZE_BITS ) >> OTP_DATA_FLASH_DEVINFO_CS1_SIZE_LSB
330+ );
331+ }
332+ }
333+
334+ void flash_devinfo_set_cs_size (uint cs , flash_devinfo_size_t size ) {
335+ invalid_params_if (HARDWARE_FLASH , cs > 1 );
336+ invalid_params_if (HARDWARE_FLASH , (uint )size > (uint )FLASH_DEVINFO_SIZE_MAX );
337+ uint cs_shift = cs == 0u ? OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB : OTP_DATA_FLASH_DEVINFO_CS1_SIZE_LSB ;
338+ uint cs_mask = OTP_DATA_FLASH_DEVINFO_CS0_SIZE_BITS >> OTP_DATA_FLASH_DEVINFO_CS0_SIZE_LSB ;
339+ flash_devinfo_update_field (
340+ (uint )size << cs_shift ,
341+ cs_mask << cs_shift
342+ );
343+ }
344+
345+ bool flash_devinfo_get_d8h_erase_supported (void ) {
346+ return * flash_devinfo_ptr () & OTP_DATA_FLASH_DEVINFO_D8H_ERASE_SUPPORTED_BITS ;
347+ }
348+
349+ void flash_devinfo_set_d8h_erase_supported (bool supported ) {
350+ flash_devinfo_update_field (
351+ (uint )supported << OTP_DATA_FLASH_DEVINFO_D8H_ERASE_SUPPORTED_LSB ,
352+ OTP_DATA_FLASH_DEVINFO_D8H_ERASE_SUPPORTED_BITS
353+ );
354+ }
355+
356+ uint flash_devinfo_get_cs_gpio (uint cs ) {
357+ invalid_params_if (HARDWARE_FLASH , cs != 1 );
358+ (void )cs ;
359+ return (* flash_devinfo_ptr () & OTP_DATA_FLASH_DEVINFO_CS1_GPIO_BITS ) >> OTP_DATA_FLASH_DEVINFO_CS1_GPIO_LSB ;
360+ }
361+
362+ void flash_devinfo_set_cs_gpio (uint cs , uint gpio ) {
363+ invalid_params_if (HARDWARE_FLASH , cs != 1 );
364+ invalid_params_if (HARDWARE_FLASH , gpio >= NUM_BANK0_GPIOS );
365+ (void )cs ;
366+ flash_devinfo_update_field (
367+ gpio << OTP_DATA_FLASH_DEVINFO_CS1_GPIO_LSB ,
368+ OTP_DATA_FLASH_DEVINFO_CS1_GPIO_BITS
369+ );
370+ }
371+
372+ #endif // !PICO_RP2040
0 commit comments