From a8c8c238f2dd1abe102f83bfa392ac40f313dd73 Mon Sep 17 00:00:00 2001
From: Fredrik Hederstierna <fredrik.hederstierna@securitas-direct.com>
Date: Thu, 12 Aug 2010 08:53:29 +0200
Subject: str9x: faster flash erase of entire chip

The patch improves flash erase for STR9x in case of a full bank erase.
Then the chip erase command is used instead which improves speed significantly.

Also I think it might help if e.g. STR912 enters some state where flash banks are locked, and a chip erase command is the key for unlocking the flash.
---
 src/flash/nor/str9x.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

(limited to 'src')

diff --git a/src/flash/nor/str9x.c b/src/flash/nor/str9x.c
index 528e52e2..cfe6a777 100644
--- a/src/flash/nor/str9x.c
+++ b/src/flash/nor/str9x.c
@@ -223,6 +223,7 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
 	uint32_t adr;
 	uint8_t status;
 	uint8_t erase_cmd;
+	int total_timeout;
 
 	if (bank->target->state != TARGET_HALTED)
 	{
@@ -230,16 +231,27 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
 		return ERROR_TARGET_NOT_HALTED;
 	}
 
-	/*A slower but stable way of erasing*/
-	/* Erase sector command */
-	erase_cmd = 0x20;
+	/* Check if we can erase whole bank */
+	if ((first == 0) && (last == (bank->num_sectors - 1)))
+	{
+		/* Optimize to run erase bank command instead of sector */
+		erase_cmd = 0x80;
+                /* Add timeout duration since erase bank takes more time */
+		total_timeout = 1000 * bank->num_sectors;
+	}
+	else
+	{
+		/* Erase sector command */
+		erase_cmd = 0x20;
+		total_timeout = 1000;
+	}
 
 	for (i = first; i <= last; i++)
 	{
 		int retval;
 		adr = bank->base + bank->sectors[i].offset;
 
-		/* erase sectors */
+		/* erase sectors or block */
 		if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK)
 		{
 			return retval;
@@ -256,7 +268,8 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
 		}
 
 		int timeout;
-		for (timeout = 0; timeout < 1000; timeout++) {
+		for (timeout = 0; timeout < total_timeout; timeout++) 
+		{
 			if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK)
 			{
 				return retval;
@@ -265,7 +278,7 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
 				break;
 			alive_sleep(1);
 		}
-		if (timeout == 1000)
+		if (timeout == total_timeout)
 		{
 			LOG_ERROR("erase timed out");
 			return ERROR_FAIL;
@@ -288,6 +301,10 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
 			LOG_ERROR("error erasing flash bank, status: 0x%x", status);
 			return ERROR_FLASH_OPERATION_FAILED;
 		}
+
+		/* If we ran erase bank command, we are finished */
+		if (erase_cmd == 0x80)
+			break;
 	}
 
 	for (i = first; i <= last; i++)
-- 
cgit v1.2.3