Added SFDP fixups for Macronix octal flash, with the requirement
of the Invert Dual-byte opcode in Octal DDR mode.

Reference: linux-xlnx@08cf794

Signed-off-by: Tejas Bhumkar <tejas.arvind.bhum...@amd.com>
---
 drivers/mtd/spi/spi-nor-core.c | 49 +++++++++++++++++++++++++++++-----
 drivers/mtd/spi/spi-nor-ids.c  |  2 ++
 2 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 6b396ce681..9c2d70585a 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -4089,18 +4089,18 @@ static int spi_nor_macronix_octal_dtr_enable(struct 
spi_nor *nor)
 {
        struct spi_mem_op op;
        int ret;
-       u8 buf;
+       u8 *buf = nor->cmd_buf;
 
        ret = write_enable(nor);
        if (ret)
                return ret;
 
-       buf = SPINOR_REG_MXIC_DC_20;
+       *buf = SPINOR_REG_MXIC_DC_20;
        op = (struct spi_mem_op)
                SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1),
                           SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_DC, 1),
                           SPI_MEM_OP_NO_DUMMY,
-                          SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+                          SPI_MEM_OP_DATA_OUT(1, buf, 1));
 
        ret = spi_mem_exec_op(nor->spi, &op);
        if (ret)
@@ -4115,18 +4115,33 @@ static int spi_nor_macronix_octal_dtr_enable(struct 
spi_nor *nor)
        if (ret)
                return ret;
 
-       buf = SPINOR_REG_MXIC_OPI_DTR_EN;
+       nor->spi->flags |= SPI_XFER_SET_DDR;
+       *buf = SPINOR_REG_MXIC_OPI_DTR_EN;
        op = (struct spi_mem_op)
                SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_CR2, 1),
                           SPI_MEM_OP_ADDR(4, SPINOR_REG_MXIC_CR2_MODE, 1),
                           SPI_MEM_OP_NO_DUMMY,
-                          SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+                          SPI_MEM_OP_DATA_OUT(1, buf, 1));
 
        ret = spi_mem_exec_op(nor->spi, &op);
        if (ret) {
                dev_err(nor->dev, "Failed to enable octal DTR mode\n");
                return ret;
        }
+
+       /* Read flash ID to make sure the switch was successful. */
+       op = (struct spi_mem_op)
+               SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
+                          SPI_MEM_OP_ADDR(4, 0, 1),
+                          SPI_MEM_OP_DUMMY(4, 1),
+                          SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2), 
buf, 1));
+
+       spi_nor_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+       ret = spi_mem_exec_op(nor->spi, &op);
+       if (ret)
+               return ret;
+
        nor->reg_proto = SNOR_PROTO_8_8_8_DTR;
 
        return 0;
@@ -4134,6 +4149,20 @@ static int spi_nor_macronix_octal_dtr_enable(struct 
spi_nor *nor)
 
 static void macronix_octal_default_init(struct spi_nor *nor)
 {
+       u8 id_byte1, id_byte2;
+       /*
+        * Macronix Read Id bytes are always output in STR mode. Since tuning
+        * is based on Read Id command, adjust the Read Id bytes that will
+        * match the Read Id output in DTR mode.
+        */
+       id_byte1 = nor->spi->device_id[1];
+       id_byte2 = nor->spi->device_id[2];
+       nor->spi->device_id[1] = nor->spi->device_id[0];
+       nor->spi->device_id[2] = id_byte1;
+       nor->spi->device_id[3] = id_byte1;
+       nor->spi->device_id[4] = id_byte2;
+       nor->spi->device_id[5] = id_byte2;
+
        nor->octal_dtr_enable = spi_nor_macronix_octal_dtr_enable;
 }
 
@@ -4144,8 +4173,16 @@ static void macronix_octal_post_sfdp_fixup(struct 
spi_nor *nor,
         * Adding SNOR_HWCAPS_PP_8_8_8_DTR in hwcaps.mask when
         * SPI_NOR_OCTAL_DTR_READ flag exists.
         */
-       if (params->hwcaps.mask & SNOR_HWCAPS_READ_8_8_8_DTR)
+       if (params->hwcaps.mask & SNOR_HWCAPS_READ_8_8_8_DTR) {
                params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+               
spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8_DTR],
+                                         0, 20, SPINOR_OP_MXIC_DTR_RD,
+                                         SNOR_PROTO_8_8_8_DTR);
+               nor->cmd_ext_type = SPI_NOR_EXT_INVERT;
+               nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
+               params->rdsr_dummy = 8;
+               params->rdsr_addr_nbytes = 0;
+       }
 }
 
 static struct spi_nor_fixups macronix_octal_fixups = {
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index 34fba49592..cd3fcda70c 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -275,6 +275,8 @@ const struct flash_info spi_nor_ids[] = {
        { INFO("mx66l2g45g",  0xc2201c, 0, 64 * 1024, 4096, SECT_4K | 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
        { INFO("mx25l1633e", 0xc22415, 0, 64 * 1024,   32, SPI_NOR_QUAD_READ | 
SPI_NOR_4B_OPCODES | SECT_4K) },
        { INFO("mx25r6435f", 0xc22817, 0, 64 * 1024,   128,  SECT_4K) },
+       { INFO("mx25um51345g",   0xc2813a, 0, 64 * 1024, 1024, SECT_4K | 
SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP) },
+       { INFO("mx66um2g45g",    0xc2803c, 0, 64 * 1024, 4096, SECT_4K | 
SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP) },
        { INFO("mx66uw2g345gx0", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | 
SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
        { INFO("mx66lm1g45g",    0xc2853b, 0, 64 * 1024, 2048, SECT_4K | 
SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
        { INFO("mx25lm51245g",   0xc2853a, 0, 64 * 1024, 1024, SECT_4K | 
SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) },
-- 
2.27.0

Reply via email to