From patchwork Mon Dec 31 11:13:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 208837 X-Patchwork-Delegate: jagannadh.teki@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 8811B2C008C for ; Mon, 31 Dec 2012 22:17:04 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2CE5D4A17B; Mon, 31 Dec 2012 12:17:02 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7Wgbp93R-MmA; Mon, 31 Dec 2012 12:17:01 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 262194A168; Mon, 31 Dec 2012 12:15:48 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E3A8B4A026 for ; Mon, 31 Dec 2012 12:15:13 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pePCnAzG1f3v for ; Mon, 31 Dec 2012 12:15:05 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-da0-f48.google.com (mail-da0-f48.google.com [209.85.210.48]) by theia.denx.de (Postfix) with ESMTPS id D3F924A029 for ; Mon, 31 Dec 2012 12:14:23 +0100 (CET) Received: by mail-da0-f48.google.com with SMTP id k18so5731931dae.21 for ; Mon, 31 Dec 2012 03:14:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=gvW4SvzE2X44gdCypYfNJ4R2xC9kKWg7S+D377IAE64=; b=ZYygkZm9WUtbF4DtAnKOKS9ml3LZuboBGUNyjreTB98zc+kLaQLemR9X1J6AuRbqCN taFXV8Mf+UfINX/CGANsRhwRbZRUNzGXnDxd4p3Q8A0fcpKixnaRIrTlhrqTO3RExvnX 3kUYLGgy9pVSjqsf/wWryeGXDyBjeXhvDJUydds/W7R2MC9ZXQZCD4kJmZH6yzMCA+Ej gO2myyHTKHLbFgMy+0SZp8Fp0YmXH99tkFoYrtgT7ExLr2HK/AEG5tjI4woQ4eF4Oqbk 31+izhIqSm295ls6E43MbSdyyLw3VJekHmHg5d/zJpv6Zt89pn4XfDaCsCjGN3FpsXax lgRg== X-Received: by 10.66.80.65 with SMTP id p1mr119671265pax.20.1356952462070; Mon, 31 Dec 2012 03:14:22 -0800 (PST) Received: from localhost.localdomain ([49.204.11.250]) by mx.google.com with ESMTPS id nw9sm24715215pbb.42.2012.12.31.03.14.20 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 31 Dec 2012 03:14:21 -0800 (PST) From: Jagannadha Sutradharudu Teki To: u-boot@lists.denx.de Date: Mon, 31 Dec 2012 16:43:45 +0530 Message-Id: <1356952428-19824-7-git-send-email-jagannadh.teki@gmail.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1356952428-19824-1-git-send-email-jagannadh.teki@gmail.com> References: <1356952428-19824-1-git-send-email-jagannadh.teki@gmail.com> Subject: [U-Boot] [PATCH 06/12] cmd_sf: Add QPP(Quad-input Page Program) write instruction support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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 --- 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