Patchwork [U-Boot,v4,04/14] sf: Update sf to support all sizes of flashes

login
register
mail settings
Submitter Jagannadha Sutradharudu Teki
Date June 13, 2013, 8:55 p.m.
Message ID <767fc8a1-a4af-4150-b4fb-45595d81ecc7@CO9EHSMHS024.ehs.local>
Download mbox | patch
Permalink /patch/251162/
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Comments

Jagannadha Sutradharudu Teki - June 13, 2013, 8:55 p.m.
Updated the spi_flash framework to handle all sizes of flashes
using bank/extd addr reg facility

The current implementation in spi_flash supports 3-byte address mode
due to this up to 16Mbytes amount of flash is able to access for those
flashes which has an actual size of > 16MB.

As most of the flashes introduces a bank/extd address registers
for accessing the flashes in 16Mbytes of banks if the flash size
is > 16Mbytes, this new scheme will add the bank selection feature
for performing write/erase operations on all flashes.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes for v4:
	- none 
Changes for v3:
	- none
Changes for v2:
	- none

 drivers/mtd/spi/spi_flash.c | 39 ++++++++++++++++++++++++++-------------
 1 file changed, 26 insertions(+), 13 deletions(-)

Patch

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index cdd9546..a6c5d83 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -74,11 +74,9 @@  int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
 	unsigned long page_addr, byte_addr, page_size;
 	size_t chunk_len, actual;
 	int ret;
-	u8 cmd[4];
+	u8 cmd[4], bank_sel;
 
 	page_size = flash->page_size;
-	page_addr = offset / page_size;
-	byte_addr = offset % page_size;
 
 	ret = spi_claim_bus(flash->spi);
 	if (ret) {
@@ -88,6 +86,16 @@  int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
 
 	cmd[0] = CMD_PAGE_PROGRAM;
 	for (actual = 0; actual < len; actual += chunk_len) {
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+
+		page_addr = offset / page_size;
+		byte_addr = offset % page_size;
 		chunk_len = min(len - actual, page_size - byte_addr);
 
 		if (flash->spi->max_write_size)
@@ -117,11 +125,7 @@  int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
 		if (ret)
 			break;
 
-		byte_addr += chunk_len;
-		if (byte_addr == page_size) {
-			page_addr++;
-			byte_addr = 0;
-		}
+		offset += chunk_len;
 	}
 
 	spi_release_bus(flash->spi);
@@ -204,9 +208,9 @@  int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout)
 
 int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
 {
-	u32 end, erase_size;
+	u32 erase_size;
 	int ret;
-	u8 cmd[4];
+	u8 cmd[4], bank_sel;
 
 	erase_size = flash->sector_size;
 	if (offset % erase_size || len % erase_size) {
@@ -224,11 +228,17 @@  int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
 		cmd[0] = CMD_ERASE_4K;
 	else
 		cmd[0] = CMD_ERASE_64K;
-	end = offset + len;
 
-	while (offset < end) {
+	while (len) {
+		bank_sel = offset / SPI_FLASH_16MB_BOUN;
+
+		ret = spi_flash_cmd_bankaddr_write(flash, bank_sel);
+		if (ret) {
+			debug("SF: fail to set bank%d\n", bank_sel);
+			return ret;
+		}
+
 		spi_flash_addr(offset, cmd);
-		offset += erase_size;
 
 		debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
 		      cmd[2], cmd[3], offset);
@@ -244,6 +254,9 @@  int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len)
 		ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
 		if (ret)
 			goto out;
+
+		offset += erase_size;
+		len -= erase_size;
 	}
 
  out: