mtd: spi-nor: provide default erase_sector implementation
Subsystems (2)
PATCH v2 1/2 mtd: spi-nor: provide default erase_sector implementation
Some spi-nor drivers perform sector erase by duplicating their write_reg() command. Let's not require that the driver fill this out, and provide a default instead.
Tested on m25p80.c and Medatek's MT8173 SPI NOR flash driver.
---
v1 -> v2:
* use statically-sized array, with a check to make sure MAX is big enough
v1: http://lists.infradead.org/pipermail/linux-mtd/2015-October/062916.html
drivers/mtd/spi-nor/spi-nor.c | 37 +++++++++++++++++++++++++++++++++---- include/linux/mtd/spi-nor.h | 3 ++- 2 files changed, 35 insertions(+), 5 deletions(-)
drivers/mtd/spi-nor/spi-nor.c +33 -4
@@ -38,6 +38,7 @@#define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ)#define SPI_NOR_MAX_ID_LEN 6 +#define SPI_NOR_MAX_ADDR_WIDTH 4struct flash_info {char *name;
@@ -313,6 +314,29 @@ static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) }/* +* Initiate the erasure of a single sector +*/ +static int spi_nor_erase_sector (struct spi_nor *nor,u32 addr) +{ +u8 buf[SPI_NOR_MAX_ADDR_WIDTH ]; +int i; + +if (nor->erase) +return nor->erase (nor, addr); + +/* +* Default implementation, if driver doesn't have a specialized HW +* control +*/ +for (i = nor->addr_width -1 ; i >=0 ; i--) { + buf[i] = addr &0xff ; + addr >>=8 ; + } + +return nor->write_reg (nor, nor->erase_opcode, buf, nor->addr_width); +} + +/* * Erase an address range on the nor chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */
@@ -371,10 +395,9 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)while (len) {write_enable (nor); -if (nor->erase (nor, addr)) { - ret = -EIO ; + ret =spi_nor_erase_sector (nor, addr); +if (ret) goto erase_err; - } addr += mtd->erasesize; len -= mtd->erasesize;
@@ -1138,7 +1161,7 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)static int spi_nor_check (struct spi_nor *nor) {if (!nor->dev || !nor->read || !nor->write || - !nor->read_reg || !nor->write_reg || !nor->erase) { + !nor->read_reg || !nor->write_reg) {pr_err ("spi-nor: please fill all the necessary fields!\n" );return -EINVAL ; }
@@ -1340,6 +1363,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) nor->addr_width =3 ; } +if (nor->addr_width >SPI_NOR_MAX_ADDR_WIDTH ) { +dev_err (dev,"address width is too large: %u\n" , + nor->addr_width); +return -EINVAL ; + } + nor->read_dummy =spi_nor_read_dummy_cycles (nor); dev_info(dev, "%s (%lld Kbytes)\n", info->name,
include/linux/mtd/spi-nor.h +2 -1
@@ -144,7 +144,8 @@ struct mtd_info;* @read: [DRIVER-SPECIFIC] read data from the SPI NOR * @write: [DRIVER-SPECIFIC] write data to the SPI NOR * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR -* at the offset @offs +* at the offset @offs; if not provided by the driver, +* spi-nor will send the erase opcode via write_reg() * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
PATCH v2 2/2 mtd: m25p80: drop erase() callback
Just use the spi-nor default instead.
---
v2: no change
v1: http://lists.infradead.org/pipermail/linux-mtd/2015-October/062917.html
drivers/mtd/devices/m25p80.c | 17 ----------------- 1 file changed, 17 deletions(-)
drivers/mtd/devices/m25p80.c +0 -17
@@ -152,22 +152,6 @@ static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,return 0 ; } -static int m25p80_erase (struct spi_nor *nor,loff_t offset) -{ -struct m25p *flash = nor->priv; - -dev_dbg (nor->dev,"%dKiB at 0x%08x\n" , - flash->spi_nor.mtd.erasesize /1024 , (u32 )offset); - -/* Set up command buffer. */ - flash->command[0 ] = nor->erase_opcode; -m25p_addr2cmd (nor, offset, flash->command); - -spi_write (flash->spi, flash->command,m25p_cmdsz (nor)); - -return 0 ; -} -/* * board specific setup should have ensured the SPI clock used here * matches what the READ command supports, at least until this driver
@@ -194,7 +178,6 @@ static int m25p_probe(struct spi_device *spi)/* install the hooks */ nor->read = m25p80_read; nor->write = m25p80_write; - nor->erase = m25p80_erase; nor->write_reg = m25p80_write_reg; nor->read_reg = m25p80_read_reg;
Signature · 1 line
2.6.0.rc2.230.g3dd15c0
Quoted 4 lines · Brian Norris
Some spi-nor drivers perform sector erase by duplicating their
write_reg()command. Let's not require that the driver fill this out, and provide a default instead.
Quoted 8 lines
Tested on
m25p80.cand Medatek's MT8173 SPI NOR flash driver.Signed-off-by Brian Norris <[email protected]>---
v1 -> v2:
* use statically-sized array, with a check to make sure MAX is big enoughv1: http://lists.infradead.org/pipermail/linux-mtd/2015-October/062916.html
Pushed both to l2-mtd.git