[RFC 1/3] mtd: spi-nor: DUAL I/O and QUAD I/O modes support
marcin.krzeminski at nokia.com
marcin.krzeminski at nokia.com
Mon Jun 27 03:20:58 PDT 2016
From: Marcin Krzeminski <marcin.krzeminski at nokia.com>
This commit adds support for DUAL/QUAD I/O modes.
The work is based on Pawel Lenkow work for 3.18 kernel.
Signed-off-by: Marcin Krzeminski <marcin.krzeminski at nokia.com>
---
drivers/mtd/spi-nor/Kconfig | 8 +++++++
drivers/mtd/spi-nor/spi-nor.c | 54 +++++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/spi-nor.h | 12 ++++++++++
3 files changed, 74 insertions(+)
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index d42c98e..8975977 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -49,4 +49,12 @@ config SPI_NXP_SPIFI
Flash. Enable this option if you have a device with a SPIFI
controller and want to access the Flash as a mtd device.
+config DUAL_QUAD_IO
+ bool "Dual and Quad I/O support"
+ help
+ Enable support for Dual I/O and Quad I/O read commands that are
+ available in some Spansion and Macronix devices.
+ In Spansion FS-S family you must enable this if you want to use
+ Quad/Dual but not QPI mode.
+
endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index a63922e..847db69 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -75,6 +75,10 @@ struct flash_info {
* bit. Must be used with
* SPI_NOR_HAS_LOCK.
*/
+#ifdef CONFIG_DUAL_QUAD_IO
+#define SPI_NOR_DUALIO_READ BIT(10) /* Flash supports Dual I/O Read */
+#define SPI_NOR_QUADIO_READ BIT(11) /* Flash supports Quad I/O Read */
+#endif
};
#define JEDEC_MFR(info) ((info)->id[0])
@@ -149,6 +153,10 @@ static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
case SPI_NOR_FAST:
case SPI_NOR_DUAL:
case SPI_NOR_QUAD:
+#ifdef CONFIG_DUAL_QUAD_IO
+ case SPI_NOR_DUALIO:
+ case SPI_NOR_QUADIO:
+#endif
return 8;
case SPI_NOR_NORMAL:
return 0;
@@ -1415,7 +1423,37 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
/* Some devices cannot do fast-read, no matter what DT tells us */
if (info->flags & SPI_NOR_NO_FR)
nor->flash_read = SPI_NOR_NORMAL;
+#ifdef CONFIG_DUAL_QUAD_IO
+ /*
+ * Quad/Dual-read mode takes precedence over fast/normal
+ * and Quad/Dual I/O take precedence over Quad/Dual
+ */
+ if (mode == SPI_NOR_QUADIO) {
+ if (info->flags & SPI_NOR_QUADIO_READ)
+ nor->flash_read = SPI_NOR_QUADIO;
+ else
+ mode = SPI_NOR_QUAD;
+ } else if (mode == SPI_NOR_DUALIO) {
+ if (info->flags & SPI_NOR_DUALIO_READ)
+ nor->flash_read = SPI_NOR_DUALIO;
+ else
+ mode = SPI_NOR_DUAL;
+ }
+ if (mode == SPI_NOR_QUAD && (info->flags & SPI_NOR_QUAD_READ))
+ nor->flash_read = SPI_NOR_QUAD;
+ else if (mode == SPI_NOR_DUAL && (info->flags & SPI_NOR_DUAL_READ))
+ nor->flash_read = SPI_NOR_DUAL;
+
+ if (nor->flash_read == SPI_NOR_QUAD
+ || nor->flash_read == SPI_NOR_QUADIO) {
+ ret = set_quad_mode(nor, info);
+ if (ret) {
+ dev_err(dev, "quad mode not supported\n");
+ return ret;
+ }
+ }
+#else
/* Quad/Dual-read mode takes precedence over fast/normal */
if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
ret = set_quad_mode(nor, info);
@@ -1442,6 +1480,14 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
case SPI_NOR_NORMAL:
nor->read_opcode = SPINOR_OP_READ;
break;
+#ifdef CONFIG_DUAL_QUAD_IO
+ case SPI_NOR_DUALIO:
+ nor->read_opcode = SPINOR_OP_READ_1_2_2;
+ break;
+ case SPI_NOR_QUADIO:
+ nor->read_opcode = SPINOR_OP_READ_1_4_4;
+ break;
+#endif
default:
dev_err(dev, "No Read opcode defined\n");
return -EINVAL;
@@ -1469,6 +1515,14 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
case SPI_NOR_NORMAL:
nor->read_opcode = SPINOR_OP_READ4;
break;
+#ifdef CONFIG_DUAL_QUAD_IO
+ case SPI_NOR_DUALIO:
+ nor->read_opcode = SPINOR_OP_READ4_1_2_2;
+ break;
+ case SPI_NOR_QUADIO:
+ nor->read_opcode = SPINOR_OP_READ4_1_4_4;
+ break;
+#endif
}
nor->program_opcode = SPINOR_OP_PP_4B;
/* No small sector erase for 4-byte command set */
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index c425c7b..652a8d2 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -45,6 +45,10 @@
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
+#ifdef CONFIG_DUAL_QUAD_IO
+#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (DualIO SPI) */
+#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (QuadIO SPI) */
+#endif
#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
@@ -60,6 +64,10 @@
#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
+#ifdef CONFIG_DUAL_QUAD_IO
+#define SPINOR_OP_READ4_1_2_2 0xbc /* Read data bytes (DualIO SPI) */
+#define SPINOR_OP_READ4_1_4_4 0xec /* Read data bytes (QuadIO SPI) */
+#endif
#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
@@ -105,6 +113,10 @@ enum read_mode {
SPI_NOR_FAST,
SPI_NOR_DUAL,
SPI_NOR_QUAD,
+#ifdef CONFIG_DUAL_QUAD_IO
+ SPI_NOR_DUALIO,
+ SPI_NOR_QUADIO,
+#endif
};
#define SPI_NOR_MAX_CMD_SIZE 8
--
2.7.4
More information about the linux-mtd
mailing list