diff --git a/core/flash/spi_flash.c b/core/flash/spi_flash.c index 894e3e7c..7b55c312 100644 --- a/core/flash/spi_flash.c +++ b/core/flash/spi_flash.c @@ -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, ®[1], 1, 0); status = flash->spi->xfer (flash->spi, &xfer); if (status != 0) { @@ -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, ®[1], 1, + flash->state->sr1_volatile); + } + goto exit; + } + if (flash->state->quad_enable == SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35) { cmd_len = 2; } @@ -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; @@ -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; @@ -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; @@ -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: diff --git a/core/flash/spi_flash_sfdp.c b/core/flash/spi_flash_sfdp.c index c2f5767e..4ddc279f 100644 --- a/core/flash/spi_flash_sfdp.c +++ b/core/flash/spi_flash_sfdp.c @@ -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) @@ -724,8 +724,8 @@ 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. @@ -733,6 +733,14 @@ int spi_flash_sfdp_get_quad_enable (const struct spi_flash_sfdp_basic_table *tab 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; } diff --git a/core/flash/spi_flash_sfdp.h b/core/flash/spi_flash_sfdp.h index 435e1db0..b10385a0 100644 --- a/core/flash/spi_flash_sfdp.h +++ b/core/flash/spi_flash_sfdp.h @@ -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. */ }; diff --git a/core/testing/flash/spi_flash_sfdp_test.c b/core/testing/flash/spi_flash_sfdp_test.c index fe9130a7..a89ca5ec 100644 --- a/core/testing/flash/spi_flash_sfdp_test.c +++ b/core/testing/flash/spi_flash_sfdp_test.c @@ -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; @@ -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); diff --git a/core/testing/flash/spi_flash_test.c b/core/testing/flash/spi_flash_test.c index 32979e55..af919afa 100644 --- a/core/testing/flash/spi_flash_test.c +++ b/core/testing/flash/spi_flash_test.c @@ -15802,6 +15802,160 @@ static void spi_flash_test_enable_quad_spi_quad_enable_bit1_sr2_read_35_volatile spi_flash_release (&flash); } +static void spi_flash_test_enable_quad_spi_w25q01rv_qer_6 (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t read_status = 0; + uint8_t reg_enable = 0x00; + uint8_t enable_expected = 0x02; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, ®_enable, 1, + FLASH_EXP_READ_REG (0x35, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &read_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, 0, + FLASH_EXP_WRITE_REG (0x31, &enable_expected, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &read_status, 1, + FLASH_EXP_READ_STATUS_REG); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_enable_quad_spi (&flash, 1); + CuAssertIntEquals (test, 0, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + +static void spi_flash_test_disable_quad_spi_w25q01rv_qer_6 (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t read_status = 0; + uint8_t reg_disable = 0xff; + uint8_t disable_expected = 0xfd; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, ®_disable, 1, + FLASH_EXP_READ_REG (0x35, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &read_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, 0, + FLASH_EXP_WRITE_REG (0x31, &disable_expected, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &read_status, 1, + FLASH_EXP_READ_STATUS_REG); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_enable_quad_spi (&flash, 0); + CuAssertIntEquals (test, 0, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + +static void spi_flash_test_is_quad_spi_enabled_w25q01rv_qer_6 (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t reg = 0x02; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, ®, 1, + FLASH_EXP_READ_REG (0x35, 1)); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_is_quad_spi_enabled (&flash); + CuAssertIntEquals (test, 1, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + +static void spi_flash_test_is_quad_spi_disabled_w25q01rv_qer_6 (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t reg = 0x00; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, ®, 1, + FLASH_EXP_READ_REG (0x35, 1)); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_is_quad_spi_enabled (&flash); + CuAssertIntEquals (test, 0, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + static void spi_flash_test_enable_quad_spi_quad_enable_bit6_sr1 (CuTest *test) { struct spi_flash_state state; @@ -17334,6 +17488,256 @@ static void spi_flash_test_clear_block_protect_quad_enable_bit1_sr2_read_35 (CuT spi_flash_release (&flash); } +static void spi_flash_test_clear_block_protect_w25q01rv_qer_6 (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t wip_status = 0; + uint8_t reg_set[] = {0xff, 0xff}; + uint8_t sr1_expected = 0x83; + uint8_t sr2_expected = 0x03; + uint8_t id[] = {0xef, 0x70, 0x21}; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, id, FLASH_ID_LEN, + FLASH_EXP_READ_REG (0x9f, FLASH_ID_LEN)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[1], 1, + FLASH_EXP_READ_REG (0x35, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[0], 1, + FLASH_EXP_READ_REG (0x05, 1)); + + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, 0, + FLASH_EXP_WRITE_REG (0x01, &sr1_expected, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, 0, + FLASH_EXP_WRITE_REG (0x31, &sr2_expected, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_clear_block_protect (&flash); + CuAssertIntEquals (test, 0, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + +static void spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr1_only (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t wip_status = 0; + uint8_t reg_set[] = {0xff, 0x03}; + uint8_t sr1_expected = 0x83; + uint8_t id[] = {0xef, 0x70, 0x21}; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, id, FLASH_ID_LEN, + FLASH_EXP_READ_REG (0x9f, FLASH_ID_LEN)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[1], 1, + FLASH_EXP_READ_REG (0x35, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[0], 1, + FLASH_EXP_READ_REG (0x05, 1)); + + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, 0, + FLASH_EXP_WRITE_REG (0x01, &sr1_expected, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_clear_block_protect (&flash); + CuAssertIntEquals (test, 0, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + +static void spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr2_only (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t wip_status = 0; + uint8_t reg_set[] = {0x83, 0xff}; + uint8_t sr2_expected = 0x03; + uint8_t id[] = {0xef, 0x70, 0x21}; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, id, FLASH_ID_LEN, + FLASH_EXP_READ_REG (0x9f, FLASH_ID_LEN)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[1], 1, + FLASH_EXP_READ_REG (0x35, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[0], 1, + FLASH_EXP_READ_REG (0x05, 1)); + + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, 0, + FLASH_EXP_WRITE_REG (0x31, &sr2_expected, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_clear_block_protect (&flash); + CuAssertIntEquals (test, 0, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + +static void spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr1_write_error (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t wip_status = 0; + uint8_t reg_set[] = {0xff, 0x03}; + uint8_t sr1_expected = 0x83; + uint8_t id[] = {0xef, 0x70, 0x21}; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, id, FLASH_ID_LEN, + FLASH_EXP_READ_REG (0x9f, FLASH_ID_LEN)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[1], 1, + FLASH_EXP_READ_REG (0x35, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[0], 1, + FLASH_EXP_READ_REG (0x05, 1)); + + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, FLASH_MASTER_XFER_FAILED, + FLASH_EXP_WRITE_REG (0x01, &sr1_expected, 1)); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_clear_block_protect (&flash); + CuAssertIntEquals (test, FLASH_MASTER_XFER_FAILED, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + +static void spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr2_write_error (CuTest *test) +{ + struct spi_flash_state state; + struct spi_flash flash; + struct flash_master_mock mock; + int status; + uint8_t wip_status = 0; + uint8_t reg_set[] = {0x83, 0xff}; + uint8_t sr2_expected = 0x03; + uint8_t id[] = {0xef, 0x70, 0x21}; + + TEST_START; + + status = flash_master_mock_init (&mock); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_init (&flash, &state, &mock.base); + CuAssertIntEquals (test, 0, status); + + state.quad_enable = SPI_FLASH_SFDP_QUAD_QE_BIT1_SR2_35_31; + + status = flash_master_mock_expect_rx_xfer (&mock, 0, id, FLASH_ID_LEN, + FLASH_EXP_READ_REG (0x9f, FLASH_ID_LEN)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[1], 1, + FLASH_EXP_READ_REG (0x35, 1)); + status |= flash_master_mock_expect_rx_xfer (&mock, 0, ®_set[0], 1, + FLASH_EXP_READ_REG (0x05, 1)); + + status |= flash_master_mock_expect_rx_xfer (&mock, 0, &wip_status, 1, + FLASH_EXP_READ_STATUS_REG); + status |= flash_master_mock_expect_xfer (&mock, 0, FLASH_EXP_WRITE_ENABLE); + status |= flash_master_mock_expect_tx_xfer (&mock, FLASH_MASTER_XFER_FAILED, + FLASH_EXP_WRITE_REG (0x31, &sr2_expected, 1)); + CuAssertIntEquals (test, 0, status); + + status = spi_flash_clear_block_protect (&flash); + CuAssertIntEquals (test, FLASH_MASTER_XFER_FAILED, status); + + status = mock_validate (&mock.mock); + CuAssertIntEquals (test, 0, status); + + spi_flash_is_write_in_progress (&flash); + + flash_master_mock_release (&mock); + spi_flash_release (&flash); +} + static void spi_flash_test_clear_block_protect_quad_enable_bit6_sr1 (CuTest *test) { struct spi_flash_state state; @@ -30002,6 +30406,8 @@ TEST (spi_flash_test_enable_quad_spi_quad_enable_bit1_sr2_no_clear); TEST (spi_flash_test_enable_quad_spi_quad_enable_bit1_sr2_no_clear_volatile_write_enable); TEST (spi_flash_test_enable_quad_spi_quad_enable_bit1_sr2_read_35); TEST (spi_flash_test_enable_quad_spi_quad_enable_bit1_sr2_read_35_volatile_write_enable); +TEST (spi_flash_test_enable_quad_spi_w25q01rv_qer_6); +TEST (spi_flash_test_disable_quad_spi_w25q01rv_qer_6); TEST (spi_flash_test_enable_quad_spi_quad_enable_bit6_sr1); TEST (spi_flash_test_enable_quad_spi_quad_enable_bit6_sr1_volatile_write_enable); TEST (spi_flash_test_enable_quad_spi_quad_enable_bit7_sr2); @@ -30017,6 +30423,8 @@ TEST (spi_flash_test_is_quad_spi_enabled_no_quad_enable_hold_disable); TEST (spi_flash_test_is_quad_spi_enabled_quad_enable_bit1_sr2); TEST (spi_flash_test_is_quad_spi_enabled_quad_enable_bit1_sr2_no_clear); TEST (spi_flash_test_is_quad_spi_enabled_quad_enable_bit1_sr2_read_35); +TEST (spi_flash_test_is_quad_spi_enabled_w25q01rv_qer_6); +TEST (spi_flash_test_is_quad_spi_disabled_w25q01rv_qer_6); TEST (spi_flash_test_is_quad_spi_enabled_quad_enable_bit6_sr1); TEST (spi_flash_test_is_quad_spi_enabled_quad_enable_bit7_sr2); TEST (spi_flash_test_is_quad_spi_enabled_null); @@ -30027,6 +30435,11 @@ TEST (spi_flash_test_clear_block_protect_quad_enable_bit1_sr2); TEST (spi_flash_test_clear_block_protect_quad_enable_bit1_sr2_no_clear); TEST (spi_flash_test_clear_block_protect_winbond_cmp_bit_set); TEST (spi_flash_test_clear_block_protect_quad_enable_bit1_sr2_read_35); +TEST (spi_flash_test_clear_block_protect_w25q01rv_qer_6); +TEST (spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr1_only); +TEST (spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr2_only); +TEST (spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr1_write_error); +TEST (spi_flash_test_clear_block_protect_w25q01rv_qer_6_sr2_write_error); TEST (spi_flash_test_clear_block_protect_quad_enable_bit6_sr1); TEST (spi_flash_test_clear_block_protect_quad_enable_bit7_sr2); TEST (spi_flash_test_clear_block_protect_volatile_write_enable);