diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index 7e15d37b64..619c786090 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -178,6 +178,8 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam _write_status_reg_2_inst = QSPIF_INST_WSR2_DEFAULT; _read_status_reg_2_inst = QSPIF_INST_RSR2_DEFAULT; + _clear_protection_method = QSPIF_BP_CLEAR_SR; + // Set default 4-byte addressing extension register write instruction _4byte_msb_reg_write_inst = QSPIF_INST_4BYTE_REG_WRITE_DEFAULT; } @@ -235,6 +237,12 @@ int QSPIFBlockDevice::init() goto exit_point; } + if (0 != _handle_vendor_quirks()) { + tr_error("Init - Could not read vendor id"); + status = QSPIF_BD_ERROR_DEVICE_ERROR; + goto exit_point; + } + /**************************** Parse SFDP Header ***********************************/ if (0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) { tr_error("Init - Parse SFDP Headers Failed"); @@ -1204,16 +1212,9 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_add return 0; } -int QSPIFBlockDevice::_clear_block_protection() +int QSPIFBlockDevice::_handle_vendor_quirks() { uint8_t vendor_device_ids[QSPI_RDID_DATA_LENGTH] = {0}; - uint8_t status_regs[QSPI_STATUS_REGISTER_COUNT] = {0}; - - if (false == _is_mem_ready()) { - tr_error("Device not ready, clearing block protection failed"); - return -1; - } - /* Read Manufacturer ID (1byte), and Device ID (2bytes) */ qspi_status_t status = _qspi_send_general_command(QSPIF_INST_RDID, QSPI_NO_ADDRESS_COMMAND, NULL, 0, @@ -1224,8 +1225,31 @@ int QSPIFBlockDevice::_clear_block_protection() } tr_debug("Vendor device ID = 0x%x 0x%x 0x%x", vendor_device_ids[0], vendor_device_ids[1], vendor_device_ids[2]); + switch (vendor_device_ids[0]) { case 0xbf: + // SST devices come preset with block protection + // enabled for some regions, issue global protection unlock to clear + tr_debug("Applying quirks for SST"); + _clear_protection_method = QSPIF_BP_ULBPR; + break; + } + + return 0; +} + +int QSPIFBlockDevice::_clear_block_protection() +{ + uint8_t status_regs[QSPI_STATUS_REGISTER_COUNT] = {0}; + + if (false == _is_mem_ready()) { + tr_error("Device not ready, clearing block protection failed"); + return -1; + } + qspi_status_t status; + switch (_clear_protection_method) { + case QSPIF_BP_ULBPR: + tr_debug("Clearing block protection via ULBPR"); // SST devices come preset with block protection // enabled for some regions, issue global protection unlock to clear if (0 != _set_write_enable()) { @@ -1238,9 +1262,10 @@ int QSPIFBlockDevice::_clear_block_protection() return -1; } break; - default: + case QSPIF_BP_CLEAR_SR: // For all other devices, to clear the block protection bits clear all bits // in status register 1 that aren't the WIP or WEL bits, or the QE bit (if it is in SR 1) + tr_debug("Clearing block protection via status register protection bits"); status = _qspi_read_status_registers(status_regs); if (QSPI_STATUS_OK != status) { tr_error("_clear_block_protection - Status register read failed"); diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index b2e99a638c..276c647916 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -313,6 +313,9 @@ private: // 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); + // Query vendor ID and handle special behavior that isn't covered by SFDP data + int _handle_vendor_quirks(); + /***********************/ /* Utilities Functions */ /***********************/ @@ -324,6 +327,11 @@ private: int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry); private: + enum qspif_clear_protection_method_t { + QSPIF_BP_ULBPR, // Issue global protection unlock instruction + QSPIF_BP_CLEAR_SR, // Clear protection bits in status register 1 + }; + // QSPI Driver Object mbed::QSPI _qspi; @@ -360,6 +368,9 @@ private: int _quad_enable_register_idx; int _quad_enable_bit; + // Clear block protection + qspif_clear_protection_method_t _clear_protection_method; + // Sector Regions Map int _regions_count; //number of regions int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size in bytes