cfi_flash: Support buffered writes on non-standard Spansion NOR flash
authorGuennadi Liakhovetski <lg@denx.de>
Thu, 3 Apr 2008 11:36:02 +0000 (13:36 +0200)
committerStefan Roese <sr@denx.de>
Sat, 12 Apr 2008 06:59:09 +0000 (08:59 +0200)
Some NOR flash chip from Spansion, for example, the s29ws-n MirrorBit
series require different addresses for buffered write commands. Define a
configuration option to support buffered writes on those chips. A more
elegant solution would be to automatically detect those chips by parsing
their CFI records, but that would require introduction of a fixup table
into the cfi_flash driver.

Signed-off-by: Guennadi Liakhovetski <lg@denx.de>
README
drivers/mtd/cfi_flash.c

diff --git a/README b/README
index 5d059e7..b29a0d2 100644 (file)
--- a/README
+++ b/README
@@ -2040,6 +2040,13 @@ Configuration Settings:
                This option also enables the building of the cfi_flash driver
                in the drivers directory
 
+- CFG_FLASH_USE_BUFFER_WRITE
+               Use buffered writes to flash.
+
+- CONFIG_FLASH_SPANSION_S29WS_N
+               s29ws-n MirrorBit flash has non-standard addresses for buffered
+               write commands.
+
 - CFG_FLASH_QUIET_TEST
                If this option is defined, the common CFI flash doesn't
                print it's warning upon not recognized FLASH banks. This
index 40fddcd..e3cfb8a 100644 (file)
@@ -844,25 +844,29 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
        void *dst = map_physmem(dest, len, MAP_NOCACHE);
        void *dst2 = dst;
        int flag = 0;
+       uint offset = 0;
+       unsigned int shift;
 
        switch (info->portwidth) {
        case FLASH_CFI_8BIT:
-               cnt = len;
+               shift = 0;
                break;
        case FLASH_CFI_16BIT:
-               cnt = len >> 1;
+               shift = 1;
                break;
        case FLASH_CFI_32BIT:
-               cnt = len >> 2;
+               shift = 2;
                break;
        case FLASH_CFI_64BIT:
-               cnt = len >> 3;
+               shift = 3;
                break;
        default:
                retcode = ERR_INVAL;
                goto out_unmap;
        }
 
+       cnt = len >> shift;
+
        while ((cnt-- > 0) && (flag == 0)) {
                switch (info->portwidth) {
                case FLASH_CFI_8BIT:
@@ -906,23 +910,7 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
                if (retcode == ERR_OK) {
                        /* reduce the number of loops by the width of
                         * the port */
-                       switch (info->portwidth) {
-                       case FLASH_CFI_8BIT:
-                               cnt = len;
-                               break;
-                       case FLASH_CFI_16BIT:
-                               cnt = len >> 1;
-                               break;
-                       case FLASH_CFI_32BIT:
-                               cnt = len >> 2;
-                               break;
-                       case FLASH_CFI_64BIT:
-                               cnt = len >> 3;
-                               break;
-                       default:
-                               retcode = ERR_INVAL;
-                               goto out_unmap;
-                       }
+                       cnt = len >> shift;
                        flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
                        while (cnt-- > 0) {
                                switch (info->portwidth) {
@@ -959,36 +947,34 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
        case CFI_CMDSET_AMD_STANDARD:
        case CFI_CMDSET_AMD_EXTENDED:
                flash_unlock_seq(info,0);
-               flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
+
+#ifdef CONFIG_FLASH_SPANSION_S29WS_N
+               offset = ((unsigned long)dst - info->start[sector]) >> shift;
+#endif
+               flash_write_cmd(info, sector, offset, AMD_CMD_WRITE_TO_BUFFER);
+               cnt = len >> shift;
+               flash_write_cmd(info, sector, offset, (uchar)cnt - 1);
 
                switch (info->portwidth) {
                case FLASH_CFI_8BIT:
-                       cnt = len;
-                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
                        while (cnt-- > 0) {
                                flash_write8(flash_read8(src), dst);
                                src += 1, dst += 1;
                        }
                        break;
                case FLASH_CFI_16BIT:
-                       cnt = len >> 1;
-                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
                        while (cnt-- > 0) {
                                flash_write16(flash_read16(src), dst);
                                src += 2, dst += 2;
                        }
                        break;
                case FLASH_CFI_32BIT:
-                       cnt = len >> 2;
-                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
                        while (cnt-- > 0) {
                                flash_write32(flash_read32(src), dst);
                                src += 4, dst += 4;
                        }
                        break;
                case FLASH_CFI_64BIT:
-                       cnt = len >> 3;
-                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
                        while (cnt-- > 0) {
                                flash_write64(flash_read64(src), dst);
                                src += 8, dst += 8;