Skip to content

Commit 1c12083

Browse files
authored
Merge pull request #12426 from VeijoPesonen/sfdp_split_bptbl
SFDP: consolidation of SFDP parsing [2/n]
2 parents 18ad99a + de22648 commit 1c12083

File tree

6 files changed

+210
-285
lines changed

6 files changed

+210
-285
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

Lines changed: 15 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ using namespace mbed;
3232

3333
/* Default QSPIF Parameters */
3434
/****************************/
35-
#define QSPIF_DEFAULT_PAGE_SIZE 256
3635
#define QSPIF_DEFAULT_SE_SIZE 4096
3736
// The SFDP spec only defines two status registers. But some devices,
3837
// have three "status-like" registers (one status, two config)
@@ -63,20 +62,9 @@ using namespace mbed;
6362
#define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
6463
#define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
6564
#define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
66-
#define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
6765
// Quad Enable Params
6866
#define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58
6967
#define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56
70-
// Erase Types Params
71-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE 29
72-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_2_BYTE 31
73-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_3_BYTE 33
74-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_4_BYTE 35
75-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE 28
76-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_2_SIZE_BYTE 30
77-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_3_SIZE_BYTE 32
78-
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_4_SIZE_BYTE 34
79-
#define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
8068

8169
#define QSPIF_BASIC_PARAM_TABLE_SOFT_RESET_BYTE 61
8270
#define QSPIF_BASIC_PARAM_TABLE_4BYTE_ADDR_BYTE 63
@@ -112,7 +100,7 @@ using namespace mbed;
112100

113101
// Default read/legacy erase instructions
114102
#define QSPIF_INST_READ_DEFAULT 0x03
115-
#define QSPIF_INST_LEGACY_ERASE_DEFAULT QSPI_NO_INST
103+
#define QSPIF_INST_LEGACY_ERASE_DEFAULT (-1)
116104

117105
// Default status register 2 read/write instructions
118106
#define QSPIF_INST_WSR2_DEFAULT QSPI_NO_INST
@@ -153,6 +141,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
153141
}
154142

155143
// Initialize parameters
144+
_sfdp_info.bptbl.legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
156145
_sfdp_info.smptbl.regions_min_common_erase_size = 0;
157146
_sfdp_info.smptbl.region_cnt = 1;
158147
_sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
@@ -172,7 +161,6 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
172161

173162
// Set default read/erase instructions
174163
_read_instruction = QSPIF_INST_READ_DEFAULT;
175-
_legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
176164

177165
_num_status_registers = QSPI_DEFAULT_STATUS_REGISTERS;
178166
// Set default status register 2 write/read instructions
@@ -253,7 +241,8 @@ int QSPIFBlockDevice::init()
253241
}
254242

