From patchwork Fri Jun 5 12:45:00 2020
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Pratyush Yadav
X-Patchwork-Id: 241831
List-Id: U-Boot discussion
From: p.yadav at ti.com (Pratyush Yadav)
Date: Fri, 5 Jun 2020 18:15:00 +0530
Subject: [PATCH v6 21/21] mtd: spi-nor-core: Allow using Micron mt35xu512aba
in Octal DTR mode
In-Reply-To: <20200605124500.17867-1-p.yadav@ti.com>
References: <20200605124500.17867-1-p.yadav@ti.com>
Message-ID: <20200605124500.17867-22-p.yadav@ti.com>
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
---
drivers/mtd/spi/Kconfig | 8 ++++
drivers/mtd/spi/spi-nor-core.c | 87 ++++++++++++++++++++++++++++++++++
drivers/mtd/spi/spi-nor-ids.c | 4 +-
include/linux/mtd/spi-nor.h | 10 +++-
4 files changed, 106 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index ecfed6d215..9c549b39b7 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -170,6 +170,14 @@ config SPI_FLASH_STMICRO
help
Add support for various STMicro SPI flash chips (M25Pxxx and N25Qxxx)
+config SPI_FLASH_MT35XU
+ bool "Micron MT35XU chip support"
+ depends on SPI_FLASH_STMICRO
+ help
+ Add support for the Micron MT35XU chip. This is a separate config
+ because the fixup hooks for this flash add extra size overhead. Boards
+ that don't use the flash can disable this to save space.
+
config SPI_FLASH_SST
bool "SST SPI flash support"
help
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 377c8b5073..8a74c4e19a 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -3087,6 +3087,88 @@ static struct spi_nor_fixups s28hs512t_fixups = {
};
#endif /* CONFIG_SPI_FLASH_S28HS512T */
+#ifdef CONFIG_SPI_FLASH_MT35XU
+static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor)
+{
+ struct spi_mem_op op;
+ u8 buf;
+ u8 addr_width = 3;
+ int ret;
+
+ /* Set dummy cycles for Fast Read to the default of 20. */
+ ret = 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(addr_width, SPINOR_REG_MT_CFR1V, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+ ret = spi_mem_exec_op(nor->spi, &op);
+ if (ret)
+ return ret;
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ return ret;
+
+ nor->read_dummy = 20;
+
+ ret = write_enable(nor);
+ if (ret)
+ return ret;
+
+ buf = SPINOR_MT_DTR_NO_DQS;
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
+ SPI_MEM_OP_ADDR(addr_width, SPINOR_REG_MT_CFR0V, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ 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;
+ }
+
+ return 0;
+}
+
+static void mt35xu512aba_default_init(struct spi_nor *nor)
+{
+ nor->octal_dtr_enable = spi_nor_micron_octal_dtr_enable;
+}
+
+static void mt35xu512aba_post_sfdp_fixup(struct spi_nor *nor,
+ struct spi_nor_flash_parameter *params)
+{
+ /* Set the Fast Read settings. */
+ params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
+ spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8_8_8_DTR],
+ 0, 20, SPINOR_OP_MT_DTR_RD,
+ SNOR_PROTO_8_8_8_DTR);
+
+ params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+
+ nor->cmd_ext_type = SPI_NOR_EXT_REPEAT;
+ params->rdsr_dummy = 8;
+ 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.
+ */
+ params->quad_enable = NULL;
+}
+
+static struct spi_nor_fixups mt35xu512aba_fixups = {
+ .default_init = mt35xu512aba_default_init,
+ .post_sfdp = mt35xu512aba_post_sfdp_fixup,
+};
+#endif /* CONFIG_SPI_FLASH_MT35XU */
+
/** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed
* @nor: pointer to a 'struct spi_nor'
*
@@ -3233,6 +3315,11 @@ void spi_nor_set_fixups(struct spi_nor *nor)
if (!strcmp(nor->info->name, "s28hs512t"))
nor->fixups = &s28hs512t_fixups;
#endif
+
+#ifdef CONFIG_SPI_FLASH_MT35XU
+ if (!strcmp(nor->info->name, "mt35xu512aba"))
+ nor->fixups = &mt35xu512aba_fixups;
+#endif
}
int spi_nor_scan(struct spi_nor *nor)
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index d515099352..336b09689a 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -185,7 +185,9 @@ const struct flash_info spi_nor_ids[] = {
{ INFO("n25q00", 0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
{ INFO("n25q00a", 0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
{ INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
- { INFO("mt35xu512aba", 0x2c5b1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) },
+#ifdef CONFIG_SPI_FLASH_MT35XU
+ { INFO("mt35xu512aba", 0x2c5b1a, 0, 128 * 1024, 512, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ) },
+#endif /* CONFIG_SPI_FLASH_MT35XU */
{ INFO("mt35xu02g", 0x2c5b1c, 0, 128 * 1024, 2048, USE_FSR | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) },
#endif
#ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 5b27f769ba..c4167deb99 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -124,8 +124,14 @@
#define SPINOR_OP_CLSR 0x30 /* Clear status register 1 */
/* Used for Micron flashes only. */
-#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
-#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */
+#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
+#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */
+#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_DTR_NO_DQS 0xc7 /* Enable Octal DTR without DQS. */
/* Status Register bits. */
#define SR_WIP BIT(0) /* Write in progress */