[U-Boot] [PATCH 06/12] cmd_sf: Add QPP(Quad-input Page Program) write instruction support
Jagannadha Sutradharudu Teki
jagannadh.teki at gmail.com
Mon Dec 31 12:13:45 CET 2012
This patch provides a support to program a flash using 'qpp'
write instruction(wr_inst) for 'sf write' and 'sf update' commands.
'qpp' will effectively increases the data transfer rate
by up to four times, as compared to the pp( Page Program).
Example:
write 0x2000 length bytes from memory at 0x10000 address to
flash offset at 0x0 using qpp write instruction.
u-boot> sf write qpp 0x10000 0x0 0x2000
erase and write 0x2000 length bytes from memory at 0x10000 address to
flash offset at 0x0 using qpp write instruction and afr read instruction.
u-boot> sf update qpp afr 0x10000 0x0 0x2000
Signed-off-by: Jagannadha Sutradharudu Teki <jagannadh.teki at gmail.com>
---
common/cmd_sf.c | 41 ++++++++++++++++++++++-----------
drivers/mtd/spi/spi_flash.c | 12 ++++++++-
drivers/mtd/spi/spi_flash_internal.h | 4 +-
include/spi_flash.h | 7 +++--
include/spi_flash_inst.h | 1 +
5 files changed, 44 insertions(+), 21 deletions(-)
diff --git a/common/cmd_sf.c b/common/cmd_sf.c
index d59ecce..b1f19ef 100644
--- a/common/cmd_sf.c
+++ b/common/cmd_sf.c
@@ -143,6 +143,7 @@ static int do_spi_flash_probe(int argc, char * const argv[])
* @param flash flash context pointer
* @param wr_inst write instruction
* @param rd_inst read instruction
+ * @param wr_qeb_req quad enable bit is required for this write operation?
* @param offset flash offset to write
* @param len number of bytes to write
* @param buf buffer to write from
@@ -151,8 +152,8 @@ static int do_spi_flash_probe(int argc, char * const argv[])
* @return NULL if OK, else a string containing the stage which failed
*/
static const char *spi_flash_update_block(struct spi_flash *flash, u8 wr_inst,
- u8 rd_inst, u32 offset, size_t len, const char *buf,
- char *cmp_buf, size_t *skipped)
+ u8 rd_inst, u8 wr_qeb_req, u32 offset, size_t len,
+ const char *buf, char *cmp_buf, size_t *skipped)
{
debug("offset=%#x, sector_size=%#x, len=%#zx\n",
offset, flash->sector_size, len);
@@ -166,7 +167,7 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u8 wr_inst,
}
if (spi_flash_erase(flash, offset, len))
return "erase";
- if (spi_flash_write(flash, wr_inst, offset, len, buf))
+ if (spi_flash_write(flash, wr_inst, wr_qeb_req, offset, len, buf))
return "write";
return NULL;
}
@@ -178,13 +179,14 @@ static const char *spi_flash_update_block(struct spi_flash *flash, u8 wr_inst,
* @param flash flash context pointer
* @param wr_inst write instruction
* @param rd_inst read instruction
+ * @param wr_qeb_req quad enable bit is required for this write operation?
* @param offset flash offset to write
* @param len number of bytes to write
* @param buf buffer to write from
* @return 0 if ok, 1 on error
*/
static int spi_flash_update(struct spi_flash *flash, u8 wr_inst, u8 rd_inst,
- u32 offset, size_t len, const char *buf)
+ u8 wr_qeb_req, u32 offset, size_t len, const char *buf)
{
const char *err_oper = NULL;
char *cmp_buf;
@@ -212,7 +214,8 @@ static int spi_flash_update(struct spi_flash *flash, u8 wr_inst, u8 rd_inst,
last_update = get_timer(0);
}
err_oper = spi_flash_update_block(flash, wr_inst,
- rd_inst, offset, todo, buf,
+ rd_inst, wr_qeb_req,
+ offset, todo, buf,
cmp_buf, &skipped);
}
} else {
@@ -241,15 +244,21 @@ static int spi_flash_update(struct spi_flash *flash, u8 wr_inst, u8 rd_inst,
* arg: specified write instruction from user
* Output:
* wr_inst: parsed write instruction for write operation
+ * wr_qeb_req: assign to 1 if this instruction require quad enable bit
+ * need to set prior to actual write operation
* Return:
* 1: for Unknown wr_inst from user
* 0: Success
*/
-static int sf_parse_wr_inst_arg(char *arg, u8 *wr_inst)
+static int sf_parse_wr_inst_arg(char *arg, u8 *wr_inst, u8 *wr_qeb_req)
{
- if (strcmp(arg, "pp") == 0)
+ if (strcmp(arg, "pp") == 0) {
*wr_inst = CMD_PAGE_PROGRAM;
- else
+ *wr_qeb_req = 0;
+ } else if (strcmp(arg, "qpp") == 0) {
+ *wr_inst = CMD_QUAD_PAGE_PROGRAM;
+ *wr_qeb_req = 1;
+ } else
return 1;
return 0;
@@ -284,6 +293,7 @@ static int do_spi_flash_read_write(int argc, char * const argv[])
void *buf;
char *endp;
u8 wr_inst, rd_inst;
+ u8 wr_qeb_req;
int update_rd_inst;
int ret;
@@ -323,7 +333,7 @@ static int do_spi_flash_read_write(int argc, char * const argv[])
}
if (strcmp(argv[0], "update") == 0) {
- ret = sf_parse_wr_inst_arg(argv[1], &wr_inst);
+ ret = sf_parse_wr_inst_arg(argv[1], &wr_inst, &wr_qeb_req);
if (ret) {
printf("SF: Unknown %s wr_inst on 'sf update'\n",
argv[1]);
@@ -338,7 +348,7 @@ static int do_spi_flash_read_write(int argc, char * const argv[])
}
ret = spi_flash_update(flash, wr_inst, rd_inst,
- offset, len, buf);
+ wr_qeb_req, offset, len, buf);
} else if (strcmp(argv[0], "read") == 0) {
ret = sf_parse_rd_inst_arg(argv[1], &rd_inst);
if (ret) {
@@ -349,14 +359,15 @@ static int do_spi_flash_read_write(int argc, char * const argv[])
ret = spi_flash_read(flash, rd_inst, offset, len, buf);
} else {
- ret = sf_parse_wr_inst_arg(argv[1], &wr_inst);
+ ret = sf_parse_wr_inst_arg(argv[1], &wr_inst, &wr_qeb_req);
if (ret) {
printf("SF: Unknown %s wr_inst on 'sf write'\n",
argv[1]);
return ret;
}
- ret = spi_flash_write(flash, wr_inst, offset, len, buf);
+ ret = spi_flash_write(flash, wr_inst, wr_qeb_req,
+ offset, len, buf);
}
unmap_physmem(buf, len);
@@ -622,15 +633,17 @@ U_BOOT_CMD(
"sf write wr_inst addr offset len\n"
" - write `len' bytes from memory\n"
" at `addr' to flash at `offset' using\n"
- " pp `wr_inst' write instruction\n"
+ " pp | qpp `wr_inst' write instructions\n"
" pp (Page Program, 02h)\n"
+ " qpp (Quad Page Program, 32h)\n"
"sf erase offset [+]len - erase `len' bytes from `offset'\n"
" `+len' round up `len' to block size\n"
"sf update wr_inst rd_inst addr offset len\n"
" - erase and write `len' bytes from memory\n"
" at `addr' to flash at `offset' using\n"
- " pp `wr_inst' write instruction and\n"
+ " pp | qpp `wr_inst' write instructions and\n"
" pp (Page Program, 02h)\n"
+ " qpp (Quad Page Program, 32h)\n"
" afr `rd_inst' read instruction\n"
" afr (Array Fast Read, 0bh)"
SF_TEST_HELP
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 0c64ac2..3d57863 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -65,8 +65,8 @@ 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, u8 wr_inst, u32 offset,
- size_t len, const void *buf)
+int spi_flash_cmd_write_multi(struct spi_flash *flash, u8 wr_inst,
+ u8 wr_qeb_req, u32 offset, size_t len, const void *buf)
{
unsigned long page_addr, byte_addr, page_size;
size_t chunk_len, actual;
@@ -83,6 +83,14 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u8 wr_inst, u32 offset,
return ret;
}
+ if (wr_qeb_req) {
+ ret = spi_flash_set_quad_enable_bit(flash);
+ if (ret) {
+ debug("SF: set quad enable bit failed\n");
+ return ret;
+ }
+ }
+
cmd[0] = wr_inst;
for (actual = 0; actual < len; actual += chunk_len) {
chunk_len = min(len - actual, page_size - byte_addr);
diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h
index dcf8813..e36f216 100644
--- a/drivers/mtd/spi/spi_flash_internal.h
+++ b/drivers/mtd/spi/spi_flash_internal.h
@@ -57,8 +57,8 @@ int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
* Write the requested data out breaking it up into multiple write
* commands as needed per the write size.
*/
-int spi_flash_cmd_write_multi(struct spi_flash *flash, u8 wr_inst, u32 offset,
- size_t len, const void *buf);
+int spi_flash_cmd_write_multi(struct spi_flash *flash, u8 wr_inst,
+ u8 wr_qeb_req, u32 offset, size_t len, const void *buf);
/*
* Enable writing on the SPI flash.
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 6728796..31e7d9e 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -42,7 +42,8 @@ struct spi_flash {
int (*read)(struct spi_flash *flash, u8 rd_inst,
u32 offset, size_t len, void *buf);
int (*write)(struct spi_flash *flash, u8 wr_inst,
- u32 offset, size_t len, const void *buf);
+ u8 wr_qeb_req, u32 offset, size_t len,
+ const void *buf);
int (*erase)(struct spi_flash *flash, u32 offset,
size_t len);
};
@@ -58,9 +59,9 @@ static inline int spi_flash_read(struct spi_flash *flash, u8 rd_inst,
}
static inline int spi_flash_write(struct spi_flash *flash, u8 wr_inst,
- u32 offset, size_t len, const void *buf)
+ u8 wr_qeb_req, u32 offset, size_t len, const void *buf)
{
- return flash->write(flash, wr_inst, offset, len, buf);
+ return flash->write(flash, wr_inst, wr_qeb_req, offset, len, buf);
}
static inline int spi_flash_erase(struct spi_flash *flash, u32 offset,
diff --git a/include/spi_flash_inst.h b/include/spi_flash_inst.h
index 7c1b910..a530842 100644
--- a/include/spi_flash_inst.h
+++ b/include/spi_flash_inst.h
@@ -26,6 +26,7 @@
/* Write commands */
#define CMD_PAGE_PROGRAM 0x02
+#define CMD_QUAD_PAGE_PROGRAM 0x32
/* Read commands */
#define CMD_READ_ARRAY_FAST 0x0b
--
1.7.0.4
More information about the U-Boot
mailing list