@@ -125,6 +125,9 @@ static int local_math_power(int base, int exp);
125
125
// Device-specific instructions
126
126
#define QSPIF_INST_ULBPR 0x98 // Clear all write-protection bits in the Block-Protection register
127
127
128
+ // Default legacy erase instruction
129
+ #define QSPIF_INST_LEGACY_ERASE_DEFAULT QSPI_NO_INST
130
+
128
131
// Default status register 2 read/write instructions
129
132
#define QSPIF_INST_WSR2_DEFAULT QSPI_NO_INST
130
133
#define QSPIF_INST_RSR2_DEFAULT 0x35
@@ -163,6 +166,9 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
163
166
tr_error (" Too many different QSPIFBlockDevice devices - max allowed: %d" , QSPIF_MAX_ACTIVE_FLASH_DEVICES);
164
167
}
165
168
169
+ // Set default erase instructions
170
+ _legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
171
+
166
172
// Set default status register 2 write/read instructions
167
173
_write_status_reg_2_inst = QSPIF_INST_WSR2_DEFAULT;
168
174
_read_status_reg_2_inst = QSPIF_INST_RSR2_DEFAULT;
@@ -393,7 +399,7 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
393
399
int type = 0 ;
394
400
uint32_t offset = 0 ;
395
401
uint32_t chunk = 4096 ;
396
- qspi_inst_t cur_erase_inst = _erase_instruction ;
402
+ qspi_inst_t cur_erase_inst = QSPI_NO_INST ;
397
403
int size = (int )in_size;
398
404
bool erase_failed = false ;
399
405
int status = QSPIF_BD_ERROR_OK;
@@ -416,12 +422,20 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
416
422
417
423
// For each iteration erase the largest section supported by current region
418
424
while (size > 0 ) {
419
- // iterate to find next Largest erase type ( a. supported by region, b. smaller than size)
420
- // find the matching instruction and erase size chunk for that type.
421
- type = _utils_iterate_next_largest_erase_type (bitfield, size, (int )addr, _region_high_boundary[region]);
422
- cur_erase_inst = _erase_type_inst_arr[type];
423
- offset = addr % _erase_type_size_arr[type];
424
- chunk = ((offset + size) < _erase_type_size_arr[type]) ? size : (_erase_type_size_arr[type] - offset);
425
+ unsigned int eu_size;
426
+ if (_legacy_erase_instruction == QSPI_NO_INST) {
427
+ // Iterate to find next largest erase type that is a) supported by region, and b) smaller than size.
428
+ // Find the matching instruction and erase size chunk for that type.
429
+ type = _utils_iterate_next_largest_erase_type (bitfield, size, (int )addr, _region_high_boundary[region]);
430
+ cur_erase_inst = _erase_type_inst_arr[type];
431
+ eu_size = _erase_type_size_arr[type];
432
+ } else {
433
+ // Must use legacy 4k erase instruction
434
+ cur_erase_inst = _legacy_erase_instruction;
435
+ eu_size = QSPIF_DEFAULT_SE_SIZE;
436
+ }
437
+ offset = addr % eu_size;
438
+ chunk = ((offset + size) < eu_size) ? size : (eu_size - offset);
425
439
426
440
tr_debug (" Erase - addr: %llu, size:%d, Inst: 0x%xh, chunk: %lu " ,
427
441
addr, size, cur_erase_inst, chunk);
@@ -497,6 +511,11 @@ const char *QSPIFBlockDevice::get_type() const
497
511
// Find minimal erase size supported by the region to which the address belongs to
498
512
bd_size_t QSPIFBlockDevice::get_erase_size (bd_addr_t addr)
499
513
{
514
+ // If the legacy erase instruction is in use, the erase size is uniformly 4k
515
+ if (_legacy_erase_instruction != QSPI_NO_INST) {
516
+ return QSPIF_DEFAULT_SE_SIZE;
517
+ }
518
+
500
519
// Find region of current address
501
520
int region = _utils_find_addr_region (addr);
502
521
@@ -692,13 +711,9 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
692
711
param_table[4 ]);
693
712
_device_size_bytes = (density_bits + 1 ) / 8 ;
694
713
695
- // Set Default read/program/erase Instructions
714
+ // Set Default read/program Instructions
696
715
_read_instruction = QSPIF_READ;
697
716
_prog_instruction = QSPIF_PP;
698
- _erase_instruction = QSPIF_SE;
699
-
700
- _erase_instruction = _erase4k_inst;
701
-
702
717
// Set Page Size (QSPI write must be done on Page limits)
703
718
_page_size_bytes = _sfdp_detect_page_size (param_table, basic_table_size);
704
719
@@ -711,9 +726,10 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
711
726
bool shouldSetQuadEnable = false ;
712
727
bool is_qpi_mode = false ;
713
728
714
- _sfdp_detect_erase_types_inst_and_size (param_table, basic_table_size, _erase4k_inst, _erase_type_inst_arr,
715
- _erase_type_size_arr);
716
- _erase_instruction = _erase4k_inst;
729
+ if (_sfdp_detect_erase_types_inst_and_size (param_table, basic_table_size) != 0 ) {
730
+ tr_error (" Init - Detecting erase types instructions/sizes failed" );
731
+ return -1 ;
732
+ }
717
733
718
734
// Detect and Set fastest Bus mode (default 1-1-1)
719
735
_sfdp_detect_best_bus_read_mode (param_table, basic_table_size, shouldSetQuadEnable, is_qpi_mode, _read_instruction);
@@ -874,56 +890,44 @@ int QSPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int
874
890
return page_size;
875
891
}
876
892
877
- int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size (uint8_t *basic_param_table_ptr, int basic_param_table_size,
878
- qspi_inst_t &erase4k_inst,
879
- qspi_inst_t *erase_type_inst_arr, unsigned int *erase_type_size_arr)
893
+ int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size (uint8_t *basic_param_table_ptr, int basic_param_table_size)
880
894
{
881
- erase4k_inst = 0xff ;
882
- bool found_4Kerase_type = false ;
883
895
uint8_t bitfield = 0x01 ;
884
896
885
897
// Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
886
- erase4k_inst = basic_param_table_ptr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
887
-
888
- if (basic_param_table_size > QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) {
898
+ if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) {
889
899
// Loop Erase Types 1-4
890
900
for (int i_ind = 0 ; i_ind < 4 ; i_ind++) {
891
- erase_type_inst_arr[i_ind] = 0xff ; // 0xFF default for unsupported type
892
- erase_type_size_arr[i_ind] = local_math_power (2 ,
893
- basic_param_table_ptr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N
894
- tr_debug (" Erase Type(A) %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), erase_type_inst_arr[i_ind],
895
- erase_type_size_arr[i_ind]);
896
- if (erase_type_size_arr[i_ind] > 1 ) {
901
+ _erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type
902
+ _erase_type_size_arr[i_ind] = 1 << basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value
903
+ tr_debug (" Erase Type(A) %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), _erase_type_inst_arr[i_ind],
904
+ _erase_type_size_arr[i_ind]);
905
+ if (_erase_type_size_arr[i_ind] > 1 ) {
897
906
// if size==1 type is not supported
898
- erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
899
-
900
- if ((erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0 )) {
901
- // Set default minimal common erase for singal region
902
- _min_common_erase_size = erase_type_size_arr[i_ind];
903
- }
907
+ _erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE + 2 * i_ind];
904
908
905
- // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction
906
- if (erase_type_size_arr[i_ind] == 4096 ) {
907
- found_4Kerase_type = true ;
908
- if (erase4k_inst != erase_type_inst_arr[i_ind]) {
909
- // Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
910
- erase4k_inst = erase_type_inst_arr[i_ind];
911
- tr_warning (" _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K" );
912
-
913
- }
909
+ if ((_erase_type_size_arr[i_ind] < _min_common_erase_size) || (_min_common_erase_size == 0 )) {
910
+ // Set default minimal common erase for signal region
911
+ _min_common_erase_size = _erase_type_size_arr[i_ind];
914
912
}
915
- _region_erase_types_bitfield[0 ] |= bitfield; // If there's no region map, set region "0" types bitfield as defualt;
913
+ _region_erase_types_bitfield[0 ] |= bitfield; // If there's no region map, set region "0" types bitfield as default
916
914
}
917
915
918
- tr_debug (" Erase Type %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), erase_type_inst_arr [i_ind],
919
- erase_type_size_arr [i_ind]);
916
+ tr_debug (" Erase Type %d - Inst: 0x%xh, Size: %d" , (i_ind + 1 ), _erase_type_inst_arr [i_ind],
917
+ _erase_type_size_arr [i_ind]);
920
918
bitfield = bitfield << 1 ;
921
919
}
922
- }
920
+ } else {
921
+ tr_debug (" SFDP erase types are not available - falling back to legacy 4k erase instruction" );
923
922
924
- if (false == found_4Kerase_type) {
925
- tr_warning (" Couldn't find Erase Type for 4KB size" );
923
+ // 0xFF indicates that the legacy 4k erase instruction is not supported
924
+ _legacy_erase_instruction = basic_param_table_ptr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
925
+ if (_legacy_erase_instruction == 0xFF ) {
926
+ tr_error (" _detectEraseTypesInstAndSize - Legacy 4k erase instruction not supported" );
927
+ return -1 ;
928
+ }
926
929
}
930
+
927
931
return 0 ;
928
932
}
929
933
0 commit comments