Skip to content

Commit 3a3d335

Browse files
Matthew MacovskyKyle Kearney
authored andcommitted
Allow for arbitrary QSPI alt sizes
The QSPI spec allows alt to be any size that is a multiple of the number of data lines. For example, Micron's N25Q128A uses only a single alt cycle for all read modes (1, 2, or 4 bits depending on how many data lines are in use).
1 parent c385e14 commit 3a3d335

File tree

12 files changed

+270
-109
lines changed

12 files changed

+270
-109
lines changed

TESTS/mbed_hal/qspi/qspi_test_utils.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ struct Qspi {
102102
#define ADDR_SIZE_24 QSPI_CFG_ADDR_SIZE_24
103103
#define ADDR_SIZE_32 QSPI_CFG_ADDR_SIZE_32
104104

105-
#define ALT_SIZE_8 QSPI_CFG_ALT_SIZE_8
106-
#define ALT_SIZE_16 QSPI_CFG_ALT_SIZE_16
107-
#define ALT_SIZE_24 QSPI_CFG_ALT_SIZE_24
108-
#define ALT_SIZE_32 QSPI_CFG_ALT_SIZE_32
105+
#define ALT_SIZE_8 8u
106+
#define ALT_SIZE_16 16u
107+
#define ALT_SIZE_24 24u
108+
#define ALT_SIZE_32 32u
109109

110110
#define STATUS_REG QSPI_CMD_RDSR
111111
#define CONFIG_REG0 QSPI_CMD_RDCR0

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ int QSPIFBlockDevice::init()
247247

248248
// Configure BUS Mode to 1_1_1 for all commands other than Read
249249
_qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
250-
QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
250+
0, QSPI_CFG_BUS_SINGLE, 0);
251251

252252
_is_initialized = true;
253253

@@ -303,7 +303,7 @@ int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
303303

304304
// Configure Bus for Reading
305305
_qspi_configure_format(_inst_width, _address_width, _address_size, QSPI_CFG_BUS_SINGLE,
306-
QSPI_CFG_ALT_SIZE_8, _data_width, _dummy_and_mode_cycles);
306+
0, _data_width, _dummy_and_mode_cycles);
307307

308308
if (QSPI_STATUS_OK != _qspi_send_read_command(_read_instruction, buffer, addr, size)) {
309309
status = QSPIF_BD_ERROR_DEVICE_ERROR;
@@ -312,7 +312,7 @@ int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
312312

313313
// All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus)
314314
_qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
315-
QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
315+
0, QSPI_CFG_BUS_SINGLE, 0);
316316

317317
_mutex.unlock();
318318
return status;
@@ -718,7 +718,7 @@ int QSPIFBlockDevice::_sfdp_parse_sfdp_headers(uint32_t &basic_table_addr, size_
718718

719719
// Set 1-1-1 bus mode for SFDP header parsing
720720
_qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
721-
QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
721+
0, QSPI_CFG_BUS_SINGLE, 8);
722722

723723
qspi_status_t status = _qspi_send_read_command(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length);
724724
if (status != QSPI_STATUS_OK) {
@@ -885,7 +885,7 @@ int QSPIFBlockDevice::_sfdp_set_quad_enabled(uint8_t *basic_param_table_ptr)
885885

886886
// Configure BUS Mode to 1_1_1 for all commands other than Read
887887
_qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
888-
QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
888+
0, QSPI_CFG_BUS_SINGLE, 0);
889889

