It looks odd to compute a logical AND between the e_rd_cmd field of
struct spi_flash_params and the mode_rx field of struct spi_slave.

Indeed, these two fields don't use the same range of values.
mode_rx is limited to SPI_RX_{SLOW, FAST, DUAL, QUAD}. Even completed
with the SPI_TX_{DUAL, QUAD} flags from the mode field, this is not
enough to find out whether the SPI controller driver supports
Fast Read 4-4-4 (Micron, Macronix, Winbond) commands.
With only the SPI_RX_QUAD and the SPI_TX_QUAD, how to make the
difference between Fast Read 1-4-4 and Fast Read 4-4-4 ?

On the other hand, the e_rd_cmd field already provides a more accurate
knowledge of the Fast Read commands supported by the SPI flash memory.

Then this patch provides a safe convertion from mode_rx + mode values
into e_rd_cmd values to be used by the sf_probe.c driver: this driver
never try using the Fast Read 4-4-4 command.
Other drivers will provide an exhaustive list of supported Fast Read
commands.

Hence a more accurate op code is chosen according to both the SPI flash
memory and the SPI controller capabilities.

Please note that we cannot simply extend the SPI_TX_* and SPI_RX_* flags
of the struct spi_slave since they are set according DT properties
shared with Linux: spi-tx-bus-width and spi-rx-bus-width.

These two DT properties don't allow us to make the difference between
the SPI 1-4-4 and SPI 4-4-4 protocols.

Signed-off-by: Cyrille Pitchen <cyrille.pitc...@atmel.com>
---
 drivers/mtd/spi/sf_internal.h | 14 +++++++++++---
 drivers/mtd/spi/sf_params.c   | 32 ++++++++++++++++----------------
 drivers/mtd/spi/sf_probe.c    | 19 ++++++++++++++++++-
 drivers/mtd/spi/spi_flash.c   |  9 ++++++---
 4 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
index c5966fb37ac8..8b8521369e4e 100644
--- a/drivers/mtd/spi/sf_internal.h
+++ b/drivers/mtd/spi/sf_internal.h
@@ -29,12 +29,19 @@ enum spi_read_cmds {
        QUAD_OUTPUT_FAST        = BIT(3),
        DUAL_IO_FAST            = BIT(4),
        QUAD_IO_FAST            = BIT(5),
+       DUAL_CMD_FAST           = BIT(6),
+       QUAD_CMD_FAST           = BIT(7),
 };
 
 /* Normal - Extended - Full command set */
 #define RD_NORM                (ARRAY_SLOW | ARRAY_FAST)
