[PATCH v8 26/28] mtd: spi-nor-core: Add non-uniform erase for Spansion/Cypress

Takahiro Kuwano tkuw584924 at gmail.com
Tue Apr 6 03:48:48 CEST 2021


On 4/2/2021 4:31 AM, Pratyush Yadav wrote:
> From: Takahiro Kuwano <Takahiro.Kuwano at infineon.com>
> 
> Some of Spansion/Cypress chips have overlaid 4KB sectors at top and/or
> bottom, depending on the device configuration, while U-Boot supports
> uniform sector layout only.
> 
> The spansion_erase_non_uniform()  erases overlaid 4KB sectors,
> non-overlaid portion of normal sector, and remaining normal sectors, by
> selecting correct erase command and size based on the address to erase
> and size of overlaid portion in parameters. Since different Spansion
> flashes can use different opcode for erasing the 4K sectors, the opcode
> must pe passed in as a parameter based on the flash being used.
> 
Typo: "must be passed"

> Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano at infineon.com>
> Signed-off-by: Pratyush Yadav <p.yadav at ti.com>
> [p.yadav at ti.com: Refactor the function to be compatible with nor->erase,
> make 4K opcode customizable, call spi_nor_setup_op() before executing
> the op.]
> ---
> 
Thank you for refactoring. I would like to take this for the next revision
of my series. I think I need to remove spi_nor_setup_op() for my series.

> Unfortunately there is a race between this and Takahiro's series [0].
> Some of his patches depend on this series and I am taking this patch
> from his series. Not sure how to resolve this problem but I figure it is
> worth pointing out.
> 
> BTW, I changed the #ifdef to CONFIG_SPI_FLASH_S28HS512T instead of
> CONFIG_SPI_FLASH_SPANSION otherwise there would be build warnings when
> the S28 config is not enabled. Once Takahiro's series lands it should be
> changed back to CONFIG_SPI_FLASH_SPANSION.
> 
> [0] https://patchwork.ozlabs.org/project/uboot/list/?series=230084&archive=both&state=*
> 
>  drivers/mtd/spi/spi-nor-core.c | 61 ++++++++++++++++++++++++++++++++++
>  1 file changed, 61 insertions(+)
> 
> --
> 2.30.0
> 
> diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
> index 8934d65ce2..7637539087 100644
> --- a/drivers/mtd/spi/spi-nor-core.c
> +++ b/drivers/mtd/spi/spi-nor-core.c
> @@ -887,6 +887,67 @@ erase_err:
>  	return ret;
>  }
> 
> +#ifdef CONFIG_SPI_FLASH_S28HS512T
> +/**
> + * spansion_erase_non_uniform() - erase non-uniform sectors for Spansion/Cypress
> + *                                chips
> + * @nor:	pointer to a 'struct spi_nor'
> + * @addr:	address of the sector to erase
> + * @opcode_4k:	opcode for 4K sector erase
> + * @ovlsz_top:	size of overlaid portion at the top address
> + * @ovlsz_btm:	size of overlaid portion at the bottom address
> + *
> + * Erase an address range on the nor chip that can contain 4KB sectors overlaid
> + * on top and/or bottom. The appropriate erase opcode and size are chosen by
> + * address to erase and size of overlaid portion.
> + *
> + * Return: number of bytes erased on success, -errno otherwise.
> + */
> +static int spansion_erase_non_uniform(struct spi_nor *nor, u32 addr,
> +				      u8 opcode_4k, u32 ovlsz_top,
> +				      u32 ovlsz_btm)
> +{
> +	struct spi_mem_op op =
> +		SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 0),
> +			   SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
> +			   SPI_MEM_OP_NO_DUMMY,
> +			   SPI_MEM_OP_NO_DATA);
> +	struct mtd_info *mtd = &nor->mtd;
> +	u32 erasesize;
> +	int ret;
> +
> +	/* 4KB sectors */
> +	if (op.addr.val < ovlsz_btm ||
> +	    op.addr.val >= mtd->size - ovlsz_top) {
> +		op.cmd.opcode = opcode_4k;
> +		erasesize = SZ_4K;
> +
> +	/* Non-overlaid portion in the normal sector at the bottom */
> +	} else if (op.addr.val == ovlsz_btm) {
> +		op.cmd.opcode = nor->erase_opcode;
> +		erasesize = mtd->erasesize - ovlsz_btm;
> +
> +	/* Non-overlaid portion in the normal sector at the top */
> +	} else if (op.addr.val == mtd->size - mtd->erasesize) {
> +		op.cmd.opcode = nor->erase_opcode;
> +		erasesize = mtd->erasesize - ovlsz_top;
> +
> +	/* Normal sectors */
> +	} else {
> +		op.cmd.opcode = nor->erase_opcode;
> +		erasesize = mtd->erasesize;
> +	}
> +
> +	spi_nor_setup_op(nor, &op, nor->write_proto);
> +
> +	ret = spi_mem_exec_op(nor->spi, &op);
> +	if (ret)
> +		return ret;
> +
> +	return erasesize;
> +}
> +#endif
> +
>  #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST)
>  /* Write status register and ensure bits in mask match written values */
>  static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
> 

Best Regards,
Takahiro


More information about the U-Boot mailing list