mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #12426 from VeijoPesonen/sfdp_split_bptbl
SFDP: consolidation of SFDP parsing [2/n]pull/12450/head
						commit
						1c12083949
					
				| 
						 | 
					@ -32,7 +32,6 @@ using namespace mbed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Default QSPIF Parameters */
 | 
					/* Default QSPIF Parameters */
 | 
				
			||||||
/****************************/
 | 
					/****************************/
 | 
				
			||||||
#define QSPIF_DEFAULT_PAGE_SIZE  256
 | 
					 | 
				
			||||||
#define QSPIF_DEFAULT_SE_SIZE    4096
 | 
					#define QSPIF_DEFAULT_SE_SIZE    4096
 | 
				
			||||||
// The SFDP spec only defines two status registers. But some devices,
 | 
					// The SFDP spec only defines two status registers. But some devices,
 | 
				
			||||||
// have three "status-like" registers (one status, two config)
 | 
					// have three "status-like" registers (one status, two config)
 | 
				
			||||||
| 
						 | 
					@ -63,20 +62,9 @@ using namespace mbed;
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
 | 
					#define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
 | 
					#define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
 | 
					#define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
 | 
					 | 
				
			||||||
// Quad Enable Params
 | 
					// Quad Enable Params
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58
 | 
					#define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56
 | 
					#define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56
 | 
				
			||||||
// Erase Types Params
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE 29
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_2_BYTE 31
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_3_BYTE 33
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_4_BYTE 35
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE 28
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_2_SIZE_BYTE 30
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_3_SIZE_BYTE 32
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_4_SIZE_BYTE 34
 | 
					 | 
				
			||||||
#define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_SOFT_RESET_BYTE 61
 | 
					#define QSPIF_BASIC_PARAM_TABLE_SOFT_RESET_BYTE 61
 | 
				
			||||||
#define QSPIF_BASIC_PARAM_TABLE_4BYTE_ADDR_BYTE 63
 | 
					#define QSPIF_BASIC_PARAM_TABLE_4BYTE_ADDR_BYTE 63
 | 
				
			||||||
| 
						 | 
					@ -112,7 +100,7 @@ using namespace mbed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Default read/legacy erase instructions
 | 
					// Default read/legacy erase instructions
 | 
				
			||||||
#define QSPIF_INST_READ_DEFAULT          0x03
 | 
					#define QSPIF_INST_READ_DEFAULT          0x03
 | 
				
			||||||
#define QSPIF_INST_LEGACY_ERASE_DEFAULT  QSPI_NO_INST
 | 
					#define QSPIF_INST_LEGACY_ERASE_DEFAULT  (-1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Default status register 2 read/write instructions
 | 
					// Default status register 2 read/write instructions
 | 
				
			||||||
#define QSPIF_INST_WSR2_DEFAULT    QSPI_NO_INST
 | 
					#define QSPIF_INST_WSR2_DEFAULT    QSPI_NO_INST
 | 
				
			||||||
| 
						 | 
					@ -153,6 +141,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Initialize parameters
 | 
					    // Initialize parameters
 | 
				
			||||||
 | 
					    _sfdp_info.bptbl.legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
 | 
				
			||||||
    _sfdp_info.smptbl.regions_min_common_erase_size = 0;
 | 
					    _sfdp_info.smptbl.regions_min_common_erase_size = 0;
 | 
				
			||||||
    _sfdp_info.smptbl.region_cnt = 1;
 | 
					    _sfdp_info.smptbl.region_cnt = 1;
 | 
				
			||||||
    _sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
 | 
					    _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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set default read/erase instructions
 | 
					    // Set default read/erase instructions
 | 
				
			||||||
    _read_instruction = QSPIF_INST_READ_DEFAULT;
 | 
					    _read_instruction = QSPIF_INST_READ_DEFAULT;
 | 
				
			||||||
    _legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _num_status_registers = QSPI_DEFAULT_STATUS_REGISTERS;
 | 
					    _num_status_registers = QSPI_DEFAULT_STATUS_REGISTERS;
 | 
				
			||||||
    // Set default status register 2 write/read instructions
 | 
					    // Set default status register 2 write/read instructions
 | 
				
			||||||
