[U-Boot] [PATCH] cfi_flash: Micron Nor flash don't support read operation after send

Qi Wang 王起 (qiwang)
2014-03-12T02:30:15Z

Micron Nor flash don't support read operation after send write command. As below,

flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER);
cnt = len >> shift;
flash_write_cmd(info, sector, offset, cnt - 1);

switch (info->portwidth) {
case FLASH_CFI_8BIT:
while (cnt-- > 0) {
flash_write8(flash_read8(src), dst);
src += 1, dst += 1;
}
break;

If the src address locate in NOR flash, flash_read operation will be failed.
So, read out the data to DRAM before send write command operation.
---
drivers/mtd/cfi_flash.c | 70 +++++++++++++++++++++++++++++++----------------
1 file changed, 46 insertions(+), 24 deletions(-)

diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index a389cd1..0f532c0 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -25,6 +25,8 @@
#include <environment.h>
#include <mtd/cfi_flash.h>
#include <watchdog.h>
+#include <malloc.h>
+#include <asm-generic/errno.h>

/*
* This file implements a Common Flash Interface (CFI) driver for
@@ -855,6 +857,8 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
int cnt;
int retcode;
void *src = cp;
+ void *src2;
+ void *src2_bak;
void *dst = (void *)dest;
void *dst2 = dst;
int flag = 1;
@@ -880,29 +884,45 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
goto out_unmap;
}

+ src2 = malloc(len);
+ if(!src2)
+ {
+ free(src2);
+ return -ENOMEM;
+ }
+
+ src2_bak = src2;
cnt = len >> shift;

while ((cnt-- > 0) && (flag == 1)) {
switch (info->portwidth) {
case FLASH_CFI_8BIT:
- flag = ((flash_read8(dst2) & flash_read8(src)) ==
- flash_read8(src));
+ *(u8 *)src2 = flash_read8(src);
+ flag = ((flash_read8(dst2) & *(u8 *)src2) ==
+ *(u8 *)src2);
src += 1, dst2 += 1;
+ src2 +=1;
break;
case FLASH_CFI_16BIT:
- flag = ((flash_read16(dst2) & flash_read16(src)) ==
- flash_read16(src));
+ *(u16 *)src2 = flash_read16(src);
+ flag = ((flash_read16(dst2) & *(u16 *)src2) ==
+ *(u16 *)src2);
src += 2, dst2 += 2;
+ src2 += 2;
break;
case FLASH_CFI_32BIT:
- flag = ((flash_read32(dst2) & flash_read32(src)) ==
- flash_read32(src));
+ *(u32 *)src2 = flash_read32(src);
+ flag = ((flash_read32(dst2) & *(u32 *)src2) ==
+ *(u32 *)src2);
src += 4, dst2 += 4;
+ src2 += 4;
break;
case FLASH_CFI_64BIT:
- flag = ((flash_read64(dst2) & flash_read64(src)) ==
- flash_read64(src));
+ *(u64 *)src2 = flash_read64(src);
+ flag = ((flash_read64(dst2) & *(u64 *)src2) ==
+ *(u64 *)src2);
src += 8, dst2 += 8;
+ src2 += 8;
break;
}
}
@@ -912,6 +932,7 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
}

src = cp;
+ src2 = src2_bak;
sector = find_sector (info, dest);

switch (info->vendor) {
@@ -934,20 +955,20 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
while (cnt-- > 0) {
switch (info->portwidth) {
case FLASH_CFI_8BIT:
- flash_write8(flash_read8(src), dst);
- src += 1, dst += 1;
+ flash_write8(*(u8 *)src2, dst);
+ src2 += 1, dst += 1;
break;
case FLASH_CFI_16BIT:
- flash_write16(flash_read16(src), dst);
- src += 2, dst += 2;
+ flash_write16(*(u16 *)src2, dst);
+ src2 += 2, dst += 2;
break;
case FLASH_CFI_32BIT:
- flash_write32(flash_read32(src), dst);
- src += 4, dst += 4;
+ flash_write32(*(u32 *)src2, dst);
+ src2 += 4, dst += 4;
break;
case FLASH_CFI_64BIT:
- flash_write64(flash_read64(src), dst);
- src += 8, dst += 8;
+ flash_write64(*(u64 *)src2, dst);
+ src2 += 8, dst += 8;
break;
default:
retcode = ERR_INVAL;
@@ -977,26 +998,26 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
switch (info->portwidth) {
case FLASH_CFI_8BIT:
while (cnt-- > 0) {
- flash_write8(flash_read8(src), dst);
- src += 1, dst += 1;
+ flash_write8(*(u8 *)src2, dst);
+ src2 += 1, dst += 1;
}
break;
case FLASH_CFI_16BIT:
while (cnt-- > 0) {
- flash_write16(flash_read16(src), dst);
- src += 2, dst += 2;
+ flash_write16(*(u16 *)src2, dst);
+ src2 += 2, dst += 2;
}
break;
case FLASH_CFI_32BIT:
while (cnt-- > 0) {
- flash_write32(flash_read32(src), dst);
- src += 4, dst += 4;
+ flash_write32(*(u32 *)src2, dst);
+ src2 += 4, dst += 4;
}
break;
case FLASH_CFI_64BIT:
while (cnt-- > 0) {
- flash_write64(flash_read64(src), dst);
- src += 8, dst += 8;
+ flash_write64(*(u64 *)src2, dst);
+ src2 += 8, dst += 8;
}
break;
default:
@@ -1023,6 +1044,7 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
}

out_unmap:
+ free(src2_bak);
return retcode;
}
#endif /* CONFIG_SYS_FLASH_USE_BUFFER_WRITE */
--
1.7.9.5

Best Regards,
Qi Wang
EBU APAC SE
Tel: 86-021-38997158
Mobile: 86-15201958202
Email: qiwang at micron.com
Address: No 601 Fasai Rd, Pudong, Shanghai, China, 200131