Major CFI-FLASH driver update:
authorStefan Roese <sr@denx.de>
Tue, 28 Feb 2006 14:29:58 +0000 (15:29 +0100)
committerStefan Roese <sr@denx.de>
Tue, 28 Feb 2006 14:29:58 +0000 (15:29 +0100)
* Add env-variable "unlock" to handle initial state of sectors
  (locked/unlocked).

  Only the U-Boot image and it's environment is protected,
  all other sectors are unprotected (unlocked) if flash
  hardware protection is used (CFG_FLASH_PROTECTION) and
  the environment variable "unlock" is set to "yes".

  Patch by Stefan Roese, 28 Feb 2006

* Update drivers/cfi_flash.c:
  - find_sector() called in both versions of flash_write_cfiword()
  Patch by Peter Pearse, 27th Feb 2006

* CFI support for a x8/x16 AMD/Spansion flash configured in x8 mode
  Patch by Jose Maria Lopez, 16 Jan 2006

* Add support for AMD/Spansion Flashes in flash_write_cfibuffer
  Patch by Alex Bastos and Thomas Schaefer, 2005-08-29

* Changes/fixes for drivers/cfi_flash.c:
  We *should* check if there are any error bits if the previous call
  returned ERR_OK (Otherwise we will have output an error message in
  flash_status_check() already.)  The original code would only check for
  error bits if flash_status_check() returns ERR_TIMEOUT.
  Patch by Marcus Hall, 23 Aug 2005

* Changes/fixes for drivers/cfi_flash.c:
  - Add CFG_FLASH_PROTECT_CLEAR on drivers/cfi_flash.c
  - Prohibit buffer write when buffer_size is 1 on drivers/cfi_flash.c
  Patch by Sangmoon Kim, 19 Aug 2005

* Fixes for drivers/cfi_flash.c:
  - Fix wrong timeout value usage in flash_status_check()
  - Round write_tout up when converting to msec in flash_get_size()
  - Remove clearing flash status at the end of flash_write_cfibuffer()
    which sets Intel 28F640J3 flash back to command mode on CSB472
  Patch by Tolunay Orkun, 02 July 2005

CHANGELOG
board/tqm85xx/tqm85xx.c
drivers/cfi_flash.c
include/flash.h

index 44989b849de6b6f3fef1156563da8519fa328ddd..5e4d0770d2e20754df162170154994c7ead7e681 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,45 @@
 Changes since U-Boot 1.1.4:
 ======================================================================
 
+* Add env-variable "unlock" to handle initial state of sectors
+  (locked/unlocked).
+
+  Only the U-Boot image and it's environment is protected,
+  all other sectors are unprotected (unlocked) if flash
+  hardware protection is used (CFG_FLASH_PROTECTION) and
+  the environment variable "unlock" is set to "yes".
+
+  Patch by Stefan Roese, 28 Feb 2006
+
+* Update drivers/cfi_flash.c:
+  - find_sector() called in both versions of flash_write_cfiword()
+  Patch by Peter Pearse, 27th Feb 2006
+
+* CFI support for a x8/x16 AMD/Spansion flash configured in x8 mode
+  Patch by Jose Maria Lopez, 16 Jan 2006
+
+* Add support for AMD/Spansion Flashes in flash_write_cfibuffer
+  Patch by Alex Bastos and Thomas Schaefer, 2005-08-29
+
+* Changes/fixes for drivers/cfi_flash.c:
+  We *should* check if there are any error bits if the previous call
+  returned ERR_OK (Otherwise we will have output an error message in
+  flash_status_check() already.)  The original code would only check for
+  error bits if flash_status_check() returns ERR_TIMEOUT.
+  Patch by Marcus Hall, 23 Aug 2005
+
+* Changes/fixes for drivers/cfi_flash.c:
+  - Add CFG_FLASH_PROTECT_CLEAR on drivers/cfi_flash.c
+  - Prohibit buffer write when buffer_size is 1 on drivers/cfi_flash.c
+  Patch by Sangmoon Kim, 19 Aug 2005
+
+* Fixes for drivers/cfi_flash.c:
+  - Fix wrong timeout value usage in flash_status_check()
+  - Round write_tout up when converting to msec in flash_get_size()
+  - Remove clearing flash status at the end of flash_write_cfibuffer()
+    which sets Intel 28F640J3 flash back to command mode on CSB472
+  Patch by Tolunay Orkun, 02 July 2005
+
 * Add GIT version information (commid ID) to untagged U-Boot versions
 
   As done in the linux kernel, the U-Boot version (U_BOOT_VERSION)
