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(¶ms->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