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