Clear block protection on non-SST flash devices

pull/11531/head
Matthew Macovsky 2019-08-30 02:54:59 -07:00 committed by Kyle Kearney
parent cf9b6d565a
commit 08a0b3daeb
2 changed files with 76 additions and 23 deletions

View File

@ -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

View File

@ -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();