Skip to content

Commit cf9b6d5

Browse files
Matthew MacovskyKyle Kearney
authored andcommitted
Enable 4-byte addressing when supported in accordance with the SFDP standard
1 parent 4785e83 commit cf9b6d5

File tree

2 files changed

+183
-28
lines changed

2 files changed

+183
-28
lines changed

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

Lines changed: 174 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ using namespace mbed;
7474
#define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
7575

7676
#define QSPIF_BASIC_PARAM_TABLE_SOFT_RESET_BYTE 61
77+
#define QSPIF_BASIC_PARAM_TABLE_4BYTE_ADDR_BYTE 63
7778

7879
#define SOFT_RESET_RESET_INST_BITMASK 0b001000
7980
#define SOFT_RESET_ENABLE_AND_RESET_INST_BITMASK 0b010000
@@ -84,6 +85,15 @@ using namespace mbed;
8485
#define ERASE_BITMASK_NONE 0x00
8586
#define ERASE_BITMASK_ALL 0x0F
8687

88+
// 4-Byte Addressing Support Bitmasks
89+
#define FOURBYTE_ADDR_B7_BITMASK 0b00000001
90+
#define FOURBYTE_ADDR_B7_WREN_BITMASK 0b00000010
91+
#define FOURBYTE_ADDR_EXT_ADDR_REG_BITMASK 0b00000100
92+
#define FOURBYTE_ADDR_BANK_REG_BITMASK 0b00001000
93+
#define FOURBYTE_ADDR_CONF_REG_BITMASK 0b00010000
94+
#define FOURBYTE_ADDR_INSTS_BITMASK 0b00100000
95+
#define FOURBYTE_ADDR_ALWAYS_BITMASK 0b01000000
96+
8797
#define IS_MEM_READY_MAX_RETRIES 10000
8898

8999
enum qspif_default_instructions {
@@ -113,6 +123,9 @@ static int local_math_power(int base, int exp);
113123
#define QSPIF_INST_WSR2_DEFAULT QSPI_NO_INST
114124
#define QSPIF_INST_RSR2_DEFAULT 0x35
115125

126+
// Default 4-byte extended addressing register write instruction
127+
#define QSPIF_INST_4BYTE_REG_WRITE_DEFAULT QSPI_NO_INST
128+
116129
/* Init function to initialize Different Devices CS static list */
117130
static PinName *generate_initialized_active_qspif_csel_arr();
118131
// Static Members for different devices csel
@@ -142,6 +155,9 @@ QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinNam
142155
// Set default status register 2 write/read instructions
143156
_write_status_reg_2_inst = QSPIF_INST_WSR2_DEFAULT;
144157
_read_status_reg_2_inst = QSPIF_INST_RSR2_DEFAULT;
158+
159+
// Set default 4-byte addressing extension register write instruction
160+
_4byte_msb_reg_write_inst = QSPIF_INST_4BYTE_REG_WRITE_DEFAULT;
145161
}
146162

147163
int QSPIFBlockDevice::init()
@@ -694,9 +710,9 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
694710
return -1;
695711
}
696712

697-
// Check address size, currently only supports 3byte addresses
698-
if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
699-
tr_error("Init - verify 3byte addressing Failed");
713+
// Check that density is not greater than 4 gigabits (i.e. that addressing beyond 4 bytes is not required)
714+
if ((param_table[7] & 0x80) != 0) {
715+
tr_error("Init - verify flash density failed");
700716
return -1;
701717
}
702718

@@ -745,6 +761,17 @@ int QSPIFBlockDevice::_sfdp_parse_basic_param_table(uint32_t basic_table_addr, s
745761
_sfdp_set_qpi_enabled(param_table);
746762
}
747763
}
764+
765+
if (_sfdp_detect_and_enable_4byte_addressing(param_table, basic_table_size) != QSPIF_BD_ERROR_OK) {
766+
tr_error("Init - Detecting/enabling 4-byte addressing failed");
767+
return -1;
768+
}
769+
770+
if (false == _is_mem_ready()) {
771+
tr_error("Init - _is_mem_ready Failed");
772+
return -1;
773+
}
774+
748775
return 0;
749776
}
750777

@@ -1033,6 +1060,84 @@ int QSPIFBlockDevice::_sfdp_detect_best_bus_read_mode(uint8_t *basic_param_table
10331060
return 0;
10341061
}
10351062