-#define RD_EXTN                (RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST)
-#define RD_FULL                (RD_EXTN | QUAD_OUTPUT_FAST | QUAD_IO_FAST)
+#define RD_EXTN                (RD_NORM | DUAL_OUTPUT_FAST)
+#define RD_DUAL                (RD_NORM | DUAL_OUTPUT_FAST | DUAL_IO_FAST)
+#define RD_DCMD                (RD_DUAL | DUAL_CMD_FAST)
+#define RD_QUAD                (RD_NORM | QUAD_OUTPUT_FAST | QUAD_IO_FAST)
+#define RD_QCMD                (RD_QUAD | QUAD_CMD_FAST)
+#define RD_FULL                (RD_DUAL | RD_QUAD)
+#define RD_FCMD                (RD_DCMD | RD_QCMD)
 
 /* sf param flags */
 enum {
@@ -240,6 +247,7 @@ void spi_flash_mtd_unregister(void);
 /**
  * spi_flash_scan - scan the SPI FLASH
  * @flash:     the spi flash structure
+ * @e_rd_cmd:  Enum list for read commands supported by the SPI controller
  *
  * The drivers can use this fuction to scan the SPI FLASH.
  * In the scanning, it will try to get all the necessary information to
@@ -247,6 +255,6 @@ void spi_flash_mtd_unregister(void);
  *
  * Return: 0 for success, others for failure.
  */
-int spi_flash_scan(struct spi_flash *flash);
+int spi_flash_scan(struct spi_flash *flash, u8 e_rd_cmd);
 
 #endif /* _SF_INTERNAL_H_ */
diff --git a/drivers/mtd/spi/sf_params.c b/drivers/mtd/spi/sf_params.c
index 4f37e33eb068..d3103dbc8742 100644
--- a/drivers/mtd/spi/sf_params.c
+++ b/drivers/mtd/spi/sf_params.c
@@ -47,10 +47,10 @@ const struct spi_flash_params spi_flash_params_table[] = {
        {"MX25L1605D",     0xc22015, 0x0,       64 * 1024,    32, RD_NORM,      
                  0},
        {"MX25L3205D",     0xc22016, 0x0,       64 * 1024,    64, RD_NORM,      
                  0},
        {"MX25L6405D",     0xc22017, 0x0,       64 * 1024,   128, RD_NORM,      
                  0},
-       {"MX25L12805",     0xc22018, 0x0,       64 * 1024,   256, RD_FULL,      
             WR_QPP},
-       {"MX25L25635F",    0xc22019, 0x0,       64 * 1024,   512, RD_FULL,      
             WR_QPP},
-       {"MX25L51235F",    0xc2201a, 0x0,       64 * 1024,  1024, RD_FULL,      
             WR_QPP},
-       {"MX25L12855E",    0xc22618, 0x0,       64 * 1024,   256, RD_FULL,      
             WR_QPP},
+       {"MX25L12805",     0xc22018, 0x0,       64 * 1024,   256, RD_QCMD,      
             WR_QPP},
+       {"MX25L25635F",    0xc22019, 0x0,       64 * 1024,   512, RD_QCMD,      
             WR_QPP},
+       {"MX25L51235F",    0xc2201a, 0x0,       64 * 1024,  1024, RD_QCMD,      
             WR_QPP},
+       {"MX25L12855E",    0xc22618, 0x0,       64 * 1024,   256, RD_QCMD,      
             WR_QPP},
 #endif
 #ifdef CONFIG_SPI_FLASH_SPANSION       /* SPANSION */
        {"S25FL008A",      0x010213, 0x0,       64 * 1024,    16, RD_NORM,      
                  0},
@@ -83,18 +83,18 @@ const struct spi_flash_params spi_flash_params_table[] = {
        {"M25P64",         0x202017, 0x0,       64 * 1024,   128, RD_NORM,      
                  0},
        {"M25P128",        0x202018, 0x0,      256 * 1024,    64, RD_NORM,      
                  0},
        {"M25PX64",        0x207117, 0x0,       64 * 1024,   128, RD_NORM,      
            SECT_4K},
-       {"N25Q32",         0x20ba16, 0x0,       64 * 1024,    64, RD_FULL,      
   WR_QPP | SECT_4K},
-       {"N25Q32A",        0x20bb16, 0x0,       64 * 1024,    64, RD_FULL,      
   WR_QPP | SECT_4K},
-       {"N25Q64",         0x20ba17, 0x0,       64 * 1024,   128, RD_FULL,      
   WR_QPP | SECT_4K},
-       {"N25Q64A",        0x20bb17, 0x0,       64 * 1024,   128, RD_FULL,      
   WR_QPP | SECT_4K},
-       {"N25Q128",        0x20ba18, 0x0,       64 * 1024,   256, RD_FULL,      
             WR_QPP},
-       {"N25Q128A",       0x20bb18, 0x0,       64 * 1024,   256, RD_FULL,      
             WR_QPP},
-       {"N25Q256",        0x20ba19, 0x0,       64 * 1024,   512, RD_FULL,      
   WR_QPP | SECT_4K},
-       {"N25Q256A",       0x20bb19, 0x0,       64 * 1024,   512, RD_FULL,      
   WR_QPP | SECT_4K},
-       {"N25Q512",        0x20ba20, 0x0,       64 * 1024,  1024, RD_FULL, 
WR_QPP | E_FSR | SECT_4K},
-       {"N25Q512A",       0x20bb20, 0x0,       64 * 1024,  1024, RD_FULL, 
WR_QPP | E_FSR | SECT_4K},
-       {"N25Q1024",       0x20ba21, 0x0,       64 * 1024,  2048, RD_FULL, 
WR_QPP | E_FSR | SECT_4K},
-       {"N25Q1024A",      0x20bb21, 0x0,       64 * 1024,  2048, RD_FULL, 
WR_QPP | E_FSR | SECT_4K},
+       {"N25Q32",         0x20ba16, 0x0,       64 * 1024,    64, RD_FCMD,      
   WR_QPP | SECT_4K},
+       {"N25Q32A",        0x20bb16, 0x0,       64 * 1024,    64, RD_FCMD,      
   WR_QPP | SECT_4K},
+       {"N25Q64",         0x20ba17, 0x0,       64 * 1024,   128, RD_FCMD,      
   WR_QPP | SECT_4K},
+       {"N25Q64A",        0x20bb17, 0x0,       64 * 1024,   128, RD_FCMD,      
   WR_QPP | SECT_4K},
+       {"N25Q128",        0x20ba18, 0x0,       64 * 1024,   256, RD_FCMD,      
             WR_QPP},
+       {"N25Q128A",       0x20bb18, 0x0,       64 * 1024,   256, RD_FCMD,      
             WR_QPP},
+       {"N25Q256",        0x20ba19, 0x0,       64 * 1024,   512, RD_FCMD,      
   WR_QPP | SECT_4K},
+       {"N25Q256A",       0x20bb19, 0x0,       64 * 1024,   512, RD_FCMD,      
   WR_QPP | SECT_4K},
+       {"N25Q512",        0x20ba20, 0x0,       64 * 1024,  1024, RD_FCMD, 
WR_QPP | E_FSR | SECT_4K},
+       {"N25Q512A",       0x20bb20, 0x0,       64 * 1024,  1024, RD_FCMD, 
WR_QPP | E_FSR | SECT_4K},
+       {"N25Q1024",       0x20ba21, 0x0,       64 * 1024,  2048, RD_FCMD, 
WR_QPP | E_FSR | SECT_4K},
+       {"N25Q1024A",      0x20bb21, 0x0,       64 * 1024,  2048, RD_FCMD, 
WR_QPP | E_FSR | SECT_4K},
 #endif
 #ifdef CONFIG_SPI_FLASH_SST            /* SST */
        {"SST25VF040B",    0xbf258d, 0x0,       64 * 1024,     8, RD_NORM,      
    SECT_4K | SST_WR},
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 837535fdb7a5..8a0345bc1994 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -26,6 +26,7 @@
 static int spi_flash_probe_slave(struct spi_flash *flash)
 {
        struct spi_slave *spi = flash->spi;
+       u8 mode_rx, e_rd_cmd;
        int ret;
 
        /* Setup spi_slave */
@@ -34,6 +35,22 @@ static int spi_flash_probe_slave(struct spi_flash *flash)
                return -ENODEV;
        }
 
+       /* Convert SPI mode_rx and mode to SPI flash read commands */
+       mode_rx = spi->mode_rx;
+       if (mode_rx & SPI_RX_QUAD) {
+               e_rd_cmd = RD_NORM | QUAD_OUTPUT_FAST;
+               if (spi->mode & SPI_TX_QUAD)
+                       e_rd_cmd |= QUAD_IO_FAST;
+       } else if (mode_rx & SPI_RX_DUAL) {
+               e_rd_cmd = RD_NORM | DUAL_OUTPUT_FAST;
+               if (spi->mode & SPI_TX_DUAL)
+                       e_rd_cmd |= DUAL_IO_FAST;
+       } else if ((mode_rx & (SPI_RX_SLOW | SPI_RX_FAST)) == SPI_RX_SLOW) {
+               e_rd_cmd = ARRAY_SLOW;
+       } else {
+               e_rd_cmd = RD_NORM;
+       }
+
        /* Claim spi bus */
        ret = spi_claim_bus(spi);
        if (ret) {
@@ -41,7 +58,7 @@ static int spi_flash_probe_slave(struct spi_flash *flash)
                return ret;
        }
 
-       ret = spi_flash_scan(flash);
+       ret = spi_flash_scan(flash, e_rd_cmd);
        if (ret)
                goto err_read_id;
 
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 7f5341a87c07..5ba148bd3626 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -987,7 +987,7 @@ int spi_flash_decode_fdt(const void *blob, struct spi_flash 
*flash)
 }
 #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
 
-int spi_flash_scan(struct spi_flash *flash)
+int spi_flash_scan(struct spi_flash *flash, u8 e_rd_cmd)
 {
        struct spi_slave *spi = flash->spi;
        const struct spi_flash_params *params;
@@ -1000,7 +1000,10 @@ int spi_flash_scan(struct spi_flash *flash)
                CMD_READ_DUAL_OUTPUT_FAST,
                CMD_READ_QUAD_OUTPUT_FAST,
                CMD_READ_DUAL_IO_FAST,
-               CMD_READ_QUAD_IO_FAST };
+               CMD_READ_QUAD_IO_FAST,
+               CMD_READ_DUAL_IO_FAST,  /* same op code as for DUAL_IO_FAST */
+               CMD_READ_QUAD_IO_FAST,  /* same op code as for QUAD_IO_FAST */
+       };
 
        /* Assign spi_flash ops */
 #ifndef CONFIG_DM_SPI_FLASH
@@ -1115,7 +1118,7 @@ int spi_flash_scan(struct spi_flash *flash)
        flash->sector_size = flash->erase_size;
 
        /* Look for the fastest read cmd */
-       cmd = fls(params->e_rd_cmd & spi->mode_rx);
+       cmd = fls(params->e_rd_cmd & e_rd_cmd);
        if (cmd) {
                cmd = spi_read_cmds_array[cmd - 1];
                flash->read_cmd = cmd;
-- 
1.8.2.2

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to