12
12
#include "hardware/structs/ssi.h"
13
13
#else
14
14
#include "hardware/structs/qmi.h"
15
+ #include "hardware/regs/otp_data.h"
15
16
#endif
16
17
#include "hardware/xip_cache.h"
17
18
@@ -70,6 +71,43 @@ static void __no_inline_not_in_flash_func(flash_enable_xip_via_boot2)(void) {
70
71
71
72
#endif
72
73
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
+
73
111
//-----------------------------------------------------------------------------
74
112
// Actual flash programming shims (work whether or not PICO_NO_FLASH==1)
75
113
@@ -87,6 +125,10 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
87
125
flash_init_boot2_copyout ();
88
126
// Commit any pending writes to external RAM, to avoid losing them in the subsequent flush:
89
127
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
90
132
91
133
// No flash accesses after this point
92
134
__compiler_memory_barrier ();
@@ -96,6 +138,9 @@ void __no_inline_not_in_flash_func(flash_range_erase)(uint32_t flash_offs, size_
96
138
flash_range_erase_func (flash_offs , count , FLASH_BLOCK_SIZE , FLASH_BLOCK_ERASE_CMD );
97
139
flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
98
140
flash_enable_xip_via_boot2 ();
141
+ #if PICO_RP2350
142
+ flash_rp2350_restore_qmi_cs1 (& qmi_save );
143
+ #endif
99
144
}
100
145
101
146
void __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
116
161
assert (connect_internal_flash_func && flash_exit_xip_func && flash_range_program_func && flash_flush_cache_func );
117
162
flash_init_boot2_copyout ();
118
163
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
119
168
120
169
__compiler_memory_barrier ();
121
170
@@ -124,6 +173,9 @@ void __no_inline_not_in_flash_func(flash_range_program)(uint32_t flash_offs, con
124
173
flash_range_program_func (flash_offs , data , count );
125
174
flash_flush_cache_func (); // Note this is needed to remove CSn IO force as well as cache flushing
126
175
flash_enable_xip_via_boot2 ();
176
+ #if PICO_RP2350
177
+ flash_rp2350_restore_qmi_cs1 (& qmi_save );
178
+ #endif
127
179
}
128
180
129
181
//-----------------------------------------------------------------------------
@@ -157,6 +209,10 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
157
209
assert (connect_internal_flash_func && flash_exit_xip_func && flash_flush_cache_func );
158
210
flash_init_boot2_copyout ();
159
211
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
160
216
161
217
__compiler_memory_barrier ();
162
218
connect_internal_flash_func ();
@@ -204,6 +260,9 @@ void __no_inline_not_in_flash_func(flash_do_cmd)(const uint8_t *txbuf, uint8_t *
204
260
205
261
flash_flush_cache_func ();
206
262
flash_enable_xip_via_boot2 ();
263
+ #if PICO_RP2350
264
+ flash_rp2350_restore_qmi_cs1 (& qmi_save );
265
+ #endif
207
266
}
208
267
#endif
209
268
@@ -225,3 +284,89 @@ void flash_get_unique_id(uint8_t *id_out) {
225
284
id_out [i ] = rxbuf [i + 1 + FLASH_RUID_DUMMY_BYTES ];
226
285
#endif
227
286
}
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