1063+
int QSPIFBlockDevice::_sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size)
1064+
{
1065+
int status = QSPIF_BD_ERROR_OK;
1066+
qspi_status_t qspi_status = QSPI_STATUS_OK;
1067+
1068+
// Always enable 4-byte addressing if possible
1069+
if (basic_param_table_size > QSPIF_BASIC_PARAM_TABLE_4BYTE_ADDR_BYTE) {
1070+
uint8_t examined_byte = basic_param_table_ptr[QSPIF_BASIC_PARAM_TABLE_4BYTE_ADDR_BYTE];
1071+
1072+
if (examined_byte & FOURBYTE_ADDR_ALWAYS_BITMASK) {
1073+
// No need to do anything if 4-byte addressing is always enabled
1074+
_address_size = QSPI_CFG_ADDR_SIZE_32;
1075+
} else if (examined_byte & FOURBYTE_ADDR_B7_BITMASK) {
1076+
// Issue instruction B7h to enable 4-byte addressing
1077+
qspi_status = _qspi_send_general_command(0xB7, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
1078+
status = (qspi_status == QSPI_STATUS_OK) ? QSPIF_BD_ERROR_OK : QSPIF_BD_ERROR_PARSING_FAILED;
1079+
if (status == QSPIF_BD_ERROR_OK) {
1080+
_address_size = QSPI_CFG_ADDR_SIZE_32;
1081+
}
1082+
} else if (examined_byte & FOURBYTE_ADDR_B7_WREN_BITMASK) {
1083+
// Issue WREN and then instruction B7h to enable 4-byte addressing
1084+
if (_set_write_enable() == 0) {
1085+
qspi_status = _qspi_send_general_command(0xB7, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0);
1086+
status = (qspi_status == QSPI_STATUS_OK) ? QSPIF_BD_ERROR_OK : QSPIF_BD_ERROR_PARSING_FAILED;
1087+
1088+
if (status == QSPIF_BD_ERROR_OK) {
1089+
_address_size = QSPI_CFG_ADDR_SIZE_32;
1090+
}
1091+
} else {
1092+
tr_error("Write enable failed");
1093+
status = QSPIF_BD_ERROR_WREN_FAILED;
1094+
}
1095+
} else if (examined_byte & FOURBYTE_ADDR_CONF_REG_BITMASK) {
1096+
// Write 1 to bit 0 of a configuration register to enable 4-byte addressing
1097+
// Write to register with instruction B1h, read from register with instruction B5h
1098+
uint8_t conf_register = 0;
1099+
qspi_status = _qspi_send_general_command(0xB5, QSPI_NO_ADDRESS_COMMAND, NULL, 0, (char *) &conf_register, 1);
1100+
status = (qspi_status == QSPI_STATUS_OK) ? QSPIF_BD_ERROR_OK : QSPIF_BD_ERROR_PARSING_FAILED;
1101+
1102+
if (status == QSPIF_BD_ERROR_OK) {
1103+
conf_register |= 0b00000001;
1104+
if (_set_write_enable() == 0) {
1105+
qspi_status_t qspi_status = _qspi_send_general_command(0xB1, QSPI_NO_ADDRESS_COMMAND, (char *) &conf_register, 1, NULL, 0);
1106+
status = (qspi_status == QSPI_STATUS_OK) ? QSPIF_BD_ERROR_OK : QSPIF_BD_ERROR_PARSING_FAILED;
1107+
1108+
if (status == QSPIF_BD_ERROR_OK) {
1109+
_address_size = QSPI_CFG_ADDR_SIZE_32;
1110+
}
1111+
} else {
1112+
tr_error("Write enable failed");
1113+
status = QSPIF_BD_ERROR_WREN_FAILED;
1114+
}
1115+
}
1116+
} else if (examined_byte & FOURBYTE_ADDR_BANK_REG_BITMASK) {
1117+
// Write 1 to bit 7 of a bank register to enable 4-byte addressing
1118+
// Write to register with instruction 17h, read from register with instruction 16h
1119+
uint8_t to_write = 0b10000000;
1120+
qspi_status = _qspi_send_general_command(0x17, QSPI_NO_ADDRESS_COMMAND, (char *) &to_write, 1, NULL, 0);
1121+
status = (qspi_status == QSPI_STATUS_OK) ? QSPIF_BD_ERROR_OK : QSPIF_BD_ERROR_PARSING_FAILED;
1122+
if (status == QSPIF_BD_ERROR_OK) {
1123+
_address_size = QSPI_CFG_ADDR_SIZE_32;
1124+
}
1125+
} else if (examined_byte & FOURBYTE_ADDR_EXT_ADDR_REG_BITMASK) {
1126+
// Extended address register stores most significant byte of a 4-byte address
1127+
// Instructions are sent with the lower 3 bytes of the address
1128+
// Write to register with instruction C5h, read from register with instruction C8h
1129+
_4byte_msb_reg_write_inst = 0xC5;
1130+
_address_size = QSPI_CFG_ADDR_SIZE_24;
1131+
} else {
1132+
// Either part specific instructions are required to use 4-byte addressing or it isn't supported, so use 3-byte addressing instead
1133+
tr_debug("_sfdp_detect_and_enable_4byte_addressing - 4-byte addressing not supported, falling back to 3-byte addressing");
1134+
_address_size = QSPI_CFG_ADDR_SIZE_24;
1135+
}
1136+
}
1137+
1138+
return status;
1139+
}
1140+
10361141
int QSPIFBlockDevice::_sfdp_detect_reset_protocol_and_reset(uint8_t *basic_param_table_ptr)
10371142
{
10381143
int status = QSPIF_BD_ERROR_OK;
@@ -1245,69 +1350,110 @@ qspi_status_t QSPIFBlockDevice::_qspi_set_frequency(int freq)
12451350
return _qspi.set_frequency(freq);
12461351
}
12471352

1353+
qspi_status_t QSPIFBlockDevice::_qspi_update_4byte_ext_addr_reg(bd_addr_t addr)
1354+
{
1355+
qspi_status_t status = QSPI_STATUS_OK;
1356+
// Only update register if in the extended address register mode
1357+
if (_4byte_msb_reg_write_inst != QSPI_NO_INST) {
1358+
// Set register to the most significant byte of the address
1359+
uint8_t most_significant_byte = addr >> 24;
1360+
if (_set_write_enable() == 0) {
1361+
status = _qspi.command_transfer(_4byte_msb_reg_write_inst, (int) QSPI_NO_ADDRESS_COMMAND,
1362+
(char *) &most_significant_byte, 1,
1363+
NULL, 0);
1364+
} else {
1365+
tr_error("Write enable failed");
1366+
status = QSPI_STATUS_ERROR;
1367+
}
1368+
} else if ((_address_size != QSPI_CFG_ADDR_SIZE_32) && (addr != QSPI_NO_ADDRESS_COMMAND) && (addr >= (1 << 24))) {
1369+
tr_error("Attempted to use 4-byte address but 4-byte addressing is not supported");
1370+
status = QSPI_STATUS_ERROR;
1371+
}
1372+
return status;
1373+
}
1374+
12481375
qspi_status_t QSPIFBlockDevice::_qspi_send_read_command(qspi_inst_t read_inst, void *buffer, bd_addr_t addr,
12491376
bd_size_t size)
12501377
{
1251-
// Send Read command to device driver
12521378
size_t buf_len = size;
12531379

1254-
if (_qspi.read(read_inst, (_alt_size == 0) ? -1 : QSPI_ALT_DEFAULT_VALUE, (unsigned int)addr, (char *)buffer, &buf_len) != QSPI_STATUS_OK) {
1255-
tr_error("Read failed");
1256-
return QSPI_STATUS_ERROR;
1380+
qspi_status_t status = _qspi_update_4byte_ext_addr_reg(addr);
1381+
if (QSPI_STATUS_OK != status) {
1382+
tr_error("QSPI Read - Updating 4-byte addressing extended address register failed");
1383+
return status;
12571384
}
12581385

1259-
return QSPI_STATUS_OK;
1386+
// Send read command to device driver
1387+
status = _qspi.read(read_inst, -1, (unsigned int)addr, (char *)buffer, &buf_len);
1388+
if (QSPI_STATUS_OK != status) {
1389+
tr_error("QSPI Read failed");
1390+
return status;
1391+
}
12601392

1393+
return QSPI_STATUS_OK;
12611394
}
12621395

12631396
qspi_status_t QSPIFBlockDevice::_qspi_send_program_command(qspi_inst_t progInst, const void *buffer, bd_addr_t addr,
12641397
bd_size_t *size)
12651398
{
1266-
// Send Program (write) command to device driver
1267-
qspi_status_t result = QSPI_STATUS_OK;
12681399

1269-
result = _qspi.write(progInst, -1, addr, (char *)buffer, (size_t *)size);
1270-
if (result != QSPI_STATUS_OK) {
1400+
qspi_status_t status = _qspi_update_4byte_ext_addr_reg(addr);
1401+
if (QSPI_STATUS_OK != status) {
1402+
tr_error("QSPI Write - Updating 4-byte addressing extended address register failed");
1403+
return status;
1404+
}
1405+
1406+
// Send program (write) command to device driver
1407+
status = _qspi.write(prog_inst, -1, addr, (char *)buffer, (size_t *)size);
1408+
if (QSPI_STATUS_OK != status) {
12711409
tr_error("QSPI Write failed");
1410+
return status;
12721411
}
12731412

1274-
return result;
1413+
return QSPI_STATUS_OK;
12751414
}
12761415

12771416
qspi_status_t QSPIFBlockDevice::_qspi_send_erase_command(qspi_inst_t erase_inst, bd_addr_t addr, bd_size_t size)
12781417
{
1279-
// Send Erase Instruction command to driver
1280-
qspi_status_t result = QSPI_STATUS_OK;
1281-
12821418
tr_debug("Inst: 0x%xh, addr: %llu, size: %llu", erase_inst, addr, size);
12831419

1284-
result = _qspi.command_transfer(erase_inst, // command to send
1285-
(((int)addr) & 0x00FFF000), // Align addr to 4096
1286-
NULL, // do not transmit
1287-
0, // do not transmit
1288-
NULL, // just receive two bytes of data
1289-
0); // store received values in status_value
1420+
qspi_status_t status = _qspi_update_4byte_ext_addr_reg(addr);
1421+
if (QSPI_STATUS_OK != status) {
1422+
tr_error("QSPI Erase - Updating 4-byte addressing extended address register failed");
1423+
return status;
1424+
}
12901425

1291-
if (QSPI_STATUS_OK != result) {
1426+
// Send erase command to driver
1427+
status = _qspi.command_transfer(erase_inst,
1428+
(((int) addr) & 0x00FFF000), // Align addr to 4096
1429+
NULL, 0, NULL, 0); // Do not transmit or receive
1430+
1431+
if (QSPI_STATUS_OK != status) {
12921432
tr_error("QSPI Erase failed");
1433+
return status;
12931434
}
12941435

1295-
return result;
1296-
1436+
return QSPI_STATUS_OK;
12971437
}
12981438

12991439
qspi_status_t QSPIFBlockDevice::_qspi_send_general_command(qspi_inst_t instruction, bd_addr_t addr,
13001440
const char *tx_buffer,
13011441
mbed::bd_size_t tx_length, const char *rx_buffer, mbed::bd_size_t rx_length)
13021442
{
1303-
// Send a general command Instruction to driver
1304-
qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length);
1443+
qspi_status_t status = _qspi_update_4byte_ext_addr_reg(addr);
1444+
if (QSPI_STATUS_OK != status) {
1445+
tr_error("QSPI Generic command - Updating 4-byte addressing extended address register failed");
1446+
return status;
1447+
}
13051448

1449+
// Send a general command instruction to driver
1450+
status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length);
13061451
if (QSPI_STATUS_OK != status) {
13071452
tr_error("Sending Generic command: %x", instruction);
1453+
return status;
13081454
}
13091455

1310-
return status;
1456+
return QSPI_STATUS_OK;
13111457
}
13121458

13131459
qspi_status_t QSPIFBlockDevice::_qspi_configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width,

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
262262
// Send set_frequency command to Driver
263263
qspi_status_t _qspi_set_frequency(int freq);
264264

265+
// Update the 4-byte addressing extension register with the MSB of the address if it is in use
266+
qspi_status_t _qspi_update_4byte_ext_addr_reg(bd_addr_t addr);
267+
265268
/*********************************/
266269
/* Flash Configuration Functions */
267270
/*********************************/
@@ -306,6 +309,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
306309
mbed::qspi_inst_t &erase4k_inst,
307310
mbed::qspi_inst_t *erase_type_inst_arr, unsigned int *erase_type_size_arr);
308311

312+
// Detect 4-byte addressing mode and enable it if supported
313+
int _sfdp_detect_and_enable_4byte_addressing(uint8_t *basic_param_table_ptr, int basic_param_table_size);
314+
309315
/***********************/
310316
/* Utilities Functions */
311317
/***********************/
@@ -344,6 +350,9 @@ class QSPIFBlockDevice : public mbed::BlockDevice {
344350
mbed::qspi_inst_t _write_status_reg_2_inst;
345351
mbed::qspi_inst_t _read_status_reg_2_inst;
346352

353+
// 4-byte addressing extension register write instruction
354+
mbed::qspi_inst_t _4byte_msb_reg_write_inst;
355+
347356
// Up To 4 Erase Types are supported by SFDP (each with its own command Instruction and Size)
348357
mbed::qspi_inst_t _erase_type_inst_arr[MAX_NUM_OF_ERASE_TYPES];
349358
unsigned int _erase_type_size_arr[MAX_NUM_OF_ERASE_TYPES];

0 commit comments

Comments
 (0)