QSPIF: Centralize handling of vendor quirks

Introduce a separate function for handling alterations to device interaction
which are not covered by the SFDP tables and therefore require checking against
the vendor id.
pull/11531/head
Kyle Kearney 2019-10-24 10:44:47 -07:00
parent 26314d96c5
commit eb5494e7a9
2 changed files with 45 additions and 9 deletions

View File

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

View File

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