Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 47 additions & 2 deletions core/flash/spi_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -1579,6 +1579,7 @@ int spi_flash_clear_block_protect (const struct spi_flash *flash)
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35:
case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31:
FLASH_XFER_INIT_READ_REG (xfer, FLASH_CMD_RDSR2, &reg[1], 1, 0);
status = flash->spi->xfer (flash->spi, &xfer);
if (status != 0) {
Expand All @@ -1604,6 +1605,27 @@ int spi_flash_clear_block_protect (const struct spi_flash *flash)
}

if ((reg[0] & ~mask) || (reg[1] & cmpl_bp)) {
if (flash->state->quad_enable == SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31) {
bool clear_sr1 = !!(reg[0] & ~mask);
bool clear_sr2 = !!(reg[1] & cmpl_bp);

reg[0] &= mask;
reg[1] &= cmpl_mask;
if (clear_sr1) {
status = spi_flash_write_register (flash, FLASH_CMD_WRSR, reg, 1,
flash->state->sr1_volatile);
if (status != 0) {
goto exit;
}
}

if (clear_sr2) {
status = spi_flash_write_register (flash, FLASH_CMD_WRSR2, &reg[1], 1,
flash->state->sr1_volatile);
}
goto exit;
}

if (flash->state->quad_enable == SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35) {
cmd_len = 2;
}
Expand Down Expand Up @@ -2101,6 +2123,11 @@ int spi_flash_enable_quad_spi (const struct spi_flash *flash, uint8_t enable)
cmd_len = 1;
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31:
cmd = FLASH_CMD_RDSR2;
cmd_len = 1;
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT6_SR1:
cmd_len = 1;
break;
Expand Down Expand Up @@ -2149,6 +2176,18 @@ int spi_flash_enable_quad_spi (const struct spi_flash *flash, uint8_t enable)
cmd_len = 2;
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31:
if (enable) {
reg[0] |= QSPI_ENABLE_BIT1;
}
else {
reg[0] &= ~QSPI_ENABLE_BIT1;
}

cmd = FLASH_CMD_WRSR2;
cmd_len = 1;
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT6_SR1:
if (enable) {
reg[0] |= QSPI_ENABLE_BIT6;
Expand Down Expand Up @@ -2217,6 +2256,11 @@ int spi_flash_is_quad_spi_enabled (const struct spi_flash *flash)
cmd_len = 1;
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31:
cmd = FLASH_CMD_RDSR2;
cmd_len = 1;
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT6_SR1:
cmd_len = 1;
break;
Expand All @@ -2242,8 +2286,9 @@ int spi_flash_is_quad_spi_enabled (const struct spi_flash *flash)
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35:
reg[1] = reg[0];
/* fall through */ /* no break */
case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31:
status = !!(reg[0] & QSPI_ENABLE_BIT1);
break;

case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2:
case SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_NO_CLR:
Expand Down
16 changes: 12 additions & 4 deletions core/flash/spi_flash_sfdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ struct spi_flash_sfdp_basic_parameter_table_1_5 {
#define SPI_FLASH_SFDP_QER_BIT7_SR2_3E 3
#define SPI_FLASH_SFDP_QER_BIT1_SR2_NO_CLR 4
#define SPI_FLASH_SFDP_QER_BIT1_SR2_35 5
#define SPI_FLASH_SFDP_QER_RESERVED1 6
#define SPI_FLASH_SFDP_QER_RESERVED2 7
#define SPI_FLASH_SFDP_QER_BIT1_SR2_35_31 6
#define SPI_FLASH_SFDP_QER_RESERVED 7
#define SPI_FLASH_SFDP_HOLD_RST_DISABLE (1U << 23)
uint8_t sr_write_enable; /**< 16th DWORD: Status register 1 write enable. */
#define SPI_FLASH_SFDP_NV_SR_06 (1U << 0)
Expand Down Expand Up @@ -724,15 +724,23 @@ int spi_flash_sfdp_get_quad_enable (const struct spi_flash_sfdp_basic_table *tab
quad = SPI_FLASH_SFDP_QER (params->quad_enable);

switch (quad) {
case SPI_FLASH_SFDP_QER_RESERVED1:
case SPI_FLASH_SFDP_QER_RESERVED2:
case SPI_FLASH_SFDP_QER_BIT1_SR2_35_31:
case SPI_FLASH_SFDP_QER_RESERVED:
if (table->sfdp->vendor == FLASH_ID_MICRON_X) {
/* The Micron Xcella flash device follows SFDP parameter version 1.6,
* however incorrectly reports reserved value 7 for QER.
* It does not support QUAD_1_1_4, QUAD_1_4_4 or QUAD_4_4_4. */
quad = SPI_FLASH_SFDP_QUAD_NO_QE_BIT;
break;
}
else if ((quad == SPI_FLASH_SFDP_QER_BIT1_SR2_35_31) &&
(table->sfdp->vendor == FLASH_ID_WINBOND) &&
(FLASH_ID_DEVICE_SERIES (table->sfdp->device) == FLASH_ID_W25Q_DTR)) {
/* JESD216C+ QER value 6 uses bit 1 of SR2, read with 0x35 and
* written independently with 0x31. */
quad = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31;
break;
}
else {
return SPI_FLASH_SFDP_QUAD_ENABLE_UNKNOWN;
}
Expand Down
1 change: 1 addition & 0 deletions core/flash/spi_flash_sfdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ enum spi_flash_sfdp_quad_enable {
SPI_FLASH_SFDP_QUAD_QE_BIT7_SR2, /**< Quad enable is bit 7 in status register 2. */
SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_NO_CLR, /**< Quad enable is bit 1 in status register 2, without inadvertent clearing. */
SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35, /**< Quad enable is bit 1 in status register 2, using 35 to read. */
SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31, /**< Quad enable is bit 1 in status register 2, using 35 to read and 31 to write. */
SPI_FLASH_SFDP_QUAD_NO_QE_HOLD_DISABLE = 8, /**< No quad enable bit, but HOLD/RESET can be disabled. */
};

Expand Down
135 changes: 135 additions & 0 deletions core/testing/flash/spi_flash_sfdp_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -7878,6 +7878,139 @@ static void spi_flash_sfdp_test_get_quad_enable_reserved_value_6 (CuTest *test)
spi_flash_sfdp_release (&sfdp);
}

static void spi_flash_sfdp_test_get_quad_enable_w25q01rv_qer_6 (CuTest *test)
{
struct flash_master_mock flash;
struct spi_flash_sfdp sfdp;
struct spi_flash_sfdp_basic_table table;
int status;
uint8_t id[] = {0xef, 0x70, 0x21};
uint32_t header[] = {
0x50444653,
0xff000106,
0x10010600,
0xff000010
};
uint32_t params[] = {
0xfff920e5,
0x00ffffff,
0x6b08eb44,
0xbb423b08,
0xfffffffe,
0x0000ffff,
0xeb40ffff,
0x520f200c,
0x0000d810,
0x00a60236,
0xb314ea82,
0x337663e9,
0x757a757a,
0x5cd5a2f7,
0xff6df719,
0x80f830e4
};
enum spi_flash_sfdp_quad_enable quad;

TEST_START;

status = flash_master_mock_init (&flash);
CuAssertIntEquals (test, 0, status);

spi_flash_sfdp_testing_init_expectations (test, &flash, header, id);

status = spi_flash_sfdp_init (&sfdp, &flash.base);
CuAssertIntEquals (test, 0, status);

status = mock_validate (&flash.mock);
CuAssertIntEquals (test, 0, status);

status = flash_master_mock_expect_rx_xfer (&flash, 0, (uint8_t*) params, sizeof (params),
FLASH_EXP_READ_CMD (0x5a, 0x000010, 1, -1, sizeof (params)));
CuAssertIntEquals (test, 0, status);

status = spi_flash_sfdp_basic_table_init (&table, &sfdp);
CuAssertIntEquals (test, 0, status);

status = mock_validate (&flash.mock);
CuAssertIntEquals (test, 0, status);

status = spi_flash_sfdp_get_quad_enable (&table, &quad);
CuAssertIntEquals (test, 0, status);
CuAssertIntEquals (test, SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31, quad);

status = flash_master_mock_validate_and_release (&flash);
CuAssertIntEquals (test, 0, status);

spi_flash_sfdp_basic_table_release (&table);
spi_flash_sfdp_release (&sfdp);
}

static void spi_flash_sfdp_test_get_quad_enable_w25q_qer_6 (CuTest *test)
{
struct flash_master_mock flash;
struct spi_flash_sfdp sfdp;
struct spi_flash_sfdp_basic_table table;
int status;
uint8_t id[] = {0xef, 0x40, 0x21};
uint32_t header[] = {
0x50444653,
0xff000106,
0x10010600,
0xff000010
};
uint32_t params[] = {
0xfff920e5,
0x00ffffff,
0x6b08eb44,
0xbb423b08,
0xfffffffe,
0x0000ffff,
0xeb40ffff,
0x520f200c,
0x0000d810,
0x00a60236,
0xb314ea82,
0x337663e9,
0x757a757a,
0x5cd5a2f7,
0xff6df719,
0x80f830e4
};
enum spi_flash_sfdp_quad_enable quad;

TEST_START;

status = flash_master_mock_init (&flash);
CuAssertIntEquals (test, 0, status);

spi_flash_sfdp_testing_init_expectations (test, &flash, header, id);

status = spi_flash_sfdp_init (&sfdp, &flash.base);
CuAssertIntEquals (test, 0, status);

status = mock_validate (&flash.mock);
CuAssertIntEquals (test, 0, status);

status = flash_master_mock_expect_rx_xfer (&flash, 0, (uint8_t*) params, sizeof (params),
FLASH_EXP_READ_CMD (0x5a, 0x000010, 1, -1, sizeof (params)));
CuAssertIntEquals (test, 0, status);

status = spi_flash_sfdp_basic_table_init (&table, &sfdp);
CuAssertIntEquals (test, 0, status);

status = mock_validate (&flash.mock);
CuAssertIntEquals (test, 0, status);

status = spi_flash_sfdp_get_quad_enable (&table, &quad);
CuAssertIntEquals (test, SPI_FLASH_SFDP_QUAD_ENABLE_UNKNOWN, status);

status = flash_master_mock_validate_and_release (&flash);
CuAssertIntEquals (test, 0, status);

spi_flash_sfdp_basic_table_release (&table);
spi_flash_sfdp_release (&sfdp);
}

static void spi_flash_sfdp_test_get_quad_enable_reserved_value_7 (CuTest *test)
{
struct flash_master_mock flash;
Expand Down Expand Up @@ -11585,6 +11718,8 @@ TEST (spi_flash_sfdp_test_get_quad_enable_bit1_sr2_with_35_read);
TEST (spi_flash_sfdp_test_get_quad_enable_old_table_version_no_qspi);
TEST (spi_flash_sfdp_test_get_quad_enable_null);
TEST (spi_flash_sfdp_test_get_quad_enable_reserved_value_6);
TEST (spi_flash_sfdp_test_get_quad_enable_w25q01rv_qer_6);
TEST (spi_flash_sfdp_test_get_quad_enable_w25q_qer_6);
TEST (spi_flash_sfdp_test_get_quad_enable_reserved_value_7);
TEST (spi_flash_sfdp_test_get_quad_enable_old_table_version_with_qspi);
TEST (spi_flash_sfdp_test_exit_4byte_mode_on_reset_mx25l1606e);
Expand Down
Loading