
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(-)
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]); }
/*