255243
/**************************** Parse Basic Parameters Table ***********************************/
256-
if (0 != _sfdp_parse_basic_param_table(_sfdp_info.bptbl.addr, _sfdp_info.bptbl.size)) {
244+
if (_sfdp_parse_basic_param_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command),
245+
_sfdp_info) < 0) {
257246
tr_error("Init - Parse Basic Param Table Failed");
258247
status = QSPIF_BD_ERROR_PARSING_FAILED;
259248
goto exit_point;
@@ -429,7 +418,7 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
429418
// For each iteration erase the largest section supported by current region
430419
while (size > 0) {
431420
unsigned int eu_size;
432-
if (_legacy_erase_instruction == QSPI_NO_INST) {
421+
if (_sfdp_info.bptbl.legacy_erase_instruction == QSPI_NO_INST) {
433422
// Iterate to find next largest erase type that is a) supported by region, and b) smaller than size.
434423
// Find the matching instruction and erase size chunk for that type.
435424
type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr,
@@ -439,7 +428,7 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
439428
eu_size = _sfdp_info.smptbl.erase_type_size_arr[type];
440429
} else {
441430
// Must use legacy 4k erase instruction
442-
cur_erase_inst = _legacy_erase_instruction;
431+
cur_erase_inst = _sfdp_info.bptbl.legacy_erase_instruction;
443432
eu_size = QSPIF_DEFAULT_SE_SIZE;
444433
}
445434
offset = addr % eu_size;
@@ -520,7 +509,7 @@ const char *QSPIFBlockDevice::get_type() const
520509
bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
521510
{
522511
// If the legacy erase instruction is in use, the erase size is uniformly 4k
523-
if (_legacy_erase_instruction != QSPI_NO_INST) {
512+
if (_sfdp_info.bptbl.legacy_erase_instruction != QSPI_NO_INST) {
524513
return QSPIF_DEFAULT_SE_SIZE;
525514
}
526515

@@ -627,11 +616,12 @@ int QSPIFBlockDevice::remove_csel_instance(PinName csel)
627616
/*********************************************************/
628617
/********** SFDP Parsing and Detection Functions *********/
629618
/*********************************************************/
630-
int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size)
619+
int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
620+
sfdp_hdr_info &sfdp_info)
631621
{
632-
uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 16 DWORDS = 64 Bytes */
622+
uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
633623

634-
int status = _qspi_send_read_sfdp_command(basic_table_addr, (char *)param_table, basic_table_size);
624+
int status = sfdp_reader(sfdp_info.bptbl.addr, param_table, sfdp_info.bptbl.size);
635625
if (status != QSPI_STATUS_OK) {
636626
tr_error("Init - Read SFDP First Table Failed");
637627
return -1;
@@ -651,7 +641,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
651641
_device_size_bytes = (density_bits + 1) / 8;
652642

653643
// Set Page Size (QSPI write must be done on Page limits)
654-
_page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size);
644+
_page_size_bytes = sfdp_detect_page_size(param_table, sfdp_info.bptbl.size);
655645

656646
if (_sfdp_detect_reset_protocol_and_reset(param_table) != QSPIF_BD_ERROR_OK) {
657647
tr_error("Init - Detecting reset protocol/resetting failed");
@@ -662,13 +652,13 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
662652
bool shouldSetQuadEnable = false;
663653
bool is_qpi_mode = false;
664654

665-
if (_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _sfdp_info.smptbl) != 0) {
655+
if (sfdp_detect_erase_types_inst_and_size(param_table, _sfdp_info) < 0) {
666656
tr_error("Init - Detecting erase types instructions/sizes failed");
667657
return -1;
668658
}
669659

670660
// Detect and Set fastest Bus mode (default 1-1-1)
671-
_sfdp_detect_best_bus_read_mode(param_table, basic_table_size, shouldSetQuadEnable, is_qpi_mode);
661+
_sfdp_detect_best_bus_read_mode(param_table, sfdp_info.bptbl.size, shouldSetQuadEnable, is_qpi_mode);
672662
if (true == shouldSetQuadEnable) {
673663
if (_needs_fast_mode) {
674664
_enable_fast_mode();
@@ -688,7 +678,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
688678
#ifndef TARGET_NORDIC
689679
// 4 byte addressing is not currently supported with the Nordic QSPI controller
690680
if (_attempt_4_byte_addressing) {
691-
if (_sfdp_detect_and_enable_4byte_addressing(param_table, basic_table_size) != QSPIF_BD_ERROR_OK) {
681+
if (_sfdp_detect_and_enable_4byte_addressing(param_table, sfdp_info.bptbl.size) != QSPIF_BD_ERROR_OK) {
692682
tr_error("Init - Detecting/enabling 4-byte addressing failed");
693683
return -1;
694684
}
@@ -831,67 +821,6 @@ int QSPIFBlockDevice::_sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr)
831821
return 0;
832822
}
833823

834-
int QSPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size)
835-
{
836-
unsigned int page_size = QSPIF_DEFAULT_PAGE_SIZE;
837-
838-
if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) {
839-
// Page Size is specified by 4 Bits (N), calculated by 2^N
840-
int page_to_power_size = ((int)basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
841-
page_size = 1 << page_to_power_size;
842-
tr_debug("Detected Page Size: %d", page_size);
843-
} else {
844-
tr_debug("Using Default Page Size: %d", page_size);
845-
}
846-
return page_size;
847-
}
848-
849-
int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr,
850-
int basic_param_table_size,
851-
sfdp_smptbl_info &smptbl)
852-
{
853-
uint8_t bitfield = 0x01;
854-
855-
// Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
856-
if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) {
857-
// Loop Erase Types 1-4
858-
for (int i_ind = 0; i_ind < 4; i_ind++) {
859-
smptbl.erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type
860-
smptbl.erase_type_size_arr[i_ind] = 1
861-
<< 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
862-
tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind],
863-
smptbl.erase_type_size_arr[i_ind]);
864-
if (smptbl.erase_type_size_arr[i_ind] > 1) {
865-
// if size==1 type is not supported
866-
smptbl.erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
867-
+ 2 * i_ind];
868-
869-
if ((smptbl.erase_type_size_arr[i_ind] < smptbl.regions_min_common_erase_size)
870-
|| (smptbl.regions_min_common_erase_size == 0)) {
871-
//Set default minimal common erase for signal region
872-
smptbl.regions_min_common_erase_size = smptbl.erase_type_size_arr[i_ind];
873-
}
874-
smptbl.region_erase_types_bitfld[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default
875-
}
876-
877-
tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind],
878-
smptbl.erase_type_size_arr[i_ind]);
879-
bitfield = bitfield << 1;
880-
}
881-
} else {
882-
tr_debug("SFDP erase types are not available - falling back to legacy 4k erase instruction");
883-
884-
// 0xFF indicates that the legacy 4k erase instruction is not supported
885-
_legacy_erase_instruction = basic_param_table_ptr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
886-
if (_legacy_erase_instruction == 0xFF) {
887-
tr_error("_detectEraseTypesInstAndSize - Legacy 4k erase instruction not supported");
888-
return -1;
889-
}
890-
}
891-
892-
return 0;
893-
}
894-
895824
int QSPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
896825
bool &set_quad_enable, bool &is_qpi_mode)
897826
{

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
318318
/* SFDP Detection and Parsing Functions */
319319
/****************************************/
320320
// Parse and Detect required Basic Parameters from Table
321-
int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);
321+
int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
322+
mbed::sfdp_hdr_info &sfdp_info);
322323

323324
// Detect the soft reset protocol and reset - returns error if soft reset is not supported
324325
int _sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr);
@@ -336,11 +337,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
336337
// Set Page size for program
337338
int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
338339

339-
// Detect all supported erase types
340-
int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr,
341-
int basic_param_table_size,
342-
mbed::sfdp_smptbl_info &smptbl);
343-
344340
// Detect 4-byte addressing mode and enable it if supported
345341
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
346342

@@ -386,7 +382,6 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
386382

387383
// Command Instructions
388384
mbed::qspi_inst_t _read_instruction;
389-
mbed::qspi_inst_t _legacy_erase_instruction;
390385

391386
// Status register write/read instructions
392387
unsigned int _num_status_registers;

0 commit comments

Comments
 (0)