Skip to contentSkip to conversation

drivers/mtd/devices/m25p80.c: Fix whole device erase

PATCH In review Cédric Cano 2 participants 3 messages Sep 4, 2012 – Sep 21, 2012 Memory technology devices (MTD)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 drivers/mtd/devices/m25p80.c: Fix whole device erase

From: Cédric Cano<[email protected]>

There are two ways to erase SPI Flash devices: sector per sector or the entire Flash (used when MTD partition is the whole Flash).

When the whole Flash is erased, the SPI command is sent to the device and the erase function exits. Then, when another access (read, write or erase) is done, a wait of busy is performed that fails because of Flash erase time (can be more than 30s in case of whole erase).

This patch removes chip erase and use only sector per sector erase to erase the chip. When erase is performed, Flash accesses can be done.

C. Cano

---
 drivers/mtd/devices/m25p80.c |   50 +++++-------------------------------------
 1 file changed, 5 insertions(+), 45 deletions(-)
drivers/mtd/devices/m25p80.c +5 -45
index 5257345..b8956df 100644
@@ -202,31 +202,6 @@ static int wait_till_ready(struct m25p *flash)
 	return 1;
 }
 
-/*
- * Erase the whole flash memory
- *
- * Returns 0 if successful, non-zero otherwise.
- */
-static int erase_chip(struct m25p *flash)
-{
-	pr_debug("%s: %s %lldKiB\n", dev_name(&flash->spi->dev), __func__,
-			(long long)(flash->mtd.size >> 10));
-
-	/* Wait until finished previous write command. */
-	if (wait_till_ready(flash))
-		return 1;
-
-	/* Send write enable, then erase commands. */
-	write_enable(flash);
-
-	/* Set up command buffer. */
-	flash->command[0] = OPCODE_CHIP_ERASE;
-
-	spi_write(flash->spi, flash->command, 1);
-
-	return 0;
-}
-
 static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
 {
 	/* opcode is in cmd[0] */
@@ -297,31 +272,16 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 	mutex_lock(&flash->lock);
 
-	/* whole-chip erase? */
-	if (len == flash->mtd.size) {
-		if (erase_chip(flash)) {
+	/* "sector"-at-a-time erase */
+	while (len) {
+		if (erase_sector(flash, addr)) {
 			instr->state = MTD_ERASE_FAILED;
 			mutex_unlock(&flash->lock);
 			return -EIO;
 		}
 
-	/* REVISIT in some cases we could speed up erasing large regions
-	 * by using OPCODE_SE instead of OPCODE_BE_4K.  We may have set up
-	 * to use "small sector erase", but that's not always optimal.
-	 */
-
-	/* "sector"-at-a-time erase */
-	} else {
-		while (len) {
-			if (erase_sector(flash, addr)) {
-				instr->state = MTD_ERASE_FAILED;
-				mutex_unlock(&flash->lock);
-				return -EIO;
-			}
-
-			addr += mtd->erasesize;
-			len -= mtd->erasesize;
-		}
+		addr += mtd->erasesize;
+		len -= mtd->erasesize;
 	}
 
 	mutex_unlock(&flash->lock);
#1 lore raw

PATCH 1/1 drivers/mtd/devices/m25p80.c: Fix whole device erase

From: Cédric Cano<[email protected]>

When the whole SPI Flash is erased, the chip erase command is sent to the device without waiting for end of erase. So next read/write accesses are in failure.

This patch removes chip erase to use only sector per sector erase for whole Flash too. When chip erase is done, Flash can be accessed without error.

C. Cano

---
 drivers/mtd/devices/m25p80.c |   50 +++++-------------------------------------
 1 file changed, 5 insertions(+), 45 deletions(-)
drivers/mtd/devices/m25p80.c +5 -45
index 5257345..b8956df 100644
@@ -202,31 +202,6 @@ static int wait_till_ready(struct m25p *flash)
 	return 1;
 }
 
-/*
- * Erase the whole flash memory
- *
- * Returns 0 if successful, non-zero otherwise.
- */
-static int erase_chip(struct m25p *flash)
-{
-	pr_debug("%s: %s %lldKiB\n", dev_name(&flash->spi->dev), __func__,
-			(long long)(flash->mtd.size >> 10));
-
-	/* Wait until finished previous write command. */
-	if (wait_till_ready(flash))
-		return 1;
-
-	/* Send write enable, then erase commands. */
-	write_enable(flash);
-
-	/* Set up command buffer. */
-	flash->command[0] = OPCODE_CHIP_ERASE;
-
-	spi_write(flash->spi, flash->command, 1);
-
-	return 0;
-}
-
 static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
 {
 	/* opcode is in cmd[0] */
@@ -297,31 +272,16 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 	mutex_lock(&flash->lock);
 
-	/* whole-chip erase? */
-	if (len == flash->mtd.size) {
-		if (erase_chip(flash)) {
+	/* "sector"-at-a-time erase */
+	while (len) {
+		if (erase_sector(flash, addr)) {
 			instr->state = MTD_ERASE_FAILED;
 			mutex_unlock(&flash->lock);
 			return -EIO;
 		}
 
-	/* REVISIT in some cases we could speed up erasing large regions
-	 * by using OPCODE_SE instead of OPCODE_BE_4K.  We may have set up
-	 * to use "small sector erase", but that's not always optimal.
-	 */
-
-	/* "sector"-at-a-time erase */
-	} else {
-		while (len) {
-			if (erase_sector(flash, addr)) {
-				instr->state = MTD_ERASE_FAILED;
-				mutex_unlock(&flash->lock);
-				return -EIO;
-			}
-
-			addr += mtd->erasesize;
-			len -= mtd->erasesize;
-		}
+		addr += mtd->erasesize;
+		len -= mtd->erasesize;
 	}
 
 	mutex_unlock(&flash->lock);
#2 lore raw
Quoted 5 lines · Cédric Cano

From: Cédric Cano<[email protected]>

When the whole SPI Flash is erased, the chip erase command is sent to the device without waiting for end of erase. So next read/write accesses are in failure.

Can you wait while the chip erase to finish?

Quoted 3 lines

This patch removes chip erase to use only sector per sector erase for whole Flash too. When chip erase is done, Flash can be accessed without error.

How much slower is this method?

Signature · 2 lines
Best Regards,
Artem Bityutskiy