diff options
author | Apurva Nandan <a-nandan@ti.com> | 2023-01-23 23:13:30 +0530 |
---|---|---|
committer | Praneeth Bajjuri <praneeth@ti.com> | 2023-01-25 14:10:19 -0600 |
commit | dfc772ee2d54e6e79e27a65d90f4febfb01ef95c (patch) | |
tree | fb270d693f115bc544b68530218479b2206e0f14 /drivers | |
parent | 341effe314230347f952776b4ac660229613f47a (diff) |
mtd: nand: spi: winbond: Perform Power-on-Reset(PoR) flash op in cleanup
Flash settings such as Octal-DTR mode and other register configurations
should be resetted before the flash is removed. This would enable
a clean removal and re-plug for later boot stages.
The soft-reset command doesn't restore the flash into 1S mode, so
add support for executing 66h+99h PoR flash reset when in Octal DTR mode.
Datasheet:
https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf
Signed-off-by: Apurva Nandan <a-nandan@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/nand/spi/winbond.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index 0e20176b6a..d8eb12c382 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -31,6 +31,8 @@ #define WINBOND_VCR_DUMMY_CLK_DEFAULT 0xFF #define WINBOND_VCR_DUMMY_CLK_ADDR 0x01 +#define WINBOND_POR_DELAY_US 1000 + static SPINAND_OP_VARIANTS(read_cache_variants_w25m02gv, SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), @@ -366,10 +368,36 @@ static int winbond_change_spi_protocol(struct spinand_device *spinand, return -EOPNOTSUPP; } +static void winbond_spinand_cleanup(struct spinand_device *spinand) +{ + struct spi_mem_op op; + + /* Perform Power-On-Reset if the device is in Octal-DTR mode */ + if (spinand->protocol == SPINAND_8D) { + op = (struct spi_mem_op) + SPI_MEM_OP(SPI_MEM_OP_EXT_CMD(2, 0x6666, 8, SPI_MEM_OP_DTR), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + spi_mem_exec_op(spinand->slave, &op); + + op = (struct spi_mem_op) + SPI_MEM_OP(SPI_MEM_OP_EXT_CMD(2, 0x9999, 8, SPI_MEM_OP_DTR), + SPI_MEM_OP_NO_ADDR, + SPI_MEM_OP_NO_DUMMY, + SPI_MEM_OP_NO_DATA); + spi_mem_exec_op(spinand->slave, &op); + + /* PoR can take max 500 us to complete, so sleep for 1000 us*/ + udelay(WINBOND_POR_DELAY_US); + } +} + static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = { .detect = winbond_spinand_detect, .init = winbond_spinand_init, .change_protocol = winbond_change_spi_protocol, + .cleanup = winbond_spinand_cleanup, }; const struct spinand_manufacturer winbond_spinand_manufacturer = { |