[PATCH v2 2/4] mtd: spi-nor-core: macronix: Add support for mx66lm1g45g

Tudor Ambarus
2021-11-03T23:50:49Z

mx66lm1g45g supports just 1-1-1, 8-8-8 and 8d-8d-8d modes.
Tested in 1-1-1 and 8d-8d-8d modes using microchip's Octal SPI IP.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
drivers/mtd/spi/Kconfig | 8 ++++
drivers/mtd/spi/spi-nor-core.c | 74 ++++++++++++++++++++++++++++++++++
drivers/mtd/spi/spi-nor-ids.c | 6 +++
include/linux/mtd/spi-nor.h | 8 ++++
4 files changed, 96 insertions(+)

diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 408a53f861..2d2b71c52d 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -160,6 +160,14 @@ config SPI_FLASH_MACRONIX
help
Add support for various Macronix SPI flash chips (MX25Lxxx)

+config SPI_FLASH_MX66LM1G45G
+ bool "Macronix MX66LM1G45G chip support"
+ depends on SPI_FLASH_MACRONIX
+ help
+ Add support for the Macronix mx66lm1g45g 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_SPANSION
bool "Spansion SPI flash support"
help
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index ce1ecae899..df66a73495 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -3526,6 +3526,75 @@ static struct spi_nor_fixups mt35xu512aba_fixups = {
};
#endif /* CONFIG_SPI_FLASH_MT35XU */

+#ifdef CONFIG_SPI_FLASH_MX66LM1G45G
+static int spi_nor_macronix_octal_dtr_enable(struct spi_nor *nor)
+{
+ struct spi_mem_op op;
+ u8 buf;
+ int ret;
+
+ /* Use 20 dummy cycles for memory array reads. */
+ buf = SPINOR_REG_CR2_DUMMY_20;
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRITE_CR2, 1),
+ SPI_MEM_OP_ADDR(4, SPINOR_REG_CR2_DUMMY_ADDR,
+ 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+
+ ret = write_enable(nor);
+ if (ret)
+ return ret;
+
+ ret = spi_mem_exec_op(nor->spi, &op);
+ if (ret)
+ return ret;
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ return ret;
+
+ buf = SPINOR_REG_CR2_DTR_OPI_ENABLE;
+ op = (struct spi_mem_op)
+ SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRITE_CR2, 1),
+ SPI_MEM_OP_ADDR(4, SPINOR_REG_CR2_MODE_ADDR, 1),
+ SPI_MEM_OP_NO_DUMMY,
+ SPI_MEM_OP_DATA_OUT(1, &buf, 1));
+
+ ret = write_enable(nor);
+ if (ret)
+ return ret;
+
+ return spi_mem_exec_op(nor->spi, &op);
+}
+
+static void mx66lm1g45g_default_init(struct spi_nor *nor)
+{
+ nor->octal_dtr_enable = spi_nor_macronix_octal_dtr_enable;
+}
+
+static void mx66lm1g45g_post_sfdp(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(&params->reads[SNOR_CMD_READ_8_8_8_DTR],
+ 0, 20, SPINOR_OP_MX_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_INVERT;
+ params->rdsr_dummy = 4;
+ params->rdsr_addr_nbytes = 4;
+}
+
+static struct spi_nor_fixups mx66lm1g45g_fixups = {
+ .default_init = mx66lm1g45g_default_init,
+ .post_sfdp = mx66lm1g45g_post_sfdp,
+};
+#endif /* CONFIG_SPI_FLASH_MX66LM1G45G */
+
/** spi_nor_octal_dtr_enable() - enable Octal DTR I/O if needed
* @nor: pointer to a 'struct spi_nor'
*
@@ -3696,6 +3765,11 @@ void spi_nor_set_fixups(struct spi_nor *nor)
if (!strcmp(nor->info->name, "mt35xu512aba"))
nor->fixups = &mt35xu512aba_fixups;
#endif
+
+#ifdef CONFIG_SPI_FLASH_MX66LM1G45G
+ if (!strcmp(nor->info->name, "mx66lm1g45g"))
+ nor->fixups = &mx66lm1g45g_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 3ae7bb1ed7..d5bc106e68 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -179,6 +179,12 @@ const struct flash_info spi_nor_ids[] = {
{ 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("mx66uw2g345g", 0xc2943c, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES) },
+#ifdef CONFIG_SPI_FLASH_MX66LM1G45G
+ { INFO("mx66lm1g45g", 0xc2853b, 0, 64 * 1024, 2048,
+ SPI_NOR_SKIP_SFDP | SPI_NOR_SOFT_RESET |
+ SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES)
+ },
+#endif
#endif

#ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 4ceeae623d..c8b8a242ba 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -119,6 +119,14 @@
/* Used for Macronix and Winbond flashes. */
#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
+#define SPINOR_OP_READ_CR2 0x71
+#define SPINOR_OP_WRITE_CR2 0x72
+#define SPINOR_OP_MX_DTR_RD 0xee
+#define SPINOR_REG_CR2_MODE_ADDR 0
+#define SPINOR_REG_CR2_DTR_OPI_ENABLE BIT(1)
+#define SPINOR_REG_CR2_SPI 0
+#define SPINOR_REG_CR2_DUMMY_ADDR 0x300
+#define SPINOR_REG_CR2_DUMMY_20 0

/* Used for Spansion flashes only. */
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
--
2.25.1