| 
						 | 
					@ -253,7 +241,8 @@ int QSPIFBlockDevice::init()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**************************** Parse Basic Parameters Table ***********************************/
 | 
					    /**************************** Parse Basic Parameters Table ***********************************/
 | 
				
			||||||
    if (0 != _sfdp_parse_basic_param_table(_sfdp_info.bptbl.addr, _sfdp_info.bptbl.size)) {
 | 
					    if (_sfdp_parse_basic_param_table(callback(this, &QSPIFBlockDevice::_qspi_send_read_sfdp_command),
 | 
				
			||||||
 | 
					                                      _sfdp_info) < 0) {
 | 
				
			||||||
        tr_error("Init - Parse Basic Param Table Failed");
 | 
					        tr_error("Init - Parse Basic Param Table Failed");
 | 
				
			||||||
        status = QSPIF_BD_ERROR_PARSING_FAILED;
 | 
					        status = QSPIF_BD_ERROR_PARSING_FAILED;
 | 
				
			||||||
        goto exit_point;
 | 
					        goto exit_point;
 | 
				
			||||||
| 
						 | 
					@ -429,7 +418,7 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size)
 | 
				
			||||||
    // For each iteration erase the largest section supported by current region
 | 
					    // For each iteration erase the largest section supported by current region
 | 
				
			||||||
    while (size > 0) {
 | 
					    while (size > 0) {
 | 
				
			||||||
        unsigned int eu_size;
 | 
					        unsigned int eu_size;
 | 
				
			||||||
        if (_legacy_erase_instruction == QSPI_NO_INST) {
 | 
					        if (_sfdp_info.bptbl.legacy_erase_instruction == QSPI_NO_INST) {
 | 
				
			||||||
            // Iterate to find next largest erase type that is a) supported by region, and b) smaller than size.
 | 
					            // Iterate to find next largest erase type that is a) supported by region, and b) smaller than size.
 | 
				
			||||||
            // Find the matching instruction and erase size chunk for that type.
 | 
					            // Find the matching instruction and erase size chunk for that type.
 | 
				
			||||||
            type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr,
 | 
					            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)
 | 
				
			||||||
            eu_size = _sfdp_info.smptbl.erase_type_size_arr[type];
 | 
					            eu_size = _sfdp_info.smptbl.erase_type_size_arr[type];
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // Must use legacy 4k erase instruction
 | 
					            // Must use legacy 4k erase instruction
 | 
				
			||||||
            cur_erase_inst = _legacy_erase_instruction;
 | 
					            cur_erase_inst = _sfdp_info.bptbl.legacy_erase_instruction;
 | 
				
			||||||
            eu_size = QSPIF_DEFAULT_SE_SIZE;
 | 
					            eu_size = QSPIF_DEFAULT_SE_SIZE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        offset = addr % eu_size;
 | 
					        offset = addr % eu_size;
 | 
				
			||||||
| 
						 | 
					@ -520,7 +509,7 @@ const char *QSPIFBlockDevice::get_type() const
 | 
				
			||||||
bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
 | 
					bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // If the legacy erase instruction is in use, the erase size is uniformly 4k
 | 
					    // If the legacy erase instruction is in use, the erase size is uniformly 4k
 | 
				
			||||||
    if (_legacy_erase_instruction != QSPI_NO_INST) {
 | 
					    if (_sfdp_info.bptbl.legacy_erase_instruction != QSPI_NO_INST) {
 | 
				
			||||||
        return QSPIF_DEFAULT_SE_SIZE;
 | 
					        return QSPIF_DEFAULT_SE_SIZE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -627,11 +616,12 @@ int QSPIFBlockDevice::remove_csel_instance(PinName csel)
 | 
				
			||||||
/*********************************************************/
 | 
					/*********************************************************/
 | 
				
			||||||
/********** SFDP Parsing and Detection Functions *********/
 | 
					/********** SFDP Parsing and Detection Functions *********/
 | 
				
			||||||
/*********************************************************/
 | 
					/*********************************************************/
 | 
				
			||||||
int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size)
 | 
					int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
 | 
				
			||||||
 | 
					                                                    sfdp_hdr_info &sfdp_info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 16 DWORDS = 64 Bytes */
 | 
					    uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int status = _qspi_send_read_sfdp_command(basic_table_addr, (char *)param_table, basic_table_size);
 | 
					    int status = sfdp_reader(sfdp_info.bptbl.addr, param_table, sfdp_info.bptbl.size);
 | 
				
			||||||
    if (status != QSPI_STATUS_OK) {
 | 
					    if (status != QSPI_STATUS_OK) {
 | 
				
			||||||
        tr_error("Init - Read SFDP First Table Failed");
 | 
					        tr_error("Init - Read SFDP First Table Failed");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
| 
						 | 
					@ -651,7 +641,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
 | 
				
			||||||
    _device_size_bytes = (density_bits + 1) / 8;
 | 
					    _device_size_bytes = (density_bits + 1) / 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set Page Size (QSPI write must be done on Page limits)
 | 
					    // Set Page Size (QSPI write must be done on Page limits)
 | 
				
			||||||
    _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size);
 | 
					    _page_size_bytes = sfdp_detect_page_size(param_table, sfdp_info.bptbl.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_sfdp_detect_reset_protocol_and_reset(param_table) != QSPIF_BD_ERROR_OK) {
 | 
					    if (_sfdp_detect_reset_protocol_and_reset(param_table) != QSPIF_BD_ERROR_OK) {
 | 
				
			||||||
        tr_error("Init - Detecting reset protocol/resetting failed");
 | 
					        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
 | 
				
			||||||
    bool shouldSetQuadEnable = false;
 | 
					    bool shouldSetQuadEnable = false;
 | 
				
			||||||
    bool is_qpi_mode = false;
 | 
					    bool is_qpi_mode = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _sfdp_info.smptbl) != 0) {
 | 
					    if (sfdp_detect_erase_types_inst_and_size(param_table, _sfdp_info) < 0) {
 | 
				
			||||||
        tr_error("Init - Detecting erase types instructions/sizes failed");
 | 
					        tr_error("Init - Detecting erase types instructions/sizes failed");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Detect and Set fastest Bus mode (default 1-1-1)
 | 
					    // Detect and Set fastest Bus mode (default 1-1-1)
 | 
				
			||||||
    _sfdp_detect_best_bus_read_mode(param_table, basic_table_size, shouldSetQuadEnable, is_qpi_mode);
 | 
					    _sfdp_detect_best_bus_read_mode(param_table, sfdp_info.bptbl.size, shouldSetQuadEnable, is_qpi_mode);
 | 
				
			||||||
    if (true == shouldSetQuadEnable) {
 | 
					    if (true == shouldSetQuadEnable) {
 | 
				
			||||||
        if (_needs_fast_mode) {
 | 
					        if (_needs_fast_mode) {
 | 
				
			||||||
            _enable_fast_mode();
 | 
					            _enable_fast_mode();
 | 
				
			||||||
| 
						 | 
					@ -688,7 +678,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
 | 
				
			||||||
#ifndef TARGET_NORDIC
 | 
					#ifndef TARGET_NORDIC
 | 
				
			||||||
    // 4 byte addressing is not currently supported with the Nordic QSPI controller
 | 
					    // 4 byte addressing is not currently supported with the Nordic QSPI controller
 | 
				
			||||||
    if (_attempt_4_byte_addressing) {
 | 
					    if (_attempt_4_byte_addressing) {
 | 
				
			||||||
        if (_sfdp_detect_and_enable_4byte_addressing(param_table, basic_table_size) != QSPIF_BD_ERROR_OK) {
 | 
					        if (_sfdp_detect_and_enable_4byte_addressing(param_table, sfdp_info.bptbl.size) != QSPIF_BD_ERROR_OK) {
 | 
				
			||||||
            tr_error("Init - Detecting/enabling 4-byte addressing failed");
 | 
					            tr_error("Init - Detecting/enabling 4-byte addressing failed");
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -831,67 +821,6 @@ int QSPIFBlockDevice::_sfdp_set_qpi_enabled(uint8_t *basic_param_table_ptr)
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int QSPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    unsigned int page_size = QSPIF_DEFAULT_PAGE_SIZE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) {
 | 
					 | 
				
			||||||
        // Page Size is specified by 4 Bits (N), calculated by 2^N
 | 
					 | 
				
			||||||
        int page_to_power_size = ((int)basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
 | 
					 | 
				
			||||||
        page_size = 1 << page_to_power_size;
 | 
					 | 
				
			||||||
        tr_debug("Detected Page Size: %d", page_size);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        tr_debug("Using Default Page Size: %d", page_size);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return page_size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int QSPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr,
 | 
					 | 
				
			||||||
                                                             int basic_param_table_size,
 | 
					 | 
				
			||||||
                                                             sfdp_smptbl_info &smptbl)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    uint8_t bitfield = 0x01;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
 | 
					 | 
				
			||||||
    if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) {
 | 
					 | 
				
			||||||
        // Loop Erase Types 1-4
 | 
					 | 
				
			||||||
        for (int i_ind = 0; i_ind < 4; i_ind++) {
 | 
					 | 
				
			||||||
            smptbl.erase_type_inst_arr[i_ind] = QSPI_NO_INST; // Default for unsupported type
 | 
					 | 
				
			||||||
            smptbl.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
 | 
					 | 
				
			||||||
            tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind],
 | 
					 | 
				
			||||||
                     smptbl.erase_type_size_arr[i_ind]);
 | 
					 | 
				
			||||||
            if (smptbl.erase_type_size_arr[i_ind] > 1) {
 | 
					 | 
				
			||||||
                // if size==1 type is not supported
 | 
					 | 
				
			||||||
                smptbl.erase_type_inst_arr[i_ind] = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
 | 
					 | 
				
			||||||
                                                                          + 2 * i_ind];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if ((smptbl.erase_type_size_arr[i_ind] < smptbl.regions_min_common_erase_size)
 | 
					 | 
				
			||||||
                        || (smptbl.regions_min_common_erase_size == 0)) {
 | 
					 | 
				
			||||||
                    //Set default minimal common erase for signal region
 | 
					 | 
				
			||||||
                    smptbl.regions_min_common_erase_size = smptbl.erase_type_size_arr[i_ind];
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                smptbl.region_erase_types_bitfld[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind],
 | 
					 | 
				
			||||||
                     smptbl.erase_type_size_arr[i_ind]);
 | 
					 | 
				
			||||||
            bitfield = bitfield << 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        tr_debug("SFDP erase types are not available - falling back to legacy 4k erase instruction");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // 0xFF indicates that the legacy 4k erase instruction is not supported
 | 
					 | 
				
			||||||
        _legacy_erase_instruction = basic_param_table_ptr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
 | 
					 | 
				
			||||||
        if (_legacy_erase_instruction == 0xFF) {
 | 
					 | 
				
			||||||
            tr_error("_detectEraseTypesInstAndSize - Legacy 4k erase instruction not supported");
 | 
					 | 
				
			||||||
            return -1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int QSPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
 | 
					int QSPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
 | 
				
			||||||
                                                      bool &set_quad_enable, bool &is_qpi_mode)
 | 
					                                                      bool &set_quad_enable, bool &is_qpi_mode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -318,7 +318,8 @@ private:
 | 
				
			||||||
    /* SFDP Detection and Parsing Functions */
 | 
					    /* SFDP Detection and Parsing Functions */
 | 
				
			||||||
    /****************************************/
 | 
					    /****************************************/
 | 
				
			||||||
    // Parse and Detect required Basic Parameters from Table
 | 
					    // Parse and Detect required Basic Parameters from Table
 | 
				
			||||||
    int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);
 | 
					    int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
 | 
				
			||||||
 | 
					                                      mbed::sfdp_hdr_info &sfdp_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Detect the soft reset protocol and reset - returns error if soft reset is not supported
 | 
					    // Detect the soft reset protocol and reset - returns error if soft reset is not supported
 | 
				
			||||||
    int _sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr);
 | 
					    int _sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr);
 | 
				
			||||||
| 
						 | 
					@ -336,11 +337,6 @@ private:
 | 
				
			||||||
    // Set Page size for program
 | 
					    // Set Page size for program
 | 
				
			||||||
    int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
 | 
					    int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Detect all supported erase types
 | 
					 | 
				
			||||||
    int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr,
 | 
					 | 
				
			||||||
                                               int basic_param_table_size,
 | 
					 | 
				
			||||||
                                               mbed::sfdp_smptbl_info &smptbl);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Detect 4-byte addressing mode and enable it if supported
 | 
					    // Detect 4-byte addressing mode and enable it if supported
 | 
				
			||||||
    int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
 | 
					    int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -386,7 +382,6 @@ private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Command Instructions
 | 
					    // Command Instructions
 | 
				
			||||||
    mbed::qspi_inst_t _read_instruction;
 | 
					    mbed::qspi_inst_t _read_instruction;
 | 
				
			||||||
    mbed::qspi_inst_t _legacy_erase_instruction;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Status register write/read instructions
 | 
					    // Status register write/read instructions
 | 
				
			||||||
    unsigned int _num_status_registers;
 | 
					    unsigned int _num_status_registers;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,6 @@ using namespace mbed;
 | 
				
			||||||
/****************************/
 | 
					/****************************/
 | 
				
			||||||
#define SPIF_DEFAULT_READ_SIZE  1
 | 
					#define SPIF_DEFAULT_READ_SIZE  1
 | 
				
			||||||
#define SPIF_DEFAULT_PROG_SIZE  1
 | 
					#define SPIF_DEFAULT_PROG_SIZE  1
 | 
				
			||||||
#define SPIF_DEFAULT_PAGE_SIZE  256
 | 
					 | 
				
			||||||
#define SPIF_DEFAULT_SE_SIZE    4096
 | 
					#define SPIF_DEFAULT_SE_SIZE    4096
 | 
				
			||||||
#define SPI_MAX_STATUS_REGISTER_SIZE 2
 | 
					#define SPI_MAX_STATUS_REGISTER_SIZE 2
 | 
				
			||||||
#ifndef UINT64_MAX
 | 
					#ifndef UINT64_MAX
 | 
				
			||||||
| 
						 | 
					@ -44,27 +43,20 @@ using namespace mbed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Basic Parameters Table Parsing */
 | 
					/* Basic Parameters Table Parsing */
 | 
				
			||||||
/**********************************/
 | 
					/**********************************/
 | 
				
			||||||
#define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */
 | 
					 | 
				
			||||||
//READ Instruction support according to BUS Configuration
 | 
					//READ Instruction support according to BUS Configuration
 | 
				
			||||||
#define SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2
 | 
					#define SPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2
 | 
				
			||||||
#define SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE 16
 | 
					#define SPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPORT_BYTE 16
 | 
				
			||||||
#define SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
 | 
					#define SPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
 | 
				
			||||||
#define SPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
 | 
					#define SPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
 | 
				
			||||||
#define SPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
 | 
					#define SPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
 | 
				
			||||||
#define SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
 | 
					 | 
				
			||||||
// Address Length
 | 
					// Address Length
 | 
				
			||||||
#define SPIF_ADDR_SIZE_3_BYTES 3
 | 
					#define SPIF_ADDR_SIZE_3_BYTES 3
 | 
				
			||||||
#define SPIF_ADDR_SIZE_4_BYTES 4
 | 
					#define SPIF_ADDR_SIZE_4_BYTES 4
 | 
				
			||||||
// Erase Types Params
 | 
					
 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29
 | 
					// Default read/legacy erase instructions
 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31
 | 
					#define SPIF_INST_READ_DEFAULT          0x03
 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33
 | 
					#define SPIF_INST_LEGACY_ERASE_DEFAULT  (-1)
 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35
 | 
					
 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28
 | 
					 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30
 | 
					 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32
 | 
					 | 
				
			||||||
#define SPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34
 | 
					 | 
				
			||||||
#define SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IS_MEM_READY_MAX_RETRIES 10000
 | 
					#define IS_MEM_READY_MAX_RETRIES 10000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,16 +82,15 @@ enum spif_default_instructions {
 | 
				
			||||||
// e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
 | 
					// e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
 | 
				
			||||||
SingletonPtr<PlatformMutex> SPIFBlockDevice::_mutex;
 | 
					SingletonPtr<PlatformMutex> SPIFBlockDevice::_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Local Function
 | 
					 | 
				
			||||||
static unsigned int local_math_power(int base, int exp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//***********************
 | 
					//***********************
 | 
				
			||||||
// SPIF Block Device APIs
 | 
					// SPIF Block Device APIs
 | 
				
			||||||
//***********************
 | 
					//***********************
 | 
				
			||||||
SPIFBlockDevice::SPIFBlockDevice(
 | 
					SPIFBlockDevice::SPIFBlockDevice(
 | 
				
			||||||
    PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
 | 
					    PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
 | 
				
			||||||
    : _spi(mosi, miso, sclk), _cs(csel), _read_instruction(0), _prog_instruction(0), _erase_instruction(0),
 | 
					    :
 | 
				
			||||||
      _erase4k_inst(0), _page_size_bytes(0), _device_size_bytes(0), _init_ref_count(0), _is_initialized(false)
 | 
					    _spi(mosi, miso, sclk), _cs(csel), _prog_instruction(0), _erase_instruction(0),
 | 
				
			||||||
 | 
					    _page_size_bytes(0),
 | 
				
			||||||
 | 
					    _device_size_bytes(0), _init_ref_count(0), _is_initialized(false)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _address_size = SPIF_ADDR_SIZE_3_BYTES;
 | 
					    _address_size = SPIF_ADDR_SIZE_3_BYTES;
 | 
				
			||||||
    // Initial SFDP read tables are read with 8 dummy cycles
 | 
					    // Initial SFDP read tables are read with 8 dummy cycles
 | 
				
			||||||
| 
						 | 
					@ -108,10 +99,14 @@ SPIFBlockDevice::SPIFBlockDevice(
 | 
				
			||||||
    _write_dummy_and_mode_cycles = 0;
 | 
					    _write_dummy_and_mode_cycles = 0;
 | 
				
			||||||
    _dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
 | 
					    _dummy_and_mode_cycles = _read_dummy_and_mode_cycles;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _sfdp_info.bptbl.legacy_erase_instruction = SPIF_INST_LEGACY_ERASE_DEFAULT;
 | 
				
			||||||
    _sfdp_info.smptbl.regions_min_common_erase_size = 0;
 | 
					    _sfdp_info.smptbl.regions_min_common_erase_size = 0;
 | 
				
			||||||
    _sfdp_info.smptbl.region_cnt = 1;
 | 
					    _sfdp_info.smptbl.region_cnt = 1;
 | 
				
			||||||
    _sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
 | 
					    _sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Set default read/erase instructions
 | 
				
			||||||
 | 
					    _read_instruction = SPIF_INST_READ_DEFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) {
 | 
					    if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) {
 | 
				
			||||||
        tr_error("SPI Set Frequency Failed");
 | 
					        tr_error("SPI Set Frequency Failed");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -124,10 +119,12 @@ int SPIFBlockDevice::init()
 | 
				
			||||||
    uint8_t vendor_device_ids[4];
 | 
					    uint8_t vendor_device_ids[4];
 | 
				
			||||||
    size_t data_length = 3;
 | 
					    size_t data_length = 3;
 | 
				
			||||||
    int status = SPIF_BD_ERROR_OK;
 | 
					    int status = SPIF_BD_ERROR_OK;
 | 
				
			||||||
    struct sfdp_hdr_info hdr_info;
 | 
					 | 
				
			||||||
    spif_bd_error spi_status = SPIF_BD_ERROR_OK;
 | 
					    spif_bd_error spi_status = SPIF_BD_ERROR_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memset(&hdr_info, 0, sizeof hdr_info);
 | 
					    _sfdp_info.bptbl.addr = 0x0;
 | 
				
			||||||
 | 
					    _sfdp_info.bptbl.size = 0;
 | 
				
			||||||
 | 
					    _sfdp_info.smptbl.addr = 0x0;
 | 
				
			||||||
 | 
					    _sfdp_info.smptbl.size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _mutex->lock();
 | 
					    _mutex->lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,7 +173,7 @@ int SPIFBlockDevice::init()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**************************** Parse SFDP Header ***********************************/
 | 
					    /**************************** Parse SFDP Header ***********************************/
 | 
				
			||||||
    if (0 != sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), hdr_info)) {
 | 
					    if (sfdp_parse_headers(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), _sfdp_info) < 0) {
 | 
				
			||||||
        tr_error("init - Parse SFDP Headers Failed");
 | 
					        tr_error("init - Parse SFDP Headers Failed");
 | 
				
			||||||
        status = SPIF_BD_ERROR_PARSING_FAILED;
 | 
					        status = SPIF_BD_ERROR_PARSING_FAILED;
 | 
				
			||||||
        goto exit_point;
 | 
					        goto exit_point;
 | 
				
			||||||
| 
						 | 
					@ -184,7 +181,7 @@ int SPIFBlockDevice::init()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**************************** Parse Basic Parameters Table ***********************************/
 | 
					    /**************************** Parse Basic Parameters Table ***********************************/
 | 
				
			||||||
    if (0 != _sfdp_parse_basic_param_table(hdr_info.bptbl.addr, hdr_info.bptbl.size)) {
 | 
					    if (_sfdp_parse_basic_param_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command), _sfdp_info) < 0) {
 | 
				
			||||||
        tr_error("init - Parse Basic Param Table Failed");
 | 
					        tr_error("init - Parse Basic Param Table Failed");
 | 
				
			||||||
        status = SPIF_BD_ERROR_PARSING_FAILED;
 | 
					        status = SPIF_BD_ERROR_PARSING_FAILED;
 | 
				
			||||||
        goto exit_point;
 | 
					        goto exit_point;
 | 
				
			||||||
| 
						 | 
					@ -195,9 +192,9 @@ int SPIFBlockDevice::init()
 | 
				
			||||||
        _device_size_bytes; // If there's no region map, we have a single region sized the entire device size
 | 
					        _device_size_bytes; // If there's no region map, we have a single region sized the entire device size
 | 
				
			||||||
    _sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1;
 | 
					    _sfdp_info.smptbl.region_high_boundary[0] = _device_size_bytes - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((hdr_info.smptbl.addr != 0) && (0 != hdr_info.smptbl.size)) {
 | 
					    if ((_sfdp_info.smptbl.addr != 0) && (0 != _sfdp_info.smptbl.size)) {
 | 
				
			||||||
        tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", hdr_info.smptbl.addr,
 | 
					        tr_debug("init - Parsing Sector Map Table - addr: 0x%" PRIx32 "h, Size: %d", _sfdp_info.smptbl.addr,
 | 
				
			||||||
                 hdr_info.smptbl.size);
 | 
					                 _sfdp_info.smptbl.size);
 | 
				
			||||||
        if (sfdp_parse_sector_map_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command),
 | 
					        if (sfdp_parse_sector_map_table(callback(this, &SPIFBlockDevice::_spi_send_read_sfdp_command),
 | 
				
			||||||
                                        _sfdp_info.smptbl) < 0) {
 | 
					                                        _sfdp_info.smptbl) < 0) {
 | 
				
			||||||
            tr_error("init - Parse Sector Map Table Failed");
 | 
					            tr_error("init - Parse Sector Map Table Failed");
 | 
				
			||||||
| 
						 | 
					@ -621,13 +618,12 @@ spif_bd_error SPIFBlockDevice::_spi_send_general_command(int instruction, bd_add
 | 
				
			||||||
/*********************************************************/
 | 
					/*********************************************************/
 | 
				
			||||||
/********** SFDP Parsing and Detection Functions *********/
 | 
					/********** SFDP Parsing and Detection Functions *********/
 | 
				
			||||||
/*********************************************************/
 | 
					/*********************************************************/
 | 
				
			||||||
int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size)
 | 
					int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
 | 
				
			||||||
 | 
					                                                   mbed::sfdp_hdr_info &sfdp_info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
 | 
					    uint8_t param_table[SFDP_BASIC_PARAMS_TBL_SIZE]; /* Up To 20 DWORDS = 80 Bytes */
 | 
				
			||||||
    //memset(param_table, 0, SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    spif_bd_error status = _spi_send_read_command(SPIF_SFDP, param_table, basic_table_addr /*address*/,
 | 
					    int status = sfdp_reader(sfdp_info.bptbl.addr, param_table, sfdp_info.bptbl.size);
 | 
				
			||||||
                                                  basic_table_size);
 | 
					 | 
				
			||||||
    if (status != SPIF_BD_ERROR_OK) {
 | 
					    if (status != SPIF_BD_ERROR_OK) {
 | 
				
			||||||
        tr_error("init - Read SFDP First Table Failed");
 | 
					        tr_error("init - Read SFDP First Table Failed");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
| 
						 | 
					@ -654,87 +650,22 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, si
 | 
				
			||||||
    _erase_instruction = SPIF_SE;
 | 
					    _erase_instruction = SPIF_SE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Set Page Size (SPI write must be done on Page limits)
 | 
					    // Set Page Size (SPI write must be done on Page limits)
 | 
				
			||||||
    _page_size_bytes = _sfdp_detect_page_size(param_table, basic_table_size);
 | 
					    _page_size_bytes = sfdp_detect_page_size(param_table, sfdp_info.bptbl.size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Detect and Set Erase Types
 | 
					    // Detect and Set Erase Types
 | 
				
			||||||
    _sfdp_detect_erase_types_inst_and_size(param_table, basic_table_size, _erase4k_inst, _sfdp_info.smptbl);
 | 
					    if (sfdp_detect_erase_types_inst_and_size(param_table, sfdp_info) < 0) {
 | 
				
			||||||
    _erase_instruction = _erase4k_inst;
 | 
					        tr_error("Init - Detecting erase types instructions/sizes failed");
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _erase_instruction = sfdp_info.bptbl.legacy_erase_instruction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Detect and Set fastest Bus mode (default 1-1-1)
 | 
					    // Detect and Set fastest Bus mode (default 1-1-1)
 | 
				
			||||||
    _sfdp_detect_best_bus_read_mode(param_table, basic_table_size, _read_instruction);
 | 
					    _sfdp_detect_best_bus_read_mode(param_table, sfdp_info.bptbl.size, _read_instruction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int SPIFBlockDevice::_sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    unsigned int page_size = SPIF_DEFAULT_PAGE_SIZE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (basic_param_table_size > SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE) {
 | 
					 | 
				
			||||||
        // Page Size is specified by 4 Bits (N), calculated by 2^N
 | 
					 | 
				
			||||||
        int page_to_power_size = ((int)basic_param_table_ptr[SPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
 | 
					 | 
				
			||||||
        page_size = local_math_power(2, page_to_power_size);
 | 
					 | 
				
			||||||
        tr_debug("Detected Page Size: %d", page_size);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        tr_debug("Using Default Page Size: %d", page_size);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return page_size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int SPIFBlockDevice::_sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
 | 
					 | 
				
			||||||
                                                            int &erase4k_inst,
 | 
					 | 
				
			||||||
                                                            sfdp_smptbl_info &smptbl)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    erase4k_inst = 0xff;
 | 
					 | 
				
			||||||
    bool found_4Kerase_type = false;
 | 
					 | 
				
			||||||
    uint8_t bitfield = 0x01;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
 | 
					 | 
				
			||||||
    erase4k_inst = basic_param_table_ptr[SPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (basic_param_table_size > SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE) {
 | 
					 | 
				
			||||||
        // Loop Erase Types 1-4
 | 
					 | 
				
			||||||
        for (int i_ind = 0; i_ind < 4; i_ind++) {
 | 
					 | 
				
			||||||
            smptbl.erase_type_inst_arr[i_ind] = 0xff; //0xFF default for unsupported type
 | 
					 | 
				
			||||||
            smptbl.erase_type_size_arr[i_ind] = local_math_power(
 | 
					 | 
				
			||||||
                                                    2, basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]); // Size given as 2^N
 | 
					 | 
				
			||||||
            tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), smptbl.erase_type_inst_arr[i_ind],
 | 
					 | 
				
			||||||
                     smptbl.erase_type_size_arr[i_ind]);
 | 
					 | 
				
			||||||
            if (smptbl.erase_type_size_arr[i_ind] > 1) {
 | 
					 | 
				
			||||||
                // if size==1 type is not supported
 | 
					 | 
				
			||||||
                smptbl.erase_type_inst_arr[i_ind] =
 | 
					 | 
				
			||||||
                    basic_param_table_ptr[SPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if ((smptbl.erase_type_size_arr[i_ind] < smptbl.regions_min_common_erase_size)
 | 
					 | 
				
			||||||
                        || (smptbl.regions_min_common_erase_size == 0)) {
 | 
					 | 
				
			||||||
                    //Set default minimal common erase for singal region
 | 
					 | 
				
			||||||
                    smptbl.regions_min_common_erase_size = smptbl.erase_type_size_arr[i_ind];
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // SFDP standard requires 4K Erase type to exist and its instruction to be identical to legacy field erase instruction
 | 
					 | 
				
			||||||
                if (smptbl.erase_type_size_arr[i_ind] == 4096) {
 | 
					 | 
				
			||||||
                    found_4Kerase_type = true;
 | 
					 | 
				
			||||||
                    if (erase4k_inst != smptbl.erase_type_inst_arr[i_ind]) {
 | 
					 | 
				
			||||||
                        //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
 | 
					 | 
				
			||||||
                        erase4k_inst = smptbl.erase_type_inst_arr[i_ind];
 | 
					 | 
				
			||||||
                        tr_warning("_detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                smptbl.region_erase_types_bitfld[0] |= bitfield; // no region map, set region "0" types bitfield as default
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            tr_info("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1),
 | 
					 | 
				
			||||||
                    smptbl.erase_type_inst_arr[i_ind], smptbl.erase_type_size_arr[i_ind]);
 | 
					 | 
				
			||||||
            bitfield = bitfield << 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (false == found_4Kerase_type) {
 | 
					 | 
				
			||||||
        tr_warning("Couldn't find Erase Type for 4KB size");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
 | 
					int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size,
 | 
				
			||||||
                                                     int &read_inst)
 | 
					                                                     int &read_inst)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -904,18 +835,3 @@ int SPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield,
 | 
				
			||||||
    return largest_erase_type;
 | 
					    return largest_erase_type;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*********************************************/
 | 
					 | 
				
			||||||
/************** Local Functions **************/
 | 
					 | 
				
			||||||
/*********************************************/
 | 
					 | 
				
			||||||
static unsigned int local_math_power(int base, int exp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    // Integer X^Y function, used to calculate size fields given in 2^N format
 | 
					 | 
				
			||||||
    int result = 1;
 | 
					 | 
				
			||||||
    while (exp) {
 | 
					 | 
				
			||||||
        result *= base;
 | 
					 | 
				
			||||||
        exp--;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return result;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -231,7 +231,8 @@ private:
 | 
				
			||||||
    int _spi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
 | 
					    int _spi_send_read_sfdp_command(mbed::bd_addr_t addr, void *rx_buffer, mbed::bd_size_t rx_length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Parse and Detect required Basic Parameters from Table
 | 
					    // Parse and Detect required Basic Parameters from Table
 | 
				
			||||||
    int _sfdp_parse_basic_param_table(uint32_t basic_table_addr, size_t basic_table_size);
 | 
					    int _sfdp_parse_basic_param_table(mbed::Callback<int(mbed::bd_addr_t, void *, mbed::bd_size_t)> sfdp_reader,
 | 
				
			||||||
 | 
					                                      mbed::sfdp_hdr_info &hdr_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Detect fastest read Bus mode supported by device
 | 
					    // Detect fastest read Bus mode supported by device
 | 
				
			||||||
    int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);
 | 
					    int _sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst);
 | 
				
			||||||
| 
						 | 
					@ -239,11 +240,6 @@ private:
 | 
				
			||||||
    // Set Page size for program
 | 
					    // Set Page size for program
 | 
				
			||||||
    unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
 | 
					    unsigned int _sfdp_detect_page_size(uint8_t *basic_param_table_ptr, int basic_param_table_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Detect all supported erase types
 | 
					 | 
				
			||||||
    int _sfdp_detect_erase_types_inst_and_size(uint8_t *basic_param_table_ptr, int basic_param_table_size,
 | 
					 | 
				
			||||||
                                               int &erase4k_inst,
 | 
					 | 
				
			||||||
                                               mbed::sfdp_smptbl_info &smptbl);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /***********************/
 | 
					    /***********************/
 | 
				
			||||||
    /* Utilities Functions */
 | 
					    /* Utilities Functions */
 | 
				
			||||||
    /***********************/
 | 
					    /***********************/
 | 
				
			||||||
| 
						 | 
					@ -302,7 +298,6 @@ private:
 | 
				
			||||||
    int _read_instruction;
 | 
					    int _read_instruction;
 | 
				
			||||||
    int _prog_instruction;
 | 
					    int _prog_instruction;
 | 
				
			||||||
    int _erase_instruction;
 | 
					    int _erase_instruction;
 | 
				
			||||||
    int _erase4k_inst;  // Legacy 4K erase instruction (default 0x20h)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Data extracted from the devices SFDP structure
 | 
					    // Data extracted from the devices SFDP structure
 | 
				
			||||||
    mbed::sfdp_hdr_info _sfdp_info;
 | 
					    mbed::sfdp_hdr_info _sfdp_info;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,24 +33,25 @@ namespace mbed {
 | 
				
			||||||
 * @{
 | 
					 * @{
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const int SFDP_HEADER_SIZE = 8; ///< Size of an SFDP header in bytes, 2 DWORDS
 | 
					constexpr int SFDP_HEADER_SIZE = 8; ///< Size of an SFDP header in bytes, 2 DWORDS
 | 
				
			||||||
static const int SFDP_BASIC_PARAMS_TBL_SIZE = 80; ///< Basic Parameter Table size in bytes, 20 DWORDS
 | 
					constexpr int SFDP_BASIC_PARAMS_TBL_SIZE = 80; ///< Basic Parameter Table size in bytes, 20 DWORDS
 | 
				
			||||||
static const int SFDP_SECTOR_MAP_MAX_REGIONS = 10; ///< Maximum number of regions with different erase granularity
 | 
					constexpr int SFDP_SECTOR_MAP_MAX_REGIONS = 10; ///< Maximum number of regions with different erase granularity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Erase Types Per Region BitMask
 | 
					// Erase Types Per Region BitMask
 | 
				
			||||||
static const int SFDP_ERASE_BITMASK_TYPE4 = 0x08; ///< Erase type 4 (erase granularity) identifier
 | 
					constexpr int SFDP_ERASE_BITMASK_TYPE4 = 0x08; ///< Erase type 4 (erase granularity) identifier
 | 
				
			||||||
static const int SFDP_ERASE_BITMASK_TYPE3 = 0x04; ///< Erase type 3 (erase granularity) identifier
 | 
					constexpr int SFDP_ERASE_BITMASK_TYPE3 = 0x04; ///< Erase type 3 (erase granularity) identifier
 | 
				
			||||||
static const int SFDP_ERASE_BITMASK_TYPE2 = 0x02; ///< Erase type 2 (erase granularity) identifier
 | 
					constexpr int SFDP_ERASE_BITMASK_TYPE2 = 0x02; ///< Erase type 2 (erase granularity) identifier
 | 
				
			||||||
static const int SFDP_ERASE_BITMASK_TYPE1 = 0x01; ///< Erase type 1 (erase granularity) identifier
 | 
					constexpr int SFDP_ERASE_BITMASK_TYPE1 = 0x01; ///< Erase type 1 (erase granularity) identifier
 | 
				
			||||||
static const int SFDP_ERASE_BITMASK_NONE = 0x00;  ///< Erase type None
 | 
					constexpr int SFDP_ERASE_BITMASK_NONE = 0x00;  ///< Erase type None
 | 
				
			||||||
static const int SFDP_ERASE_BITMASK_ALL = 0x0F;   ///< Erase type All
 | 
					constexpr int SFDP_ERASE_BITMASK_ALL = 0x0F;   ///< Erase type All
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const int SFDP_MAX_NUM_OF_ERASE_TYPES = 4;  ///< Maximum number of different erase types (erase granularity)
 | 
					constexpr int SFDP_MAX_NUM_OF_ERASE_TYPES = 4;  ///< Maximum number of different erase types (erase granularity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** SFDP Basic Parameter Table info */
 | 
					/** SFDP Basic Parameter Table info */
 | 
				
			||||||
struct sfdp_bptbl_info {
 | 
					struct sfdp_bptbl_info {
 | 
				
			||||||
    uint32_t addr; ///< Address
 | 
					    uint32_t addr; ///< Address
 | 
				
			||||||
    size_t size; ///< Size
 | 
					    size_t size; ///< Size
 | 
				
			||||||
 | 
					    int legacy_erase_instruction; ///< Legacy 4K erase instruction
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** SFDP Sector Map Table info */
 | 
					/** SFDP Sector Map Table info */
 | 
				
			||||||
| 
						 | 
					@ -72,40 +73,6 @@ struct sfdp_hdr_info {
 | 
				
			||||||
    sfdp_smptbl_info smptbl;
 | 
					    sfdp_smptbl_info smptbl;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** SFDP Header */
 | 
					 | 
				
			||||||
struct sfdp_hdr {
 | 
					 | 
				
			||||||
    uint8_t SIG_B0; ///< SFDP Signature, Byte 0
 | 
					 | 
				
			||||||
    uint8_t SIG_B1; ///< SFDP Signature, Byte 1
 | 
					 | 
				
			||||||
    uint8_t SIG_B2; ///< SFDP Signature, Byte 2
 | 
					 | 
				
			||||||
    uint8_t SIG_B3; ///< SFDP Signature, Byte 3
 | 
					 | 
				
			||||||
    uint8_t R_MINOR; ///< SFDP Minor Revision
 | 
					 | 
				
			||||||
    uint8_t R_MAJOR; ///< SFDP Major Revision
 | 
					 | 
				
			||||||
    uint8_t NPH; ///< Number of parameter headers (0-based, 0 indicates 1 parameter header)
 | 
					 | 
				
			||||||
    uint8_t ACP; ///< SFDP Access Protocol
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** SFDP Parameter header */
 | 
					 | 
				
			||||||
struct sfdp_prm_hdr {
 | 
					 | 
				
			||||||
    uint8_t PID_LSB; ///< Parameter ID LSB
 | 
					 | 
				
			||||||
    uint8_t P_MINOR; ///< Parameter Minor Revision
 | 
					 | 
				
			||||||
    uint8_t P_MAJOR; ///< Parameter Major Revision
 | 
					 | 
				
			||||||
    uint8_t P_LEN;   ///< Parameter length in DWORDS
 | 
					 | 
				
			||||||
    uint32_t DWORD2; ///< Parameter ID MSB + Parameter Table Pointer
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Parse SFDP Header
 | 
					 | 
				
			||||||
 * @param sfdp_hdr_ptr Pointer to memory holding an SFDP header
 | 
					 | 
				
			||||||
 * @return Number of Parameter Headers on success, -1 on failure
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int sfdp_parse_sfdp_header(sfdp_hdr *sfdp_hdr_ptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Parse Parameter Header
 | 
					 | 
				
			||||||
 * @param parameter_header Pointer to memory holding a single SFDP Parameter header
 | 
					 | 
				
			||||||
 * @param hdr_info Reference to a Parameter Table structure where info about the table is written
 | 
					 | 
				
			||||||
 * @return 0 on success, -1 on failure
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int sfdp_parse_single_param_header(sfdp_prm_hdr *parameter_header, sfdp_hdr_info &hdr_info);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Parse SFDP Headers
 | 
					/** Parse SFDP Headers
 | 
				
			||||||
 * Retrieves SFDP headers from a device and parses the information contained by the headers
 | 
					 * Retrieves SFDP headers from a device and parses the information contained by the headers
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -126,6 +93,24 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_smptbl_info &smtbl);
 | 
					int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader, sfdp_smptbl_info &smtbl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Detect page size used for writing on flash
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure
 | 
				
			||||||
 | 
					 * @param bptbl_size Size of memory holding a Basic Parameter Table
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return Page size
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					size_t sfdp_detect_page_size(uint8_t *bptbl_ptr, size_t bptbl_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Detect all supported erase types
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param bptbl_ptr Pointer to memory holding a Basic Parameter Table structure
 | 
				
			||||||
 | 
					 * @param smtbl     All information parsed from the table gets passed back on this structure
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return 0 on success, negative error code on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfdp_info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** @}*/
 | 
					/** @}*/
 | 
				
			||||||
} /* namespace mbed */
 | 
					} /* namespace mbed */
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,43 +42,85 @@ inline uint32_t sfdp_get_param_tbl_ptr(uint32_t dword2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace mbed {
 | 
					namespace mbed {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Verifies SFDP Header and return number of parameter headers */
 | 
					// Erase Types Params
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE = 29; ///< Erase Type 1 Instruction
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_2_BYTE = 31; ///< Erase Type 2 Instruction
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_3_BYTE = 33; ///< Erase Type 3 Instruction
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_4_BYTE = 35; ///< Erase Type 4 Instruction
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE = 28; ///< Erase Type 1 Size
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_2_SIZE_BYTE = 30; ///< Erase Type 2 Size
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_3_SIZE_BYTE = 32; ///< Erase Type 3 Size
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_4_SIZE_BYTE = 34; ///< Erase Type 4 Size
 | 
				
			||||||
 | 
					constexpr int SFDP_BASIC_PARAM_TABLE_4K_ERASE_TYPE_BYTE = 1; ///< 4 Kilobyte Erase Instruction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr int SFDP_ERASE_BITMASK_TYPE_4K_ERASE_UNSUPPORTED = 0xFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** SFDP Header */
 | 
				
			||||||
 | 
					struct sfdp_hdr {
 | 
				
			||||||
 | 
					    uint8_t SIG_B0; ///< SFDP Signature, Byte 0
 | 
				
			||||||
 | 
					    uint8_t SIG_B1; ///< SFDP Signature, Byte 1
 | 
				
			||||||
 | 
					    uint8_t SIG_B2; ///< SFDP Signature, Byte 2
 | 
				
			||||||
 | 
					    uint8_t SIG_B3; ///< SFDP Signature, Byte 3
 | 
				
			||||||
 | 
					    uint8_t R_MINOR; ///< SFDP Minor Revision
 | 
				
			||||||
 | 
					    uint8_t R_MAJOR; ///< SFDP Major Revision
 | 
				
			||||||
 | 
					    uint8_t NPH; ///< Number of parameter headers (0-based, 0 indicates 1 parameter header)
 | 
				
			||||||
 | 
					    uint8_t ACP; ///< SFDP Access Protocol
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** SFDP Parameter header */
 | 
				
			||||||
 | 
					struct sfdp_prm_hdr {
 | 
				
			||||||
 | 
					    uint8_t PID_LSB; ///< Parameter ID LSB
 | 
				
			||||||
 | 
					    uint8_t P_MINOR; ///< Parameter Minor Revision
 | 
				
			||||||
 | 
					    uint8_t P_MAJOR; ///< Parameter Major Revision
 | 
				
			||||||
 | 
					    uint8_t P_LEN;   ///< Parameter length in DWORDS
 | 
				
			||||||
 | 
					    uint32_t DWORD2; ///< Parameter ID MSB + Parameter Table Pointer
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Parse SFDP Header
 | 
				
			||||||
 | 
					 * @param sfdp_hdr_ptr Pointer to memory holding an SFDP header
 | 
				
			||||||
 | 
					 * @return Number of Parameter Headers on success, -1 on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
int sfdp_parse_sfdp_header(sfdp_hdr *sfdp_hdr_ptr)
 | 
					int sfdp_parse_sfdp_header(sfdp_hdr *sfdp_hdr_ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!(memcmp(sfdp_hdr_ptr, "SFDP", 4) == 0 && sfdp_hdr_ptr->R_MAJOR == 1)) {
 | 
					    if (!(memcmp(sfdp_hdr_ptr, "SFDP", 4) == 0 && sfdp_hdr_ptr->R_MAJOR == 1)) {
 | 
				
			||||||
        tr_error("verify SFDP signature and version Failed");
 | 
					        tr_error("Verify SFDP signature and version Failed");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    tr_debug("init - verified SFDP Signature and version Successfully");
 | 
					    tr_debug("Verified SFDP Signature and version successfully");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int hdr_cnt = sfdp_hdr_ptr->NPH + 1;
 | 
					    int hdr_cnt = sfdp_hdr_ptr->NPH + 1;
 | 
				
			||||||
    tr_debug("number of Param Headers: %d", hdr_cnt);
 | 
					    tr_debug("Number of parameter headers: %d", hdr_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return hdr_cnt;
 | 
					    return hdr_cnt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr, sfdp_hdr_info &hdr_info)
 | 
					/** Parse Parameter Header
 | 
				
			||||||
 | 
					 * @param phdr_ptr Pointer to memory holding a single SFDP Parameter header
 | 
				
			||||||
 | 
					 * @param hdr_info Reference to a Parameter Table structure where info about the table is written
 | 
				
			||||||
 | 
					 * @return 0 on success, -1 on failure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int sfdp_parse_single_param_header(sfdp_prm_hdr *phdr_ptr, sfdp_hdr_info &hdr_info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (phdr->P_MAJOR != 1) {
 | 
					    if (phdr_ptr->P_MAJOR != 1) {
 | 
				
			||||||
        tr_error("Param Header: - Major Version should be 1!");
 | 
					        tr_error("Parameter header: Major Version must be 1!");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((phdr->PID_LSB == 0) && (sfdp_get_param_id_msb(phdr->DWORD2) == 0xFF)) {
 | 
					    if ((phdr_ptr->PID_LSB == 0) && (sfdp_get_param_id_msb(phdr_ptr->DWORD2) == 0xFF)) {
 | 
				
			||||||
        tr_debug("Parameter Header: Basic Parameter Header");
 | 
					        tr_debug("Parameter header: Basic Parameter Header");
 | 
				
			||||||
        hdr_info.bptbl.addr = sfdp_get_param_tbl_ptr(phdr->DWORD2);
 | 
					        hdr_info.bptbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
 | 
				
			||||||
        hdr_info.bptbl.size = std::min((phdr->P_LEN * 4), SFDP_BASIC_PARAMS_TBL_SIZE);
 | 
					        hdr_info.bptbl.size = std::min((phdr_ptr->P_LEN * 4), SFDP_BASIC_PARAMS_TBL_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else if ((phdr->PID_LSB == 0x81) && (sfdp_get_param_id_msb(phdr->DWORD2) == 0xFF)) {
 | 
					    } else if ((phdr_ptr->PID_LSB == 0x81) && (sfdp_get_param_id_msb(phdr_ptr->DWORD2) == 0xFF)) {
 | 
				
			||||||
        tr_debug("Parameter Header: Sector Map Parameter Header");
 | 
					        tr_debug("Parameter header: Sector Map Parameter Header");
 | 
				
			||||||
        hdr_info.smptbl.addr = sfdp_get_param_tbl_ptr(phdr->DWORD2);
 | 
					        hdr_info.smptbl.addr = sfdp_get_param_tbl_ptr(phdr_ptr->DWORD2);
 | 
				
			||||||
        hdr_info.smptbl.size = phdr->P_LEN * 4;
 | 
					        hdr_info.smptbl.size = phdr_ptr->P_LEN * 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        tr_debug("Parameter Header vendor specific or unknown. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "",
 | 
					        tr_debug("Parameter header: header vendor specific or unknown. Parameter ID LSB: 0x%" PRIX8 "; MSB: 0x%" PRIX8 "",
 | 
				
			||||||
                 phdr->PID_LSB,
 | 
					                 phdr_ptr->PID_LSB,
 | 
				
			||||||
                 sfdp_get_param_id_msb(phdr->DWORD2));
 | 
					                 sfdp_get_param_id_msb(phdr_ptr->DWORD2));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
| 
						 | 
					@ -96,7 +138,7 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int status = sfdp_reader(addr, sfdp_header, data_length);
 | 
					        int status = sfdp_reader(addr, sfdp_header, data_length);
 | 
				
			||||||
        if (status < 0) {
 | 
					        if (status < 0) {
 | 
				
			||||||
            tr_error("retrieving SFDP Header failed");
 | 
					            tr_error("Retrieving SFDP Header failed");
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,7 +160,7 @@ int sfdp_parse_headers(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp_reader,
 | 
				
			||||||
        for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
 | 
					        for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
 | 
				
			||||||
            status = sfdp_reader(addr, param_header, data_length);
 | 
					            status = sfdp_reader(addr, param_header, data_length);
 | 
				
			||||||
            if (status < 0) {
 | 
					            if (status < 0) {
 | 
				
			||||||
                tr_error("retrieving Parameter Header %d failed", i_ind + 1);
 | 
					                tr_error("Retrieving a parameter header %d failed", i_ind + 1);
 | 
				
			||||||
                return -1;
 | 
					                return -1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,19 +187,19 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int status = sfdp_reader(smptbl.addr, sector_map_table, smptbl.size);
 | 
					    int status = sfdp_reader(smptbl.addr, sector_map_table, smptbl.size);
 | 
				
			||||||
    if (status < 0) {
 | 
					    if (status < 0) {
 | 
				
			||||||
        tr_error("table retrieval failed");
 | 
					        tr_error("Sector Map: Table retrieval failed");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Currently we support only Single Map Descriptor
 | 
					    // Currently we support only Single Map Descriptor
 | 
				
			||||||
    if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) {
 | 
					    if (!((sector_map_table[0] & 0x3) == 0x03) && (sector_map_table[1] == 0x0)) {
 | 
				
			||||||
        tr_error("Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
 | 
					        tr_error("Sector Map: Supporting Only Single Map Descriptor (not map commands)");
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    smptbl.region_cnt = sector_map_table[2] + 1;
 | 
					    smptbl.region_cnt = sector_map_table[2] + 1;
 | 
				
			||||||
    if (smptbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) {
 | 
					    if (smptbl.region_cnt > SFDP_SECTOR_MAP_MAX_REGIONS) {
 | 
				
			||||||
        tr_error("Supporting up to %d regions, current setup to %d regions - fail",
 | 
					        tr_error("Sector Map: Supporting up to %d regions, current setup to %d regions - fail",
 | 
				
			||||||
                 SFDP_SECTOR_MAP_MAX_REGIONS,
 | 
					                 SFDP_SECTOR_MAP_MAX_REGIONS,
 | 
				
			||||||
                 smptbl.region_cnt);
 | 
					                 smptbl.region_cnt);
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
| 
						 | 
					@ -192,5 +234,68 @@ int sfdp_parse_sector_map_table(Callback<int(bd_addr_t, void *, bd_size_t)> sfdp
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t sfdp_detect_page_size(uint8_t *basic_param_table_ptr, size_t basic_param_table_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    constexpr int SFDP_BASIC_PARAM_TABLE_PAGE_SIZE = 40;
 | 
				
			||||||
 | 
					    constexpr int SFDP_DEFAULT_PAGE_SIZE = 256;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    unsigned int page_size = SFDP_DEFAULT_PAGE_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (basic_param_table_size > SFDP_BASIC_PARAM_TABLE_PAGE_SIZE) {
 | 
				
			||||||
 | 
					        // Page Size is specified by 4 Bits (N), calculated by 2^N
 | 
				
			||||||
 | 
					        int page_to_power_size = ((int)basic_param_table_ptr[SFDP_BASIC_PARAM_TABLE_PAGE_SIZE]) >> 4;
 | 
				
			||||||
 | 
					        page_size = 1 << page_to_power_size;
 | 
				
			||||||
 | 
					        tr_debug("Detected Page Size: %d", page_size);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        tr_debug("Using Default Page Size: %d", page_size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return page_size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sfdp_detect_erase_types_inst_and_size(uint8_t *bptbl_ptr, sfdp_hdr_info &sfdp_info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t bitfield = 0x01;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
 | 
				
			||||||
 | 
					    if (sfdp_info.bptbl.size > SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE) {
 | 
				
			||||||
 | 
					        // Loop Erase Types 1-4
 | 
				
			||||||
 | 
					        for (int i_ind = 0; i_ind < 4; i_ind++) {
 | 
				
			||||||
 | 
					            sfdp_info.smptbl.erase_type_inst_arr[i_ind] = -1; // Default for unsupported type
 | 
				
			||||||
 | 
					            sfdp_info.smptbl.erase_type_size_arr[i_ind] = 1
 | 
				
			||||||
 | 
					                                                          << bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]; // Size is 2^N where N is the table value
 | 
				
			||||||
 | 
					            tr_debug("Erase Type(A) %d - Inst: 0x%xh, Size: %d", (i_ind + 1), sfdp_info.smptbl.erase_type_inst_arr[i_ind],
 | 
				
			||||||
 | 
					                     sfdp_info.smptbl.erase_type_size_arr[i_ind]);
 | 
				
			||||||
 | 
					            if (sfdp_info.smptbl.erase_type_size_arr[i_ind] > 1) {
 | 
				
			||||||
 | 
					                // if size==1 type is not supported
 | 
				
			||||||
 | 
					                sfdp_info.smptbl.erase_type_inst_arr[i_ind] = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE
 | 
				
			||||||
 | 
					                                                                        + 2 * i_ind];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ((sfdp_info.smptbl.erase_type_size_arr[i_ind] < sfdp_info.smptbl.regions_min_common_erase_size)
 | 
				
			||||||
 | 
					                        || (sfdp_info.smptbl.regions_min_common_erase_size == 0)) {
 | 
				
			||||||
 | 
					                    //Set default minimal common erase for signal region
 | 
				
			||||||
 | 
					                    sfdp_info.smptbl.regions_min_common_erase_size = sfdp_info.smptbl.erase_type_size_arr[i_ind];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                sfdp_info.smptbl.region_erase_types_bitfld[0] |= bitfield; // If there's no region map, set region "0" types bitfield as default
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            tr_debug("Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), sfdp_info.smptbl.erase_type_inst_arr[i_ind],
 | 
				
			||||||
 | 
					                     sfdp_info.smptbl.erase_type_size_arr[i_ind]);
 | 
				
			||||||
 | 
					            bitfield = bitfield << 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        tr_debug("Erase types are not available - falling back to legacy 4k erase instruction");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sfdp_info.bptbl.legacy_erase_instruction = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_4K_ERASE_TYPE_BYTE];
 | 
				
			||||||
 | 
					        if (sfdp_info.bptbl.legacy_erase_instruction == SFDP_ERASE_BITMASK_TYPE_4K_ERASE_UNSUPPORTED) {
 | 
				
			||||||
 | 
					            tr_error("Legacy 4k erase instruction not supported");
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} /* namespace mbed */
 | 
					} /* namespace mbed */
 | 
				
			||||||
#endif /* (DEVICE_SPI || DEVICE_QSPI) */
 | 
					#endif /* (DEVICE_SPI || DEVICE_QSPI) */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue