Skip to content

Commit 79bc3aa

Browse files
committed
[nrf fromtree] drivers: flash_mspi_nor: Complete handling of QER, add handling of OER
Complete implementation of quad_enable_set() by adding support for all possible Quad Enable Requirements (QER) as specified by the SFDP JEDEC standard (JESD216). Add also corresponding octal_enable_set() to handle Octal Enable Requirements. Also remove initial waiting from mxicy_mx25r_post_switch_mode() which became unneeded, as now such waiting is done in cmd_wrsr() which is called at the end of quad_enable_set(). Signed-off-by: Andrzej Głąbek <[email protected]> (cherry picked from commit 2fcb215)
1 parent 034396a commit 79bc3aa

File tree

2 files changed

+132
-25
lines changed

2 files changed

+132
-25
lines changed

drivers/flash/flash_mspi_nor.c

Lines changed: 132 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -638,31 +638,138 @@ static int dev_pm_action_cb(const struct device *dev,
638638
static int quad_enable_set(const struct device *dev, bool enable)
639639
{
640640
struct flash_mspi_nor_data *dev_data = dev->data;
641+
uint8_t op_code;
642+
uint8_t qe_bit;
643+
uint8_t status_reg;
644+
uint8_t payload_len;
645+
uint8_t payload[2];
641646
int rc;
642647

643-
rc = cmd_wren(dev);
648+
switch (dev_data->switch_info.quad_enable_req) {
649+
case JESD216_DW15_QER_VAL_S1B6:
650+
op_code = SPI_NOR_CMD_RDSR;
651+
qe_bit = BIT(6);
652+
break;
653+
case JESD216_DW15_QER_VAL_S2B7:
654+
/* Use special Read status register 2 instruction. */
655+
op_code = 0x3F;
656+
qe_bit = BIT(7);
657+
break;
658+
case JESD216_DW15_QER_VAL_S2B1v1:
659+
case JESD216_DW15_QER_VAL_S2B1v4:
660+
case JESD216_DW15_QER_VAL_S2B1v5:
661+
case JESD216_DW15_QER_VAL_S2B1v6:
662+
op_code = SPI_NOR_CMD_RDSR2;
663+
qe_bit = BIT(1);
664+
break;
665+
default:
666+
LOG_ERR("Unknown Quad Enable Requirement: %u",
667+
dev_data->switch_info.quad_enable_req);
668+
return -ENOTSUP;
669+
}
670+
671+
rc = cmd_rdsr(dev, op_code, &status_reg);
644672
if (rc < 0) {
645-
LOG_ERR("Failed to set write enable: %d", rc);
646673
return rc;
647674
}
648675

649-
if (dev_data->switch_info.quad_enable_req == JESD216_DW15_QER_VAL_S1B6) {
650-
uint8_t mode_payload = enable ? BIT(6) : 0;
676+
if (((status_reg & qe_bit) != 0) == enable) {
677+
/* Nothing to do, the QE bit is already set properly. */
678+
return 0;
679+
}
680+
681+
status_reg ^= qe_bit;
682+
683+
switch (dev_data->switch_info.quad_enable_req) {
684+
default:
685+
case JESD216_DW15_QER_VAL_S1B6:
686+
payload_len = 1;
687+
op_code = SPI_NOR_CMD_WRSR;
688+
break;
689+
case JESD216_DW15_QER_VAL_S2B7:
690+
payload_len = 1;
691+
/* Use special Write status register 2 instruction. */
692+
op_code = 0x3E;
693+
break;
694+
case JESD216_DW15_QER_VAL_S2B1v1:
695+
case JESD216_DW15_QER_VAL_S2B1v4:
696+
case JESD216_DW15_QER_VAL_S2B1v5:
697+
payload_len = 2;
698+
op_code = SPI_NOR_CMD_WRSR;
699+
break;
700+
case JESD216_DW15_QER_VAL_S2B1v6:
701+
payload_len = 1;
702+
op_code = SPI_NOR_CMD_WRSR2;
703+
break;
704+
}
705+
706+
if (payload_len == 1) {
707+
payload[0] = status_reg;
708+
} else {
709+
payload[1] = status_reg;
651710

652-
rc = cmd_wrsr(dev, SPI_NOR_CMD_WRSR, 1, &mode_payload);
711+
/* When the Write Status command is to be sent with two data
712+
* bytes (this is the case for S2B1v1, S2B1v4, and S2B1v5 QER
713+
* values), the first status register needs to be read and
714+
* sent as the first byte, so that its value is not modified.
715+
*/
716+
rc = cmd_rdsr(dev, SPI_NOR_CMD_RDSR, &payload[0]);
653717
if (rc < 0) {
654-
LOG_ERR("Failed to enable/disable quad mode: %d", rc);
655718
return rc;
656719
}
657-
} else {
658-
/* TODO: handle all DW15 QER values */
720+
}
721+
722+
rc = cmd_wrsr(dev, op_code, payload_len, payload);
723+
if (rc < 0) {
724+
return rc;
725+
}
726+
727+
return 0;
728+
}
729+
730+
static int octal_enable_set(const struct device *dev, bool enable)
731+
{
732+
struct flash_mspi_nor_data *dev_data = dev->data;
733+
uint8_t op_code;
734+
uint8_t oe_bit;
735+
uint8_t status_reg;
736+
int rc;
737+
738+
if (dev_data->switch_info.octal_enable_req != OCTAL_ENABLE_REQ_S2B3) {
739+
LOG_ERR("Unknown Octal Enable Requirement: %u",
740+
dev_data->switch_info.octal_enable_req);
659741
return -ENOTSUP;
660742
}
661743

662-
rc = wait_until_ready(dev, K_USEC(1));
744+
oe_bit = BIT(3);
663745

746+
/* Use special Read status register 2 instruction 0x65 with one address
747+
* byte 0x02 and one dummy byte.
748+
*/
749+
op_code = 0x65;
750+
set_up_xfer(dev, MSPI_RX);
751+
dev_data->xfer.rx_dummy = 8;
752+
dev_data->xfer.addr_length = 1;
753+
dev_data->packet.address = 0x02;
754+
dev_data->packet.num_bytes = sizeof(uint8_t);
755+
dev_data->packet.data_buf = &status_reg;
756+
rc = perform_xfer(dev, op_code, false);
757+
if (rc < 0) {
758+
LOG_ERR("cmd_rdsr 0x%02x failed: %d", op_code, rc);
759+
return rc;
760+
}
761+
762+
if (((status_reg & oe_bit) != 0) == enable) {
763+
/* Nothing to do, the OE bit is already set properly. */
764+
return 0;
765+
}
766+
767+
status_reg ^= oe_bit;
768+
769+
/* Use special Write status register 2 instruction to clear the bit. */
770+
op_code = (status_reg & oe_bit) ? SPI_NOR_CMD_WRSR2 : 0x3E;
771+
rc = cmd_wrsr(dev, op_code, 1, &status_reg);
664772
if (rc < 0) {
665-
LOG_ERR("Failed waiting until device ready after enabling quad: %d", rc);
666773
return rc;
667774
}
668775

@@ -699,18 +806,24 @@ static int switch_to_target_io_mode(const struct device *dev)
699806
int rc = 0;
700807

701808
if (dev_data->switch_info.quad_enable_req != JESD216_DW15_QER_VAL_NONE) {
702-
/* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined
703-
* in JEDEC216 BFP DW15 QER
704-
*/
705-
if (io_mode == MSPI_IO_MODE_SINGLE) {
706-
rc = quad_enable_set(dev, false);
707-
} else if (io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
708-
io_mode == MSPI_IO_MODE_QUAD_1_4_4) {
709-
rc = quad_enable_set(dev, true);
710-
}
809+
bool quad_needed = io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
810+
io_mode == MSPI_IO_MODE_QUAD_1_4_4;
711811

812+
rc = quad_enable_set(dev, quad_needed);
712813
if (rc < 0) {
713814
LOG_ERR("Failed to modify Quad Enable bit: %d", rc);
815+
return rc;
816+
}
817+
}
818+
819+
if (dev_data->switch_info.octal_enable_req != OCTAL_ENABLE_REQ_NONE) {
820+
bool octal_needed = io_mode == MSPI_IO_MODE_OCTAL_1_1_8 ||
821+
io_mode == MSPI_IO_MODE_OCTAL_1_8_8;
822+
823+
rc = octal_enable_set(dev, octal_needed);
824+
if (rc < 0) {
825+
LOG_ERR("Failed to modify Octal Enable bit: %d", rc);
826+
return rc;
714827
}
715828
}
716829

drivers/flash/flash_mspi_nor_quirks.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,6 @@ static inline int mxicy_mx25r_post_switch_mode(const struct device *dev)
7070
return 0;
7171
}
7272

73-
/* Wait for previous write to finish */
74-
rc = wait_until_ready(dev, K_USEC(1));
75-
if (rc < 0) {
76-
return rc;
77-
}
78-
7973
/* Write enable */
8074
rc = cmd_wren(dev);
8175
if (rc < 0) {

0 commit comments

Comments
 (0)