Commit c6815bcc authored by Ye Li's avatar Ye Li Committed by Jason Liu
Browse files

MLK-15958-1 mtd: spi: Add 4bytes extend address support



Current SPI flash framework only supports to set bank register
(CONFIG_SPI_FLASH_BAR) for flash with size > 16MiB. But some new flash device
(for example, mt35xu512aba) does not support this way, it only supports
4bytes extend address.

To access the whole memory size for such flash device, we add the support
for this 4bytes extend address mode to SPI flash framework.
The configuration CONFIG_SPI_FLASH_4BYTES_ADDR is used to enable the feature.
Signed-off-by: default avatarYe Li <ye.li@nxp.com>
parent 926ebc32
......@@ -42,6 +42,13 @@ config SPI_FLASH_BAR
Bank/Extended address registers are used to access the flash
which has size > 16MiB in 3-byte addressing.
config SPI_FLASH_4BYTES_ADDR
bool "SPI flash 4bytes (32) address mode support"
depends on SPI_FLASH && !SPI_FLASH_BAR
help
Enable the SPI flash 4bytes extend address mode support to access the flash
which has size > 16MiB.
if SPI_FLASH
config SPI_FLASH_ATMEL
......
......@@ -64,6 +64,14 @@ enum spi_nor_option_flags {
#define CMD_READ_CONFIG 0x35
#define CMD_FLAG_STATUS 0x70
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
#define CMD_READ_ARRAY_FAST_4B 0x0c
#define CMD_PAGE_PROGRAM_4B 0x12
#define CMD_ERASE_64K_4B 0xdc
#define CMD_ERASE_4K_4B 0x21
#define CMD_EN4B 0xB7
#endif
/* Bank addr access commands */
#ifdef CONFIG_SPI_FLASH_BAR
# define CMD_BANKADDR_BRWR 0x17
......
......@@ -30,6 +30,17 @@ static void spi_flash_addr(u32 addr, u8 *cmd)
cmd[3] = addr >> 0;
}
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
static void spi_flash_addr_4b(u32 addr, u8 *cmd)
{
/* cmd[0] is actual command */
cmd[1] = addr >> 24;
cmd[2] = addr >> 16;
cmd[3] = addr >> 8;
cmd[4] = addr >> 0;
}
#endif
static int read_sr(struct spi_flash *flash, u8 *rs)
{
int ret;
......@@ -293,8 +304,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;
u8 cmd[SPI_FLASH_CMD_LEN];
u32 erase_size, erase_addr, cmd_len;
u8 cmd[SPI_FLASH_CMD_LEN + 1];
int ret = -1;
erase_size = flash->erase_size;
......@@ -325,11 +336,19 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
return ret;
#endif
spi_flash_addr(erase_addr, cmd);
cmd_len = SPI_FLASH_CMD_LEN;
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
if (flash->size > SPI_FLASH_16MB_BOUN) {
spi_flash_addr_4b(erase_addr, cmd);
cmd_len = SPI_FLASH_CMD_LEN + 1;
}
#endif
debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
cmd[2], cmd[3], erase_addr);
ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
ret = spi_flash_write_common(flash, cmd, cmd_len, NULL, 0);
if (ret < 0) {
debug("SF: erase failed\n");
break;
......@@ -348,8 +367,8 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
struct spi_slave *spi = flash->spi;
unsigned long byte_addr, page_size;
u32 write_addr;
size_t chunk_len, actual;
u8 cmd[SPI_FLASH_CMD_LEN];
size_t chunk_len, actual, cmd_len;
u8 cmd[SPI_FLASH_CMD_LEN + 1];
int ret = -1;
page_size = flash->page_size;
......@@ -383,11 +402,19 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
(size_t)spi->max_write_size);
spi_flash_addr(write_addr, cmd);
cmd_len = SPI_FLASH_CMD_LEN;
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
if (flash->size > SPI_FLASH_16MB_BOUN) {
spi_flash_addr_4b(write_addr, cmd);
cmd_len = SPI_FLASH_CMD_LEN + 1;
}
#endif
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);
ret = spi_flash_write_common(flash, cmd, sizeof(cmd),
ret = spi_flash_write_common(flash, cmd, cmd_len,
buf + actual, chunk_len);
if (ret < 0) {
debug("SF: write failed\n");
......@@ -460,6 +487,11 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
}
cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
if (flash->size > SPI_FLASH_16MB_BOUN)
cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte + 1;
#endif
cmd = calloc(1, cmdsz);
if (!cmd) {
debug("SF: Failed to allocate cmd\n");
......@@ -489,6 +521,12 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
spi_flash_addr(read_addr, cmd);
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
if (flash->size > SPI_FLASH_16MB_BOUN) {
spi_flash_addr_4b(read_addr, cmd);
read_len = len; /* Not care remain len for current bank */
}
#endif
ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
if (ret < 0) {
debug("SF: read failed\n");
......@@ -914,6 +952,13 @@ static int set_quad_mode(struct spi_flash *flash,
}
}
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
static int enter_4bytes_addr(struct spi_flash *flash)
{
return spi_flash_cmd(flash->spi, CMD_EN4B, NULL, 0);
}
#endif
#if CONFIG_IS_ENABLED(OF_CONTROL)
int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash)
{
......@@ -1039,6 +1084,21 @@ int spi_flash_scan(struct spi_flash *flash)
/* Go for default supported write cmd */
flash->write_cmd = CMD_PAGE_PROGRAM;
#ifdef CONFIG_SPI_FLASH_4BYTES_ADDR
if (flash->size > SPI_FLASH_16MB_BOUN) {
flash->read_cmd = CMD_READ_ARRAY_FAST_4B;
flash->write_cmd = CMD_PAGE_PROGRAM_4B;
if (flash->erase_cmd == CMD_ERASE_4K)
flash->erase_cmd = CMD_ERASE_4K_4B;
else
flash->erase_cmd = CMD_ERASE_64K_4B;
enter_4bytes_addr(flash);
}
#endif
/* Set the quad enable bit - only for quad commands */
if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) ||
(flash->read_cmd == CMD_READ_QUAD_IO_FAST) ||
......@@ -1100,13 +1160,13 @@ int spi_flash_scan(struct spi_flash *flash)
puts("\n");
#endif
#ifndef CONFIG_SPI_FLASH_BAR
#if !defined(CONFIG_SPI_FLASH_BAR) && !defined(CONFIG_SPI_FLASH_4BYTES_ADDR)
if (((flash->dual_flash == SF_SINGLE_FLASH) &&
(flash->size > SPI_FLASH_16MB_BOUN)) ||
((flash->dual_flash > SF_SINGLE_FLASH) &&
(flash->size > SPI_FLASH_16MB_BOUN << 1))) {
puts("SF: Warning - Only lower 16MiB accessible,");
puts(" Full access #define CONFIG_SPI_FLASH_BAR\n");
puts(" Full access #define CONFIG_SPI_FLASH_BAR or #define CONFIG_SPI_FLASH_4BYTES_ADDR\n");
}
#endif
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment