Skip to content

Commit 02dbf68

Browse files
author
Kyle Kearney
committed
QSPIF: Handle parts with extra config registers
Default to 2 status registers, but update this value if necessary during vendor quirk handling for parts (currently only Macronix) which have one status register and two control registers. For the purposes of QSPIFBlockDevice, these are all considered status (or at least "status-like") registers because they are all written via the Write Status Register instruction. Set the custom RDCR instruction for Macronix during quirk handling. Update reading and writing of status registers to handle a variable number of status registers.
1 parent eb5494e commit 02dbf68

File tree

2 files changed

+39
-18
lines changed

2 files changed

+39
-18
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ using namespace mbed;
3131
/****************************/
3232
#define QSPIF_DEFAULT_PAGE_SIZE 256
3333
#define QSPIF_DEFAULT_SE_SIZE 4096
34-
#define QSPI_STATUS_REGISTER_COUNT 2
34+
// The SFDP spec only defines two status registers. But some devices,
35+
// have three "status-like" registers (one status, two config)
36+
#define QSPI_MAX_STATUS_REGISTERS 3
37+
#define QSPI_DEFAULT_STATUS_REGISTERS 2
3538
#ifndef UINT64_MAX
3639
#define UINT64_MAX -1
3740
#endif
@@ -110,6 +113,7 @@ using namespace mbed;
110113

111114
// Device-specific instructions
112115
#define QSPIF_INST_ULBPR 0x98 // Clear all write-protection bits in the Block-Protection register
116+
#define QSPIF_INST_RDCR 0x15 // Read the two control registers
113117

114118
// Default read/legacy erase instructions
115119
#define QSPIF_INST_READ_DEFAULT 0x03
@@ -174,6 +178,7 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
174178
_read_instruction = QSPIF_INST_READ_DEFAULT;
175179
_legacy_erase_instruction = QSPIF_INST_LEGACY_ERASE_DEFAULT;
176180

181+
_num_status_registers = QSPI_DEFAULT_STATUS_REGISTERS;
177182
// Set default status register 2 write/read instructions
178183
_write_status_reg_2_inst = QSPIF_INST_WSR2_DEFAULT;
179184
_read_status_reg_2_inst = QSPIF_INST_RSR2_DEFAULT;
@@ -757,8 +762,8 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
757762

758763
int QSPIFBlockDevice::_sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr)
759764
{
760-
uint8_t status_reg_setup[QSPI_STATUS_REGISTER_COUNT] = {0};
761-
uint8_t status_regs[QSPI_STATUS_REGISTER_COUNT] = {0};
765+
uint8_t status_reg_setup[QSPI_MAX_STATUS_REGISTERS] = {0};
766+
uint8_t status_regs[QSPI_MAX_STATUS_REGISTERS] = {0};
762767

763768
// QUAD Enable procedure is specified by 3 bits
764769
uint8_t qer_value = (basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4;
@@ -807,7 +812,7 @@ int QSPIFBlockDevice::_sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr)
807812
_qspi_read_status_registers(status_regs);
808813

809814
// Set Bits for Quad Enable
810-
for (int i = 0; i < QSPI_STATUS_REGISTER_COUNT; i++) {
815+
for (int i = 0; i < QSPI_MAX_STATUS_REGISTERS; i++) {
811816
status_regs[i] |= status_reg_setup[i];
812817
}
813818

@@ -820,7 +825,7 @@ int QSPIFBlockDevice::_sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr)
820825
}
821826

822827
// For Debug
823-
memset(status_regs, 0, QSPI_STATUS_REGISTER_COUNT);
828+
memset(status_regs, 0, QSPI_MAX_STATUS_REGISTERS);
824829
_qspi_read_status_registers(status_regs);
825830
if (((status_regs[0] & status_reg_setup[0]) | (status_regs[1] & status_reg_setup[1])) == 0) {
826831
tr_error("Status register not set correctly");
@@ -1233,14 +1238,22 @@ int QSPIFBlockDevice::_handle_vendor_quirks()
12331238
tr_debug("Applying quirks for SST");
12341239
_clear_protection_method = QSPIF_BP_ULBPR;
12351240
break;
1241+
case 0xc2:
1242+
// Macronix devices have two quirks:
1243+
// 1. Have one status register and 2 config registers, with a nonstandard instruction for reading the config registers
1244+
// 2. Require setting a "fast mode" bit in config register 2 to operate at higher clock rates
1245+
tr_debug("Applying quirks for macronix");
1246+
_num_status_registers = 3;
1247+
_read_status_reg_2_inst = QSPIF_INST_RDCR;
1248+
break;
12361249
}
12371250

12381251
return 0;
12391252
}
12401253

