diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp index c13d776a32..67924eb5c2 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp @@ -118,6 +118,11 @@ static int local_math_power(int base, int exp); // General QSPI instructions #define QSPIF_INST_WSR1 0x01 // Write status register 1 #define QSPIF_INST_RSR1 0x05 // Read status register 1 +#define QSPIF_INST_RSFDP 0x5A // Read SFDP +#define QSPIF_INST_RDID 0x9F // Read Manufacturer and JDEC Device ID + +// Device-specific instructions +#define QSPIF_INST_ULBPR 0x98 // Clear all write-protection bits in the Block-Protection register // Default status register 2 read/write instructions #define QSPIF_INST_WSR2_DEFAULT QSPI_NO_INST @@ -126,6 +131,11 @@ static int local_math_power(int base, int exp); // Default 4-byte extended addressing register write instruction #define QSPIF_INST_4BYTE_REG_WRITE_DEFAULT QSPI_NO_INST + +// Length of data returned from RDID instruction +#define QSPI_RDID_DATA_LENGTH 3 + + /* Init function to initialize Different Devices CS static list */ static PinName *generate_initialized_active_qspif_csel_arr(); // Static Members for different devices csel @@ -172,14 +182,11 @@ int QSPIFBlockDevice::init() return QSPIF_BD_ERROR_DEVICE_MAX_EXCEED; } - uint8_t vendor_device_ids[4]; - size_t data_length = 3; int status = QSPIF_BD_ERROR_OK; uint32_t basic_table_addr = 0; size_t basic_table_size = 0; uint32_t sector_map_table_addr = 0; size_t sector_map_table_size = 0; - int qspi_status = QSPI_STATUS_OK; _mutex.lock(); @@ -211,26 +218,6 @@ int QSPIFBlockDevice::init() goto exit_point; } - /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/ - qspi_status = _qspi_send_general_command(QSPIF_RDID, QSPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)vendor_device_ids, - data_length); - if (qspi_status != QSPI_STATUS_OK) { - tr_error("Init - Read Vendor ID Failed"); - status = QSPIF_BD_ERROR_DEVICE_ERROR; - goto exit_point; - } - - tr_debug("Vendor device ID = 0x%x 0x%x 0x%x 0x%x", vendor_device_ids[0], - vendor_device_ids[1], vendor_device_ids[2], vendor_device_ids[3]); - switch (vendor_device_ids[0]) { - case 0xbf: - // SST devices come preset with block protection - // enabled for some regions, issue global protection unlock to clear - _set_write_enable(); - _qspi_send_general_command(QSPIF_ULBPR, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0); - break; - } - //Synchronize Device if (false == _is_mem_ready()) { tr_error("Init - _is_mem_ready Failed"); @@ -275,6 +262,12 @@ int QSPIFBlockDevice::init() goto exit_point; } + if (0 != _clear_block_protection()) { + tr_error("Init - clearing block protection failed"); + status = QSPIF_BD_ERROR_PARSING_FAILED; + goto exit_point; + } + _is_initialized = true; exit_point: @@ -1233,6 +1226,64 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_add return 0; } +int QSPIFBlockDevice::_clear_block_protection() +{ + 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, + (char *) vendor_device_ids, QSPI_RDID_DATA_LENGTH); + if (QSPI_STATUS_OK != status) { + tr_error("Read Vendor ID Failed"); + return -1; + } + + 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 + if (0 != _set_write_enable()) { + tr_error("Write enable failed"); + return -1; + } + status = _qspi_send_general_command(QSPIF_INST_ULBPR, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0); + if (QSPI_STATUS_OK != status) { + tr_error("Global block protection unlock failed"); + return -1; + } + break; + default: + // For all other devices, clear all bits in status register 1 that aren't the WIP or WEL bits to clear the block protection bits + status = _qspi_read_status_registers(status_regs); + if (QSPI_STATUS_OK != status) { + tr_error("_clear_block_protection - Status register read failed"); + return -1; + } + status_regs[0] &= (QSPIF_STATUS_BIT_WIP | QSPIF_STATUS_BIT_WEL); + status = _qspi_write_status_registers(status_regs); + if (QSPI_STATUS_OK != status) { + tr_error("__clear_block_protection - Status register write failed"); + return -1; + } + break; + } + + if (false == _is_mem_ready()) { + tr_error("Device not ready, clearing block protection failed"); + return -1; + } + + return 0; +} + int QSPIFBlockDevice::_set_write_enable() { // Check Status Register Busy Bit to Verify the Device isn't Busy diff --git a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h index bbf1b7460a..9039146095 100644 --- a/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h @@ -268,6 +268,8 @@ private: /*********************************/ /* Flash Configuration Functions */ /*********************************/ + // Clear the device's block protection + int _clear_block_protection(); // Configure Write Enable in Status Register int _set_write_enable();