mtd: spi-nor: scale up timeout for full-chip erase
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@amd.com>
This commit is contained in:
committed by
Tom Rini
parent
146be6f036
commit
948616894c
@@ -44,6 +44,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 {
|
||||
@@ -855,6 +861,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
|
||||
@@ -989,7 +1009,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,
|
||||
@@ -1003,6 +1023,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;
|
||||
@@ -1035,7 +1056,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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user