index 13ea6f48ddebf624d133d6c76ff354b5609bc202..b36beadea789a5b34dbba2db19ffeff50710d32b 100644 (file)
@@ -40,7 +40,6 @@ extern flash_info_t flash_info[];     /* FLASH chips info */
 
 void local_bus_init (void);
 long int fixed_sdram (void);
-ulong flash_get_size (ulong base, int banknum);
 
 #ifdef CONFIG_CPM2
 /*
@@ -296,7 +295,7 @@ int misc_init_r (void)
 
                /* Monitor protection ON by default */
                flash_protect (FLAG_PROTECT_SET,
-                              CFG_MONITOR_BASE, 0xffffffff,
+                              CFG_MONITOR_BASE, CFG_MONITOR_BASE + monitor_flash_len - 1,
                               &flash_info[CFG_MAX_FLASH_BANKS - 1]);
 
                /* Environment protection ON by default */
index 4b7a1107a9a5b6fa905d357c438521f495c91923..df17da5eafb40e624271efbf48aac6ee269d04f3 100644 (file)
 #define AMD_CMD_ERASE_SECTOR           0x30
 #define AMD_CMD_UNLOCK_START           0xAA
 #define AMD_CMD_UNLOCK_ACK             0x55
+#define AMD_CMD_WRITE_TO_BUFFER                0x25
+#define AMD_CMD_WRITE_BUFFER_CONFIRM   0x29
 
 #define AMD_STATUS_TOGGLE              0x40
 #define AMD_STATUS_ERROR               0x20
-#define AMD_ADDR_ERASE_START           0x555
-#define AMD_ADDR_START                 0x555
-#define AMD_ADDR_ACK                   0x2AA
+
+#define AMD_ADDR_ERASE_START   ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
+#define AMD_ADDR_START         ((info->portwidth == FLASH_CFI_8BIT) ? 0xAAA : 0x555)
+#define AMD_ADDR_ACK           ((info->portwidth == FLASH_CFI_8BIT) ? 0x555 : 0x2AA)
 
 #define FLASH_OFFSET_CFI               0x55
 #define FLASH_OFFSET_CFI_RESP          0x10
@@ -175,6 +178,13 @@ static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST;
 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];          /* FLASH chips info */
 #endif
 
+/*
+ * Check if chip width is defined. If not, start detecting with 8bit.
+ */
+#ifndef CFG_FLASH_CFI_WIDTH
+#define CFG_FLASH_CFI_WIDTH    FLASH_CFI_8BIT
+#endif
+
 
 /*-----------------------------------------------------------------------
  * Functions
@@ -190,7 +200,6 @@ static int flash_isequal (flash_info_t * info, flash_sect_t sect, uint offset, u
 static int flash_isset (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
 static int flash_toggle (flash_info_t * info, flash_sect_t sect, uint offset, uchar cmd);
 static int flash_detect_cfi (flash_info_t * info);
-ulong flash_get_size (ulong base, int banknum);
 static int flash_write_cfiword (flash_info_t * info, ulong dest, cfiword_t cword);
 static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
                                    ulong tout, char *prompt);
@@ -328,6 +337,7 @@ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)
        return retval;
 }
 
+
 /*-----------------------------------------------------------------------
  */
 unsigned long flash_init (void)
@@ -345,6 +355,24 @@ unsigned long flash_init (void)
                                i, flash_info[i].size, flash_info[i].size << 20);
 #endif /* CFG_FLASH_QUIET_TEST */
                }
