From c452d49849d48bd37ae97fc2bc92c6435707c35f Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 25 Jul 2022 12:24:59 +0300 Subject: mtd: spi-nor: s/addr_width/addr_nbytes Address width was an unfortunate name, as it means the number of IO lines used for the address, whereas in the code it is used as the number of address bytes. s/addr_width/addr_nbytes throughout the entire SPI NOR framework. Signed-off-by: Tudor Ambarus Reviewed-by: Michael Walle Acked-by: Pratyush Yadav Link: https://lore.kernel.org/r/20220725092505.446315-2-tudor.ambarus@microchip.com --- drivers/mtd/spi-nor/sfdp.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/mtd/spi-nor/sfdp.c') diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index a5211543d30d..61ae8c8c5237 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -134,7 +134,7 @@ struct sfdp_4bait { /** * spi_nor_read_raw() - raw read of serial flash memory. read_opcode, - * addr_width and read_dummy members of the struct spi_nor + * addr_nbytes and read_dummy members of the struct spi_nor * should be previously * set. * @nor: pointer to a 'struct spi_nor' @@ -178,21 +178,21 @@ static int spi_nor_read_raw(struct spi_nor *nor, u32 addr, size_t len, u8 *buf) static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr, size_t len, void *buf) { - u8 addr_width, read_opcode, read_dummy; + u8 addr_nbytes, read_opcode, read_dummy; int ret; read_opcode = nor->read_opcode; - addr_width = nor->addr_width; + addr_nbytes = nor->addr_nbytes; read_dummy = nor->read_dummy; nor->read_opcode = SPINOR_OP_RDSFDP; - nor->addr_width = 3; + nor->addr_nbytes = 3; nor->read_dummy = 8; ret = spi_nor_read_raw(nor, addr, len, buf); nor->read_opcode = read_opcode; - nor->addr_width = addr_width; + nor->addr_nbytes = addr_nbytes; nor->read_dummy = read_dummy; return ret; @@ -462,11 +462,11 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4: - nor->addr_width = 3; + nor->addr_nbytes = 3; break; case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: - nor->addr_width = 4; + nor->addr_nbytes = 4; break; default: @@ -637,12 +637,12 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, } /** - * spi_nor_smpt_addr_width() - return the address width used in the + * spi_nor_smpt_addr_nbytes() - return the number of address bytes used in the * configuration detection command. * @nor: pointer to a 'struct spi_nor' * @settings: configuration detection command descriptor, dword1 */ -static u8 spi_nor_smpt_addr_width(const struct spi_nor *nor, const u32 settings) +static u8 spi_nor_smpt_addr_nbytes(const struct spi_nor *nor, const u32 settings) { switch (settings & SMPT_CMD_ADDRESS_LEN_MASK) { case SMPT_CMD_ADDRESS_LEN_0: @@ -653,7 +653,7 @@ static u8 spi_nor_smpt_addr_width(const struct spi_nor *nor, const u32 settings) return 4; case SMPT_CMD_ADDRESS_LEN_USE_CURRENT: default: - return nor->addr_width; + return nor->addr_nbytes; } } @@ -690,7 +690,7 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt, u32 addr; int err; u8 i; - u8 addr_width, read_opcode, read_dummy; + u8 addr_nbytes, read_opcode, read_dummy; u8 read_data_mask, map_id; /* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */ @@ -698,7 +698,7 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt, if (!buf) return ERR_PTR(-ENOMEM); - addr_width = nor->addr_width; + addr_nbytes = nor->addr_nbytes; read_dummy = nor->read_dummy; read_opcode = nor->read_opcode; @@ -709,7 +709,7 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt, break; read_data_mask = SMPT_CMD_READ_DATA(smpt[i]); - nor->addr_width = spi_nor_smpt_addr_width(nor, smpt[i]); + nor->addr_nbytes = spi_nor_smpt_addr_nbytes(nor, smpt[i]); nor->read_dummy = spi_nor_smpt_read_dummy(nor, smpt[i]); nor->read_opcode = SMPT_CMD_OPCODE(smpt[i]); addr = smpt[i + 1]; @@ -756,7 +756,7 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt, /* fall through */ out: kfree(buf); - nor->addr_width = addr_width; + nor->addr_nbytes = addr_nbytes; nor->read_dummy = read_dummy; nor->read_opcode = read_opcode; return ret; @@ -1044,7 +1044,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, /* * We need at least one 4-byte op code per read, program and erase * operation; the .read(), .write() and .erase() hooks share the - * nor->addr_width value. + * nor->addr_nbytes value. */ if (!read_hwcaps || !pp_hwcaps || !erase_mask) goto out; @@ -1098,7 +1098,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, * Spansion memory. However this quirk is no longer needed with new * SFDP compliant memories. */ - nor->addr_width = 4; + nor->addr_nbytes = 4; nor->flags |= SNOR_F_4B_OPCODES | SNOR_F_HAS_4BAIT; /* fall through */ -- cgit v1.2.3 From 47c6f8a67f2ce1b95202c16fa126411d6f5c7d5c Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 25 Jul 2022 12:25:01 +0300 Subject: mtd: spi-nor: Do not change nor->addr_nbytes at SFDP parsing time At the SFDP parsing time we should not change members of struct spi_nor, but instead fill members of struct spi_nor_flash_parameters which could later on be used by callers. The caller will then decide if SFDP params should be used and more importantly when they should be used. Clean the code flow and don't initialize nor->addr_nbytes at SFDP parsing time. Signed-off-by: Tudor Ambarus Tested-by: Takahiro Kuwano Reviewed-by: Michael Walle Reviewed-by: Pratyush Yadav Link: https://lore.kernel.org/r/20220725092505.446315-4-tudor.ambarus@microchip.com --- drivers/mtd/spi-nor/core.c | 5 ++--- drivers/mtd/spi-nor/core.h | 2 ++ drivers/mtd/spi-nor/issi.c | 2 +- drivers/mtd/spi-nor/sfdp.c | 8 ++++---- 4 files changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/mtd/spi-nor/sfdp.c') diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 31604188ee59..9f07f1036151 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2251,8 +2251,8 @@ static int spi_nor_default_setup(struct spi_nor *nor, static int spi_nor_set_addr_nbytes(struct spi_nor *nor) { - if (nor->addr_nbytes) { - /* already configured from SFDP */ + if (nor->params->addr_nbytes) { + nor->addr_nbytes = nor->params->addr_nbytes; } else if (nor->read_proto == SNOR_PROTO_8_8_8_DTR) { /* * In 8D-8D-8D mode, one byte takes half a cycle to transfer. So @@ -2492,7 +2492,6 @@ static void spi_nor_sfdp_init_params_deprecated(struct spi_nor *nor) if (spi_nor_parse_sfdp(nor)) { memcpy(nor->params, &sfdp_params, sizeof(*nor->params)); - nor->addr_nbytes = 0; nor->flags &= ~SNOR_F_4B_OPCODES; } } diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 19a692e27c92..7dc4cda41db3 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -340,6 +340,7 @@ struct spi_nor_otp { * @writesize Minimal writable flash unit size. Defaults to 1. Set to * ECC unit size for ECC-ed flashes. * @page_size: the page size of the SPI NOR flash memory. + * @addr_nbytes: number of address bytes to send. * @rdsr_dummy: dummy cycles needed for Read Status Register command * in octal DTR mode. * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register @@ -372,6 +373,7 @@ struct spi_nor_flash_parameter { u64 size; u32 writesize; u32 page_size; + u8 addr_nbytes; u8 rdsr_dummy; u8 rdsr_addr_nbytes; diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c index 71687e5babdc..89a66a19d754 100644 --- a/drivers/mtd/spi-nor/issi.c +++ b/drivers/mtd/spi-nor/issi.c @@ -20,7 +20,7 @@ is25lp256_post_bfpt_fixups(struct spi_nor *nor, */ if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) == BFPT_DWORD1_ADDRESS_BYTES_3_ONLY) - nor->addr_nbytes = 4; + nor->params->addr_nbytes = 4; return 0; } diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 61ae8c8c5237..3a48173a2d78 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -462,11 +462,11 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) { case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4: - nor->addr_nbytes = 3; + params->addr_nbytes = 3; break; case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: - nor->addr_nbytes = 4; + params->addr_nbytes = 4; break; default: @@ -653,7 +653,7 @@ static u8 spi_nor_smpt_addr_nbytes(const struct spi_nor *nor, const u32 settings return 4; case SMPT_CMD_ADDRESS_LEN_USE_CURRENT: default: - return nor->addr_nbytes; + return nor->params->addr_nbytes; } } @@ -1098,7 +1098,7 @@ static int spi_nor_parse_4bait(struct spi_nor *nor, * Spansion memory. However this quirk is no longer needed with new * SFDP compliant memories. */ - nor->addr_nbytes = 4; + params->addr_nbytes = 4; nor->flags |= SNOR_F_4B_OPCODES | SNOR_F_HAS_4BAIT; /* fall through */ -- cgit v1.2.3 From d7931a21506321327351f68fdebf74a56a58e675 Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Mon, 25 Jul 2022 12:25:03 +0300 Subject: mtd: spi-nor: core: Track flash's internal address mode We need to track the flash's internal address mode as there are flashes that can operate with 4B opcodes but unfortunately do not have a 4B opcode correspondent for all the 3B opcodes. Such an example is the Infineon Semper chips which provide 4B opcodes for read/program/erase but do not provide 4B opcodes for Read/Write Any Register. These registers are indexed by address and require the internal address mode of the flash before Read/Write Any Register opcodes are issued. 4B opcodes are preferred over changing the flash's address mode to 4byte, as set_4byte_addr_mode could be done in a non-volatile way and could break the boot sequence. Thus we need to track the flash's internal address mode so that we can use 4B opcodes together with opcodes that don't have a 4B opcode correspondent. Track flash's internal address mode. addr_mode_nbytes is discovered when parsing BFPT. For the BFPT_DWORD1_ADDRESS_BYTES_3_OR_4 case, one could introduce a method that queries the flash's internal address mode at run-time (works for Winbond). If a run-time querying can not be accomplished or if SFDP is not defined at all, but the address mode is volatile and resets to a default known value at boot, one can change the default addr_mode_nbytes value of 3 by introducing a flash_info flag. If the address mode can not be queried, discovered and it is configured via a non-volatile register, we may introduce a dt property, but it will harm the generic approach of the jedec,spi-nor compatible. All this complexity is not needed now, so let it for future development. Signed-off-by: Tudor Ambarus Reviewed-by: Takahiro Kuwano Reviewed-by: Michael Walle Link: https://lore.kernel.org/r/20220725092505.446315-6-tudor.ambarus@microchip.com --- drivers/mtd/spi-nor/core.h | 5 +++++ drivers/mtd/spi-nor/sfdp.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/mtd/spi-nor/sfdp.c') diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h index 7dc4cda41db3..85b0cf254e97 100644 --- a/drivers/mtd/spi-nor/core.h +++ b/drivers/mtd/spi-nor/core.h @@ -341,6 +341,10 @@ struct spi_nor_otp { * ECC unit size for ECC-ed flashes. * @page_size: the page size of the SPI NOR flash memory. * @addr_nbytes: number of address bytes to send. + * @addr_mode_nbytes: number of address bytes of current address mode. Useful + * when the flash operates with 4B opcodes but needs the + * internal address mode for opcodes that don't have a 4B + * opcode correspondent. * @rdsr_dummy: dummy cycles needed for Read Status Register command * in octal DTR mode. * @rdsr_addr_nbytes: dummy address bytes needed for Read Status Register @@ -374,6 +378,7 @@ struct spi_nor_flash_parameter { u32 writesize; u32 page_size; u8 addr_nbytes; + u8 addr_mode_nbytes; u8 rdsr_dummy; u8 rdsr_addr_nbytes; diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c index 3a48173a2d78..2257f1b4c2e2 100644 --- a/drivers/mtd/spi-nor/sfdp.c +++ b/drivers/mtd/spi-nor/sfdp.c @@ -463,10 +463,12 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY: case BFPT_DWORD1_ADDRESS_BYTES_3_OR_4: params->addr_nbytes = 3; + params->addr_mode_nbytes = 3; break; case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY: params->addr_nbytes = 4; + params->addr_mode_nbytes = 4; break; default: @@ -653,7 +655,7 @@ static u8 spi_nor_smpt_addr_nbytes(const struct spi_nor *nor, const u32 settings return 4; case SMPT_CMD_ADDRESS_LEN_USE_CURRENT: default: - return nor->params->addr_nbytes; + return nor->params->addr_mode_nbytes; } } -- cgit v1.2.3