From ff1b3dedb085ff095f2ba6424d2ea30d0ee0268b Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Fri, 14 Aug 2015 14:41:15 +0530 Subject: [PATCH] spi: sf: Add 4byte addressing support Add 4 byte addressing support in sf framework for the devices of size greater thab 16M and for the controllers which are capable of 4 byte addressing. Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- drivers/mtd/spi/sf_ops.c | 95 +++++++++++++++++++++++++++----------- drivers/mtd/spi/sf_probe.c | 11 ++++- include/spi.h | 4 ++ 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/drivers/mtd/spi/sf_ops.c b/drivers/mtd/spi/sf_ops.c index 87818196d2e..4cedbd56508 100644 --- a/drivers/mtd/spi/sf_ops.c +++ b/drivers/mtd/spi/sf_ops.c @@ -17,12 +17,19 @@ #include "sf_internal.h" -static void spi_flash_addr(u32 addr, u8 *cmd) +static void spi_flash_addr(u32 addr, u8 *cmd, u8 four_byte) { /* cmd[0] is actual command */ - cmd[1] = addr >> 16; - cmd[2] = addr >> 8; - cmd[3] = addr >> 0; + if (four_byte) { + cmd[1] = addr >> 24; + cmd[2] = addr >> 16; + cmd[3] = addr >> 8; + cmd[4] = addr >> 0; + } else { + cmd[1] = addr >> 16; + cmd[2] = addr >> 8; + cmd[3] = addr >> 0; + } } int spi_flash_cmd_read_status(struct spi_flash *flash, u8 *rs) @@ -384,7 +391,8 @@ int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) { u32 erase_size, erase_addr, bank_addr; - u8 cmd[SPI_FLASH_CMD_LEN]; + u8 cmd[SPI_FLASH_CMD_LEN + 1]; + u32 cmdlen; int ret = -1; erase_size = flash->erase_size; @@ -404,12 +412,19 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) if (flash->dual_flash == SF_DUAL_STACKED_FLASH) bank_addr = erase_addr; #endif + + if (flash->spi->bytemode != SPI_4BYTE_MODE) { #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_bank(flash, bank_addr); - if (ret < 0) - return ret; + ret = spi_flash_bank(flash, bank_addr); + if (ret < 0) + return ret; #endif - spi_flash_addr(erase_addr, cmd); + spi_flash_addr(erase_addr, cmd, 0); + cmdlen = SPI_FLASH_CMD_LEN; + } else { + spi_flash_addr(erase_addr, cmd, 1); + cmdlen = SPI_FLASH_CMD_LEN + 1; + } debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], cmd[2], cmd[3], erase_addr); @@ -419,7 +434,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) flash->spi->flags |= SPI_XFER_STRIPE; #endif - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); + ret = spi_flash_write_common(flash, cmd, cmdlen, NULL, 0); if (ret < 0) { debug("SF: erase failed\n"); break; @@ -438,8 +453,9 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, unsigned long byte_addr, page_size; u32 write_addr, bank_addr; size_t chunk_len, actual; - u8 cmd[SPI_FLASH_CMD_LEN]; + u8 cmd[SPI_FLASH_CMD_LEN + 1]; int ret = -1; + u32 cmdlen; page_size = flash->page_size; @@ -454,11 +470,15 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, if (flash->dual_flash == SF_DUAL_STACKED_FLASH) bank_addr = write_addr; #endif + + if (flash->spi->bytemode != SPI_4BYTE_MODE) { #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_bank(flash, bank_addr); - if (ret < 0) - return ret; + ret = spi_flash_bank(flash, bank_addr); + if (ret < 0) + return ret; #endif + } + byte_addr = offset % page_size; chunk_len = min(len - actual, (size_t)(page_size - byte_addr)); @@ -466,7 +486,13 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, chunk_len = min(chunk_len, (size_t)flash->spi->max_write_size); - spi_flash_addr(write_addr, cmd); + if (flash->spi->bytemode == SPI_4BYTE_MODE) { + spi_flash_addr(write_addr, cmd, 1); + cmdlen = SPI_FLASH_CMD_LEN + 1; + } else { + spi_flash_addr(write_addr, cmd, 0); + cmdlen = SPI_FLASH_CMD_LEN; + } debug("SF: 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); @@ -475,7 +501,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) flash->spi->flags |= SPI_XFER_STRIPE; #endif - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), + ret = spi_flash_write_common(flash, cmd, cmdlen, buf + actual, chunk_len); if (ret < 0) { debug("SF: write failed\n"); @@ -534,6 +560,10 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, } cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; + + if (flash->spi->bytemode == SPI_4BYTE_MODE) + cmdsz += 1; + cmd = calloc(1, cmdsz); if (!cmd) { debug("SF: Failed to allocate cmd\n"); @@ -551,23 +581,32 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, if (flash->dual_flash == SF_DUAL_STACKED_FLASH) bank_addr = read_addr; #endif + if (flash->spi->bytemode != SPI_4BYTE_MODE) { #ifdef CONFIG_SPI_FLASH_BAR - bank_sel = spi_flash_bank(flash, bank_addr); - if (bank_sel < 0) - return ret; - if ((flash->dual_flash == SF_DUAL_STACKED_FLASH) && - (flash->spi->flags & SPI_XFER_U_PAGE)) - bank_sel += (flash->size >> 1)/SPI_FLASH_16MB_BOUN; + bank_sel = spi_flash_bank(flash, bank_addr); + if (bank_sel < 0) + return ret; + if ((flash->dual_flash == SF_DUAL_STACKED_FLASH) && + (flash->spi->flags & SPI_XFER_U_PAGE)) + bank_sel += (flash->size >> 1)/ + SPI_FLASH_16MB_BOUN; #endif - remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * - (bank_sel + 1)) - offset; - if (len < remain_len) + remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * + (bank_sel + 1)) - offset; + if (len < remain_len) + read_len = len; + else + read_len = remain_len; + } else { read_len = len; - else - read_len = remain_len; + } - spi_flash_addr(read_addr, cmd); + if (flash->spi->bytemode == SPI_4BYTE_MODE) + spi_flash_addr(read_addr, cmd, 1); + else + spi_flash_addr(read_addr, cmd, 0); + debug("%s: Byte Mode:0x%x\n",__func__, flash->spi->bytemode); #ifdef CONFIG_SPI_GENERIC if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) flash->spi->flags |= SPI_XFER_STRIPE; diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index bbb51ef9bd5..3e57b5da833 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -214,8 +214,15 @@ static int spi_flash_validate_params(struct spi_slave *spi, u8 *idcode, * in case of warm bootup, the chip was set to 4-byte mode in kernel. */ if (flash->size > SPI_FLASH_16MB_BOUN) { - if (spi_flash_cmd_4B_addr_switch(flash, false, idcode[0]) < 0) - debug("SF: enter 3B address mode failed\n"); + if (flash->spi->bytemode == SPI_4BYTE_MODE) { + if (spi_flash_cmd_4B_addr_switch(flash, true, + idcode[0]) < 0) + debug("SF: enter 4B address mode failed\n"); + } else { + if (spi_flash_cmd_4B_addr_switch(flash, false, + idcode[0]) < 0) + debug("SF: enter 3B address mode failed\n"); + } } #ifdef CONFIG_SF_DUAL_FLASH diff --git a/include/spi.h b/include/spi.h index 851ca9e19c6..b5bfd421a07 100644 --- a/include/spi.h +++ b/include/spi.h @@ -24,6 +24,9 @@ #define SPI_SLAVE 0x40 /* slave mode */ #define SPI_PREAMBLE 0x80 /* Skip preamble bytes */ +#define SPI_3BYTE_MODE 0x0 +#define SPI_4BYTE_MODE 0x1 + /* SPI transfer flags */ #define SPI_XFER_BEGIN 0x01 /* Assert CS before transfer */ #define SPI_XFER_END 0x02 /* Deassert CS after transfer */ @@ -137,6 +140,7 @@ struct spi_slave { u8 option; u8 dio; u32 flags; + u32 bytemode; }; /** -- 2.47.3