+#ifdef CFG_FLASH_PROTECTION
+               else {
+                       char *s = getenv("unlock");
+
+                       if (((s = getenv("unlock")) != NULL) && (strcmp(s, "yes") == 0)) {
+                               /*
+                                * Only the U-Boot image and it's environment is protected,
+                                * all other sectors are unprotected (unlocked) if flash
+                                * hardware protection is used (CFG_FLASH_PROTECTION) and
+                                * the environment variable "unlock" is set to "yes".
+                                */
+                               flash_protect (FLAG_PROTECT_CLEAR,
+                                              flash_info[i].start[0],
+                                              flash_info[i].start[0] + flash_info[i].size - 1,
+                                              &flash_info[i]);
+                       }
+               }
+#endif /* CFG_FLASH_PROTECTION */
        }
 
        /* Monitor protection ON by default */
@@ -565,7 +593,22 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
        buffered_size = (info->portwidth / info->chipwidth);
        buffered_size *= info->buffer_size;
        while (cnt >= info->portwidth) {
-               i = buffered_size > cnt ? cnt : buffered_size;
+               /* prohibit buffer write when buffer_size is 1 */
+               if (info->buffer_size == 1) {
+                       cword.l = 0;
+                       for (i = 0; i < info->portwidth; i++)
+                               flash_add_byte (info, &cword, *src++);
+                       if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
+                               return rc;
+                       wp += info->portwidth;
+                       cnt -= info->portwidth;
+                       continue;
+               }
+
+               /* write buffer until next buffered_size aligned boundary */
+               i = buffered_size - (wp % buffered_size);
+               if (i > cnt)
+                       i = cnt;
                if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
                        return rc;
                i -= i & (info->portwidth - 1);
@@ -705,7 +748,7 @@ static int flash_status_check (flash_info_t * info, flash_sect_t sector,
        /* Wait for command completion */
        start = get_timer (0);
        while (flash_is_busy (info, sector)) {
-               if (get_timer (start) > info->erase_blk_tout * CFG_HZ) {
+               if (get_timer (start) > tout) {
                        printf ("Flash %s timeout at address %lx data %lx\n",
                                prompt, info->start[sector],
                                flash_read_long (info, sector, 0));
@@ -729,7 +772,7 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector,
        switch (info->vendor) {
        case CFI_CMDSET_INTEL_EXTENDED:
        case CFI_CMDSET_INTEL_STANDARD:
-               if ((retcode != ERR_OK)
+               if ((retcode == ERR_OK)
                    && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
                        retcode = ERR_INVAL;
                        printf ("Flash %s error at address %lx\n", prompt,
@@ -985,7 +1028,7 @@ static int flash_detect_cfi (flash_info_t * info)
 {
        debug ("flash detect cfi\n");
 
-       for (info->portwidth = FLASH_CFI_8BIT;
+       for (info->portwidth = CFG_FLASH_CFI_WIDTH;
             info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
                for (info->chipwidth = FLASH_CFI_BY8;
                     info->chipwidth <= info->portwidth;
@@ -1106,8 +1149,9 @@ ulong flash_get_size (ulong base, int banknum)
                info->erase_blk_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_EMAX_TOUT)));
                tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT);
                info->buffer_write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)));
-               tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT);
-               info->write_tout = (tmp * (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT))) / 1000;
+               tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) *
+                     (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT));
+               info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); /* round up when converting to ms */
                info->flash_id = FLASH_MAN_CFI;
                if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
                        info->portwidth >>= 1;  /* XXX - Need to test on x8/x16 in parallel. */
@@ -1118,13 +1162,26 @@ ulong flash_get_size (ulong base, int banknum)
        return (info->size);
 }
 
+/* loop through the sectors from the highest address
+ * when the passed address is greater or equal to the sector address
+ * we have a match
+ */
+static flash_sect_t find_sector (flash_info_t * info, ulong addr)
+{
+       flash_sect_t sector;
+
+       for (sector = info->sector_count - 1; sector >= 0; sector--) {
+               if (addr >= info->start[sector])
+                       break;
+       }
+       return sector;
+}
 
 /*-----------------------------------------------------------------------
  */
 static int flash_write_cfiword (flash_info_t * info, ulong dest,
                                cfiword_t cword)
 {
-
        cfiptr_t ctladdr;
        cfiptr_t cptr;
        int flag;
@@ -1188,26 +1245,12 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest,
        if (flag)
                enable_interrupts ();
 
-       return flash_full_status_check (info, 0, info->write_tout, "write");
+       return flash_full_status_check (info, find_sector (info, dest),
+                                       info->write_tout, "write");
 }
 
 #ifdef CFG_FLASH_USE_BUFFER_WRITE
 
-/* loop through the sectors from the highest address
- * when the passed address is greater or equal to the sector address
- * we have a match
- */
-static flash_sect_t find_sector (flash_info_t * info, ulong addr)
-{
-       flash_sect_t sector;
-
-       for (sector = info->sector_count - 1; sector >= 0; sector--) {
-               if (addr >= info->start[sector])
-                       break;
-       }
-       return sector;
-}
-
 static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
                                  int len)
 {
@@ -1216,66 +1259,106 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp,
        int retcode;
        volatile cfiptr_t src;
        volatile cfiptr_t dst;
-       /* buffered writes in the AMD chip set is not supported yet */
-       if((info->vendor ==  CFI_CMDSET_AMD_STANDARD) ||
-               (info->vendor == CFI_CMDSET_AMD_EXTENDED))
-               return ERR_INVAL;
 
-       src.cp = cp;
-       dst.cp = (uchar *) dest;
-       sector = find_sector (info, dest);
-       flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
-       flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
-       if ((retcode =
-            flash_status_check (info, sector, info->buffer_write_tout,
-                                "write to buffer")) == ERR_OK) {
-               /* reduce the number of loops by the width of the port  */
+       switch (info->vendor) {
+       case CFI_CMDSET_INTEL_STANDARD:
+       case CFI_CMDSET_INTEL_EXTENDED:
+               src.cp = cp;
+               dst.cp = (uchar *) dest;
+               sector = find_sector (info, dest);
+               flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+               flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
+               if ((retcode = flash_status_check (info, sector, info->buffer_write_tout,
+                                                  "write to buffer")) == 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:
+                               return ERR_INVAL;
+                               break;
+                       }
+                       flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
+                       while (cnt-- > 0) {
+                               switch (info->portwidth) {
+                               case FLASH_CFI_8BIT:
+                                       *dst.cp++ = *src.cp++;
+                                       break;
+                               case FLASH_CFI_16BIT:
+                                       *dst.wp++ = *src.wp++;
+                                       break;
+                               case FLASH_CFI_32BIT:
+                                       *dst.lp++ = *src.lp++;
+                                       break;
+                               case FLASH_CFI_64BIT:
+                                       *dst.llp++ = *src.llp++;
+                                       break;
+                               default:
+                                       return ERR_INVAL;
+                                       break;
+                               }
+                       }
+                       flash_write_cmd (info, sector, 0,
+                                        FLASH_CMD_WRITE_BUFFER_CONFIRM);
+                       retcode = flash_full_status_check (info, sector,
+                                                          info->buffer_write_tout,
+                                                          "buffer write");
+               }
+               return retcode;
+
+       case CFI_CMDSET_AMD_STANDARD:
+       case CFI_CMDSET_AMD_EXTENDED:
+               src.cp = cp;
+               dst.cp = (uchar *) dest;
+               sector = find_sector (info, dest);
+
+               flash_unlock_seq(info,0);
+               flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER);
+
                switch (info->portwidth) {
                case FLASH_CFI_8BIT:
                        cnt = len;
+                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
+                       while (cnt-- > 0) *dst.cp++ = *src.cp++;
                        break;
                case FLASH_CFI_16BIT:
                        cnt = len >> 1;
+                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
+                       while (cnt-- > 0) *dst.wp++ = *src.wp++;
                        break;
                case FLASH_CFI_32BIT:
                        cnt = len >> 2;
+                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
+                       while (cnt-- > 0) *dst.lp++ = *src.lp++;
                        break;
                case FLASH_CFI_64BIT:
                        cnt = len >> 3;
+                       flash_write_cmd (info, sector, 0,  (uchar) cnt - 1);
+                       while (cnt-- > 0) *dst.llp++ = *src.llp++;
                        break;
                default:
                        return ERR_INVAL;
-                       break;
-               }
-               flash_write_cmd (info, sector, 0, (uchar) cnt - 1);
-               while (cnt-- > 0) {
-                       switch (info->portwidth) {
-                       case FLASH_CFI_8BIT:
-                               *dst.cp++ = *src.cp++;
-                               break;
-                       case FLASH_CFI_16BIT:
-                               *dst.wp++ = *src.wp++;
-                               break;
-                       case FLASH_CFI_32BIT:
-                               *dst.lp++ = *src.lp++;
-                               break;
-                       case FLASH_CFI_64BIT:
-                               *dst.llp++ = *src.llp++;
-                               break;
-                       default:
-                               return ERR_INVAL;
-                               break;
-                       }
                }
-               flash_write_cmd (info, sector, 0,
-                                FLASH_CMD_WRITE_BUFFER_CONFIRM);
-               retcode =
-                       flash_full_status_check (info, sector,
-                                                info->buffer_write_tout,
-                                                "buffer write");
+
+               flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
+               retcode = flash_full_status_check (info, sector, info->buffer_write_tout,
+                                                  "buffer write");
+               return retcode;
+
+       default:
+               debug ("Unknown Command Set\n");
+               return ERR_INVAL;
        }
