diff mbox

[1/1] mtd: m25p80: Add erase timer to status polling.

Message ID 1262720401-23480-2-git-send-email-andreas.fenkart@streamunlimited.com
State New, archived
Headers show

Commit Message

Andreas Fenkart Jan. 5, 2010, 7:40 p.m. UTC
Signed-off-by: Andreas Fenkart <andreas.fenkart@streamunlimited.com>
---
 drivers/mtd/devices/m25p80.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)
diff mbox

Patch

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index f3f4768..42925cc 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -80,6 +80,9 @@  struct m25p {
 	u16			addr_width;
 	u8			erase_opcode;
 	u8			*command;
+	int			erase_running;
+	unsigned long		erase_start;
+	int			erase_delay;
 };
 
 static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
@@ -159,6 +162,39 @@  static int wait_till_ready(struct m25p *flash)
 
 	deadline = jiffies + MAX_READY_WAIT_JIFFIES;
 
+	if (flash->erase_running) {
+		unsigned long erase_expires;
+		int idle;
+
+		flash->erase_running = 0;
+
+		if (flash->erase_delay < 0)
+			flash->erase_delay = HZ / 4; /* 250 ms */
+
+		erase_expires = flash->erase_start + flash->erase_delay;
+
+		if (time_before(jiffies, erase_expires)) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(erase_expires - jiffies);
+		}
+
+		if (time_before(jiffies, erase_expires + 2)) {
+			sr = read_sr(flash);
+			if (sr < 0)
+				return 1;
+
+			idle = !(sr & SR_WIP);
+			if (idle)
+				/* favor flash latency/throughput over cpu */
+				flash->erase_delay -= HZ / 20; /* 50 ms */
+			else
+				flash->erase_delay += HZ / 100; /* 10 ms */
+
+			if (idle)
+				return 0;
+		}
+	}
+
 	do {
 		if ((sr = read_sr(flash)) < 0)
 			break;
@@ -234,6 +270,8 @@  static int erase_sector(struct m25p *flash, u32 offset)
 	flash->command[0] = flash->erase_opcode;
 	m25p_addr2cmd(flash, offset, flash->command);
 
+	flash->erase_running = 1;
+	flash->erase_start = jiffies;
 	spi_write(flash->spi, flash->command, m25p_cmdsz(flash));
 
 	return 0;
@@ -821,6 +859,7 @@  static int __devinit m25p_probe(struct spi_device *spi)
 	}
 
 	flash->spi = spi;
+	flash->erase_delay = HZ / 4; /* 250 ms */
 	mutex_init(&flash->lock);
 	dev_set_drvdata(&spi->dev, flash);