@@ -195,6 +195,14 @@ struct spi_nor_data {
195195#endif /* CONFIG_FLASH_PAGE_LAYOUT */
196196#endif /* CONFIG_SPI_NOR_SFDP_RUNTIME */
197197#endif /* CONFIG_SPI_NOR_SFDP_MINIMAL */
198+
199+ #ifdef CONFIG_SPI_EXTENDED_MODES
200+ enum spi_nor_protocol nor_protocol ;
201+
202+ uint8_t read_cmd ;
203+ uint8_t program_cmd ;
204+ uint8_t erase_cmd ;
205+ #endif
198206};
199207
200208#ifdef CONFIG_SPI_NOR_SFDP_MINIMAL
@@ -393,6 +401,7 @@ static int spi_nor_access(const struct device *const dev,
393401 }
394402 };
395403
404+ #ifndef CONFIG_SPI_EXTENDED_MODES
396405 buf [0 ] = opcode ;
397406 if (is_addressed ) {
398407 bool access_24bit = (access & NOR_ACCESS_24BIT_ADDR ) != 0 ;
@@ -425,6 +434,131 @@ static int spi_nor_access(const struct device *const dev,
425434 .buffers = spi_buf ,
426435 .count = 2 ,
427436 };
437+ #else
438+
439+ spi_buf [0 ].spi_mem_op .cmd .opcode = opcode ;
440+ spi_buf [0 ].spi_mem_op .cmd .nbytes = 1 ;
441+
442+ if (is_addressed ) {
443+ bool access_24bit = (access & NOR_ACCESS_24BIT_ADDR ) != 0 ;
444+ bool access_32bit = (access & NOR_ACCESS_32BIT_ADDR ) != 0 ;
445+ bool use_32bit = (access_32bit
446+ || (!access_24bit
447+ && driver_data -> flag_access_32bit ));
448+
449+ spi_buf [0 ].spi_mem_op .addr .nbytes = use_32bit ? 4 : 3 ;
450+ };
451+ spi_buf [0 ].spi_mem_op .addr .val = addr ;
452+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_SINGLE ;
453+ spi_buf [0 ].spi_mem_op .addr .dtr = 0 ;
454+
455+ spi_buf [0 ].spi_mem_op .data .nbytes = length ;
456+ spi_buf [0 ].spi_mem_op .data .buf = data ;
457+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_SINGLE ;
458+ spi_buf [0 ].spi_mem_op .data .dtr = 0 ;
459+
460+
461+ switch (driver_data -> nor_protocol ) {
462+ case PROTO_1_1_1 :
463+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
464+ spi_buf [0 ].spi_mem_op .cmd .dtr = 0 ;
465+ break ;
466+ case PROTO_1_1_2 :
467+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
468+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_SINGLE ;
469+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_DUAL ;
470+ break ;
471+ case PROTO_1_2_2 :
472+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
473+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_DUAL ;
474+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_DUAL ;
475+ break ;
476+ case PROTO_1_1_4 :
477+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
478+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_SINGLE ;
479+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
480+ break ;
481+ case PROTO_1_4_4 :
482+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
483+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_QUAD ;
484+ spi_buf [0 ].spi_mem_op .addr .dtr = 1 ;
485+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
486+ spi_buf [0 ].spi_mem_op .data .dtr = 1 ;
487+ break ;
488+ case PROTO_1_4D_4D :
489+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
490+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_QUAD ;
491+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
492+ break ;
493+ case PROTO_4_4_4 :
494+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_QUAD ;
495+ spi_buf [0 ].spi_mem_op .cmd .dtr = 0 ;
496+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_QUAD ;
497+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
498+ if (opcode == SPI_NOR_CMD_4READ ) {
499+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 6 ;
500+ }
501+ break ;
502+ case PROTO_8_8_8 :
503+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_OCTAL ;
504+ spi_buf [0 ].spi_mem_op .cmd .dtr = 0 ;
505+ spi_buf [0 ].spi_mem_op .cmd .opcode = (opcode << 8 ) | (0xFF - opcode );
506+ spi_buf [0 ].spi_mem_op .cmd .nbytes = 2 ;
507+
508+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
509+ spi_buf [0 ].spi_mem_op .addr .dtr = 0 ;
510+
511+ if ((opcode == SPI_NOR_CMD_RDID ) || (opcode == SPI_NOR_CMD_RDSR )) {
512+ spi_buf [0 ].spi_mem_op .addr .val = 0 ;
513+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
514+ spi_buf [0 ].spi_mem_op .addr .nbytes = 4 ;
515+
516+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 4 ;
517+ }
518+ if (opcode == 0xEC ) {
519+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 20 ;
520+ }
521+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_OCTAL ;
522+ spi_buf [0 ].spi_mem_op .data .dtr = 0 ;
523+ break ;
524+ case PROTO_8D_8D_8D :
525+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_OCTAL ;
526+ spi_buf [0 ].spi_mem_op .cmd .dtr = 1 ;
527+ spi_buf [0 ].spi_mem_op .cmd .opcode = (opcode << 8 ) | (0xFF - opcode );
528+ spi_buf [0 ].spi_mem_op .cmd .nbytes = 2 ;
529+
530+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
531+ spi_buf [0 ].spi_mem_op .addr .dtr = 1 ;
532+
533+ spi_buf [0 ].spi_mem_op .data .dtr = 1 ;
534+
535+ if ((opcode == SPI_NOR_CMD_RDID ) || (opcode == SPI_NOR_CMD_RDSR )) {
536+ spi_buf [0 ].spi_mem_op .addr .val = 0 ;
537+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
538+ spi_buf [0 ].spi_mem_op .addr .nbytes = 4 ;
539+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 6 ;
540+ spi_buf [0 ].spi_mem_op .data .dtr = 0 ;
541+ } else if (opcode == 0xEE ) {
542+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 20 ;
543+ }
544+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_OCTAL ;
545+
546+ break ;
547+ default :
548+ break ;
549+ };
550+
551+ const struct spi_buf_set tx_set = {
552+ .buffers = spi_buf ,
553+ .count = 1 ,
554+ };
555+
556+ const struct spi_buf_set rx_set = {
557+ .buffers = spi_buf ,
558+ .count = 1 ,
559+ };
560+
561+ #endif
428562
429563 if (is_write ) {
430564 return spi_write_dt (& driver_cfg -> spi , & tx_set );
@@ -785,9 +919,121 @@ static int mxicy_configure(const struct device *dev, const uint8_t *jedec_id)
785919
786920#endif /* ANY_INST_HAS_MXICY_MX25R_POWER_MODE */
787921
922+ #ifdef CONFIG_SPI_EXTENDED_MODES
923+ /**
924+ * @brief Write the configuration register2.
925+ *
926+ * @note The device must be externally acquired before invoking this
927+ * function.
928+ *
929+ * @param dev Device struct
930+ * @param sr The new value of the configuration register2
931+ *
932+ * @return 0 on success or a negative error code.
933+ */
934+ static int spi_nor_wrcr2 (const struct device * dev ,
935+ uint8_t cr )
936+ {
937+ int ret = spi_nor_cmd_write (dev , SPI_NOR_CMD_WREN );
938+
939+ if (ret == 0 ) {
940+
941+ struct spi_nor_data * data = dev -> data ;
942+
943+ data -> flag_access_32bit = true;
944+
945+ ret = spi_nor_cmd_addr_write (dev , SPI_NOR_CMD_WR_CFGREG2 , 0 , & cr , sizeof (cr ));
946+ }
947+
948+ return ret ;
949+ }
950+
951+ static int spi_nor_change_protocol (const struct device * dev ,
952+ enum spi_nor_protocol nor_protocol )
953+ {
954+ struct spi_nor_data * data = dev -> data ;
955+ uint8_t cr2 ;
956+ int ret = 0 ;
957+
958+ switch (nor_protocol ) {
959+ case PROTO_1_1_1 :
960+ data -> nor_protocol = PROTO_1_1_1 ;
961+ data -> flag_access_32bit = false;
962+ data -> read_cmd = SPI_NOR_CMD_READ ;
963+ data -> program_cmd = SPI_NOR_CMD_PP ;
964+ data -> erase_cmd = SPI_NOR_CMD_SE ;
965+ break ;
966+ case PROTO_1_1_2 :
967+ data -> nor_protocol = PROTO_1_1_2 ;
968+ data -> flag_access_32bit = false;
969+ data -> read_cmd = SPI_NOR_CMD_READ ;
970+ data -> program_cmd = SPI_NOR_CMD_PP ;
971+ data -> erase_cmd = SPI_NOR_CMD_SE ;
972+ break ;
973+ case PROTO_1_2_2 :
974+ data -> nor_protocol = PROTO_1_2_2 ;
975+ data -> flag_access_32bit = false;
976+ data -> read_cmd = SPI_NOR_CMD_READ ;
977+ data -> program_cmd = SPI_NOR_CMD_PP ;
978+ data -> erase_cmd = SPI_NOR_CMD_SE ;
979+ break ;
980+ case PROTO_1_1_4 :
981+ data -> nor_protocol = PROTO_1_1_4 ;
982+ data -> flag_access_32bit = false;
983+ data -> read_cmd = SPI_NOR_CMD_READ ;
984+ data -> program_cmd = SPI_NOR_CMD_PP ;
985+ data -> erase_cmd = SPI_NOR_CMD_SE ;
986+ break ;
987+ case PROTO_1_4_4 :
988+ data -> nor_protocol = PROTO_1_4_4 ;
989+ data -> flag_access_32bit = false;
990+ data -> read_cmd = SPI_NOR_CMD_READ ;
991+ data -> program_cmd = SPI_NOR_CMD_PP ;
992+ data -> erase_cmd = SPI_NOR_CMD_SE ;
993+ break ;
994+ case PROTO_1_4D_4D :
995+ data -> nor_protocol = PROTO_1_4D_4D ;
996+ data -> flag_access_32bit = false;
997+ data -> read_cmd = SPI_NOR_CMD_READ ;
998+ data -> program_cmd = SPI_NOR_CMD_PP ;
999+ data -> erase_cmd = SPI_NOR_CMD_SE ;
1000+ break ;
1001+ case PROTO_4_4_4 :
1002+ ret = spi_nor_cmd_write (dev , SPI_NOR_CMD_EQIO );
1003+ data -> nor_protocol = PROTO_4_4_4 ;
1004+ data -> flag_access_32bit = false;
1005+ data -> read_cmd = SPI_NOR_CMD_4READ ;
1006+ data -> program_cmd = SPI_NOR_CMD_PP ;
1007+ data -> erase_cmd = SPI_NOR_CMD_SE ;
1008+ break ;
1009+ case PROTO_8_8_8 :
1010+ data -> flag_access_32bit = true;
1011+ data -> read_cmd = SPI_NOR_OCMD_RD ;
1012+ data -> program_cmd = SPI_NOR_CMD_PP_4B ;
1013+ data -> erase_cmd = SPI_NOR_OCMD_SE ;
1014+ cr2 = 0x01 ;
1015+ ret = spi_nor_wrcr2 (dev , cr2 );
1016+ data -> nor_protocol = PROTO_8_8_8 ;
1017+ break ;
1018+ case PROTO_8D_8D_8D :
1019+ data -> flag_access_32bit = true;
1020+ data -> read_cmd = SPI_NOR_OCMD_DTR_RD ;
1021+ data -> program_cmd = SPI_NOR_CMD_PP_4B ;
1022+ data -> erase_cmd = SPI_NOR_OCMD_SE ;
1023+ cr2 = 0x02 ;
1024+ ret = spi_nor_wrcr2 (dev , cr2 );
1025+ data -> nor_protocol = PROTO_8D_8D_8D ;
1026+ break ;
1027+ }
1028+
1029+ return ret ;
1030+ }
1031+ #endif
1032+
7881033static int spi_nor_read (const struct device * dev , off_t addr , void * dest ,
7891034 size_t size )
7901035{
1036+ struct spi_nor_data * data = dev -> data ;
7911037 const size_t flash_size = dev_flash_size (dev );
7921038 int ret ;
7931039
@@ -803,14 +1049,19 @@ static int spi_nor_read(const struct device *dev, off_t addr, void *dest,
8031049
8041050 acquire_device (dev );
8051051
1052+ uint8_t read_cmd = SPI_NOR_CMD_READ ;
1053+ #ifdef CONFIG_SPI_EXTENDED_MODES
1054+ read_cmd = data -> read_cmd ;
1055+ #endif
1056+
8061057 if (IS_ENABLED (ANY_INST_USE_4B_ADDR_OPCODES ) && DEV_CFG (dev )-> use_4b_addr_opcodes ) {
8071058 if (addr > SPI_NOR_3B_ADDR_MAX ) {
8081059 ret = spi_nor_cmd_addr_read_4b (dev , SPI_NOR_CMD_READ_4B , addr , dest , size );
8091060 } else {
810- ret = spi_nor_cmd_addr_read_3b (dev , SPI_NOR_CMD_READ , addr , dest , size );
1061+ ret = spi_nor_cmd_addr_read_3b (dev , read_cmd , addr , dest , size );
8111062 }
8121063 } else {
813- ret = spi_nor_cmd_addr_read (dev , SPI_NOR_CMD_READ , addr , dest , size );
1064+ ret = spi_nor_cmd_addr_read (dev , read_cmd , addr , dest , size );
8141065 }
8151066
8161067 release_device (dev );
@@ -857,6 +1108,7 @@ static int spi_nor_write(const struct device *dev, off_t addr,
8571108 const void * src ,
8581109 size_t size )
8591110{
1111+ struct spi_nor_data * data = dev -> data ;
8601112 const size_t flash_size = dev_flash_size (dev );
8611113 const uint16_t page_size = dev_page_size (dev );
8621114 int ret ;
@@ -894,17 +1146,22 @@ static int spi_nor_write(const struct device *dev, off_t addr,
8941146 break ;
8951147 }
8961148
1149+ uint8_t program_cmd = SPI_NOR_CMD_PP ;
1150+ #ifdef CONFIG_SPI_EXTENDED_MODES
1151+ program_cmd = data -> program_cmd ;
1152+ #endif
1153+
8971154 if (IS_ENABLED (ANY_INST_USE_4B_ADDR_OPCODES ) &&
8981155 DEV_CFG (dev )-> use_4b_addr_opcodes ) {
8991156 if (addr > SPI_NOR_3B_ADDR_MAX ) {
9001157 ret = spi_nor_cmd_addr_write_4b (dev , SPI_NOR_CMD_PP_4B ,
9011158 addr , src , to_write );
9021159 } else {
903- ret = spi_nor_cmd_addr_write_3b (dev , SPI_NOR_CMD_PP , addr ,
904- src , to_write );
1160+ ret = spi_nor_cmd_addr_write_3b (dev , program_cmd ,
1161+ addr , src , to_write );
9051162 }
9061163 } else {
907- ret = spi_nor_cmd_addr_write (dev , SPI_NOR_CMD_PP , addr , src ,
1164+ ret = spi_nor_cmd_addr_write (dev , program_cmd , addr , src ,
9081165 to_write );
9091166 }
9101167
@@ -1426,6 +1683,32 @@ static int setup_pages_layout(const struct device *dev)
14261683#endif /* CONFIG_FLASH_PAGE_LAYOUT */
14271684#endif /* CONFIG_SPI_NOR_SFDP_MINIMAL */
14281685
1686+ #ifdef CONFIG_SPI_EXTENDED_MODES
1687+ static enum spi_nor_protocol spi_config_get_lines (const struct spi_config * config )
1688+ {
1689+ enum spi_nor_protocol nor_protocol ;
1690+
1691+ switch (config -> operation & SPI_LINES_MASK ) {
1692+ case SPI_LINES_SINGLE :
1693+ nor_protocol = PROTO_1_1_1 ;
1694+ break ;
1695+ case SPI_LINES_DUAL :
1696+ nor_protocol = PROTO_1_2_2 ;
1697+ break ;
1698+ case SPI_LINES_QUAD :
1699+ nor_protocol = PROTO_4_4_4 ;
1700+ break ;
1701+ case SPI_LINES_OCTAL :
1702+ nor_protocol = PROTO_8_8_8 ;
1703+ break ;
1704+ default :
1705+ nor_protocol = PROTO_1_1_1 ;
1706+ }
1707+
1708+ return nor_protocol ;
1709+ }
1710+ #endif
1711+
14291712/**
14301713 * @brief Configure the flash
14311714 *
@@ -1509,6 +1792,15 @@ static int spi_nor_configure(const struct device *dev)
15091792 }
15101793#endif
15111794
1795+ #ifdef CONFIG_SPI_EXTENDED_MODES
1796+
1797+ rc = spi_nor_change_protocol (dev , spi_config_get_lines (& cfg -> spi .config ));
1798+ if (rc != 0 ) {
1799+ LOG_ERR ("Change protocol failed: %d" , rc );
1800+ return - ENODEV ;
1801+ }
1802+ #endif
1803+
15121804 /* Check for block protect bits that need to be cleared. This
15131805 * information cannot be determined from SFDP content, so the
15141806 * devicetree node property must be set correctly for any device
0 commit comments