From f6adec1af4b2f5d3012480c6cdce7743b74a6156 Mon Sep 17 00:00:00 2001 From: Pratyush Yadav Date: Sat, 26 Jun 2021 00:47:29 +0530 Subject: [PATCH] mtd: spi-nor-core: Allow using Micron mt35xu512aba in Octal DTR mode 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. Signed-off-by: Pratyush Yadav Reviewed-by: Jagan Teki --- 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 | 6 +++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index 98c0b23478..1b2ef37e92 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -180,6 +180,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 3a1060b04b..8dd44c0f1e 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -3148,6 +3148,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_OCT_DTR; + 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' * @@ -3295,6 +3377,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 bbed88a4b7..59f2d3e4d6 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -193,7 +193,9 @@ const struct flash_info spi_nor_ids[] = { { INFO("n25q00a", 0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { INFO("mt25ql01g", 0x21ba20, 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 6ece401b37..d68e48fd94 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -126,6 +126,12 @@ /* 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_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 with DQS. */ /* Status Register bits. */ #define SR_WIP BIT(0) /* Write in progress */ -- 2.39.5