309 lines
9.2 KiB
Diff
309 lines
9.2 KiB
Diff
|
From 6cfe5c5e7f6a4b3d46f65967fe10820ee2e3d2fa Mon Sep 17 00:00:00 2001
|
||
|
From: Yunhui Cui <yunhui.cui@nxp.com>
|
||
|
Date: Fri, 13 May 2016 16:30:33 +0800
|
||
|
Subject: [PATCH 31/93] mtd: sf: add exceed flash 16MB support for qspi
|
||
|
|
||
|
spi/spi_flash.c: The flash S25FS512S cannot legacy commands
|
||
|
such as Bank Address Related Command, So we need add the exceed
|
||
|
16MB suuport. So we extend the cmd[] size to support 32-bit address,
|
||
|
what's more, as to spi/fsl_qspi.c need to a flag to pionts the address
|
||
|
mask, So add the magic num '0xaa' into cmd[].
|
||
|
|
||
|
Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
|
||
|
---
|
||
|
arch/arm/dts/fsl-ls1012a.dtsi | 2 +-
|
||
|
drivers/mtd/spi/sf_internal.h | 7 ++++
|
||
|
drivers/mtd/spi/spi_flash.c | 73 ++++++++++++++++++++++++++++++--------
|
||
|
drivers/spi/fsl_qspi.c | 30 ++++++++++++++--
|
||
|
include/configs/ls1012a_common.h | 3 +-
|
||
|
5 files changed, 95 insertions(+), 20 deletions(-)
|
||
|
|
||
|
diff --git a/arch/arm/dts/fsl-ls1012a.dtsi b/arch/arm/dts/fsl-ls1012a.dtsi
|
||
|
index 87a287a..2549c91 100644
|
||
|
--- a/arch/arm/dts/fsl-ls1012a.dtsi
|
||
|
+++ b/arch/arm/dts/fsl-ls1012a.dtsi
|
||
|
@@ -108,7 +108,7 @@
|
||
|
#address-cells = <1>;
|
||
|
#size-cells = <0>;
|
||
|
reg = <0x0 0x1550000 0x0 0x10000>,
|
||
|
- <0x0 0x40000000 0x0 0x4000000>;
|
||
|
+ <0x0 0x40000000 0x0 0x8000000>;
|
||
|
reg-names = "QuadSPI", "QuadSPI-memory";
|
||
|
num-cs = <2>;
|
||
|
big-endian;
|
||
|
diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h
|
||
|
index c778b60..3c38425 100644
|
||
|
--- a/drivers/mtd/spi/sf_internal.h
|
||
|
+++ b/drivers/mtd/spi/sf_internal.h
|
||
|
@@ -57,6 +57,13 @@ enum spi_nor_option_flags {
|
||
|
#define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN)
|
||
|
#define SPI_FLASH_16MB_BOUN 0x1000000
|
||
|
|
||
|
+#define SPI_FLASH_ADDR_MAGIC 0xaa
|
||
|
+#define SPI_FLASH_ADDR_MAGIC_LEN 1
|
||
|
+#define SPI_FLASH_4B_ADDR_LEN 4
|
||
|
+#define SPI_FLASH_CMD_LEN_EXT (1 + SPI_FLASH_4B_ADDR_LEN + \
|
||
|
+ SPI_FLASH_ADDR_MAGIC_LEN)
|
||
|
+#define SPI_FLASH_64MB_BOUN 0x4000000
|
||
|
+
|
||
|
/* CFI Manufacture ID's */
|
||
|
#define SPI_FLASH_CFI_MFR_SPANSION 0x01
|
||
|
#define SPI_FLASH_CFI_MFR_STMICRO 0x20
|
||
|
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
|
||
|
index 97e53c7..9d61ac0 100644
|
||
|
--- a/drivers/mtd/spi/spi_flash.c
|
||
|
+++ b/drivers/mtd/spi/spi_flash.c
|
||
|
@@ -21,12 +21,20 @@
|
||
|
|
||
|
DECLARE_GLOBAL_DATA_PTR;
|
||
|
|
||
|
-static void spi_flash_addr(u32 addr, u8 *cmd)
|
||
|
+static void spi_flash_addr(u32 addr, u8 *cmd, u32 offset_ext)
|
||
|
{
|
||
|
- /* cmd[0] is actual command */
|
||
|
- cmd[1] = addr >> 16;
|
||
|
- cmd[2] = addr >> 8;
|
||
|
- cmd[3] = addr >> 0;
|
||
|
+ if (offset_ext >= SPI_FLASH_16MB_BOUN) {
|
||
|
+ /* cmd[0] is actual command */
|
||
|
+ cmd[1] = addr >> 24;
|
||
|
+ cmd[2] = addr >> 16;
|
||
|
+ cmd[3] = addr >> 8;
|
||
|
+ cmd[4] = addr >> 0;
|
||
|
+ cmd[5] = SPI_FLASH_ADDR_MAGIC;
|
||
|
+ } else {
|
||
|
+ cmd[1] = addr >> 16;
|
||
|
+ cmd[2] = addr >> 8;
|
||
|
+ cmd[3] = addr >> 0;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
/* Read commands array */
|
||
|
@@ -302,9 +310,11 @@ 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];
|
||
|
+ u8 *cmd, cmdsz;
|
||
|
int ret = -1;
|
||
|
+ u32 offset_ext;
|
||
|
|
||
|
+ offset_ext = offset;
|
||
|
erase_size = flash->erase_size;
|
||
|
if (offset % erase_size || len % erase_size) {
|
||
|
debug("SF: Erase offset/length not multiple of erase size\n");
|
||
|
@@ -319,7 +329,18 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ if (offset > SPI_FLASH_16MB_BOUN)
|
||
|
+ cmdsz = SPI_FLASH_CMD_LEN_EXT + flash->dummy_byte;
|
||
|
+ else
|
||
|
+ cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
|
||
|
+ cmd = calloc(1, cmdsz);
|
||
|
+ if (!cmd) {
|
||
|
+ debug("SF: Failed to allocate cmd\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ memset(cmd, 0x0, cmdsz);
|
||
|
cmd[0] = flash->erase_cmd;
|
||
|
+
|
||
|
while (len) {
|
||
|
erase_addr = offset;
|
||
|
|
||
|
@@ -332,7 +353,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
|
||
|
if (ret < 0)
|
||
|
return ret;
|
||
|
#endif
|
||
|
- spi_flash_addr(erase_addr, cmd);
|
||
|
+ spi_flash_addr(erase_addr, cmd, offset_ext);
|
||
|
|
||
|
debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
|
||
|
cmd[2], cmd[3], erase_addr);
|
||
|
@@ -347,6 +368,7 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len)
|
||
|
len -= erase_size;
|
||
|
}
|
||
|
|
||
|
+ free(cmd);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
@@ -356,9 +378,11 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
|
||
|
unsigned long byte_addr, page_size;
|
||
|
u32 write_addr;
|
||
|
size_t chunk_len, actual;
|
||
|
- u8 cmd[SPI_FLASH_CMD_LEN];
|
||
|
+ u8 *cmd, cmdsz;
|
||
|
int ret = -1;
|
||
|
+ u32 offset_ext;
|
||
|
|
||
|
+ offset_ext = offset;
|
||
|
page_size = flash->page_size;
|
||
|
|
||
|
if (flash->flash_is_locked) {
|
||
|
@@ -369,6 +393,16 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ if (offset > SPI_FLASH_16MB_BOUN)
|
||
|
+ cmdsz = SPI_FLASH_CMD_LEN_EXT + flash->dummy_byte;
|
||
|
+ else
|
||
|
+ cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
|
||
|
+ cmd = calloc(1, cmdsz);
|
||
|
+ if (!cmd) {
|
||
|
+ debug("SF: Failed to allocate cmd\n");
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ memset(cmd, 0x0, cmdsz);
|
||
|
cmd[0] = flash->write_cmd;
|
||
|
for (actual = 0; actual < len; actual += chunk_len) {
|
||
|
write_addr = offset;
|
||
|
@@ -389,7 +423,7 @@ 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);
|
||
|
+ spi_flash_addr(write_addr, cmd, offset_ext);
|
||
|
|
||
|
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);
|
||
|
@@ -404,6 +438,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset,
|
||
|
offset += chunk_len;
|
||
|
}
|
||
|
|
||
|
+ free(cmd);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
@@ -442,6 +477,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
|
||
|
u32 remain_len, read_len, read_addr;
|
||
|
int bank_sel = 0;
|
||
|
int ret = -1;
|
||
|
+ u32 offset_ext;
|
||
|
+
|
||
|
+ offset_ext = offset;
|
||
|
|
||
|
/* Handle memory-mapped SPI */
|
||
|
if (flash->memory_map) {
|
||
|
@@ -456,15 +494,18 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
|
||
|
spi_release_bus(flash->spi);
|
||
|
return 0;
|
||
|
}
|
||
|
-
|
||
|
- cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
|
||
|
+ if (offset > SPI_FLASH_16MB_BOUN)
|
||
|
+ cmdsz = SPI_FLASH_CMD_LEN_EXT + flash->dummy_byte;
|
||
|
+ else
|
||
|
+ cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte;
|
||
|
cmd = calloc(1, cmdsz);
|
||
|
if (!cmd) {
|
||
|
debug("SF: Failed to allocate cmd\n");
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
-
|
||
|
+ memset(cmd, 0x0, cmdsz);
|
||
|
cmd[0] = flash->read_cmd;
|
||
|
+
|
||
|
while (len) {
|
||
|
read_addr = offset;
|
||
|
|
||
|
@@ -478,14 +519,18 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset,
|
||
|
return ret;
|
||
|
bank_sel = flash->bank_curr;
|
||
|
#endif
|
||
|
- remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
|
||
|
+ if (offset_ext >= SPI_FLASH_16MB_BOUN) {
|
||
|
+ remain_len = flash->size - offset;
|
||
|
+ } else {
|
||
|
+ remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
|
||
|
(bank_sel + 1)) - offset;
|
||
|
+ }
|
||
|
if (len < remain_len)
|
||
|
read_len = len;
|
||
|
else
|
||
|
read_len = remain_len;
|
||
|
|
||
|
- spi_flash_addr(read_addr, cmd);
|
||
|
+ spi_flash_addr(read_addr, cmd, offset_ext);
|
||
|
|
||
|
ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len);
|
||
|
if (ret < 0) {
|
||
|
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
|
||
|
index 2b20038..09759fa 100644
|
||
|
--- a/drivers/spi/fsl_qspi.c
|
||
|
+++ b/drivers/spi/fsl_qspi.c
|
||
|
@@ -26,6 +26,9 @@ DECLARE_GLOBAL_DATA_PTR;
|
||
|
#endif
|
||
|
|
||
|
#define OFFSET_BITS_MASK GENMASK(23, 0)
|
||
|
+/* the qspi contrller memmap space ,instead of flash space */
|
||
|
+#define OFFSET_BITS_MASK_QSPI_SPACE GENMASK(27, 0)
|
||
|
+#define SPI_FLASH_ADDR_EXT_MAGIC 0xaa
|
||
|
|
||
|
#define FLASH_STATUS_WEL 0x02
|
||
|
|
||
|
@@ -757,6 +760,13 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
|
||
|
u32 bytes = DIV_ROUND_UP(bitlen, 8);
|
||
|
static u32 wr_sfaddr;
|
||
|
u32 txbuf;
|
||
|
+ u8 offset_ext = 0;
|
||
|
+ u32 flash_offset;
|
||
|
+
|
||
|
+ if (((u8 *)dout)[5] == SPI_FLASH_ADDR_EXT_MAGIC) {
|
||
|
+ offset_ext = 1;
|
||
|
+ memcpy(&flash_offset, dout + 1, 4);
|
||
|
+ }
|
||
|
|
||
|
if (dout) {
|
||
|
if (flags & SPI_XFER_BEGIN) {
|
||
|
@@ -772,14 +782,28 @@ int qspi_xfer(struct fsl_qspi_priv *priv, unsigned int bitlen,
|
||
|
|
||
|
if (priv->cur_seqid == QSPI_CMD_FAST_READ ||
|
||
|
priv->cur_seqid == QSPI_CMD_RDAR) {
|
||
|
- priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
|
||
|
+ if (offset_ext)
|
||
|
+ priv->sf_addr = swab32(flash_offset) &
|
||
|
+ OFFSET_BITS_MASK_QSPI_SPACE;
|
||
|
+ else
|
||
|
+ priv->sf_addr = swab32(txbuf) &
|
||
|
+ OFFSET_BITS_MASK;
|
||
|
} else if ((priv->cur_seqid == QSPI_CMD_SE) ||
|
||
|
(priv->cur_seqid == QSPI_CMD_BE_4K)) {
|
||
|
- priv->sf_addr = swab32(txbuf) & OFFSET_BITS_MASK;
|
||
|
+ if (offset_ext)
|
||
|
+ priv->sf_addr = swab32(flash_offset) &
|
||
|
+ OFFSET_BITS_MASK_QSPI_SPACE;
|
||
|
+ else
|
||
|
+ priv->sf_addr = swab32(txbuf) &
|
||
|
+ OFFSET_BITS_MASK;
|
||
|
qspi_op_erase(priv);
|
||
|
} else if (priv->cur_seqid == QSPI_CMD_PP ||
|
||
|
priv->cur_seqid == QSPI_CMD_WRAR) {
|
||
|
- wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
|
||
|
+ if (offset_ext)
|
||
|
+ wr_sfaddr = swab32(flash_offset) &
|
||
|
+ OFFSET_BITS_MASK_QSPI_SPACE;
|
||
|
+ else
|
||
|
+ wr_sfaddr = swab32(txbuf) & OFFSET_BITS_MASK;
|
||
|
} else if ((priv->cur_seqid == QSPI_CMD_BRWR) ||
|
||
|
(priv->cur_seqid == QSPI_CMD_WREAR)) {
|
||
|
#ifdef CONFIG_SPI_FLASH_BAR
|
||
|
diff --git a/include/configs/ls1012a_common.h b/include/configs/ls1012a_common.h
|
||
|
index 3fd360a..150444d 100644
|
||
|
--- a/include/configs/ls1012a_common.h
|
||
|
+++ b/include/configs/ls1012a_common.h
|
||
|
@@ -63,9 +63,8 @@
|
||
|
#define QSPI0_AMBA_BASE 0x40000000
|
||
|
#define CONFIG_SPI_FLASH_SPANSION
|
||
|
#define CONFIG_DM_SPI_FLASH
|
||
|
-#define CONFIG_SPI_FLASH_BAR
|
||
|
|
||
|
-#define FSL_QSPI_FLASH_SIZE (1 << 24)
|
||
|
+#define FSL_QSPI_FLASH_SIZE (1 << 26)
|
||
|
#define FSL_QSPI_FLASH_NUM 2
|
||
|
|
||
|
/*
|
||
|
--
|
||
|
1.7.9.5
|
||
|
|