From 6a60574cf590d7fc67e1be8af7b37ed7f13cd4b2 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Thu, 13 Feb 2020 10:42:21 +0200 Subject: [PATCH] SFDP: consolidates sfdp_detect_erase_types_inst_and_size --- .../COMPONENT_QSPIF/QSPIFBlockDevice.cpp | 56 ++----------------- .../COMPONENT_QSPIF/QSPIFBlockDevice.h | 6 -- .../COMPONENT_SPIF/SPIFBlockDevice.cpp | 55 +++--------------- .../COMPONENT_SPIF/SPIFBlockDevice.h | 5 -- drivers/internal/SFDP.h | 35 ++++++------ drivers/source/SFDP.cpp | 56 +++++++++++++++++++ 6 files changed, 85 insertions(+), 128 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 4e776f7e4f..61db90fe49 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -140,6 +140,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam } // 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.region_cnt = 1; _sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; @@ -159,7 +160,6 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam // Set default read/erase instructions _read_instruction = QSPIF_INST_READ_DEFAULT; - _legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT; _num_status_registers = QSPI_DEFAULT_STATUS_REGISTERS; // Set default status register 2 write/read instructions @@ -417,7 +417,7 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) // For each iteration erase the largest section supported by current region while (size > 0) { 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. // Find the matching instruction and erase size chunk for that type. type = _utils_iterate_next_largest_erase_type(bitfield, size, (int)addr, @@ -427,7 +427,7 @@ int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t in_size) eu_size = _sfdp_info.smptbl.erase_type_size_arr[type]; } else { // 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; } offset = addr % eu_size; @@ -508,7 +508,7 @@ const char *QSPIFBlockDevice::get_type() const 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 (_legacy_erase_instruction != QSPI_NO_INST) { + if (_sfdp_info.bptbl.legacy_erase_instruction != QSPI_NO_INST) { return QSPIF_DEFAULT_SE_SIZE; } @@ -651,7 +651,7 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(Callback SFDP_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[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), 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[SFDP_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[SFDP_BASIC_PARAM_TABLE_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, bool &set_quad_enable, bool &is_qpi_mode) { diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index 8c20b40eef..41928708f3 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -336,11 +336,6 @@ private: // Set Page size for program 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 int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size); @@ -386,7 +381,6 @@ private: // Command Instructions mbed::qspi_inst_t _read_instruction; - int _legacy_erase_instruction; // Status register write/read instructions unsigned int _num_status_registers; diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp index 1e4110e646..9e7c3d6532 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.cpp @@ -98,14 +98,13 @@ SPIFBlockDevice::SPIFBlockDevice( _write_dummy_and_mode_cycles = 0; _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.region_cnt = 1; _sfdp_info.smptbl.region_erase_types_bitfld[0] = SFDP_ERASE_BITMASK_NONE; // Set default read/erase instructions _read_instruction = SPIF_INST_READ_DEFAULT; - _legacy_erase_instruction = SPIF_INST_LEGACY_ERASE_DEFAULT; - if (SPIF_BD_ERROR_OK != _spi_set_frequency(freq)) { tr_error("SPI Set Frequency Failed"); @@ -653,8 +652,12 @@ int SPIFBlockDevice::_sfdp_parse_basic_param_table(Callback SFDP_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] = 0xff; //0xFF default for unsupported type - smptbl.erase_type_size_arr[i_ind] = 1 - << basic_param_table_ptr[SFDP_BASIC_PARAM_TABLE_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[SFDP_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 singal region - smptbl.regions_min_common_erase_size = smptbl.erase_type_size_arr[i_ind]; - } - 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; - } - } 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[SFDP_BASIC_PARAM_TABLE_4K_ERASE_TYPE_BYTE]; - if (_legacy_erase_instruction == 0xFF) { - tr_error("sfdp_detect_erase_types_inst_and_size - Legacy 4k erase instruction not supported"); - return -1; - } - } - return 0; -} - int SPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table_ptr, int basic_param_table_size, int &read_inst) { diff --git a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h index 20b3389c25..7f8784e594 100644 --- a/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SPIF/SPIFBlockDevice.h @@ -239,10 +239,6 @@ private: // Set Page size for program 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, - mbed::sfdp_smptbl_info &smptbl); - /***********************/ /* Utilities Functions */ /***********************/ @@ -301,7 +297,6 @@ private: int _read_instruction; int _prog_instruction; int _erase_instruction; - int _legacy_erase_instruction; // Legacy 4K erase instruction (default 0x20h) // Data extracted from the devices SFDP structure mbed::sfdp_hdr_info _sfdp_info; diff --git a/drivers/internal/SFDP.h b/drivers/internal/SFDP.h index d09512875a..0cf268bb56 100644 --- a/drivers/internal/SFDP.h +++ b/drivers/internal/SFDP.h @@ -38,30 +38,20 @@ static const int SFDP_BASIC_PARAMS_TBL_SIZE = 80; ///< Basic Parameter Table siz static const int SFDP_SECTOR_MAP_MAX_REGIONS = 10; ///< Maximum number of regions with different erase granularity // Erase Types Per Region BitMask -static const 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 -static const 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 -static const 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_TYPE4 = 0x08; ///< Erase type 4 (erase granularity) identifier +constexpr int SFDP_ERASE_BITMASK_TYPE3 = 0x04; ///< Erase type 3 (erase granularity) identifier +constexpr int SFDP_ERASE_BITMASK_TYPE2 = 0x02; ///< Erase type 2 (erase granularity) identifier +constexpr int SFDP_ERASE_BITMASK_TYPE1 = 0x01; ///< Erase type 1 (erase granularity) identifier +constexpr int SFDP_ERASE_BITMASK_NONE = 0x00; ///< Erase type None +constexpr int SFDP_ERASE_BITMASK_ALL = 0x0F; ///< Erase type All -// Erase Types Params -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_BYTE 29 -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_2_BYTE 31 -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_3_BYTE 33 -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_4_BYTE 35 -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_1_SIZE_BYTE 28 -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_2_SIZE_BYTE 30 -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_3_SIZE_BYTE 32 -#define SFDP_BASIC_PARAM_TABLE_ERASE_TYPE_4_SIZE_BYTE 34 -#define SFDP_BASIC_PARAM_TABLE_4K_ERASE_TYPE_BYTE 1 - -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 */ struct sfdp_bptbl_info { uint32_t addr; ///< Address size_t size; ///< Size + int legacy_erase_instruction; ///< Legacy 4K erase instruction }; /** SFDP Sector Map Table info */ @@ -146,6 +136,15 @@ int sfdp_parse_sector_map_table(Callback sfdp */ 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 */ #endif diff --git a/drivers/source/SFDP.cpp b/drivers/source/SFDP.cpp index 3c43da35f9..17521b6113 100644 --- a/drivers/source/SFDP.cpp +++ b/drivers/source/SFDP.cpp @@ -42,6 +42,17 @@ inline uint32_t sfdp_get_param_tbl_ptr(uint32_t dword2) namespace mbed { +// 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 + /* Verifies SFDP Header and return number of parameter headers */ int sfdp_parse_sfdp_header(sfdp_hdr *sfdp_hdr_ptr) { @@ -210,6 +221,51 @@ size_t sfdp_detect_page_size(uint8_t *basic_param_table_ptr, size_t basic_param_ 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("SFDP erase types are not available - falling back to legacy 4k erase instruction"); + + // 0xFF indicates that the legacy 4k erase instruction is not supported + sfdp_info.bptbl.legacy_erase_instruction = bptbl_ptr[SFDP_BASIC_PARAM_TABLE_4K_ERASE_TYPE_BYTE]; + if (sfdp_info.bptbl.legacy_erase_instruction == 0xFF) { + tr_error("_detectEraseTypesInstAndSize - Legacy 4k erase instruction not supported"); + return -1; + } + } + + return 0; +} + + } /* namespace mbed */ #endif /* (DEVICE_SPI || DEVICE_QSPI) */