Merge with http://www.denx.de/git/u-boot.git
[oweals/u-boot.git] / board / trab / flash.c
index d86c4bf7706aea006d2c1c9635c3a946f9a3c763..8cdd82400bba2b49b2314d14489fa328f97e4c9f 100644 (file)
@@ -39,7 +39,10 @@ flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
 #define CMD_PROGRAM            0x00A000A0
 #define CMD_UNLOCK_BYPASS      0x00200020
 #define CMD_READ_MANF_ID       0x00900090
+#define CMD_UNLOCK_BYPASS_RES1 0x00900090
+#define CMD_UNLOCK_BYPASS_RES2 0x00000000
 
+#define MEM_FLASH_ADDR         (*(volatile u32 *)CFG_FLASH_BASE)
 #define MEM_FLASH_ADDR1                (*(volatile u32 *)(CFG_FLASH_BASE + (0x00000555 << 2)))
 #define MEM_FLASH_ADDR2                (*(volatile u32 *)(CFG_FLASH_BASE + (0x000002AA << 2)))
 
@@ -80,6 +83,7 @@ ulong flash_init (void)
 
                        switch (info->flash_id & FLASH_TYPEMASK) {
                        case (FLASH_AM320B & FLASH_TYPEMASK):
+                       case (FLASH_MXLV320B & FLASH_TYPEMASK):
                                /* Boot sector type: 8 x 8 + N x 128 kB */
                                flashbase += (j < 8) ? 0x4000 : 0x20000;
                                break;
@@ -99,7 +103,7 @@ ulong flash_init (void)
         */
        flash_protect ( FLAG_PROTECT_SET,
                        CFG_FLASH_BASE,
-                       CFG_FLASH_BASE + _armboot_end_data - _armboot_start,
+                       CFG_FLASH_BASE + monitor_flash_len - 1,
                        &flash_info[0]);
 
        flash_protect ( FLAG_PROTECT_SET,
@@ -127,6 +131,8 @@ void flash_print_info (flash_info_t * info)
                        printf ("AMD ");                break;
        case (FLASH_MAN_FUJ & FLASH_VENDMASK):
                        printf ("FUJITSU ");            break;
+       case (FLASH_MAN_MX  & FLASH_VENDMASK):
+                       printf ("MACRONIX ");           break;
        default:        printf ("Unknown Vendor ");     break;
        }
 
@@ -134,6 +140,9 @@ void flash_print_info (flash_info_t * info)
        case (FLASH_AM320B & FLASH_TYPEMASK):
                printf ("2x Am29LV320DB (32Mbit)\n");
                break;
+       case (FLASH_MXLV320B & FLASH_TYPEMASK):
+               printf ("2x MX29LV320DB (32Mbit)\n");
+               break;
        case (FLASH_AM640U & FLASH_TYPEMASK):
                printf ("2x Am29LV640D (64Mbit)\n");
                break;
@@ -157,7 +166,7 @@ void flash_print_info (flash_info_t * info)
        }
        printf ("\n");
 
-  Done:
+Done:  ;
 }
 
 /*-----------------------------------------------------------------------
@@ -185,9 +194,13 @@ int flash_erase (flash_info_t * info, int s_first, int s_last)
                return ERR_INVAL;
        }
 
-       if ((info->flash_id & FLASH_VENDMASK) !=
-               (FLASH_MAN_AMD & FLASH_VENDMASK)) {
-               return ERR_UNKNOWN_FLASH_VENDOR;
+       switch (info->flash_id & FLASH_VENDMASK) {
+       case (FLASH_MAN_AMD & FLASH_VENDMASK):  break;  /* OK */
+       case (FLASH_MAN_FUJ & FLASH_VENDMASK):  break;  /* OK */
+       case (FLASH_MAN_MX  & FLASH_VENDMASK):  break;  /* OK */
+       default:
+               debug ("## flash_erase: unknown manufacturer\n");
+               return (ERR_UNKNOWN_FLASH_VENDOR);
        }
 
        prot = 0;
@@ -295,8 +308,7 @@ outahere:
  * Copy memory to flash
  */
 
-volatile static int write_word (flash_info_t * info, ulong dest,
-                                                               ulong data)
+static int write_word (flash_info_t * info, ulong dest, ulong data)
 {
        vu_long *addr = (vu_long *) dest;
        ulong result;
@@ -328,9 +340,6 @@ volatile static int write_word (flash_info_t * info, ulong dest,
 #endif
        iflag = disable_interrupts ();
 
-       MEM_FLASH_ADDR1 = CMD_UNLOCK1;
-       MEM_FLASH_ADDR2 = CMD_UNLOCK2;
-       MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
        *addr = CMD_PROGRAM;
        *addr = data;
 
@@ -399,6 +408,10 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
        int l;
        int i, rc;
 
+       MEM_FLASH_ADDR1 = CMD_UNLOCK1;
+       MEM_FLASH_ADDR2 = CMD_UNLOCK2;
+       MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
+
        wp = (addr & ~3);       /* get lower word aligned address */
 
        /*
@@ -419,7 +432,7 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
                }
 
                if ((rc = write_word (info, wp, data)) != 0) {
-                       return (rc);
+                       goto Done;
                }
                wp += 4;
        }
@@ -428,9 +441,17 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
         * handle word aligned part
         */
        while (cnt >= 4) {
-               data = *((vu_long *) src);
+               if (((ulong)src) & 0x3) {
+                       for (i = 0; i < 4; i++) {
+                               ((char *)&data)[i] = ((vu_char *)src)[i];
+                       }
+               }
+               else {
+                       data = *((vu_long *) src);
+               }
+
                if ((rc = write_word (info, wp, data)) != 0) {
-                       return (rc);
+                       goto Done;
                }
                src += 4;
                wp += 4;
@@ -438,7 +459,8 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
        }
 
        if (cnt == 0) {
-               return ERR_OK;
+               rc = ERR_OK;
+               goto Done;
        }
 
        /*
@@ -453,7 +475,14 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
                data = (data >> 8) | (*(uchar *) cp << 24);
        }
 
-       return write_word (info, wp, data);
+       rc = write_word (info, wp, data);
+
+       Done:
+
+       MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES1;
+       MEM_FLASH_ADDR = CMD_UNLOCK_BYPASS_RES2;
+
+       return (rc);
 }
 
 /*-----------------------------------------------------------------------
@@ -479,6 +508,9 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
        case FUJ_MANUFACT:
                info->flash_id = FLASH_MAN_FUJ;
                break;
+       case MX_MANUFACT:
+               info->flash_id = FLASH_MAN_MX;
+               break;
        default:
                info->flash_id = FLASH_UNKNOWN;
                info->sector_count = 0;
@@ -509,6 +541,14 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
                addr[0] = 0x00F000F0;           /* restore read mode */
                break;                          /* => 16 MB             */
 
+       case MX_ID_LV320B:
+               info->flash_id += FLASH_MXLV320B;
+               info->sector_count = 71;
+               info->size = 0x00800000;
+
+               addr[0] = 0x00FF00FF;           /* restore read mode */
+               break;                          /* =>  8 MB             */
+
        default:
                debug ("## flash_init: unknown flash chip\n");
                info->flash_id = FLASH_UNKNOWN;