@@ -4124,6 +4124,11 @@ static void spi_nor_select_preferred_mode(struct spi_nor *nor, u32 hwcaps)
if (hwcaps & SNOR_HWCPAS_READ_OCTO && hwcaps & SNOR_HWCAPS_PP_OCTO)
return;
+ if (hwcaps & SNOR_HWCAPS_OPI_FULL_DTR) {
+ nor->preferred_mode = SPI_NOR_MODE_OPI_FULL_DTR;
+ return;
+ }
+
if (hwcaps & SNOR_HWCAPS_OPI) {
nor->preferred_mode = SPI_NOR_MODE_OPI;
return;
@@ -4132,6 +4137,11 @@ static void spi_nor_select_preferred_mode(struct spi_nor *nor, u32 hwcaps)
if (hwcaps & SNOR_HWCAPS_READ_QUAD && hwcaps & SNOR_HWCAPS_PP_QUAD)
return;
+ if (hwcaps & SNOR_HWCAPS_QPI_FULL_DTR) {
+ nor->preferred_mode = SPI_NOR_MODE_QPI_FULL_DTR;
+ return;
+ }
+
if (hwcaps & SNOR_HWCAPS_QPI) {
nor->preferred_mode = SPI_NOR_MODE_QPI;
return;
@@ -4140,6 +4150,11 @@ static void spi_nor_select_preferred_mode(struct spi_nor *nor, u32 hwcaps)
if (hwcaps & SNOR_HWCAPS_READ_DUAL)
return;
+ if (hwcaps & SNOR_HWCAPS_DPI_FULL_DTR) {
+ nor->preferred_mode = SPI_NOR_MODE_DPI_FULL_DTR;
+ return;
+ }
+
if (hwcaps & SNOR_HWCAPS_DPI) {
nor->preferred_mode = SPI_NOR_MODE_DPI;
return;
@@ -4177,7 +4192,7 @@ static int spi_nor_setup(struct spi_nor *nor, const struct flash_info *info,
* controller directly implements the spi_nor interface.
* Yet another reason to switch to spi-mem.
*/
- ignored_mask = SNOR_HWCAPS_X_X_X;
+ ignored_mask = SNOR_HWCAPS_X_X_X | SNOR_HWCAPS_XD_XD_XD;
if (shared_mask & ignored_mask) {
dev_dbg(nor->dev,
"SPI n-n-n protocols are not supported.\n");
@@ -188,6 +188,10 @@
#define SNOR_PROTO_1_XD_XD(_nbits) \
(SNOR_PROTO_DATA_IS_DTR | SNOR_PROTO_ADDR_IS_DTR | \
SNOR_PROTO_STR(1, _nbits, _nbits))
+#define SNOR_PROTO_XD_XD_XD(_nbits) \
+ (SNOR_PROTO_INST_IS_DTR | SNOR_PROTO_DATA_IS_DTR | \
+ SNOR_PROTO_ADDR_IS_DTR | \
+ SNOR_PROTO_STR(_nbits, _nbits, _nbits))
enum spi_nor_protocol {
SNOR_PROTO_1_1_1 = SNOR_PROTO_STR(1, 1, 1),
@@ -360,9 +364,13 @@ struct flash_info;
enum spi_nor_mode {
SPI_NOR_MODE_SPI,
+ SPI_NOR_MODE_SPI_FULL_DTR,
SPI_NOR_MODE_DPI,
+ SPI_NOR_MODE_DPI_FULL_DTR,
SPI_NOR_MODE_QPI,
+ SPI_NOR_MODE_QPI_FULL_DTR,
SPI_NOR_MODE_OPI,
+ SPI_NOR_MODE_OPI_FULL_DTR,
SPI_NOR_NUM_MODES,
};
@@ -561,19 +569,34 @@ struct spi_nor_hwcaps {
#define SNOR_HWCAPS_DPI BIT(24)
#define SNOR_HWCAPS_QPI BIT(25)
#define SNOR_HWCAPS_OPI BIT(26)
+#define SNOR_HWCAPS_SPI_FULL_DTR BIT(27)
+#define SNOR_HWCAPS_DPI_FULL_DTR BIT(28)
+#define SNOR_HWCAPS_QPI_FULL_DTR BIT(29)
+#define SNOR_HWCAPS_OPI_FULL_DTR BIT(30)
#define SNOR_HWCAPS_X_X_X (SNOR_HWCAPS_DPI | \
SNOR_HWCAPS_QPI | \
- SNOR_HWCAPS_OPI)
+ SNOR_HWCAPS_OPI | \
+ SNOR_HWCAPS_SPI_FULL_DTR | \
+ SNOR_HWCAPS_DPI_FULL_DTR | \
+ SNOR_HWCAPS_QPI_FULL_DTR | \
+ SNOR_HWCAPS_OPI_FULL_DTR)
+
+#define SNOR_HWCAPS_XD_XD_XD (SNOR_HWCAPS_SPI_FULL_DTR | \
+ SNOR_HWCAPS_DPI_FULL_DTR | \
+ SNOR_HWCAPS_QPI_FULL_DTR | \
+ SNOR_HWCAPS_OPI_FULL_DTR)
#define SNOR_HWCAPS_DTR (SNOR_HWCAPS_READ_1_1D_1D | \
SNOR_HWCAPS_READ_1_2D_2D | \
SNOR_HWCAPS_READ_1_4D_4D | \
- SNOR_HWCAPS_READ_1_8D_8D)
+ SNOR_HWCAPS_READ_1_8D_8D | \
+ SNOR_HWCAPS_XD_XD_XD)
#define SNOR_HWCAPS_ALL (SNOR_HWCAPS_READ_MASK | \
SNOR_HWCAPS_PP_MASK | \
- SNOR_HWCAPS_X_X_X)
+ SNOR_HWCAPS_X_X_X | \
+ SNOR_HWCAPS_XD_XD_XD)
/**
* spi_nor_scan() - scan the SPI NOR
Full DTR modes are modes where even the instruction opcode is sent using DTR. Define the relevant macros and enum to add such modes and patch spi_nor_select_preferred_mode() to select them when appropriate. Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> --- drivers/mtd/spi-nor/spi-nor.c | 17 ++++++++++++++++- include/linux/mtd/spi-nor.h | 29 ++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-)