Skip to content

Commit 08a0b3d

Browse files
Matthew MacovskyKyle Kearney
authored andcommitted
Clear block protection on non-SST flash devices
1 parent cf9b6d5 commit 08a0b3d

File tree

2 files changed

+76
-23
lines changed

2 files changed

+76
-23
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ static int local_math_power(int base, int exp);
118118
// General QSPI instructions
119119
#define QSPIF_INST_WSR1 0x01 // Write status register 1
120120
#define QSPIF_INST_RSR1 0x05 // Read status register 1
121+
#define QSPIF_INST_RSFDP 0x5A // Read SFDP
122+
#define QSPIF_INST_RDID 0x9F // Read Manufacturer and JDEC Device ID
123+
124+
// Device-specific instructions
125+
#define QSPIF_INST_ULBPR 0x98 // Clear all write-protection bits in the Block-Protection register
121126

122127
// Default status register 2 read/write instructions
123128
#define QSPIF_INST_WSR2_DEFAULT QSPI_NO_INST
@@ -126,6 +131,11 @@ static int local_math_power(int base, int exp);
126131
// Default 4-byte extended addressing register write instruction
127132
#define QSPIF_INST_4BYTE_REG_WRITE_DEFAULT QSPI_NO_INST
128133

134+
135+
// Length of data returned from RDID instruction
136+
#define QSPI_RDID_DATA_LENGTH 3
137+
138+
129139
/* Init function to initialize Different Devices CS static list */
130140
static PinName *generate_initialized_active_qspif_csel_arr();
131141
// Static Members for different devices csel
@@ -172,14 +182,11 @@ int QSPIFBlockDevice::init()
172182
return QSPIF_BD_ERROR_DEVICE_MAX_EXCEED;
173183
}
174184

175-
uint8_t vendor_device_ids[4];
176-
size_t data_length = 3;
177185
int status = QSPIF_BD_ERROR_OK;
178186
uint32_t basic_table_addr = 0;
179187
size_t basic_table_size = 0;
180188
uint32_t sector_map_table_addr = 0;
181189
size_t sector_map_table_size = 0;
182-
int qspi_status = QSPI_STATUS_OK;
183190

184191
_mutex.lock();
185192

@@ -211,26 +218,6 @@ int QSPIFBlockDevice::init()
211218
goto exit_point;
212219
}
213220

214-
/* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
215-
qspi_status = _qspi_send_general_command(QSPIF_RDID, QSPI_NO_ADDRESS_COMMAND, NULL, 0, (char *)vendor_device_ids,
216-
data_length);
217-
if (qspi_status != QSPI_STATUS_OK) {
218-
tr_error("Init - Read Vendor ID Failed");
219-
status = QSPIF_BD_ERROR_DEVICE_ERROR;
220-
goto exit_point;
221-
}
222-
223-
tr_debug("Vendor device ID = 0x%x 0x%x 0x%x 0x%x", vendor_device_ids[0],
224-
vendor_device_ids[1], vendor_device_ids[2], vendor_device_ids[3]);
225-
switch (vendor_device_ids[0]) {
226-
case 0xbf:
227-
// SST devices come preset with block protection
228-
// enabled for some regions, issue global protection unlock to clear
229-
_set_write_enable();
230-
_qspi_send_general_command(QSPIF_ULBPR, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
231-
break;
232-
}
233-
234221
//Synchronize Device
235222
if (false == _is_mem_ready()) {
236223
tr_error("Init - _is_mem_ready Failed");
@@ -275,6 +262,12 @@ int QSPIFBlockDevice::init()
275262
goto exit_point;
276263
}
277264

265+
if (0 != _clear_block_protection()) {
266+
tr_error("Init - clearing block protection failed");
267+
status = QSPIF_BD_ERROR_PARSING_FAILED;
268+
goto exit_point;
269+
}
270+
278271
_is_initialized = true;
279272

280273
exit_point:
@@ -1233,6 +1226,64 @@ int QSPIFBlockDevice::_sfdp_parse_sector_map_table(uint32_t sector_map_table_add
12331226
return 0;
12341227
}
12351228

1229+
int QSPIFBlockDevice::_clear_block_protection()
1230+
{
1231+
uint8_t vendor_device_ids[QSPI_RDID_DATA_LENGTH] = {0};
1232+
uint8_t status_regs[QSPI_STATUS_REGISTER_COUNT] = {0};
1233+
1234+
if (false == _is_mem_ready()) {
1235+
tr_error("Device not ready, clearing block protection failed");
1236+
return -1;
1237+
}
1238+
1239+
/* Read Manufacturer ID (1byte), and Device ID (2bytes) */
1240+
qspi_status_t status = _qspi_send_general_command(QSPIF_INST_RDID, QSPI_NO_ADDRESS_COMMAND,
1241+
NULL, 0,
1242+
(char *) vendor_device_ids, QSPI_RDID_DATA_LENGTH);
1243+
if (QSPI_STATUS_OK != status) {
1244+
tr_error("Read Vendor ID Failed");
1245+
return -1;
1246+
}
1247+
1248+
tr_debug("Vendor device ID = 0x%x 0x%x 0x%x", vendor_device_ids[0], vendor_device_ids[1], vendor_device_ids[2]);
1249+
switch (vendor_device_ids[0]) {
1250+
case 0xbf:
1251+
// SST devices come preset with block protection
1252+
// enabled for some regions, issue global protection unlock to clear
1253+
if (0 != _set_write_enable()) {
1254+
tr_error("Write enable failed");
1255+
return -1;
1256+
}
1257+
status = _qspi_send_general_command(QSPIF_INST_ULBPR, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
1258+
if (QSPI_STATUS_OK != status) {
1259+
tr_error("Global block protection unlock failed");
1260+
return -1;
1261+
}
1262+
break;
1263+
default:
1264+
// 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
1265+
status = _qspi_read_status_registers(status_regs);
1266+
if (QSPI_STATUS_OK != status) {
1267+
tr_error("_clear_block_protection - Status register read failed");
1268+
return -1;
1269+
}
1270+
status_regs[0] &= (QSPIF_STATUS_BIT_WIP | QSPIF_STATUS_BIT_WEL);
1271+
status = _qspi_write_status_registers(status_regs);
1272+
if (QSPI_STATUS_OK != status) {
1273+
tr_error("__clear_block_protection - Status register write failed");
1274+
return -1;
1275+
}
1276+
break;
1277+
}
1278+
1279+
if (false == _is_mem_ready()) {
1280+
tr_error("Device not ready, clearing block protection failed");
1281+
return -1;
1282+
}
1283+
1284+
return 0;
1285+
}
1286+
12361287
int QSPIFBlockDevice::_set_write_enable()
12371288
{
12381289
// Check Status Register Busy Bit to Verify the Device isn't Busy

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
268268
/*********************************/
269269
/* Flash Configuration Functions */
270270
/*********************************/
271+
// Clear the device's block protection
272+
int _clear_block_protection();
271273

272274
// Configure Write Enable in Status Register
273275
int _set_write_enable();

0 commit comments

Comments
 (0)