mtd: spi-nor-core: allow truncated erases

On devices with non-uniform sector sizes like Spansion S25 or S28 family
of flashes the sector under erase does not necessarily have to be
mtd->erasesize bytes long. For example, on S28 flashes the first 128 KiB
region is composed of 32 4 KiB sectors, then a 128 KiB sector, and then
256 KiB sectors till the end.

Let the flash-specific erase functions erase less than the requested
length in case of the 4 or 128 KiB sectors and report the number of
bytes erased back to the calling function.

Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
Reviewed-by: Jagan Teki <jagan@amarulasolutions.com>
This commit is contained in:
Pratyush Yadav
2021-06-26 00:47:26 +05:30
committed by Jagan Teki
parent 0be8ab1f16
commit aba0bcd7bd

View File

@@ -806,7 +806,8 @@ static int read_bar(struct spi_nor *nor, const struct flash_info *info)
#endif #endif
/* /*
* Initiate the erasure of a single sector * Initiate the erasure of a single sector. Returns the number of bytes erased
* on success, a negative error code on error.
*/ */
static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr) static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
{ {
@@ -815,6 +816,7 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
SPI_MEM_OP_ADDR(nor->addr_width, addr, 0), SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_NO_DUMMY,
SPI_MEM_OP_NO_DATA); SPI_MEM_OP_NO_DATA);
int ret;
spi_nor_setup_op(nor, &op, nor->write_proto); spi_nor_setup_op(nor, &op, nor->write_proto);
@@ -825,7 +827,11 @@ static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
* Default implementation, if driver doesn't have a specialized HW * Default implementation, if driver doesn't have a specialized HW
* control * control
*/ */
return spi_mem_exec_op(nor->spi, &op); ret = spi_mem_exec_op(nor->spi, &op);
if (ret)
return ret;
return nor->mtd.erasesize;
} }
/* /*
@@ -861,11 +867,11 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
write_enable(nor); write_enable(nor);
ret = spi_nor_erase_sector(nor, addr); ret = spi_nor_erase_sector(nor, addr);
if (ret) if (ret < 0)
goto erase_err; goto erase_err;
addr += mtd->erasesize; addr += ret;
len -= mtd->erasesize; len -= ret;
ret = spi_nor_wait_till_ready(nor); ret = spi_nor_wait_till_ready(nor);
if (ret) if (ret)