diff options
| author | Jagannadha Sutradharudu Teki <jaganna@xilinx.com> | 2013-05-30 20:24:14 +0530 | 
|---|---|---|
| committer | Jagannadha Sutradharudu Teki <jaganna@xilinx.com> | 2013-06-23 22:02:50 +0530 | 
| commit | e3ff9d51ecf5fb00eccafa35965112e487f8b522 (patch) | |
| tree | 75a9861ab24ad1b02afe9e7f88640ff720008a27 /drivers/mtd/spi/spi_flash.c | |
| parent | e612ddf5939ba257f2933c7539ee39a3f760e8ce (diff) | |
| download | olio-uboot-2014.01-e3ff9d51ecf5fb00eccafa35965112e487f8b522.tar.xz olio-uboot-2014.01-e3ff9d51ecf5fb00eccafa35965112e487f8b522.zip | |
sf: Update sf to support all sizes of flashes
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>
Diffstat (limited to 'drivers/mtd/spi/spi_flash.c')
| -rw-r--r-- | drivers/mtd/spi/spi_flash.c | 39 | 
1 files changed, 26 insertions, 13 deletions
| diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 64b57ecc7..7f1ef1778 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: |