Skip to content

Commit 5a16efa

Browse files
committed
[nrf fromlist] 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(). Upstream PR #: 93093 Signed-off-by: Andrzej Głąbek <[email protected]>
1 parent 505db63 commit 5a16efa

File tree

2 files changed

+134
-25
lines changed

2 files changed

+134
-25
lines changed

drivers/flash/flash_mspi_nor.c

Lines changed: 134 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -598,31 +598,138 @@ static int dev_pm_action_cb(const struct device *dev,
598598
static int quad_enable_set(const struct device *dev, bool enable)
599599
{
600600
struct flash_mspi_nor_data *dev_data = dev->data;
601+
uint8_t op_code;
602+
uint8_t qe_bit;
603+
uint8_t status_reg;
604+
uint8_t payload_len;
605+
uint8_t payload[2];
601606
int rc;
602607

603-
rc = cmd_wren(dev);
608+
switch (dev_data->switch_info.quad_enable_req) {
609+
case JESD216_DW15_QER_VAL_S1B6:
610+
op_code = SPI_NOR_CMD_RDSR;
611+
qe_bit = BIT(6);
612+
break;
613+
case JESD216_DW15_QER_VAL_S2B7:
614+
/* Use special Read status register 2 instruction. */
615+
op_code = 0x3F;
616+
qe_bit = BIT(7);
617+
break;
618+
case JESD216_DW15_QER_VAL_S2B1v1:
619+
case JESD216_DW15_QER_VAL_S2B1v4:
620+
case JESD216_DW15_QER_VAL_S2B1v5:
621+
case JESD216_DW15_QER_VAL_S2B1v6:
622+
op_code = SPI_NOR_CMD_RDSR2;
623+
qe_bit = BIT(1);
624+
break;
625+
default:
626+
LOG_ERR("Unknown Quad Enable Requirement: %u",
627+
dev_data->switch_info.quad_enable_req);
628+
return -ENOTSUP;
629+
}
630+
631+
rc = cmd_rdsr(dev, op_code, &status_reg);
604632
if (rc < 0) {
605-
LOG_ERR("Failed to set write enable: %d", rc);
606633
return rc;
607634
}
608635

609-
if (dev_data->switch_info.quad_enable_req == JESD216_DW15_QER_VAL_S1B6) {
610-
uint8_t mode_payload = enable ? BIT(6) : 0;
636+
if (((status_reg & qe_bit) != 0) == enable) {
637+
/* Nothing to do, the QE bit is already set properly. */
638+
return 0;
639+
}
640+
641+
status_reg ^= qe_bit;
642+
643+
switch (dev_data->switch_info.quad_enable_req) {
644+
default:
645+
case JESD216_DW15_QER_VAL_S1B6:
646+
payload_len = 1;
647+
op_code = SPI_NOR_CMD_WRSR;
648+
break;
649+
case JESD216_DW15_QER_VAL_S2B7:
650+
payload_len = 1;
651+
/* Use special Write status register 2 instruction. */
652+
op_code = 0x3E;
653+
break;
654+
case JESD216_DW15_QER_VAL_S2B1v1:
655+
case JESD216_DW15_QER_VAL_S2B1v4:
656+
case JESD216_DW15_QER_VAL_S2B1v5:
657+
payload_len = 2;
658+
op_code = SPI_NOR_CMD_WRSR;
659+
break;
660+
case JESD216_DW15_QER_VAL_S2B1v6:
661+
payload_len = 1;
662+
op_code = SPI_NOR_CMD_WRSR2;
663+
break;
664+
}
665+
666+
if (payload_len == 1) {
667+
payload[0] = status_reg;
668+
} else {
669+
payload[1] = status_reg;
611670

612-
rc = cmd_wrsr(dev, SPI_NOR_CMD_WRSR, 1, &mode_payload);
671+
/* When the Write Status command is to be sent with two data
672+
* bytes (this is the case for S2B1v1, S2B1v4, and S2B1v5 QER
673+
* values), the first status register needs to be read and
674+
* sent as the first byte, so that its value is not modified.
675+
*/
676+
rc = cmd_rdsr(dev, SPI_NOR_CMD_RDSR, &payload[0]);
613677
if (rc < 0) {
614-
LOG_ERR("Failed to enable/disable quad mode: %d", rc);
615678
return rc;
616679
}
617-
} else {
618-
/* TODO: handle all DW15 QER values */
680+
}
681+
682+
rc = cmd_wrsr(dev, op_code, payload_len, payload);
683+
if (rc < 0) {
684+
return rc;
685+
}
686+
687+
return 0;
688+
}
689+
690+
static int octal_enable_set(const struct device *dev, bool enable)
691+
{
692+
struct flash_mspi_nor_data *dev_data = dev->data;
693+
uint8_t op_code;
694+
uint8_t oe_bit;
695+
uint8_t status_reg;
696+
int rc;
697+
698+
if (dev_data->switch_info.octal_enable_req != BFP_DW19_OER_VAL_S2B3) {
699+
LOG_ERR("Unknown Octal Enable Requirement: %u",
700+
dev_data->switch_info.octal_enable_req);
619701
return -ENOTSUP;
620702
}
621703

622-
rc = wait_until_ready(dev, K_USEC(1));
704+
oe_bit = BIT(3);
623705

706+
/* Use special Read status register 2 instruction 0x65 with one address
707+
* byte 0x02 and one dummy byte.
708+
*/
709+
op_code = 0x65;
710+
set_up_xfer(dev, MSPI_RX);
711+
dev_data->xfer.rx_dummy = 8;
712+
dev_data->xfer.addr_length = 1;
713+
dev_data->packet.address = 0x02;
714+
dev_data->packet.num_bytes = sizeof(uint8_t);
715+
dev_data->packet.data_buf = &status_reg;
716+
rc = perform_xfer(dev, op_code, false);
717+
if (rc < 0) {
718+
LOG_ERR("cmd_rdsr 0x%02x failed: %d", op_code, rc);
719+
return rc;
720+
}
721+
722+
if (((status_reg & oe_bit) != 0) == enable) {
723+
/* Nothing to do, the OE bit is already set properly. */
724+
return 0;
725+
}
726+
727+
status_reg ^= oe_bit;
728+
729+
/* Use special Write status register 2 instruction to clear the bit. */
730+
op_code = (status_reg & oe_bit) ? SPI_NOR_CMD_WRSR2 : 0x3E;
731+
rc = cmd_wrsr(dev, op_code, 1, &status_reg);
624732
if (rc < 0) {
625-
LOG_ERR("Failed waiting until device ready after enabling quad: %d", rc);
626733
return rc;
627734
}
628735

@@ -659,18 +766,26 @@ static int switch_to_target_io_mode(const struct device *dev)
659766
int rc = 0;
660767

661768
if (dev_data->switch_info.quad_enable_req != JESD216_DW15_QER_VAL_NONE) {
662-
/* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined
663-
* in JEDEC216 BFP DW15 QER
664-
*/
665-
if (io_mode == MSPI_IO_MODE_SINGLE) {
666-
rc = quad_enable_set(dev, false);
667-
} else if (io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
668-
io_mode == MSPI_IO_MODE_QUAD_1_4_4) {
669-
rc = quad_enable_set(dev, true);
670-
}
769+
bool quad_needed = io_mode == MSPI_IO_MODE_QUAD_1_1_4 ||
770+
io_mode == MSPI_IO_MODE_QUAD_1_4_4 ||
771+
io_mode == MSPI_IO_MODE_QUAD;
671772

773+
rc = quad_enable_set(dev, quad_needed);
672774
if (rc < 0) {
673775
LOG_ERR("Failed to modify Quad Enable bit: %d", rc);
776+
return rc;
777+
}
778+
}
779+
780+
if (dev_data->switch_info.octal_enable_req != BFP_DW19_OER_VAL_NONE) {
781+
bool octal_needed = io_mode == MSPI_IO_MODE_OCTAL_1_1_8 ||
782+
io_mode == MSPI_IO_MODE_OCTAL_1_8_8 ||
783+
io_mode == MSPI_IO_MODE_OCTAL;
784+
785+
rc = octal_enable_set(dev, octal_needed);
786+
if (rc < 0) {
787+
LOG_ERR("Failed to modify Octal Enable bit: %d", rc);
788+
return rc;
674789
}
675790
}
676791

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)