Re: [PATCH v2 11/14] mtd: spinand: Perform Power-on-Reset on the flash in mtd_suspend()

Boris Brezillon
2021-10-12T07:25:28Z

On Tue, 12 Oct 2021 02:16:16 +0530
Apurva Nandan <a-nandan@ti.com> wrote:

> A soft reset using FFh command doesn't erase the flash's configuration
> and doesn't reset the SPI IO mode also. This can result in the flash
> being in a different SPI IO mode, e.g. Octal DTR, when resuming from
> sleep. This could put the flash in an unrecognized SPI IO mode, making
> it unusable.
>
> Perform a Power-on-Reset (PoR), if available in the flash, when
> performing mtd_suspend(). This would set the flash to clean
> state for reinitialization during resume and would also ensure that it
> is in standard SPI IO mode (1S-1S-1S) before the resume begins.
>
> Signed-off-by: Apurva Nandan <a-nandan@ti.com>
> ---
> drivers/mtd/nand/spi/core.c | 21 +++++++++++++++++++++
> 1 file changed, 21 insertions(+)
>
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 9b570570ee81..60408531979a 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -1316,6 +1316,11 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
> int ret;
>
> spinand->reg_proto = SPINAND_SINGLE_STR;
> + /*
> + * PoR Reset (if available by the manufacturer) is performed at the suspend
> + * time. Hence, those flashes remain in power-on-state at this point, in a
> + * standard SPI IO mode. So, now the core unanimously performs a soft reset.
> + */
> ret = spinand_reset_op(spinand);
> if (ret)
> return;
> @@ -1327,6 +1332,21 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
> spinand_ecc_enable(spinand, false);
> }
>
> +static int spinand_mtd_suspend(struct mtd_info *mtd)
> +{
> + struct spinand_device *spinand = mtd_to_spinand(mtd);
> + int ret;
> +
> + if (!(spinand->flags & SPINAND_HAS_POR_CMD_BIT))
> + return 0;
> +
> + ret = spinand_power_on_rst_op(spinand);
> + if (ret)
> + dev_err(&spinand->spimem->spi->dev, "suspend() failed\n");
> +
> + return ret;
> +}

I suspect you need to implement the spi_mem_driver.shutdown() method
and do a PoR in that case too. If the device doesn't support the PoR
command, we should at least switch back to the 1-1-1-STR mode manually.

> +
> static int spinand_init(struct spinand_device *spinand)
> {
> struct device *dev = &spinand->spimem->spi->dev;
> @@ -1399,6 +1419,7 @@ static int spinand_init(struct spinand_device *spinand)
> mtd->_erase = spinand_mtd_erase;
> mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks;
> mtd->_resume = spinand_mtd_resume;
> + mtd->_suspend = spinand_mtd_suspend;
>
> if (nand->ecc.engine) {
> ret = mtd_ooblayout_count_freebytes(mtd);