[U-Boot,v2,5/7] mtd/st_smi: Write to flash in a tight loop

Submitted by Vipin Kumar on Dec. 6, 2012, 8:47 a.m.

Details

Message ID 276b3fa86b7171e21eefd4fdf4af9c246280393b.1354783388.git.vipin.kumar@st.com
State Deferred
Delegated to: Heiko Schocher
Headers show

Commit Message

Vipin Kumar Dec. 6, 2012, 8:47 a.m.
The write loop is checking for dest_addr alignment with page size. This
sometimes leads to smi controller coming out of write mode and eventually the
next write failing with ERF1 being set.

To avoid this, write to flash in a tight loop and write bytewise to also support
not word aligned data bytes to be written. Additionally, enable burst mode
before this loop so that the controller does not deselect the chip if the
transfer is finished.

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/st_smi.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

Comments

Stefan Roese Dec. 6, 2012, 11:40 a.m.
On 12/06/2012 09:47 AM, Vipin Kumar wrote:
> The write loop is checking for dest_addr alignment with page size. This
> sometimes leads to smi controller coming out of write mode and eventually the
> next write failing with ERF1 being set.
> 
> To avoid this, write to flash in a tight loop and write bytewise to also support
> not word aligned data bytes to be written. Additionally, enable burst mode
> before this loop so that the controller does not deselect the chip if the
> transfer is finished.
> 
> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>

Acked-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

Patch hide | download patch | download mbox

diff --git a/drivers/mtd/st_smi.c b/drivers/mtd/st_smi.c
index 6c3e594..5f67807 100644
--- a/drivers/mtd/st_smi.c
+++ b/drivers/mtd/st_smi.c
@@ -368,13 +368,11 @@  static int smi_sector_erase(flash_info_t *info, unsigned int sector)
  *
  * Write to SMI flash
  */
-static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
+static int smi_write(unsigned char *src_addr, unsigned char *dst_addr,
 		     unsigned int length, ulong bank_addr)
 {
-	u8 *src_addr8 = (u8 *)src_addr;
-	u8 *dst_addr8 = (u8 *)dst_addr;
 	int banknum;
-	int i, issue_we;
+	int issue_we;
 
 	switch (bank_addr) {
 	case SMIBANK0_BASE:
@@ -400,7 +398,10 @@  static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
 	writel(readl(&smicntl->smi_cr1) & ~SW_MODE, &smicntl->smi_cr1);
 
 	/* Perform the write command */
-	for (i = 0; i < length; i += 4) {
+	while (length) {
+		int k;
+		unsigned int wlen = min(SFLASH_PAGE_SIZE, length);
+
 		if (issue_we || (((ulong)(dst_addr) % SFLASH_PAGE_SIZE) == 0)) {
 			issue_we = 0;
 
@@ -412,19 +413,14 @@  static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
 				return -EIO;
 		}
 
-		if (length < 4) {
-			int k;
+		setbits_le32(&smicntl->smi_cr1, WB_MODE);
 
-			/*
-			 * Handle special case, where length < 4 (redundant env)
-			 */
-			for (k = 0; k < length; k++)
-				*dst_addr8++ = *src_addr8++;
-		} else {
-			/* Normal 32bit write */
+		for (k = 0; k < wlen; k++)
 			*dst_addr++ = *src_addr++;
-		}
 
+		clrbits_le32(&smicntl->smi_cr1, WB_MODE);
+
+		length -= wlen;
 		if ((readl(&smicntl->smi_sr) & (ERF1 | ERF2)))
 			return -EIO;
 	}
@@ -448,8 +444,8 @@  static int smi_write(unsigned int *src_addr, unsigned int *dst_addr,
  */
 int write_buff(flash_info_t *info, uchar *src, ulong dest_addr, ulong length)
 {
-	return smi_write((unsigned int *)src, (unsigned int *)dest_addr,
-			 length, info->start[0]);
+	return smi_write(src, (unsigned char *)dest_addr, length,
+			info->start[0]);
 }
 
 /*