summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
authorJagannadha Sutradharudu Teki <jaganna@xilinx.com>2013-05-30 20:24:14 +0530
committerJagannadha Sutradharudu Teki <jaganna@xilinx.com>2013-06-23 22:02:50 +0530
commite3ff9d51ecf5fb00eccafa35965112e487f8b522 (patch)
tree75a9861ab24ad1b02afe9e7f88640ff720008a27 /drivers/mtd
parente612ddf5939ba257f2933c7539ee39a3f760e8ce (diff)
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')
-rw-r--r--drivers/mtd/spi/spi_flash.c39
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 64b57ecc71..7f1ef1778c 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: