From 6fd10002249580966ba59d60cc6893341cdaf826 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 14 Jun 2013 21:03:51 +0530 Subject: sf: spansion: Correct name of S25FL128S 64K Sector part Corrected the name of S25FL128S 64K sector part SPI flash, S25FL128S supported has been added in below commit "sf: spansion: Add support for S25FL128S" (sha1: 1bfb9f156aa66cca6bb9c773867a1f02a84b14be) Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/spansion.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index b3ef90f..dad4fbb 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -101,7 +101,7 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { .idcode2 = 0x4d01, .pages_per_sector = 256, .nr_sectors = 256, - .name = "S25FL129P_64K/S25FL128S", + .name = "S25FL129P_64K/S25FL128S_64K", }, { .idcode1 = 0x0219, -- cgit v1.1 From e9fd312088c73388155814cb2326426cbb0d241b Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 28 May 2013 00:41:58 +0530 Subject: sf: winbond: Update the names for W25Q 0x40XX ID's flash parts Use the exact names for W25Q 0x40XX ID's flash parts, as the same sizes of flashes comes with different ID's. so-that the distinguishes becomes easy with this change. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/winbond.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 8457808..3c0ca88 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -55,27 +55,27 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { { .id = 0x4014, .nr_blocks = 16, - .name = "W25Q80BL", + .name = "W25Q80BL/W25Q80BV", }, { .id = 0x4015, .nr_blocks = 32, - .name = "W25Q16", + .name = "W25Q16CL/W25Q16DV", }, { .id = 0x4016, .nr_blocks = 64, - .name = "W25Q32", + .name = "W25Q32BV", }, { .id = 0x4017, .nr_blocks = 128, - .name = "W25Q64", + .name = "W25Q64CV", }, { .id = 0x4018, .nr_blocks = 256, - .name = "W25Q128", + .name = "W25Q128BV", }, { .id = 0x4019, -- cgit v1.1 From 920559f19ef9acb902aa619271b81ecdaba7f723 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 28 May 2013 00:49:26 +0530 Subject: sf: winbond: Add support for W25Q128FW Add support for Winbond W25Q128FW SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/winbond.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 3c0ca88..e07480b 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -97,6 +97,11 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { .nr_blocks = 128, .name = "W25Q64DW", }, + { + .id = 0x6018, + .nr_blocks = 256, + .name = "W25Q128FW", + }, }; struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) -- cgit v1.1 From f0293fb59513d1d63be8c436594fad743fe47fc0 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 28 May 2013 00:55:00 +0530 Subject: sf: winbond: Add support for W25Q16DW Add support for Winbond W25Q16DW SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/winbond.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index e07480b..9fb4910 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -88,6 +88,11 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { .name = "W25Q80BW", }, { + .id = 0x6015, + .nr_blocks = 32, + .name = "W25Q16DW", + }, + { .id = 0x6016, .nr_blocks = 64, .name = "W25Q32DW", -- cgit v1.1 From 1e77deec6ee81e5a435057910651599a8afb9d6b Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Thu, 30 May 2013 16:34:19 +0530 Subject: sf: winbond: Add support for W25QXXXFV Add support for Winbond W25QXXXFV SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/winbond.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 9fb4910..c399bf1 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -65,17 +65,17 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { { .id = 0x4016, .nr_blocks = 64, - .name = "W25Q32BV", + .name = "W25Q32BV/W25Q32FV_SPI", }, { .id = 0x4017, .nr_blocks = 128, - .name = "W25Q64CV", + .name = "W25Q64CV/W25Q64FV_SPI", }, { .id = 0x4018, .nr_blocks = 256, - .name = "W25Q128BV", + .name = "W25Q128BV/W25Q128FV_SPI", }, { .id = 0x4019, @@ -95,17 +95,17 @@ static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { { .id = 0x6016, .nr_blocks = 64, - .name = "W25Q32DW", + .name = "W25Q32DW/W25Q32FV_QPI", }, { .id = 0x6017, .nr_blocks = 128, - .name = "W25Q64DW", + .name = "W25Q64DW/W25Q64FV_QPI", }, { .id = 0x6018, .nr_blocks = 256, - .name = "W25Q128FW", + .name = "W25Q128FW/W25Q128FV_QPI", }, }; -- cgit v1.1 From 0cb8394f8198f5b420a52b6a6f76c9bf21e68b2e Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 14 Jun 2013 21:12:19 +0800 Subject: spi: cf_qspi: Use DIV_ROUND_UP at appropriate place This change slightly improves readability. Signed-off-by: Axel Lin Signed-off-by: Richard Retanubun Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/spi/cf_qspi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/cf_qspi.c b/drivers/spi/cf_qspi.c index a37ac4e..06bcf91 100644 --- a/drivers/spi/cf_qspi.c +++ b/drivers/spi/cf_qspi.c @@ -171,7 +171,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, volatile qspi_t *qspi = dev->regs; u8 *txbuf = (u8 *)dout; u8 *rxbuf = (u8 *)din; - u32 count = ((bitlen / 8) + (bitlen % 8 ? 1 : 0)); + u32 count = DIV_ROUND_UP(bitlen, 8); u32 n, i = 0; /* Sanitize arguments */ -- cgit v1.1 From 9675fed4742338c71678cd310d0d6922b56e490a Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 14 Jun 2013 21:13:32 +0800 Subject: spi: mxc_spi: Use DIV_ROUND_UP at appropriate places This change slightly improves readability. Signed-off-by: Axel Lin Reviewed-by: Jagannadha Sutradharudu Teki --- drivers/spi/mxc_spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c index 5bed858..2ea3228 100644 --- a/drivers/spi/mxc_spi.c +++ b/drivers/spi/mxc_spi.c @@ -224,7 +224,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen, const u8 *dout, u8 *din, unsigned long flags) { struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave); - int nbytes = (bitlen + 7) / 8; + int nbytes = DIV_ROUND_UP(bitlen, 8); u32 data, cnt, i; struct cspi_regs *regs = (struct cspi_regs *)mxcs->base; @@ -294,7 +294,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen, /* Transfer completed, clear any pending request */ reg_write(®s->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF); - nbytes = (bitlen + 7) / 8; + nbytes = DIV_ROUND_UP(bitlen, 8); cnt = nbytes % 32; @@ -330,7 +330,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen, int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { - int n_bytes = (bitlen + 7) / 8; + int n_bytes = DIV_ROUND_UP(bitlen, 8); int n_bits; int ret; u32 blk_size; -- cgit v1.1 From c9fcb59d7db74b93df9ee0a830bb9f43888f195c Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Thu, 13 Jun 2013 20:37:19 +0530 Subject: sf: Add bank address register writing support This patch provides support to program a flash bank address register. extended/bank address register contains an information to access the 4th byte addressing in 3-byte address mode. reff' the spec for more details about bank addr register in Page-63, Table 8.16 http://www.spansion.com/Support/Datasheets/S25FL128S_256S_00.pdf Signed-off-by: Jagannadha Sutradharudu Teki Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 26 ++++++++++++++++++++++++++ drivers/mtd/spi/spi_flash_internal.h | 3 +++ 2 files changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 0e38f59..9ddd070 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -278,6 +278,32 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) return 0; } +int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) +{ + u8 cmd; + int ret; + + ret = spi_flash_cmd_write_enable(flash); + if (ret < 0) { + debug("SF: enabling write failed\n"); + return ret; + } + + ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &bank_sel, 1); + if (ret) { + debug("SF: fail to write bank addr register\n"); + return ret; + } + + ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret < 0) { + debug("SF: write bank addr register timed out\n"); + return ret; + } + + return 0; +} + #ifdef CONFIG_OF_CONTROL int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) { diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 141cfa8..772fef6 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -77,6 +77,9 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) /* Program the status register. */ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); +/* Program the bank address register */ +int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel); + /* * Same as spi_flash_cmd_read() except it also claims/releases the SPI * bus. Used as common part of the ->read() operation. -- cgit v1.1 From cf6b11dcda2f13d1c05c2f20e2a1735a833a41fe Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Wed, 19 Jun 2013 15:31:23 +0530 Subject: sf: Discover the bank addr commands Bank/Extended addr commands are specific to particular flash vendor so discover them based on the idocode0. Assign the discovered bank commands to spi_flash members so-that the bank read/write will use their specific operations. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/spi_flash.c | 21 +++++++++++++++++++++ drivers/mtd/spi/spi_flash_internal.h | 14 ++++++++++++++ 2 files changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 9ddd070..7e19953 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -304,6 +304,27 @@ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) return 0; } +int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0) +{ + /* discover bank cmds */ + switch (idcode0) { + case SPI_FLASH_SPANSION_IDCODE0: + flash->bank_read_cmd = CMD_BANKADDR_BRRD; + flash->bank_write_cmd = CMD_BANKADDR_BRWR; + break; + case SPI_FLASH_STMICRO_IDCODE0: + case SPI_FLASH_WINBOND_IDCODE0: + flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; + flash->bank_write_cmd = CMD_EXTNADDR_WREAR; + break; + default: + printf("SF: Unsupported bank commands %02x\n", idcode0); + return -1; + } + + return 0; +} + #ifdef CONFIG_OF_CONTROL int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) { diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 772fef6..db6c444 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -28,6 +28,17 @@ #define CMD_ERASE_64K 0xd8 #define CMD_ERASE_CHIP 0xc7 +/* Manufacture ID's */ +#define SPI_FLASH_SPANSION_IDCODE0 0x01 +#define SPI_FLASH_STMICRO_IDCODE0 0x20 +#define SPI_FLASH_WINBOND_IDCODE0 0xef + +/* Bank addr access commands */ +#define CMD_BANKADDR_BRWR 0x17 +#define CMD_BANKADDR_BRRD 0x16 +#define CMD_EXTNADDR_WREAR 0xC5 +#define CMD_EXTNADDR_RDEAR 0xC8 + /* Common status */ #define STATUS_WIP 0x01 @@ -80,6 +91,9 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); /* Program the bank address register */ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel); +/* Configure the BAR - discover the bank cmds */ +int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0); + /* * Same as spi_flash_cmd_read() except it also claims/releases the SPI * bus. Used as common part of the ->read() operation. -- cgit v1.1 From e612ddf5939ba257f2933c7539ee39a3f760e8ce Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Wed, 19 Jun 2013 15:37:09 +0530 Subject: sf: Read flash bank addr register at probe time Read the flash bank addr register to get the state of bank in a perticular flash. and also bank write happens only when there is a change in bank selection from user. bank read only valid for flashes which has > 16Mbytes those are opearted in 3-byte addr mode, each bank occupies 16Mytes. Suppose if the flash has 64Mbytes size consists of 4 banks like bank0, bank1, bank2 and bank3. Signed-off-by: Jagannadha Sutradharudu Teki Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 27 +++++++++++++++++++++++++++ drivers/mtd/spi/spi_flash_internal.h | 2 ++ 2 files changed, 29 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 7e19953..64b57ec 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -283,6 +283,12 @@ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) u8 cmd; int ret; + if (flash->bank_curr == bank_sel) { + debug("SF: not require to enable bank%d\n", bank_sel); + return 0; + } + + cmd = flash->bank_write_cmd; ret = spi_flash_cmd_write_enable(flash); if (ret < 0) { debug("SF: enabling write failed\n"); @@ -294,6 +300,7 @@ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) debug("SF: fail to write bank addr register\n"); return ret; } + flash->bank_curr = bank_sel; ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); if (ret < 0) { @@ -306,6 +313,9 @@ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0) { + u8 cmd; + u8 curr_bank = 0; + /* discover bank cmds */ switch (idcode0) { case SPI_FLASH_SPANSION_IDCODE0: @@ -322,6 +332,18 @@ int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0) return -1; } + /* read the bank reg - on which bank the flash is in currently */ + cmd = flash->bank_read_cmd; + if (flash->size > SPI_FLASH_16MB_BOUN) { + if (spi_flash_read_common(flash, &cmd, 1, &curr_bank, 1)) { + debug("SF: fail to read bank addr register\n"); + return -1; + } + flash->bank_curr = curr_bank; + } else { + flash->bank_curr = curr_bank; + } + return 0; } @@ -469,6 +491,11 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; } + /* Configure the BAR - disover bank cmds and read current bank */ + ret = spi_flash_bank_config(flash, *idp); + if (ret < 0) + goto err_manufacturer_probe; + #ifdef CONFIG_OF_CONTROL if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { debug("SF: FDT decode error\n"); diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index db6c444..00ed1ee 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -28,6 +28,8 @@ #define CMD_ERASE_64K 0xd8 #define CMD_ERASE_CHIP 0xc7 +#define SPI_FLASH_16MB_BOUN 0x1000000 + /* Manufacture ID's */ #define SPI_FLASH_SPANSION_IDCODE0 0x01 #define SPI_FLASH_STMICRO_IDCODE0 0x20 -- cgit v1.1 From e3ff9d51ecf5fb00eccafa35965112e487f8b522 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Thu, 30 May 2013 20:24:14 +0530 Subject: 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 Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 64b57ec..7f1ef17 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: -- cgit v1.1 From fc207ee4db20ef6e769b0d08dab8b102748acb35 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 31 May 2013 16:00:36 +0530 Subject: sf: Update sf read to support all sizes of flashes This patch updated the spi_flash read func to support all sizes of flashes using bank reg addr facility. The same support has been added in below patch for erase/write spi_flash functions: "sf: Support all sizes of flashes using bank addr reg facility" (sha1: c956f600cbb0943d0afe1004cdb503f4fcd8f415) With these new updates on sf framework, the flashes which has < 16MB are not effected as per as performance is concern and but the u-boot.bin size incrased ~460 bytes. sf update(for first 16MBytes), Changes before: U-Boot> sf update 0x1000000 0x0 0x1000000 - N25Q256 16777216 bytes written, 0 bytes skipped in 199.72s, speed 86480 B/s - W25Q128BV 16777216 bytes written, 0 bytes skipped in 351.739s, speed 48913 B/s - S25FL256S_64K 16777216 bytes written, 0 bytes skipped in 65.659s, speed 262144 B/s sf update(for first 16MBytes), Changes before: U-Boot> sf update 0x1000000 0x0 0x1000000 - N25Q256 16777216 bytes written, 0 bytes skipped in 198.953s, speed 86480 B/s - W25Q128BV 16777216 bytes written, 0 bytes skipped in 350.90s, speed 49200 B/s - S25FL256S_64K 16777216 bytes written, 0 bytes skipped in 66.521s, speed 262144 B/s Signed-off-by: Jagannadha Sutradharudu Teki Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 7f1ef17..562f6ad 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -148,7 +148,9 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, size_t len, void *data) { - u8 cmd[5]; + u8 cmd[5], bank_sel; + u32 remain_len, read_len; + int ret = -1; /* Handle memory-mapped SPI */ if (flash->memory_map) { @@ -157,10 +159,38 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, } cmd[0] = CMD_READ_ARRAY_FAST; - spi_flash_addr(offset, cmd); cmd[4] = 0x00; - return spi_flash_read_common(flash, cmd, sizeof(cmd), data, len); + 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; + } + + remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset); + if (len < remain_len) + read_len = len; + else + read_len = remain_len; + + spi_flash_addr(offset, cmd); + + ret = spi_flash_read_common(flash, cmd, sizeof(cmd), + data, read_len); + if (ret < 0) { + debug("SF: read failed\n"); + break; + } + + offset += read_len; + len -= read_len; + data += read_len; + } + + return ret; } int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, -- cgit v1.1 From 1dcd6d03811d4f30052a5e24377b378867211b05 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Wed, 19 Jun 2013 15:33:58 +0530 Subject: sf: Add bank addr code in CONFIG_SPI_FLASH_BAR Defined bank addr code on CONFIG_SPI_FLASH_BAR macro, to reduce the size for existing boards which has < 16Mbytes SPI flashes. It's upto user which has provision to use the bank addr code for flashes which has > 16Mbytes. Signed-off-by: Jagannadha Sutradharudu Teki Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 23 +++++++++++++++++------ drivers/mtd/spi/spi_flash_internal.h | 12 ++++++++---- 2 files changed, 25 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 562f6ad..f05f8f4 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -74,7 +74,7 @@ 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], bank_sel; + u8 cmd[4]; page_size = flash->page_size; @@ -86,6 +86,9 @@ 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) { +#ifdef CONFIG_SPI_FLASH_BAR + u8 bank_sel; + bank_sel = offset / SPI_FLASH_16MB_BOUN; ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); @@ -93,7 +96,7 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, debug("SF: fail to set bank%d\n", bank_sel); return ret; } - +#endif page_addr = offset / page_size; byte_addr = offset % page_size; chunk_len = min(len - actual, page_size - byte_addr); @@ -148,7 +151,7 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, size_t len, void *data) { - u8 cmd[5], bank_sel; + u8 cmd[5], bank_sel = 0; u32 remain_len, read_len; int ret = -1; @@ -162,6 +165,7 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, cmd[4] = 0x00; while (len) { +#ifdef CONFIG_SPI_FLASH_BAR bank_sel = offset / SPI_FLASH_16MB_BOUN; ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); @@ -169,7 +173,7 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, debug("SF: fail to set bank%d\n", bank_sel); return ret; } - +#endif remain_len = (SPI_FLASH_16MB_BOUN * (bank_sel + 1) - offset); if (len < remain_len) read_len = len; @@ -240,7 +244,7 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) { u32 erase_size; int ret; - u8 cmd[4], bank_sel; + u8 cmd[4]; erase_size = flash->sector_size; if (offset % erase_size || len % erase_size) { @@ -260,6 +264,9 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) cmd[0] = CMD_ERASE_64K; while (len) { +#ifdef CONFIG_SPI_FLASH_BAR + u8 bank_sel; + bank_sel = offset / SPI_FLASH_16MB_BOUN; ret = spi_flash_cmd_bankaddr_write(flash, bank_sel); @@ -267,7 +274,7 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) debug("SF: fail to set bank%d\n", bank_sel); return ret; } - +#endif spi_flash_addr(offset, cmd); debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], @@ -321,6 +328,7 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) return 0; } +#ifdef CONFIG_SPI_FLASH_BAR int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) { u8 cmd; @@ -389,6 +397,7 @@ int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0) return 0; } +#endif #ifdef CONFIG_OF_CONTROL int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) @@ -534,10 +543,12 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, goto err_manufacturer_probe; } +#ifdef CONFIG_SPI_FLASH_BAR /* Configure the BAR - disover bank cmds and read current bank */ ret = spi_flash_bank_config(flash, *idp); if (ret < 0) goto err_manufacturer_probe; +#endif #ifdef CONFIG_OF_CONTROL if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 00ed1ee..e613ef3 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -35,11 +35,13 @@ #define SPI_FLASH_STMICRO_IDCODE0 0x20 #define SPI_FLASH_WINBOND_IDCODE0 0xef +#ifdef CONFIG_SPI_FLASH_BAR /* Bank addr access commands */ -#define CMD_BANKADDR_BRWR 0x17 -#define CMD_BANKADDR_BRRD 0x16 -#define CMD_EXTNADDR_WREAR 0xC5 -#define CMD_EXTNADDR_RDEAR 0xC8 +# define CMD_BANKADDR_BRWR 0x17 +# define CMD_BANKADDR_BRRD 0x16 +# define CMD_EXTNADDR_WREAR 0xC5 +# define CMD_EXTNADDR_RDEAR 0xC8 +#endif /* Common status */ #define STATUS_WIP 0x01 @@ -90,11 +92,13 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) /* Program the status register. */ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); +#ifdef CONFIG_SPI_FLASH_BAR /* Program the bank address register */ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel); /* Configure the BAR - discover the bank cmds */ int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0); +#endif /* * Same as spi_flash_cmd_read() except it also claims/releases the SPI -- cgit v1.1 From f76b1bd08b00bec89cace4da97eab8c8d89a74c2 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 11 Jun 2013 21:36:20 +0530 Subject: sf: Use spi_flash_addr() in write call Use the existing spi_flash_addr() for 3-byte addressing cmd filling in write call. Signed-off-by: Jagannadha Sutradharudu Teki Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index f05f8f4..0ed2295 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -71,7 +71,7 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { - unsigned long page_addr, byte_addr, page_size; + unsigned long byte_addr, page_size; size_t chunk_len, actual; int ret; u8 cmd[4]; @@ -97,16 +97,13 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, return ret; } #endif - 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) chunk_len = min(chunk_len, flash->spi->max_write_size); - cmd[1] = page_addr >> 8; - cmd[2] = page_addr; - cmd[3] = byte_addr; + spi_flash_addr(offset, cmd); debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); -- cgit v1.1 From 0569f3b9be46cf3fa34232b903236a0893793ee6 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 16 Apr 2013 20:18:29 +0530 Subject: sf: stmicro: Add support for N25Q512 Add support for Numonyx N25Q512 SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/stmicro.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 2a9972b..e9adfa5 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -140,6 +140,12 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = { .nr_sectors = 512, .name = "N25Q256A", }, + { + .id = 0xba20, + .pages_per_sector = 256, + .nr_sectors = 1024, + .name = "N25Q512", + }, }; struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) -- cgit v1.1 From fd60c0ac31cbd9c76744cb34562f32d2a13fbe44 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 16 Apr 2013 20:20:12 +0530 Subject: sf: stmicro: Add support for N25Q512A Add support for Numonyx N25Q512A SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/stmicro.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index e9adfa5..bf61a37 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -146,6 +146,12 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = { .nr_sectors = 1024, .name = "N25Q512", }, + { + .id = 0xbb20, + .pages_per_sector = 256, + .nr_sectors = 1024, + .name = "N25Q512A", + }, }; struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) -- cgit v1.1 From 221cb084ad24961c5fc3b9e0c0d06bbd83c3ac5e Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 16 Apr 2013 20:22:48 +0530 Subject: sf: stmicro: Add support for N25Q1024 Add support for Numonyx N25Q1024 SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/stmicro.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index bf61a37..cac1013 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -152,6 +152,12 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = { .nr_sectors = 1024, .name = "N25Q512A", }, + { + .id = 0xba21, + .pages_per_sector = 256, + .nr_sectors = 2048, + .name = "N25Q1024", + }, }; struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) -- cgit v1.1 From 4e2904311d2507b6b01c8418d7c28cd0c58ff30d Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Tue, 16 Apr 2013 20:23:48 +0530 Subject: sf: stmicro: Add support for N25Q1024A Add support for Numonyx N25Q1024A SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/stmicro.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index cac1013..ef4b911 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -158,6 +158,12 @@ static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = { .nr_sectors = 2048, .name = "N25Q1024", }, + { + .id = 0xbb21, + .pages_per_sector = 256, + .nr_sectors = 2048, + .name = "N25Q1024A", + }, }; struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) -- cgit v1.1 From 76e98d48179c60f2fc06ac90d41de060c9d5b42d Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Mon, 10 Jun 2013 23:41:57 +0530 Subject: sf: spansion: Add support for S25FL512S_64K Add support for Spansion S25FL512S_64K SPI flash. Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/spansion.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index dad4fbb..3ec2151 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -110,6 +110,13 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { .nr_sectors = 512, .name = "S25FL256S_64K", }, + { + .idcode1 = 0x0220, + .idcode2 = 0x4d01, + .pages_per_sector = 256, + .nr_sectors = 1024, + .name = "S25FL512S_64K", + }, }; struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) -- cgit v1.1 From ba549de6c53663e534a20741f9ec917fb6526830 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Sun, 26 May 2013 23:37:11 +0530 Subject: sf: Remove spi_flash_cmd_poll_bit() There is no other call other than spi_flash_cmd_wait_ready(), hence removed spi_flash_cmd_poll_bit and use the poll status code spi_flash_cmd_wait_ready() itself. Signed-off-by: Jagannadha Sutradharudu Teki Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 11 +++-------- drivers/mtd/spi/spi_flash_internal.h | 4 ---- 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 0ed2295..cca02d1 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -194,13 +194,14 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, return ret; } -int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, - u8 cmd, u8 poll_bit) +int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) { struct spi_slave *spi = flash->spi; unsigned long timebase; int ret; u8 status; + u8 poll_bit = STATUS_WIP; + u8 cmd = CMD_READ_STATUS; ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); if (ret) { @@ -231,12 +232,6 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, return -1; } -int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ - return spi_flash_cmd_poll_bit(flash, timeout, - CMD_READ_STATUS, STATUS_WIP); -} - int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) { u32 erase_size; diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index e613ef3..e9b85bf 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -107,10 +107,6 @@ int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0); int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, void *data, size_t data_len); -/* Send a command to the device and wait for some bit to clear itself. */ -int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, - u8 cmd, u8 poll_bit); - /* * Send the read status command to the device and wait for the wip * (write-in-progress) bit to clear itself. -- cgit v1.1 From 615a1561673a9a1b863f905d40f084f36edb9022 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 21 Jun 2013 15:56:30 +0530 Subject: sf: Add flag status register polling support Flag status register polling is required for micron 512Mb flash devices onwards, for performing erase/program operations. Like polling for WIP(Write-In-Progress) bit in read status register, spi_flash_cmd_wait_ready will poll for PEC(Program-Erase-Control) bit in flag status register. Signed-off-by: Jagannadha Sutradharudu Teki Reviewed-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 16 ++++++++++++---- drivers/mtd/spi/spi_flash_internal.h | 2 ++ drivers/mtd/spi/stmicro.c | 4 ++++ 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index cca02d1..6ce82c1 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -200,12 +200,19 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) unsigned long timebase; int ret; u8 status; + u8 check_status = 0x0; u8 poll_bit = STATUS_WIP; - u8 cmd = CMD_READ_STATUS; + u8 cmd = flash->poll_cmd; + + if (cmd == CMD_FLAG_STATUS) { + poll_bit = STATUS_PEC; + check_status = poll_bit; + } ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); if (ret) { - debug("SF: Failed to send command %02x: %d\n", cmd, ret); + debug("SF: fail to read %s status register\n", + cmd == CMD_READ_STATUS ? "read" : "flag"); return ret; } @@ -217,14 +224,14 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) if (ret) return -1; - if ((status & poll_bit) == 0) + if ((status & poll_bit) == check_status) break; } while (get_timer(timebase) < timeout); spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - if ((status & poll_bit) == 0) + if ((status & poll_bit) == check_status) return 0; /* Timed out */ @@ -584,6 +591,7 @@ void *spi_flash_do_alloc(int offset, int size, struct spi_slave *spi, /* Set up some basic fields - caller will sort out sizes */ flash->spi = spi; flash->name = name; + flash->poll_cmd = CMD_READ_STATUS; flash->read = spi_flash_cmd_read_fast; flash->write = spi_flash_cmd_write_multi; diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index e9b85bf..8147f27 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -22,6 +22,7 @@ #define CMD_PAGE_PROGRAM 0x02 #define CMD_WRITE_DISABLE 0x04 #define CMD_READ_STATUS 0x05 +#define CMD_FLAG_STATUS 0x70 #define CMD_WRITE_ENABLE 0x06 #define CMD_ERASE_4K 0x20 #define CMD_ERASE_32K 0x52 @@ -45,6 +46,7 @@ /* Common status */ #define STATUS_WIP 0x01 +#define STATUS_PEC 0x80 /* Send a single-byte command to the device and read the response */ int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len); diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index ef4b911..7e41ee1 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -210,5 +210,9 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; + /* for >= 512MiB flashes, use flag status instead of read_status */ + if (flash->size >= 0x4000000) + flash->poll_cmd = CMD_FLAG_STATUS; + return flash; } -- cgit v1.1 From acc237544a0a6b5ebfd41fccf12a7731db209959 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 21 Jun 2013 19:19:00 +0530 Subject: sf: Unify spi_flash write code Move common flash write code into spi_flash_write_common(). Signed-off-by: Jagannadha Sutradharudu Teki Acked-by: Simon Glass --- drivers/mtd/spi/spi_flash.c | 120 ++++++++++++++++------------------- drivers/mtd/spi/spi_flash_internal.h | 10 +++ 2 files changed, 63 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 6ce82c1..03cecef 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -68,15 +68,15 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len); } -int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, - size_t len, const void *buf) +int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, + size_t cmd_len, const void *buf, size_t buf_len) { - unsigned long byte_addr, page_size; - size_t chunk_len, actual; + struct spi_slave *spi = flash->spi; + unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; int ret; - u8 cmd[4]; - page_size = flash->page_size; + if (buf == NULL) + timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; ret = spi_claim_bus(flash->spi); if (ret) { @@ -84,6 +84,41 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, return ret; } + ret = spi_flash_cmd_write_enable(flash); + if (ret < 0) { + debug("SF: enabling write failed\n"); + return ret; + } + + ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); + if (ret < 0) { + debug("SF: write cmd failed\n"); + return ret; + } + + ret = spi_flash_cmd_wait_ready(flash, timeout); + if (ret < 0) { + debug("SF: write %s timed out\n", + timeout == SPI_FLASH_PROG_TIMEOUT ? + "program" : "page erase"); + return ret; + } + + spi_release_bus(spi); + + return ret; +} + +int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, + size_t len, const void *buf) +{ + unsigned long byte_addr, page_size; + size_t chunk_len, actual; + u8 cmd[4]; + int ret = -1; + + page_size = flash->page_size; + cmd[0] = CMD_PAGE_PROGRAM; for (actual = 0; actual < len; actual += chunk_len) { #ifdef CONFIG_SPI_FLASH_BAR @@ -108,27 +143,16 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, debug("PP: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); - ret = spi_flash_cmd_write_enable(flash); - if (ret < 0) { - debug("SF: enabling write failed\n"); - break; - } - - ret = spi_flash_cmd_write(flash->spi, cmd, 4, - buf + actual, chunk_len); + ret = spi_flash_write_common(flash, cmd, sizeof(cmd), + buf + actual, chunk_len); if (ret < 0) { debug("SF: write failed\n"); break; } - ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); - if (ret) - break; - offset += chunk_len; } - spi_release_bus(flash->spi); return ret; } @@ -242,8 +266,8 @@ 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 erase_size; - int ret; u8 cmd[4]; + int ret = -1; erase_size = flash->sector_size; if (offset % erase_size || len % erase_size) { @@ -251,12 +275,6 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) return -1; } - ret = spi_claim_bus(flash->spi); - if (ret) { - debug("SF: Unable to claim SPI bus\n"); - return ret; - } - if (erase_size == 4096) cmd[0] = CMD_ERASE_4K; else @@ -279,24 +297,16 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], cmd[2], cmd[3], offset); - ret = spi_flash_cmd_write_enable(flash); - if (ret) - goto out; - - ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0); - if (ret) - goto out; - - ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT); - if (ret) - goto out; + ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); + if (ret < 0) { + debug("SF: erase failed\n"); + break; + } offset += erase_size; len -= erase_size; } - out: - spi_release_bus(flash->spi); return ret; } @@ -305,22 +315,10 @@ int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) u8 cmd; int ret; - ret = spi_flash_cmd_write_enable(flash); - if (ret < 0) { - debug("SF: enabling write failed\n"); - return ret; - } - cmd = CMD_WRITE_STATUS; - ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1); - if (ret) { - debug("SF: fail to write status register\n"); - return ret; - } - - ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + ret = spi_flash_write_common(flash, &cmd, 1, &sr, 1); if (ret < 0) { - debug("SF: write status register timed out\n"); + debug("SF: fail to write status register\n"); return ret; } @@ -339,25 +337,13 @@ int spi_flash_cmd_bankaddr_write(struct spi_flash *flash, u8 bank_sel) } cmd = flash->bank_write_cmd; - ret = spi_flash_cmd_write_enable(flash); + ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); if (ret < 0) { - debug("SF: enabling write failed\n"); - return ret; - } - - ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &bank_sel, 1); - if (ret) { - debug("SF: fail to write bank addr register\n"); + debug("SF: fail to write bank register\n"); return ret; } flash->bank_curr = bank_sel; - ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); - if (ret < 0) { - debug("SF: write bank addr register timed out\n"); - return ret; - } - return 0; } diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 8147f27..be3c768 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -108,6 +108,16 @@ int spi_flash_bank_config(struct spi_flash *flash, u8 idcode0); */ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, void *data, size_t data_len); +/* + * Used for spi_flash write operation + * - SPI claim + * - spi_flash_cmd_write_enable + * - spi_flash_cmd_write + * - spi_flash_cmd_wait_ready + * - SPI release + */ +int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, + size_t cmd_len, const void *buf, size_t buf_len); /* * Send the read status command to the device and wait for the wip -- cgit v1.1 From 95e779e4f475f66995f383e71611081e225f01f4 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 21 Jun 2013 19:19:01 +0530 Subject: sf: Place the sf calls in proper order Placed the sf calls in proper order - erase/write/read Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/spi_flash.c | 184 ++++++++++++++++++++++---------------------- 1 file changed, 92 insertions(+), 92 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 03cecef..a329850 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -68,6 +68,51 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, return spi_flash_read_write(spi, cmd, cmd_len, data, NULL, data_len); } +int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) +{ + struct spi_slave *spi = flash->spi; + unsigned long timebase; + int ret; + u8 status; + u8 check_status = 0x0; + u8 poll_bit = STATUS_WIP; + u8 cmd = flash->poll_cmd; + + if (cmd == CMD_FLAG_STATUS) { + poll_bit = STATUS_PEC; + check_status = poll_bit; + } + + ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); + if (ret) { + debug("SF: fail to read %s status register\n", + cmd == CMD_READ_STATUS ? "read" : "flag"); + return ret; + } + + timebase = get_timer(0); + do { + WATCHDOG_RESET(); + + ret = spi_xfer(spi, 8, NULL, &status, 0); + if (ret) + return -1; + + if ((status & poll_bit) == check_status) + break; + + } while (get_timer(timebase) < timeout); + + spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); + + if ((status & poll_bit) == check_status) + return 0; + + /* Timed out */ + debug("SF: time out!\n"); + return -1; +} + int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, size_t cmd_len, const void *buf, size_t buf_len) { @@ -109,6 +154,53 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, return ret; } +int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) +{ + u32 erase_size; + u8 cmd[4]; + int ret = -1; + + erase_size = flash->sector_size; + if (offset % erase_size || len % erase_size) { + debug("SF: Erase offset/length not multiple of erase size\n"); + return -1; + } + + if (erase_size == 4096) + cmd[0] = CMD_ERASE_4K; + else + cmd[0] = CMD_ERASE_64K; + + while (len) { +#ifdef CONFIG_SPI_FLASH_BAR + u8 bank_sel; + + 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; + } +#endif + spi_flash_addr(offset, cmd); + + debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], + cmd[2], cmd[3], offset); + + ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); + if (ret < 0) { + debug("SF: erase failed\n"); + break; + } + + offset += erase_size; + len -= erase_size; + } + + return ret; +} + int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset, size_t len, const void *buf) { @@ -218,98 +310,6 @@ int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset, return ret; } -int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) -{ - struct spi_slave *spi = flash->spi; - unsigned long timebase; - int ret; - u8 status; - u8 check_status = 0x0; - u8 poll_bit = STATUS_WIP; - u8 cmd = flash->poll_cmd; - - if (cmd == CMD_FLAG_STATUS) { - poll_bit = STATUS_PEC; - check_status = poll_bit; - } - - ret = spi_xfer(spi, 8, &cmd, NULL, SPI_XFER_BEGIN); - if (ret) { - debug("SF: fail to read %s status register\n", - cmd == CMD_READ_STATUS ? "read" : "flag"); - return ret; - } - - timebase = get_timer(0); - do { - WATCHDOG_RESET(); - - ret = spi_xfer(spi, 8, NULL, &status, 0); - if (ret) - return -1; - - if ((status & poll_bit) == check_status) - break; - - } while (get_timer(timebase) < timeout); - - spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END); - - if ((status & poll_bit) == check_status) - return 0; - - /* Timed out */ - debug("SF: time out!\n"); - return -1; -} - -int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - u32 erase_size; - u8 cmd[4]; - int ret = -1; - - erase_size = flash->sector_size; - if (offset % erase_size || len % erase_size) { - debug("SF: Erase offset/length not multiple of erase size\n"); - return -1; - } - - if (erase_size == 4096) - cmd[0] = CMD_ERASE_4K; - else - cmd[0] = CMD_ERASE_64K; - - while (len) { -#ifdef CONFIG_SPI_FLASH_BAR - u8 bank_sel; - - 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; - } -#endif - spi_flash_addr(offset, cmd); - - debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], - cmd[2], cmd[3], offset); - - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); - if (ret < 0) { - debug("SF: erase failed\n"); - break; - } - - offset += erase_size; - len -= erase_size; - } - - return ret; -} - int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) { u8 cmd; -- cgit v1.1 From 29fbfc10f4b3eee5773f7e1f0a56f936730b639d Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 21 Jun 2013 19:19:02 +0530 Subject: sf: Add debug messages on spi_flash_read_common - Added debug's on spi_flash_read_common() - Added space Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/spi_flash.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index a329850..51142d8 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -254,8 +254,18 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, struct spi_slave *spi = flash->spi; int ret; - spi_claim_bus(spi); + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); + if (ret < 0) { + debug("SF: read cmd failed\n"); + return ret; + } + spi_release_bus(spi); return ret; -- cgit v1.1 From b9e31be0f8adc1a55179ae3b45c9e274f4650007 Mon Sep 17 00:00:00 2001 From: Jagannadha Sutradharudu Teki Date: Fri, 21 Jun 2013 19:19:03 +0530 Subject: sf: Warn to use BAR for > 16MiB flashes Warning for > 16MiB flashes to #define CONFIG_SPI_FLASH_BAR Signed-off-by: Jagannadha Sutradharudu Teki --- drivers/mtd/spi/spi_flash.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 51142d8..a468208 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -557,6 +557,12 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, if (flash->memory_map) printf(", mapped at %p", flash->memory_map); puts("\n"); +#ifndef CONFIG_SPI_FLASH_BAR + if (flash->size > SPI_FLASH_16MB_BOUN) { + puts("SF: Warning - Only lower 16MiB accessible,"); + puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); + } +#endif spi_release_bus(spi); -- cgit v1.1