[U-Boot] [PATCH 11/18] sf: fix selection of supported READ commands for QSPI memories
Cyrille Pitchen
cyrille.pitchen at atmel.com
Tue Mar 15 19:12:33 CET 2016
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.pitchen at 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
More information about the U-Boot
mailing list