890890
// Read Status Register
891891
if (QSPI_STATUS_OK == _qspi_send_general_command(_read_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0,
@@ -1206,7 +1206,7 @@ int QSPIFBlockDevice::_enable_fast_mdoe()
12061206

12071207
// Configure BUS Mode to 1_1_1 for all commands other than Read
12081208
_qspi_configure_format(QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
1209-
QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
1209+
0, QSPI_CFG_BUS_SINGLE, 0);
12101210

12111211
// Read Status Register
12121212
if (QSPI_STATUS_OK == _qspi_send_general_command(read_conf_register_inst, QSPI_NO_ADDRESS_COMMAND, NULL, 0,
@@ -1306,7 +1306,6 @@ int QSPIFBlockDevice::_utils_iterate_next_largest_erase_type(uint8_t &bitfield,
13061306
tr_error("No erase type was found for current region addr");
13071307
}
13081308
return largest_erase_type;
1309-
13101309
}
13111310

13121311
/***************************************************/

components/storage/blockdevice/COMPONENT_QSPIF/QSPIFBlockDevice.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ enum qspif_bd_error {
2929
QSPIF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
3030
QSPIF_BD_ERROR_READY_FAILED = -4003, /* Wait for Mem Ready failed */
3131
QSPIF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
32-
QSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
33-
QSPIF_BD_ERROR_DEVICE_NOT_UNIQE = -4006, /* Only one instance per csel is allowed */
34-
QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4007 /* Max active QSPIF devices exceeded */
32+
QSPIF_BD_ERROR_CONF_FORMAT_FAILED = -4005, /* Configure format failed */
33+
QSPIF_BD_ERROR_INVALID_ERASE_PARAMS = -4006, /* Erase command not on sector aligned addresses or exceeds device size */
34+
QSPIF_BD_ERROR_DEVICE_NOT_UNIQE = -4007, /* Only one instance per csel is allowed */
35+
QSPIF_BD_ERROR_DEVICE_MAX_EXCEED = -4008 /* Max active QSPIF devices exceeded */
3536
};
3637

3738
/** Enum qspif polarity mode

drivers/QSPI.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class QSPI : private NonCopyable<QSPI> {
106106
* @param address_width Bus width used by address phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
107107
* @param address_size Size in bits used by address phase(Valid values are QSPI_CFG_ADDR_SIZE_8, QSPI_CFG_ADDR_SIZE_16, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_ADDR_SIZE_32)
108108
* @param alt_width Bus width used by alt phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
109-
* @param alt_size Size in bits used by alt phase(Valid values are QSPI_CFG_ALT_SIZE_8, QSPI_CFG_ALT_SIZE_16, QSPI_CFG_ALT_SIZE_24, QSPI_CFG_ALT_SIZE_32)
109+
* @param alt_size Size in bits used by alt phase (must be a multiple of the number of bus lines indicated in alt_width)
110110
* @param data_width Bus width used by data phase(Valid values are QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_DUAL, QSPI_CFG_BUS_QUAD)
111111
* @param dummy_cycles Number of dummy clock cycles to be used after alt phase
112112
*

drivers/source/QSPI.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ namespace mbed {
2626
QSPI *QSPI::_owner = NULL;
2727
SingletonPtr<PlatformMutex> QSPI::_mutex;
2828

29+
uint8_t convert_bus_width_to_line_count(qspi_bus_width_t width)
30+
{
31+
switch (width) {
32+
case QSPI_CFG_BUS_SINGLE:
33+
return 1;
34+
case QSPI_CFG_BUS_DUAL:
35+
return 2;
36+
case QSPI_CFG_BUS_QUAD:
37+
return 4;
38+
default:
39+
// Unrecognized bus width
40+
return 0;
41+
}
42+
}
43+
2944
QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName ssel, int mode) : _qspi()
3045
{
3146
_qspi_io0 = io0;
@@ -38,7 +53,7 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
3853
_address_width = QSPI_CFG_BUS_SINGLE;
3954
_address_size = QSPI_CFG_ADDR_SIZE_24;
4055
_alt_width = QSPI_CFG_BUS_SINGLE;
41-
_alt_size = QSPI_CFG_ALT_SIZE_8;
56+
_alt_size = 0;
4257
_data_width = QSPI_CFG_BUS_SINGLE;
4358
_num_dummy_cycles = 0;
4459
_mode = mode;
@@ -52,7 +67,14 @@ QSPI::QSPI(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, Pin
5267

5368
qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width_t address_width, qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width, int dummy_cycles)
5469
{
55-
qspi_status_t ret_status = QSPI_STATUS_OK;
70+
// Check that alt_size/alt_width are a valid combination
71+
uint8_t alt_lines = convert_bus_width_to_line_count(alt_width);
72+
if (alt_lines == 0) {
73+
return QSPI_STATUS_ERROR;
74+
} else if (alt_size % alt_lines != 0) {
75+
// Invalid alt size/width combination (alt size is not a multiple of the number of bus lines used to transmit it)
76+
return QSPI_STATUS_ERROR;
77+
}
5678

5779
lock();
5880
_inst_width = inst_width;
@@ -62,10 +84,9 @@ qspi_status_t QSPI::configure_format(qspi_bus_width_t inst_width, qspi_bus_width
6284
_alt_size = alt_size;
6385
_data_width = data_width;
6486
_num_dummy_cycles = dummy_cycles;
65-
6687
unlock();
6788

68-
return ret_status;
89+
return QSPI_STATUS_OK;
6990
}
7091

7192
qspi_status_t QSPI::set_frequency(int hz)

features/storage/TESTS/kvstore/direct_access_devicekey_test/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ void test_direct_access_to_device_inject_root()
255255
ret = devkey.device_inject_root_of_trust(key, DEVICE_KEY_16BYTE);
256256
TEST_ASSERT_EQUAL_INT(DEVICEKEY_SUCCESS, ret);
257257

258-
// Now use Direct Access To DeviceKey to retrieve it */
258+
// Now use Direct Access To DeviceKey to retrieve it
259259
uint32_t internal_start_address;
260260
uint32_t internal_rbp_size;
261261
bool is_conf_tdb_internal = false;

hal/qspi_api.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,7 @@ typedef enum qspi_address_size {
6060

6161
/** Alternative size in bits
6262
*/
63-
typedef enum qspi_alt_size {
64-
QSPI_CFG_ALT_SIZE_8,
65-
QSPI_CFG_ALT_SIZE_16,
66-
QSPI_CFG_ALT_SIZE_24,
67-
QSPI_CFG_ALT_SIZE_32,
68-
} qspi_alt_size_t;
63+
typedef uint8_t qspi_alt_size_t;
6964

7065
/** QSPI command
7166
*

targets/TARGET_Cypress/TARGET_PSOC6/cy_qspi_api.c

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,6 @@ static inline cyhal_qspi_size_t cyhal_qspi_convert_addr_size(qspi_address_size_t
6969
}
7070
}
7171

72-
static inline cyhal_qspi_size_t cyhal_qspi_convert_alt_size(qspi_alt_size_t size)
73-
{
74-
switch (size) {
75-
case QSPI_CFG_ALT_SIZE_8:
76-
return CYHAL_QSPI_CFG_SIZE_8;
77-
case QSPI_CFG_ALT_SIZE_16:
78-
return CYHAL_QSPI_CFG_SIZE_16;
79-
case QSPI_CFG_ALT_SIZE_24:
80-
return CYHAL_QSPI_CFG_SIZE_24;
81-
default: // fallthrough
82-
case QSPI_CFG_ALT_SIZE_32:
83-
return CYHAL_QSPI_CFG_SIZE_32;
84-
}
85-
}
86-
8772
static void cyhal_qspi_convert_command(const qspi_command_t *from, cyhal_qspi_command_t *to)
8873
{
8974
to->instruction.bus_width = cyhal_qspi_convert_width(from->instruction.bus_width);
@@ -94,7 +79,7 @@ static void cyhal_qspi_convert_command(const qspi_command_t *from, cyhal_qspi_co
9479
to->address.value = from->address.value;
9580
to->address.disabled = from->address.disabled;
9681
to->mode_bits.bus_width = cyhal_qspi_convert_width(from->alt.bus_width);
97-
to->mode_bits.size = cyhal_qspi_convert_alt_size(from->alt.size);
82+
to->mode_bits.size = from->alt.size;
9883
to->mode_bits.value = from->alt.value;
9984
to->mode_bits.disabled = from->alt.disabled;
10085
to->dummy_count = from->dummy_count;

targets/TARGET_Cypress/TARGET_PSOC6/psoc6csp/hal/include/cyhal_qspi.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,12 @@ typedef enum {
7171
} cyhal_qspi_event_t;
7272

7373
#define CYHAL_QSPI_RSLT_ERR_BUS_WIDTH (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 0)) /**< Bus width Error. >*/
74-
#define CYHAL_QSPI_RSLT_ERR_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 1)) /**< Pin related Error. >*/
75-
#define CYHAL_QSPI_RSLT_ERR_DATA_SEL (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 2)) /**< Data select Error. >*/
76-
#define CYHAL_QSPI_RSLT_ERR_INSTANCE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 3)) /**< QSPI instance related Error. >*/
74+
#define CYHAL_QSPI_RSLT_ERR_SIZE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 1)) /**< Size Error. >*/
75+
#define CYHAL_QSPI_RSLT_ERR_PIN (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 2)) /**< Pin related Error. >*/
76+
#define CYHAL_QSPI_RSLT_ERR_DATA_SEL (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 3)) /**< Data select Error. >*/
77+
#define CYHAL_QSPI_RSLT_ERR_INSTANCE (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 4)) /**< QSPI instance related Error. >*/
78+
#define CYHAL_QSPI_RSLT_ERR_ALT_SIZE_WIDTH_MISMATCH (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 5)) /**< Provided alt size is incompatible with provided alt width. >*/
79+
#define CYHAL_QSPI_RSLT_ERR_ALT_SIZE_DUMMY_CYCLES_MISMATCH (CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CYHAL_RSLT_MODULE_QSPI, 6)) /**< Provided alt size is incompatible with provided number of dummy cycles (due to device-specific restrictions). >*/
7780

7881
/** @brief QSPI command settings */
7982
typedef struct cyhal_qspi_command {
@@ -90,7 +93,7 @@ typedef struct cyhal_qspi_command {
9093
} address;
9194
struct {
9295
cyhal_qspi_bus_width_t bus_width; /**< Bus width for mode bits >*/
93-
cyhal_qspi_size_t size; /**< Mode bits size >*/
96+
uint8_t size; /**< Mode bits size >*/
9497
uint32_t value; /**< Mode bits value >*/
9598
bool disabled; /**< Mode bits phase skipped if disabled is set to true >*/
9699
} mode_bits;

0 commit comments

Comments
 (0)