mtd: spi-nor: micron-st: allow using MT35XU512ABA in Octal DTR mode
authorPratyush Yadav <p.yadav@ti.com>
Mon, 5 Oct 2020 15:31:38 +0000 (21:01 +0530)
committerVignesh Raghavendra <vigneshr@ti.com>
Mon, 9 Nov 2020 13:30:14 +0000 (19:00 +0530)
Since this flash doesn't have a Profile 1.0 table, the Octal DTR
capabilities are enabled in the post SFDP fixup, along with the 8D-8D-8D
fast read settings.

Enable Octal DTR mode with 20 dummy cycles to allow running at the
maximum supported frequency of 200Mhz.

The flash supports the soft reset sequence. So, add the flag in the
flash's info.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Link: https://lore.kernel.org/r/20201005153138.6437-16-p.yadav@ti.com
drivers/mtd/spi-nor/micron-st.c

index ef36950..c224e59 100644 (file)
 
 #include "core.h"
 
+#define SPINOR_OP_MT_DTR_RD    0xfd    /* Fast Read opcode in DTR mode */
+#define SPINOR_OP_MT_RD_ANY_REG        0x85    /* Read volatile register */
+#define SPINOR_OP_MT_WR_ANY_REG        0x81    /* Write volatile register */
+#define SPINOR_REG_MT_CFR0V    0x00    /* For setting octal DTR mode */
+#define SPINOR_REG_MT_CFR1V    0x01    /* For setting dummy cycles */
+#define SPINOR_MT_OCT_DTR      0xe7    /* Enable Octal DTR. */
+#define SPINOR_MT_EXSPI                0xff    /* Enable Extended SPI (default) */
+
+static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor, bool enable)
+{
+       struct spi_mem_op op;
+       u8 *buf = nor->bouncebuf;
+       int ret;
+
+       if (enable) {
+               /* Use 20 dummy cycles for memory array reads. */
+               ret = spi_nor_write_enable(nor);
+               if (ret)
+                       return ret;
+
+               *buf = 20;
+               op = (struct spi_mem_op)
+                       SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
+                                  SPI_MEM_OP_ADDR(3, SPINOR_REG_MT_CFR1V, 1),
+                                  SPI_MEM_OP_NO_DUMMY,
+                                  SPI_MEM_OP_DATA_OUT(1, buf, 1));
+
+               ret = spi_mem_exec_op(nor->spimem, &op);
+               if (ret)
+                       return ret;
+
+               ret = spi_nor_wait_till_ready(nor);
+               if (ret)
+                       return ret;
+       }
+
+       ret = spi_nor_write_enable(nor);
+       if (ret)
+               return ret;
+
+       if (enable)
+               *buf = SPINOR_MT_OCT_DTR;
+       else
+               *buf = SPINOR_MT_EXSPI;
+
+       op = (struct spi_mem_op)
+               SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
+                          SPI_MEM_OP_ADDR(enable ? 3 : 4,
+                                          SPINOR_REG_MT_CFR0V, 1),
+                          SPI_MEM_OP_NO_DUMMY,
+                          SPI_MEM_OP_DATA_OUT(1, buf, 1));
+
+       if (!enable)
+               spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+       ret = spi_mem_exec_op(nor->spimem, &op);
+       if (ret)
+               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_NO_ADDR,
+                          SPI_MEM_OP_DUMMY(enable ? 8 : 0, 1),
+                          SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
+                                             buf, 1));
+
+       if (enable)
+               spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+
+       ret = spi_mem_exec_op(nor->spimem, &op);
+       if (ret)
+               return ret;
+
+       if (memcmp(buf, nor->info->id, nor->info->id_len))
+               return -EINVAL;
+
+       return 0;
+}
+
+static void mt35xu512aba_default_init(struct spi_nor *nor)
+{
+       nor->params->octal_dtr_enable = spi_nor_micron_octal_dtr_enable;
+}
+
+static void mt35xu512aba_post_sfdp_fixup(struct spi_nor *nor)
+{
+       /* Set the Fast Read settings. */
+       nor->params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
+       spi_nor_set_read_settings(&nor->params->reads[SNOR_CMD_READ_8_8_8_DTR],
+                                 0, 20, SPINOR_OP_MT_DTR_RD,
+                                 SNOR_PROTO_8_8_8_DTR);
+
+       nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+       nor->params->rdsr_dummy = 8;
+       nor->params->rdsr_addr_nbytes = 0;
+
+       /*
+        * The BFPT quad enable field is set to a reserved value so the quad
+        * enable function is ignored by spi_nor_parse_bfpt(). Make sure we
+        * disable it.
+        */
+       nor->params->quad_enable = NULL;
+}
+
+static struct spi_nor_fixups mt35xu512aba_fixups = {
+       .default_init = mt35xu512aba_default_init,
+       .post_sfdp = mt35xu512aba_post_sfdp_fixup,
+};
+
 static const struct flash_info micron_parts[] = {
        { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
                               SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
-                              SPI_NOR_4B_OPCODES) },
+                              SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ |
+                              SPI_NOR_OCTAL_DTR_PP |
+                              SPI_NOR_IO_MODE_EN_VOLATILE)
+         .fixups = &mt35xu512aba_fixups},
        { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
                            SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
                            SPI_NOR_4B_OPCODES) },