-       flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
-       return retcode;
 }
 #endif /* CFG_FLASH_USE_BUFFER_WRITE */
 #endif /* CFG_FLASH_CFI */
index 069aa63414d05190963b05114c78253d4227e2c9..91087233664cc8681d9fb3372c357c6160cf4f8e 100644 (file)
@@ -80,6 +80,7 @@ extern void flash_print_info (flash_info_t *);
 extern int flash_erase (flash_info_t *, int, int);
 extern int flash_sect_erase (ulong addr_first, ulong addr_last);
 extern int flash_sect_protect (int flag, ulong addr_first, ulong addr_last);
+extern ulong flash_get_size (ulong base, int banknum);
 
 /* common/flash.c */
 extern void flash_protect (int flag, ulong from, ulong to, flash_info_t *info);
@@ -274,6 +275,12 @@ extern void flash_read_factory_serial(flash_info_t * info, void * buffer, int of
 #define INTEL_ID_28F64K3    0x88018801 /*  64M =  32K x 255 + 32k x 4 */
 #define INTEL_ID_28F128K3   0x88028802 /* 128M =  64K x 255 + 32k x 4 */
 #define INTEL_ID_28F256K3   0x88038803 /* 256M = 128K x 255 + 32k x 4 */
+#define INTEL_ID_28F64P30T  0x88178817 /*  64M =  32K x 255 + 32k x 4 */
+#define INTEL_ID_28F64P30B  0x881A881A /*  64M =  32K x 255 + 32k x 4 */
+#define INTEL_ID_28F128P30T 0x88188818 /* 128M =  64K x 255 + 32k x 4 */
+#define INTEL_ID_28F128P30B 0x881B881B /* 128M =  64K x 255 + 32k x 4 */
+#define INTEL_ID_28F256P30T 0x88198819 /* 256M = 128K x 255 + 32k x 4 */
+#define INTEL_ID_28F256P30B 0x881C881C /* 256M = 128K x 255 + 32k x 4 */
 
 #define INTEL_ID_28F160S3   0x00D000D0 /*  16M = 512K x  32 (64kB x 32)        */
 #define INTEL_ID_28F320S3   0x00D400D4 /*  32M = 512K x  64 (64kB x 64)        */