@@ -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
@@ -807,10 +1053,10 @@ static int spi_nor_read(const struct device *dev, off_t addr, void *dest,
8071053 if (addr > SPI_NOR_3B_ADDR_MAX ) {
8081054 ret = spi_nor_cmd_addr_read_4b (dev , SPI_NOR_CMD_READ_4B , addr , dest , size );
8091055 } else {
810- ret = spi_nor_cmd_addr_read_3b (dev , SPI_NOR_CMD_READ , addr , dest , size );
1056+ ret = spi_nor_cmd_addr_read_3b (dev , data -> read_cmd , addr , dest , size );
8111057 }
8121058 } else {
813- ret = spi_nor_cmd_addr_read (dev , SPI_NOR_CMD_READ , addr , dest , size );
1059+ ret = spi_nor_cmd_addr_read (dev , data -> read_cmd , addr , dest , size );
8141060 }
8151061
8161062 release_device (dev );
@@ -857,6 +1103,7 @@ static int spi_nor_write(const struct device *dev, off_t addr,
8571103 const void * src ,
8581104 size_t size )
8591105{
1106+ struct spi_nor_data * data = dev -> data ;
8601107 const size_t flash_size = dev_flash_size (dev );
8611108 const uint16_t page_size = dev_page_size (dev );
8621109 int ret ;
@@ -900,11 +1147,11 @@ static int spi_nor_write(const struct device *dev, off_t addr,
9001147 ret = spi_nor_cmd_addr_write_4b (dev , SPI_NOR_CMD_PP_4B ,
9011148 addr , src , to_write );
9021149 } else {
903- ret = spi_nor_cmd_addr_write_3b (dev , SPI_NOR_CMD_PP , addr ,
1150+ ret = spi_nor_cmd_addr_write_3b (dev , data -> program_cmd , addr ,
9041151 src , to_write );
9051152 }
9061153 } else {
907- ret = spi_nor_cmd_addr_write (dev , SPI_NOR_CMD_PP , addr , src ,
1154+ ret = spi_nor_cmd_addr_write (dev , data -> program_cmd , addr , src ,
9081155 to_write );
9091156 }
9101157
@@ -1426,6 +1673,32 @@ static int setup_pages_layout(const struct device *dev)
14261673#endif /* CONFIG_FLASH_PAGE_LAYOUT */
14271674#endif /* CONFIG_SPI_NOR_SFDP_MINIMAL */
14281675
1676+ #ifdef CONFIG_SPI_EXTENDED_MODES
1677+ static enum spi_nor_protocol spi_config_get_lines (const struct spi_config * config )
1678+ {
1679+ enum spi_nor_protocol nor_protocol ;
1680+
1681+ switch (config -> operation & SPI_LINES_MASK ) {
1682+ case SPI_LINES_SINGLE :
1683+ nor_protocol = PROTO_1_1_1 ;
1684+ break ;
1685+ case SPI_LINES_DUAL :
1686+ nor_protocol = PROTO_1_2_2 ;
1687+ break ;
1688+ case SPI_LINES_QUAD :
1689+ nor_protocol = PROTO_4_4_4 ;
1690+ break ;
1691+ case SPI_LINES_OCTAL :
1692+ nor_protocol = PROTO_8_8_8 ;
1693+ break ;
1694+ default :
1695+ nor_protocol = PROTO_1_1_1 ;
1696+ }
1697+
1698+ return nor_protocol ;
1699+ }
1700+ #endif
1701+
14291702/**
14301703 * @brief Configure the flash
14311704 *
@@ -1509,6 +1782,15 @@ static int spi_nor_configure(const struct device *dev)
15091782 }
15101783#endif
15111784
1785+ #ifdef CONFIG_SPI_EXTENDED_MODES
1786+
1787+ rc = spi_nor_change_protocol (dev , spi_config_get_lines (spi_cfg ));
1788+ if (rc != 0 ) {
1789+ LOG_ERR ("Change protocol failed: %d" , rc );
1790+ return - ENODEV ;
1791+ }
1792+ #endif
1793+
15121794 /* Check for block protect bits that need to be cleared. This
15131795 * information cannot be determined from SFDP content, so the
15141796 * devicetree node property must be set correctly for any device
0 commit comments