Skip to content

Commit eb5494e

Browse files
author
Kyle Kearney
committed
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.
1 parent 26314d9 commit eb5494e

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
178178
_write_status_reg_2_inst = QSPIF_INST_WSR2_DEFAULT;
179179
_read_status_reg_2_inst = QSPIF_INST_RSR2_DEFAULT;
180180

181+
_clear_protection_method = QSPIF_BP_CLEAR_SR;
182+
181183
// Set default 4-byte addressing extension register write instruction
182184
_4byte_msb_reg_write_inst = QSPIF_INST_4BYTE_REG_WRITE_DEFAULT;
183185
}
@@ -235,6 +237,12 @@ int QSPIFBlockDevice::init()
235237
goto exit_point;
236238
}
237239

240+
if (0 != _handle_vendor_quirks()) {
241+
tr_error("Init - Could not read vendor id");
242+
status = QSPIF_BD_ERROR_DEVICE_ERROR;
243+
goto exit_point;
244+
}
245+
238246
/**************************** Parse SFDP Header ***********************************/
239247
if (0 != _sfdp_parse_sfdp_headers(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
240248
tr_error("Init - Parse SFDP Headers Failed");
@@ -1204,16 +1212,9 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_add
12041212
return 0;
12051213
}
12061214

1207-
int QSPIFBlockDevice::_clear_block_protection()
1215+
int QSPIFBlockDevice::_handle_vendor_quirks()
12081216
{
12091217
uint8_t vendor_device_ids[QSPI_RDID_DATA_LENGTH] = {0};
1210-
uint8_t status_regs[QSPI_STATUS_REGISTER_COUNT] = {0};
1211-
1212-
if (false == _is_mem_ready()) {
1213-
tr_error("Device not ready, clearing block protection failed");
1214-
return -1;
1215-
}
1216-
12171218
/* Read Manufacturer ID (1byte), and Device ID (2bytes) */
12181219
qspi_status_t status = _qspi_send_general_command(QSPIF_INST_RDID, QSPI_NO_ADDRESS_COMMAND,
12191220
NULL, 0,
@@ -1224,8 +1225,31 @@ int QSPIFBlockDevice::_clear_block_protection()
12241225
}
12251226

12261227
tr_debug("Vendor device ID = 0x%x 0x%x 0x%x", vendor_device_ids[0], vendor_device_ids[1], vendor_device_ids[2]);
1228+
12271229
switch (vendor_device_ids[0]) {
12281230
case 0xbf:
1231+
// SST devices come preset with block protection
1232+
// enabled for some regions, issue global protection unlock to clear
1233+
tr_debug("Applying quirks for SST");
1234+
_clear_protection_method = QSPIF_BP_ULBPR;
1235+
break;
1236+
}
1237+
1238+
return 0;
1239+
}
1240+
1241+
int QSPIFBlockDevice::_clear_block_protection()
1242+
{
1243+
uint8_t status_regs[QSPI_STATUS_REGISTER_COUNT] = {0};
1244+
1245+
if (false == _is_mem_ready()) {
1246+
tr_error("Device not ready, clearing block protection failed");
1247+
return -1;
1248+
}
1249+
qspi_status_t status;
1250+
switch (_clear_protection_method) {
1251+
case QSPIF_BP_ULBPR:
1252+
tr_debug("Clearing block protection via ULBPR");
12291253
// SST devices come preset with block protection
12301254
// enabled for some regions, issue global protection unlock to clear
12311255
if (0 != _set_write_enable()) {
@@ -1238,9 +1262,10 @@ int QSPIFBlockDevice::_clear_block_protection()
12381262
return -1;
12391263
}
12401264
break;
1241-
default:
1265+
case QSPIF_BP_CLEAR_SR:
12421266
// For all other devices, to clear the block protection bits clear all bits
12431267
// in status register 1 that aren't the WIP or WEL bits, or the QE bit (if it is in SR 1)
1268+
tr_debug("Clearing block protection via status register protection bits");
12441269
status = _qspi_read_status_registers(status_regs);
12451270
if (QSPI_STATUS_OK != status) {
12461271
tr_error("_clear_block_protection - Status register read failed");

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
313313
// Detect 4-byte addressing mode and enable it if supported
314314
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
315315

316+
// Query vendor ID and handle special behavior that isn't covered by SFDP data
317+
int _handle_vendor_quirks();
318+
316319
/***********************/
317320
/* Utilities Functions */
318321
/***********************/
@@ -324,6 +327,11 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
324327
int _utils_iterate_next_largest_erase_type(uint8_t &bitfield, int size, int offset, int boundry);
325328

326329
private:
330+
enum qspif_clear_protection_method_t {
331+
QSPIF_BP_ULBPR, // Issue global protection unlock instruction
332+
QSPIF_BP_CLEAR_SR, // Clear protection bits in status register 1
333+
};
334+
327335
// QSPI Driver Object
328336
mbed::QSPI _qspi;
329337

@@ -360,6 +368,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
360368
int _quad_enable_register_idx;
361369
int _quad_enable_bit;
362370

371+
// Clear block protection
372+
qspif_clear_protection_method_t _clear_protection_method;
373+
363374
// Sector Regions Map
364375
int _regions_count; //number of regions
365376
int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size in bytes

0 commit comments

Comments
 (0)