[PATCH] mtd: spi-nor: scale up timeout for full-chip erase
Venkatesh Yadav Abbarapu
venkatesh.abbarapu at amd.com
Tue Jan 2 13:53:03 CET 2024
This patch fixes timeout issues seen on large NOR flash.
For full-chip erase, where we use the SPINOR_OP_CHIP_ERASE (0xc7)
opcode. Use a different timeout for full-chip erase than for other
commands.
[Ported from Linux kernel commit
09b6a377687b ("mtd: spi-nor: scale up timeout for
full-chip erase") ]
Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu at amd.com>
---
drivers/mtd/spi/spi-nor-core.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index 9a1801ba93..171c68787c 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -45,6 +45,12 @@
#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ)
+/*
+ * For full-chip erase, calibrated to a 2MB flash (M25P16); should be scaled up
+ * for larger flash
+ */
+#define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ)
+
#define ROUND_UP_TO(x, y) (((x) + (y) - 1) / (y) * (y))
struct sfdp_parameter_header {
@@ -832,6 +838,20 @@ static int spi_nor_wait_till_ready(struct spi_nor *nor)
DEFAULT_READY_WAIT_JIFFIES);
}
+static int spi_nor_erase_chip_wait_till_ready(struct spi_nor *nor, unsigned long size)
+{
+ /*
+ * Scale the timeout linearly with the size of the flash, with
+ * a minimum calibrated to an old 2MB flash. We could try to
+ * pull these from CFI/SFDP, but these values should be good
+ * enough for now.
+ */
+ unsigned long timeout = max(CHIP_ERASE_2MB_READY_WAIT_JIFFIES,
+ CHIP_ERASE_2MB_READY_WAIT_JIFFIES *
+ (unsigned long)(size / SZ_2M));
+ return spi_nor_wait_till_ready_with_timeout(nor, timeout);
+}
+
#ifdef CONFIG_SPI_FLASH_BAR
/*
* This "clean_bar" is necessary in a situation when one was accessing
@@ -966,7 +986,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct spi_nor *nor = mtd_to_spi_nor(mtd);
bool addr_known = false;
- u32 addr, len, rem;
+ u32 addr, len, rem, max_size;
int ret, err;
dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
@@ -980,6 +1000,7 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
addr = instr->addr;
len = instr->len;
+ max_size = instr->len;
instr->state = MTD_ERASING;
addr_known = true;
@@ -1012,7 +1033,13 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
addr += ret;
len -= ret;
- ret = spi_nor_wait_till_ready(nor);
+ if (max_size == mtd->size &&
+ !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
+ ret = spi_nor_erase_chip_wait_till_ready(nor, mtd->size);
+ } else {
+ ret = spi_nor_wait_till_ready(nor);
+ }
+
if (ret)
goto erase_err;
}
--
2.25.1
More information about the U-Boot
mailing list