summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorApurva Nandan <a-nandan@ti.com>2023-01-23 23:13:30 +0530
committerPraneeth Bajjuri <praneeth@ti.com>2023-01-25 14:10:19 -0600
commitdfc772ee2d54e6e79e27a65d90f4febfb01ef95c (patch)
treefb270d693f115bc544b68530218479b2206e0f14 /drivers
parent341effe314230347f952776b4ac660229613f47a (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.c28
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 = {