Patchwork [U-Boot,Drivers,04/19] mtd/st_smi: Write to flash in a tight loop

login
register
mail settings
Submitter Vipin Kumar
Date Nov. 2, 2012, 5:39 p.m.
Message ID <6a0635261e331561e8a4b6bd106d1bf9f8d783e4.1351877124.git.vipin.kumar@st.com>
Download mbox | patch
Permalink /patch/196706/
State Superseded
Delegated to: Albert ARIBAUD
Headers show

Comments

Vipin Kumar - Nov. 2, 2012, 5:39 p.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(-)

Patch

diff --git a/drivers/mtd/st_smi.c b/drivers/mtd/st_smi.c
index 1b9ff0e..5298723 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;
+		writel(readl(&smicntl->smi_cr1) | WB_MODE, &smicntl->smi_cr1);
 
-			/*
-			 * 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++;
-		}
 
+		writel(readl(&smicntl->smi_cr1) & ~WB_MODE, &smicntl->smi_cr1);
+
+		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]);
 }
 
 /*