12411254
int QSPIFBlockDevice::_clear_block_protection()
12421255
{
1243-
uint8_t status_regs[QSPI_STATUS_REGISTER_COUNT] = {0};
1256+
uint8_t status_regs[QSPI_MAX_STATUS_REGISTERS] = {0};
12441257

12451258
if (false == _is_mem_ready()) {
12461259
tr_error("Device not ready, clearing block protection failed");
@@ -1329,10 +1342,9 @@ int QSPIFBlockDevice::_set_write_enable()
13291342

13301343
int QSPIFBlockDevice::_enable_fast_mode()
13311344
{
1332-
const int NUM_REGISTERS = QSPI_STATUS_REGISTER_COUNT + 1; // Status registers + one config register
1333-
char status_reg[NUM_REGISTERS] = {0};
1345+
char status_reg[QSPI_MAX_STATUS_REGISTERS] = {0};
13341346
unsigned int read_conf_register_inst = 0x15;
1335-
char status_reg_qer_setup[NUM_REGISTERS] = {0};
1347+
char status_reg_qer_setup[QSPI_MAX_STATUS_REGISTERS] = {0};
13361348

13371349
status_reg_qer_setup[2] = 0x2; // Bit 1 of config Reg 2
13381350

@@ -1347,15 +1359,15 @@ int QSPIFBlockDevice::_enable_fast_mode()
13471359
// Read Status Register
13481360
if (QSPI_STATUS_OK == _qspi_send_general_command(read_conf_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0,
13491361
&status_reg[1],
1350-
NUM_REGISTERS - 1)) { // store received values in status_value
1362+
QSPI_MAX_STATUS_REGISTERS - 1)) { // store received values in status_value
13511363
tr_debug("Reading Config Register Success: value = 0x%x", (int)status_reg[2]);
13521364
} else {
13531365
tr_error("Reading Config Register failed");
13541366
return -1;
13551367
}
13561368

13571369
// Set Bits for Quad Enable
1358-
for (int i = 0; i < NUM_REGISTERS; i++) {
1370+
for (int i = 0; i < QSPI_MAX_STATUS_REGISTERS; i++) {
13591371
status_reg[i] |= status_reg_qer_setup[i];
13601372
}
13611373

@@ -1366,7 +1378,7 @@ int QSPIFBlockDevice::_enable_fast_mode()
13661378
}
13671379

13681380
if (QSPI_STATUS_OK == _qspi_send_general_command(QSPIF_INST_WSR1, QSPI_NO_ADDRESS_COMMAND, status_reg,
1369-
NUM_REGISTERS, NULL,
1381+
QSPI_MAX_STATUS_REGISTERS, NULL,
13701382
0)) { // Write Fast mode bit to status_register
13711383
tr_debug("fast mode enable - Writing Config Register Success: value = 0x%x",
13721384
(int)status_reg[2]);
@@ -1381,10 +1393,10 @@ int QSPIFBlockDevice::_enable_fast_mode()
13811393
}
13821394

13831395
// For Debug
1384-
memset(status_reg, 0, NUM_REGISTERS);
1396+
memset(status_reg, 0, QSPI_MAX_STATUS_REGISTERS);
13851397
if (QSPI_STATUS_OK == _qspi_send_general_command(read_conf_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0,
13861398
&status_reg[1],
1387-
NUM_REGISTERS - 1)) { // store received values in status_value
1399+
QSPI_MAX_STATUS_REGISTERS - 1)) { // store received values in status_value
13881400
tr_debug("Verifying Config Register Success: value = 0x%x", (int)status_reg[2]);
13891401
} else {
13901402
tr_error("Verifying Config Register failed");
@@ -1647,12 +1659,16 @@ qspi_status_t QSPIFBlockDevice::_qspi_read_status_registers(uint8_t *reg_buffer)
16471659
return status;
16481660
}
16491661

1650-
// Read Status Register 2
1662+
// Read Status Register 2 (and beyond, if applicable)
1663+
unsigned int read_length = _num_status_registers - 1; // We already read status reg 1 above
16511664
status = _qspi_send_general_command(_read_status_reg_2_inst, QSPI_NO_ADDRESS_COMMAND,
16521665
NULL, 0,
1653-
(char *) &reg_buffer[1], 1);
1666+
(char *) &reg_buffer[1], read_length);
16541667
if (QSPI_STATUS_OK == status) {
16551668
tr_debug("Reading Status Register 2 Success: value = 0x%x", (int) reg_buffer[1]);
1669+
if (_num_status_registers > 2) {
1670+
tr_debug("Reading Register 3 Success: value = 0x%x", (int) reg_buffer[2]);
1671+
}
16561672
} else {
16571673
tr_error("Reading Status Register 2 failed");
16581674
return status;
@@ -1672,17 +1688,21 @@ qspi_status_t QSPIFBlockDevice::_qspi_write_status_registers(uint8_t *reg_buffer
16721688
return QSPI_STATUS_ERROR;
16731689
}
16741690
status = _qspi_send_general_command(QSPIF_INST_WSR1, QSPI_NO_ADDRESS_COMMAND,
1675-
(char *) reg_buffer, 2,
1691+
(char *) reg_buffer, _num_status_registers,
16761692
NULL, 0);
16771693
if (QSPI_STATUS_OK == status) {
16781694
tr_debug("Writing Status Registers Success: reg 1 value = 0x%x, reg 2 value = 0x%x",
16791695
(int) reg_buffer[0], (int) reg_buffer[1]);
1696+
if (_num_status_registers > 2) {
1697+
tr_debug("Writing Register 3 Success: value = 0x%x", (int) reg_buffer[2]);
1698+
}
16801699
} else {
16811700
tr_error("Writing Status Registers failed");
16821701
return status;
16831702
}
16841703
} else {
16851704
// Status registers are written using different commands
1705+
MBED_ASSERT(_num_status_registers == 2); // This flow doesn't support a nonstandard third status/config register
16861706

16871707
// Write status register 1
16881708
if (_set_write_enable() != 0) {

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
354354
mbed::qspi_inst_t _legacy_erase_instruction;
355355

356356
// Status register write/read instructions
357+
unsigned int _num_status_registers;
357358
mbed::qspi_inst_t _write_status_reg_2_inst;
358-
mbed::qspi_inst_t _read_status_reg_2_inst;
359+
mbed::qspi_inst_t _read_status_reg_2_inst; // If three registers, this instruction reads the latter two
359360

360361
// 4-byte addressing extension register write instruction
361362
mbed::qspi_inst_t _4byte_msb_reg_write_inst;

0 commit comments

Comments
 (0)