@@ -170,6 +170,14 @@ struct spi_nor_data {
170170#endif /* CONFIG_FLASH_PAGE_LAYOUT */
171171#endif /* CONFIG_SPI_NOR_SFDP_RUNTIME */
172172#endif /* CONFIG_SPI_NOR_SFDP_MINIMAL */
173+
174+ #ifdef CONFIG_SPI_EXTENDED_MODES
175+ enum spi_nor_protocol nor_protocol ;
176+
177+ uint8_t read_cmd ;
178+ uint8_t program_cmd ;
179+ uint8_t erase_cmd ;
180+ #endif
173181};
174182
175183#ifdef CONFIG_SPI_NOR_SFDP_MINIMAL
@@ -332,7 +340,7 @@ static int spi_nor_access(const struct device *const dev,
332340 .len = length
333341 }
334342 };
335-
343+ #ifndef CONFIG_SPI_EXTENDED_MODES
336344 buf [0 ] = opcode ;
337345 if (is_addressed ) {
338346 bool access_24bit = (access & NOR_ACCESS_24BIT_ADDR ) != 0 ;
@@ -365,7 +373,131 @@ static int spi_nor_access(const struct device *const dev,
365373 .buffers = spi_buf ,
366374 .count = 2 ,
367375 };
376+ #else
377+
378+ spi_buf [0 ].spi_mem_op .cmd .opcode = opcode ;
379+ spi_buf [0 ].spi_mem_op .cmd .nbytes = 1 ;
380+
381+ if (is_addressed ) {
382+ bool access_24bit = (access & NOR_ACCESS_24BIT_ADDR ) != 0 ;
383+ bool access_32bit = (access & NOR_ACCESS_32BIT_ADDR ) != 0 ;
384+ bool use_32bit = (access_32bit
385+ || (!access_24bit
386+ && driver_data -> flag_access_32bit ));
387+
388+ spi_buf [0 ].spi_mem_op .addr .nbytes = use_32bit ? 4 : 3 ;
389+ };
390+ spi_buf [0 ].spi_mem_op .addr .val = addr ;
391+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_SINGLE ;
392+ spi_buf [0 ].spi_mem_op .addr .dtr = 0 ;
393+
394+ spi_buf [0 ].spi_mem_op .data .nbytes = length ;
395+ spi_buf [0 ].spi_mem_op .data .buf = data ;
396+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_SINGLE ;
397+ spi_buf [0 ].spi_mem_op .data .dtr = 0 ;
398+
399+
400+ switch (driver_data -> nor_protocol ) {
401+ case PROTO_1_1_1 :
402+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
403+ spi_buf [0 ].spi_mem_op .cmd .dtr = 0 ;
404+ break ;
405+ case PROTO_1_1_2 :
406+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
407+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_SINGLE ;
408+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_DUAL ;
409+ break ;
410+ case PROTO_1_2_2 :
411+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
412+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_DUAL ;
413+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_DUAL ;
414+ break ;
415+ case PROTO_1_1_4 :
416+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
417+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_SINGLE ;
418+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
419+ break ;
420+ case PROTO_1_4_4 :
421+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
422+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_QUAD ;
423+ spi_buf [0 ].spi_mem_op .addr .dtr = 1 ;
424+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
425+ spi_buf [0 ].spi_mem_op .data .dtr = 1 ;
426+ break ;
427+ case PROTO_1_4D_4D :
428+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_SINGLE ;
429+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_QUAD ;
430+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
431+ break ;
432+ case PROTO_4_4_4 :
433+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_QUAD ;
434+ spi_buf [0 ].spi_mem_op .cmd .dtr = 0 ;
435+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_QUAD ;
436+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_QUAD ;
437+ if (opcode == SPI_NOR_CMD_4READ ){
438+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 6 ;
439+ }
440+ break ;
441+ case PROTO_8_8_8 :
442+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_OCTAL ;
443+ spi_buf [0 ].spi_mem_op .cmd .dtr = 0 ;
444+ spi_buf [0 ].spi_mem_op .cmd .opcode = (opcode << 8 ) | (0xFF - opcode );
445+ spi_buf [0 ].spi_mem_op .cmd .nbytes = 2 ;
446+
447+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
448+ spi_buf [0 ].spi_mem_op .addr .dtr = 0 ;
449+
450+ if ((opcode == SPI_NOR_CMD_RDID ) || (opcode == SPI_NOR_CMD_RDSR )){
451+ spi_buf [0 ].spi_mem_op .addr .val = 0 ;
452+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
453+ spi_buf [0 ].spi_mem_op .addr .nbytes = 4 ;
454+
455+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 4 ;
456+ }
457+ if (opcode == 0xEC ){
458+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 20 ;
459+ }
460+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_OCTAL ;
461+ spi_buf [0 ].spi_mem_op .data .dtr = 0 ;
462+ break ;
463+ case PROTO_8D_8D_8D :
464+ spi_buf [0 ].spi_mem_op .cmd .buswidth = SPI_LINES_OCTAL ;
465+ spi_buf [0 ].spi_mem_op .cmd .dtr = 1 ;
466+ spi_buf [0 ].spi_mem_op .cmd .opcode = (opcode << 8 ) | (0xFF - opcode );
467+ spi_buf [0 ].spi_mem_op .cmd .nbytes = 2 ;
468+
469+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
470+ spi_buf [0 ].spi_mem_op .addr .dtr = 1 ;
471+
472+ spi_buf [0 ].spi_mem_op .data .dtr = 1 ;
473+
474+ if ((opcode == SPI_NOR_CMD_RDID ) || (opcode == SPI_NOR_CMD_RDSR )){
475+ spi_buf [0 ].spi_mem_op .addr .val = 0 ;
476+ spi_buf [0 ].spi_mem_op .addr .buswidth = SPI_LINES_OCTAL ;
477+ spi_buf [0 ].spi_mem_op .addr .nbytes = 4 ;
478+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 6 ;
479+ spi_buf [0 ].spi_mem_op .data .dtr = 0 ;
480+ } else if (opcode == 0xEE ){
481+ spi_buf [0 ].spi_mem_op .dummy .nbytes = 20 ;
482+ }
483+ spi_buf [0 ].spi_mem_op .data .buswidth = SPI_LINES_OCTAL ;
484+
485+ break ;
486+ default :
487+ break ;
488+ };
368489
490+ const struct spi_buf_set tx_set = {
491+ .buffers = spi_buf ,
492+ .count = 1 ,
493+ };
494+
495+ const struct spi_buf_set rx_set = {
496+ .buffers = spi_buf ,
497+ .count = 1 ,
498+ };
499+
500+ #endif
369501 if (is_write ) {
370502 return spi_write_dt (& driver_cfg -> spi , & tx_set );
371503 }
@@ -683,9 +815,122 @@ static int mxicy_configure(const struct device *dev, const uint8_t *jedec_id)
683815
684816#endif /* DT_INST_NODE_HAS_PROP(0, mxicy_mx25r_power_mode) */
685817
818+
819+ #ifdef CONFIG_SPI_EXTENDED_MODES
820+ /**
821+ * @brief Write the configuration register2.
822+ *
823+ * @note The device must be externally acquired before invoking this
824+ * function.
825+ *
826+ * @param dev Device struct
827+ * @param sr The new value of the configuration register2
828+ *
829+ * @return 0 on success or a negative error code.
830+ */
831+ static int spi_nor_wrcr2 (const struct device * dev ,
832+ uint8_t cr )
833+ {
834+ int ret = spi_nor_cmd_write (dev , SPI_NOR_CMD_WREN );
835+
836+ if (ret == 0 ) {
837+
838+ struct spi_nor_data * data = dev -> data ;
839+
840+ data -> flag_access_32bit = true;
841+
842+ ret = spi_nor_cmd_addr_write (dev , SPI_NOR_CMD_WR_CFGREG2 , 0 , & cr , sizeof (cr ));
843+ }
844+
845+ return ret ;
846+ }
847+
848+ static int spi_nor_change_protocol (const struct device * dev ,
849+ enum spi_nor_protocol nor_protocol )
850+ {
851+ struct spi_nor_data * data = dev -> data ;
852+ uint8_t cr2 ;
853+ int ret = 0 ;
854+
855+ switch (nor_protocol ) {
856+ case PROTO_1_1_1 :
857+ data -> nor_protocol = PROTO_1_1_1 ;
858+ data -> flag_access_32bit = false;
859+ data -> read_cmd = SPI_NOR_CMD_READ ;
860+ data -> program_cmd = SPI_NOR_CMD_PP ;
861+ data -> erase_cmd = SPI_NOR_CMD_SE ;
862+ break ;
863+ case PROTO_1_1_2 :
864+ data -> nor_protocol = PROTO_1_1_2 ;
865+ data -> flag_access_32bit = false;
866+ data -> read_cmd = SPI_NOR_CMD_READ ;
867+ data -> program_cmd = SPI_NOR_CMD_PP ;
868+ data -> erase_cmd = SPI_NOR_CMD_SE ;
869+ break ;
870+ case PROTO_1_2_2 :
871+ data -> nor_protocol = PROTO_1_2_2 ;
872+ data -> flag_access_32bit = false;
873+ data -> read_cmd = SPI_NOR_CMD_READ ;
874+ data -> program_cmd = SPI_NOR_CMD_PP ;
875+ data -> erase_cmd = SPI_NOR_CMD_SE ;
876+ break ;
877+ case PROTO_1_1_4 :
878+ data -> nor_protocol = PROTO_1_1_4 ;
879+ data -> flag_access_32bit = false;
880+ data -> read_cmd = SPI_NOR_CMD_READ ;
881+ data -> program_cmd = SPI_NOR_CMD_PP ;
882+ data -> erase_cmd = SPI_NOR_CMD_SE ;
883+ break ;
884+ case PROTO_1_4_4 :
885+ data -> nor_protocol = PROTO_1_4_4 ;
886+ data -> flag_access_32bit = false;
887+ data -> read_cmd = SPI_NOR_CMD_READ ;
888+ data -> program_cmd = SPI_NOR_CMD_PP ;
889+ data -> erase_cmd = SPI_NOR_CMD_SE ;
890+ break ;
891+ case PROTO_1_4D_4D :
892+ data -> nor_protocol = PROTO_1_4D_4D ;
893+ data -> flag_access_32bit = false;
894+ data -> read_cmd = SPI_NOR_CMD_READ ;
895+ data -> program_cmd = SPI_NOR_CMD_PP ;
896+ data -> erase_cmd = SPI_NOR_CMD_SE ;
897+ break ;
898+ case PROTO_4_4_4 :
899+ ret = spi_nor_cmd_write (dev , SPI_NOR_CMD_EQIO );
900+ data -> nor_protocol = PROTO_4_4_4 ;
901+ data -> flag_access_32bit = false;
902+ data -> read_cmd = SPI_NOR_CMD_4READ ;
903+ data -> program_cmd = SPI_NOR_CMD_PP ;
904+ data -> erase_cmd = SPI_NOR_CMD_SE ;
905+ break ;
906+ case PROTO_8_8_8 :
907+ data -> flag_access_32bit = true;
908+ data -> read_cmd = SPI_NOR_OCMD_RD ;
909+ data -> program_cmd = SPI_NOR_CMD_PP_4B ;
910+ data -> erase_cmd = SPI_NOR_OCMD_SE ;
911+ cr2 = 0x01 ;
912+ ret = spi_nor_wrcr2 (dev , cr2 );
913+ data -> nor_protocol = PROTO_8_8_8 ;
914+ break ;
915+ case PROTO_8D_8D_8D :
916+ data -> flag_access_32bit = true;
917+ data -> read_cmd = SPI_NOR_OCMD_DTR_RD ;
918+ data -> program_cmd = SPI_NOR_CMD_PP_4B ;
919+ data -> erase_cmd = SPI_NOR_OCMD_SE ;
920+ cr2 = 0x02 ;
921+ ret = spi_nor_wrcr2 (dev , cr2 );
922+ data -> nor_protocol = PROTO_8D_8D_8D ;
923+ break ;
924+ }
925+
926+ return ret ;
927+ }
928+ #endif
929+
686930static int spi_nor_read (const struct device * dev , off_t addr , void * dest ,
687931 size_t size )
688932{
933+ struct spi_nor_data * data = dev -> data ;
689934 const size_t flash_size = dev_flash_size (dev );
690935 int ret ;
691936
@@ -696,7 +941,7 @@ static int spi_nor_read(const struct device *dev, off_t addr, void *dest,
696941
697942 acquire_device (dev );
698943
699- ret = spi_nor_cmd_addr_read (dev , SPI_NOR_CMD_READ , addr , dest , size );
944+ ret = spi_nor_cmd_addr_read (dev , data -> read_cmd , addr , dest , size );
700945
701946 release_device (dev );
702947 return ret ;
@@ -734,6 +979,7 @@ static int spi_nor_write(const struct device *dev, off_t addr,
734979 const void * src ,
735980 size_t size )
736981{
982+ struct spi_nor_data * data = dev -> data ;
737983 const size_t flash_size = dev_flash_size (dev );
738984 const uint16_t page_size = dev_page_size (dev );
739985 int ret = 0 ;
@@ -761,7 +1007,7 @@ static int spi_nor_write(const struct device *dev, off_t addr,
7611007 }
7621008
7631009 spi_nor_cmd_write (dev , SPI_NOR_CMD_WREN );
764- ret = spi_nor_cmd_addr_write (dev , SPI_NOR_CMD_PP , addr ,
1010+ ret = spi_nor_cmd_addr_write (dev , data -> program_cmd , addr ,
7651011 src , to_write );
7661012 if (ret != 0 ) {
7671013 break ;
@@ -1190,6 +1436,32 @@ static int setup_pages_layout(const struct device *dev)
11901436#endif /* CONFIG_FLASH_PAGE_LAYOUT */
11911437#endif /* CONFIG_SPI_NOR_SFDP_MINIMAL */
11921438
1439+ #ifdef CONFIG_SPI_EXTENDED_MODES
1440+ static enum spi_nor_protocol spi_config_get_lines (const struct spi_config * config )
1441+ {
1442+ enum spi_nor_protocol nor_protocol ;
1443+
1444+ switch (config -> operation & SPI_LINES_MASK ) {
1445+ case SPI_LINES_SINGLE :
1446+ nor_protocol = PROTO_1_1_1 ;
1447+ break ;
1448+ case SPI_LINES_DUAL :
1449+ nor_protocol = PROTO_1_2_2 ;
1450+ break ;
1451+ case SPI_LINES_QUAD :
1452+ nor_protocol = PROTO_4_4_4 ;
1453+ break ;
1454+ case SPI_LINES_OCTAL :
1455+ nor_protocol = PROTO_8_8_8 ;
1456+ break ;
1457+ default :
1458+ nor_protocol = PROTO_1_1_1 ;
1459+ }
1460+
1461+ return nor_protocol ;
1462+ }
1463+ #endif
1464+
11931465/**
11941466 * @brief Configure the flash
11951467 *
@@ -1265,6 +1537,17 @@ static int spi_nor_configure(const struct device *dev)
12651537 }
12661538#endif
12671539
1540+ #ifdef CONFIG_SPI_EXTENDED_MODES
1541+
1542+ rc = spi_nor_change_protocol (dev , spi_config_get_lines (spi_cfg ));
1543+ //rc = spi_nor_change_protocol(dev, PROTO_8_8_8);
1544+ //rc = spi_nor_change_protocol(dev, PROTO_8D_8D_8D);
1545+ if (rc != 0 ) {
1546+ LOG_ERR ("Change protocol failed: %d" , rc );
1547+ return - ENODEV ;
1548+ }
1549+ #endif
1550+
12681551 /* Check for block protect bits that need to be cleared. This
12691552 * information cannot be determined from SFDP content, so the
12701553 * devicetree node property must be set correctly for any device
0 commit comments