rename CFG_ macros to CONFIG_SYS
[platform/kernel/u-boot.git] / board / mpl / common / flash.c
index f0c541b..302d7a3 100644 (file)
 
 /*
  * Modified 3/7/2001
- * - adopted for pip405, Denis Peter, MPL AG Switzerland
+ * - adapted for pip405, Denis Peter, MPL AG Switzerland
  * TODO:
  * clean-up
  */
 
 #include <common.h>
+
+#if !defined(CONFIG_PATI)
 #include <ppc4xx.h>
 #include <asm/processor.h>
-#ifdef CONFIG_PIP405
+#include "common_util.h"
+#if defined(CONFIG_MIP405)
+#include "../mip405/mip405.h"
+#endif
+#if defined(CONFIG_PIP405)
 #include "../pip405/pip405.h"
 #endif
-#ifdef CONFIG_MIP405
-#include "../mip405/mip405.h"
+#include <asm/4xx_pci.h>
+#else /* defined(CONFIG_PATI) */
+#include <mpc5xx.h>
 #endif
-#include "common_util.h"
 
-flash_info_t   flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
+flash_info_t   flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
 /*-----------------------------------------------------------------------
  * Functions
  */
 static ulong flash_get_size (vu_long *addr, flash_info_t *info);
 static int write_word (flash_info_t *info, ulong dest, ulong data);
-static void flash_get_offsets (ulong base, flash_info_t *info);
 
 void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt);
 
-
-#ifdef CONFIG_ADCIOP
-#define ADDR0           0x0aa9
-#define ADDR1           0x0556
-#define FLASH_WORD_SIZE unsigned char
-#endif
-
-#ifdef CONFIG_CPCI405
-#define ADDR0           0x5555
-#define ADDR1           0x2aaa
-#define FLASH_WORD_SIZE unsigned short
-#endif
-
-#ifdef CONFIG_PIP405
 #define ADDR0           0x5555
 #define ADDR1           0x2aaa
 #define FLASH_WORD_SIZE unsigned short
-#endif
-
-#ifdef CONFIG_MIP405
-#define ADDR0           0x5555
-#define ADDR1           0x2aaa
-#define FLASH_WORD_SIZE unsigned short
-#endif
 
 #define FALSE           0
 #define TRUE            1
 
+#if !defined(CONFIG_PATI)
+
 /*-----------------------------------------------------------------------
+ * Some CS switching routines:
+ *
+ * On PIP/MIP405 we have 3 (4) possible boot mode
+ *
+ * - Boot from Flash (Flash CS = CS0, MPS CS = CS1)
+ * - Boot from MPS   (Flash CS = CS1, MPS CS = CS0)
+ * - Boot from PCI with Flash map (Flash CS = CS0, MPS CS = CS1)
+ * - Boot from PCI with MPS map   (Flash CS = CS1, MPS CS = CS0)
+ * The flash init is the first board specific routine which is called
+ * after code relocation (running from SDRAM)
+ * The first thing we do is to map the Flash CS to the Flash area and
+ * the MPS CS to the MPS area. Since the flash size is unknown at this
+ * point, we use the max flash size and the lowest flash address as base.
+ *
+ * After flash detection we adjust the size of the CS area accordingly.
+ * The board_init_r will fill in wrong values in the board init structure,
+ * but this will be fixed in the misc_init_r routine:
+ * bd->bi_flashstart=0-flash_info[0].size
+ * bd->bi_flashsize=flash_info[0].size-CONFIG_SYS_MONITOR_LEN
+ * bd->bi_flashoffset=0
+ *
  */
+int get_boot_mode(void)
+{
+       unsigned long pbcr;
+       int res = 0;
+       pbcr = mfdcr (strap);
+       if ((pbcr & PSR_ROM_WIDTH_MASK) == 0)
+               /* boot via MPS or MPS mapping */
+               res = BOOT_MPS;
+       if(pbcr & PSR_ROM_LOC)
+               /* boot via PCI.. */
+               res |= BOOT_PCI;
+        return res;
+}
 
+/* Map the flash high (in boot area)
+   This code can only be executed from SDRAM (after relocation).
+*/
+void setup_cs_reloc(void)
+{
+       int mode;
+       /* Since we are relocated, we can set-up the CS finaly
+        * but first of all, switch off PCI mapping (in case it was a PCI boot) */
+       out32r(PMM0MA,0L);
+       icache_enable (); /* we are relocated */
+       /* get boot mode */
+       mode=get_boot_mode();
+       /* we map the flash high in every case */
+       /* first findout on which cs the flash is */
+       if(mode & BOOT_MPS) {
+               /* map flash high on CS1 and MPS on CS0 */
+               mtdcr (ebccfga, pb0ap);
+               mtdcr (ebccfgd, MPS_AP);
+               mtdcr (ebccfga, pb0cr);
+               mtdcr (ebccfgd, MPS_CR);
+               /* we use the default values (max values) for the flash
+                * because its real size is not yet known */
+               mtdcr (ebccfga, pb1ap);
+               mtdcr (ebccfgd, FLASH_AP);
+               mtdcr (ebccfga, pb1cr);
+               mtdcr (ebccfgd, FLASH_CR_B);
+       }
+       else {
+               /* map flash high on CS0 and MPS on CS1 */
+               mtdcr (ebccfga, pb1ap);
+               mtdcr (ebccfgd, MPS_AP);
+               mtdcr (ebccfga, pb1cr);
+               mtdcr (ebccfgd, MPS_CR);
+               /* we use the default values (max values) for the flash
+                * because its real size is not yet known */
+               mtdcr (ebccfga, pb0ap);
+               mtdcr (ebccfgd, FLASH_AP);
+               mtdcr (ebccfga, pb0cr);
+               mtdcr (ebccfgd, FLASH_CR_B);
+       }
+}
+
+#endif /* #if !defined(CONFIG_PATI) */
 
 unsigned long flash_init (void)
 {
-       unsigned long size_b0, size_b1;
+       unsigned long size_b0;
        int i;
-  unsigned long pbcr;
-  unsigned long base_b0, base_b1;
-  unsigned char rc;
-
-  rc=switch_cs(FALSE); /* map Flash High */
 
-       if(rc)
-               printf("(MPS Boot) ");
+#if !defined(CONFIG_PATI)
+       unsigned long size_b1,flashcr,size_reg;
+       int mode;
+       extern char version_string;
+       char *p = &version_string;
+
+       /* Since we are relocated, we can set-up the CS finally */
+       setup_cs_reloc();
+       /* get and display boot mode */
+       mode=get_boot_mode();
+       if(mode & BOOT_PCI)
+               printf("(PCI Boot %s Map) ",(mode & BOOT_MPS) ?
+                       "MPS" : "Flash");
        else
-               printf("(Flash Boot) ");
+               printf("(%s Boot) ",(mode & BOOT_MPS) ?
+                       "MPS" : "Flash");
+#endif /* #if !defined(CONFIG_PATI) */
        /* Init: no FLASHes known */
-       for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+       for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
                flash_info[i].flash_id = FLASH_UNKNOWN;
        }
 
        /* Static FLASH Bank configuration here - FIXME XXX */
 
-       size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+       size_b0 = flash_get_size((vu_long *)CONFIG_SYS_MONITOR_BASE, &flash_info[0]);
 
        if (flash_info[0].flash_id == FLASH_UNKNOWN) {
                printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
                        size_b0, size_b0<<20);
        }
-       /* Only one bank */
-       if (CFG_MAX_FLASH_BANKS == 1)
-         {
-           /* Setup offsets */
-                       /*  flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]); */
-           /* Monitor protection ON by default */
-#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
-                   flash_protect(FLAG_PROTECT_SET,
-                               CFG_MONITOR_BASE,
-                               CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
-                               &flash_info[0]);
+       /* protect the bootloader */
+       /* Monitor protection ON by default */
+#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE
+       flash_protect(FLAG_PROTECT_SET,
+                       CONFIG_SYS_MONITOR_BASE,
+                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
+                       &flash_info[0]);
 #endif
-           size_b1 = 0 ;
-           flash_info[0].size = size_b0;
-         }
-
-       /* 2 banks */
-       else
-         {
-           size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
-
-           /* Re-do sizing to get full correct info */
-
-           if (size_b1)
-             {
-               mtdcr(ebccfga, pb0cr);
-               pbcr = mfdcr(ebccfgd);
-               mtdcr(ebccfga, pb0cr);
-               base_b1 = -size_b1;
-               pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
-               mtdcr(ebccfgd, pbcr);
-               /*          printf("pb1cr = %x\n", pbcr); */
-             }
-
-           if (size_b0)
-             {
+#if !defined(CONFIG_PATI)
+       /* protect reset vector */
+       flash_info[0].protect[flash_info[0].sector_count-1] = 1;
+       size_b1 = 0 ;
+       flash_info[0].size = size_b0;
+       /* set up flash cs according to the size */
+       size_reg=(flash_info[0].size >>20);
+       switch (size_reg) {
+               case 0:
+               case 1: i=0; break; /* <= 1MB */
+               case 2: i=1; break; /* = 2MB */
+               case 4: i=2; break; /* = 4MB */
+               case 8: i=3; break; /* = 8MB */
+               case 16: i=4; break; /* = 16MB */
+               case 32: i=5; break; /* = 32MB */
+               case 64: i=6; break; /* = 64MB */
+               case 128: i=7; break; /*= 128MB */
+               default:
+                       printf("\n #### ERROR, wrong size %ld MByte reset board #####\n",size_reg);
+                       while(1);
+       }
+       if(mode & BOOT_MPS) {
+               /* flash is on CS1 */
                mtdcr(ebccfga, pb1cr);
-               pbcr = mfdcr(ebccfgd);
+               flashcr = mfdcr (ebccfgd);
+               /* we map the flash high in every case */
+               flashcr&=0x0001FFFF; /* mask out address bits */
+               flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */
+               flashcr|= (i << 17); /* size addr */
                mtdcr(ebccfga, pb1cr);
-               base_b0 = base_b1 - size_b0;
-               pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
-               mtdcr(ebccfgd, pbcr);
-               /*            printf("pb0cr = %x\n", pbcr); */
-             }
-
-           size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]);
-
-           flash_get_offsets (base_b0, &flash_info[0]);
-
-           /* monitor protection ON by default */
-           (void)flash_protect(FLAG_PROTECT_SET,
-                               base_b0+size_b0-CFG_MONITOR_LEN,
-                               base_b0+size_b0-1,
-                               &flash_info[0]);
-
-           if (size_b1) {
-             /* Re-do sizing to get full correct info */
-             size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]);
-
-             flash_get_offsets (base_b1, &flash_info[1]);
-
-             /* monitor protection ON by default */
-             (void)flash_protect(FLAG_PROTECT_SET,
-                                 base_b1+size_b1-CFG_MONITOR_LEN,
-                                 base_b1+size_b1-1,
-                                 &flash_info[1]);
-             /* monitor protection OFF by default (one is enough) */
-             (void)flash_protect(FLAG_PROTECT_CLEAR,
-                                 base_b0+size_b0-CFG_MONITOR_LEN,
-                                 base_b0+size_b0-1,
-                                 &flash_info[0]);
-           } else {
-             flash_info[1].flash_id = FLASH_UNKNOWN;
-             flash_info[1].sector_count = -1;
-           }
-
-           flash_info[0].size = size_b0;
-           flash_info[1].size = size_b1;
-         }/* else 2 banks */
-       switch_cs(rc); /* switch mode back */
-       return (size_b0 + size_b1);
-}
-
-
-static void flash_get_offsets (ulong base, flash_info_t *info)
-{
-       return;
-}
+               mtdcr(ebccfgd, flashcr);
+       }
+       else {
+               /* flash is on CS0 */
+               mtdcr(ebccfga, pb0cr);
+               flashcr = mfdcr (ebccfgd);
+               /* we map the flash high in every case */
+               flashcr&=0x0001FFFF; /* mask out address bits */
+               flashcr|= ((0-flash_info[0].size) & 0xFFF00000); /* start addr */
+               flashcr|= (i << 17); /* size addr */
+               mtdcr(ebccfga, pb0cr);
+               mtdcr(ebccfgd, flashcr);
+       }
 #if 0
-/*-----------------------------------------------------------------------
- */
-static void flash_get_offsets (ulong base, flash_info_t *info)
-{
-       int i;
-
-       /* set up sector start address table */
-  if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
-           (info->flash_id  == FLASH_AM040)){
-               for (i = 0; i < info->sector_count; i++)
-                       info->start[i] = base + (i * 0x00010000);
-  }
-  else {
-               if (info->flash_id & FLASH_BTYPE) {
-               /* set sector offsets for bottom boot block type        */
-               info->start[0] = base + 0x00000000;
-               info->start[1] = base + 0x00004000;
-               info->start[2] = base + 0x00006000;
-               info->start[3] = base + 0x00008000;
-               for (i = 4; i < info->sector_count; i++) {
-                       info->start[i] = base + (i * 0x00010000) - 0x00030000;
-               }
-           } else {
-               /* set sector offsets for top boot block type           */
-               i = info->sector_count - 1;
-               info->start[i--] = base + info->size - 0x00004000;
-               info->start[i--] = base + info->size - 0x00006000;
-               info->start[i--] = base + info->size - 0x00008000;
-               for (; i >= 0; i--) {
-                       info->start[i] = base + i * 0x00010000;
+       /* enable this (PIP405/MIP405 only) if you want to test if
+          the relocation has be done ok.
+          This will disable both Chipselects */
+       mtdcr (ebccfga, pb0cr);
+       mtdcr (ebccfgd, 0L);
+       mtdcr (ebccfga, pb1cr);
+       mtdcr (ebccfgd, 0L);
+       printf("CS0 & CS1 switched off for test\n");
+#endif
+       /* patch version_string */
+       for(i=0;i<0x100;i++) {
+               if(*p=='\n') {
+                       *p=0;
+                       break;
                }
-           }
+               p++;
        }
+#else /* #if !defined(CONFIG_PATI) */
+#ifdef CONFIG_ENV_IS_IN_FLASH
+       /* ENV protection ON by default */
+       flash_protect(FLAG_PROTECT_SET,
+                     CONFIG_ENV_ADDR,
+                     CONFIG_ENV_ADDR+CONFIG_ENV_SECT_SIZE-1,
+                     &flash_info[0]);
+#endif
+#endif /* #if !defined(CONFIG_PATI) */
+       return (size_b0);
 }
 
-#endif
+
 /*-----------------------------------------------------------------------
  */
 void flash_print_info  (flash_info_t *info)
 {
        int i;
-    int k;
-       int size;
-    int erased;
-    volatile unsigned long *flash;
+       int k;
+       int size;
+       int erased;
+       volatile unsigned long *flash;
 
        if (info->flash_id == FLASH_UNKNOWN) {
                printf ("missing or unknown FLASH type\n");
@@ -288,6 +316,8 @@ void flash_print_info  (flash_info_t *info)
                                break;
        case FLASH_INTEL320T:   printf ("TE28F320C3 (32 Mbit, top sector size)\n");
                                break;
+       case FLASH_AM640U:      printf ("AM29LV640U (64 Mbit, uniform sector size)\n");
+                               break;
        default:                printf ("Unknown Chip Type\n");
                                break;
        }
@@ -297,40 +327,30 @@ void flash_print_info  (flash_info_t *info)
 
        printf ("  Sector Start Addresses:");
        for (i=0; i<info->sector_count; ++i) {
-       /*
-     * Check if whole sector is erased
-     */
+               /*
+                * Check if whole sector is erased
+               */
                if (i != (info->sector_count-1))
-       size = info->start[i+1] - info->start[i];
+                       size = info->start[i+1] - info->start[i];
                else
-      size = info->start[0] + info->size - info->start[i];
-    erased = 1;
-    flash = (volatile unsigned long *)info->start[i];
-    size = size >> 2;        /* divide by 4 for longword access */
-    for (k=0; k<size; k++)
-    {
-       if (*flash++ != 0xffffffff)
-                       {
-                               erased = 0;
+                       size = info->start[0] + info->size - info->start[i];
+               erased = 1;
+               flash = (volatile unsigned long *)info->start[i];
+               size = size >> 2;        /* divide by 4 for longword access */
+               for (k=0; k<size; k++) {
+                       if (*flash++ != 0xffffffff) {
+                               erased = 0;
                                break;
                        }
-               }
+               }
                if ((i % 5) == 0)
                        printf ("\n   ");
-#if 0 /* test-only */
-               printf (" %08lX%s",
-                       info->start[i],
-                       info->protect[i] ? " (RO)" : "     "
-#else
                printf (" %08lX%s%s",
                        info->start[i],
                        erased ? " E" : "  ",
-                       info->protect[i] ? "RO " : "   "
-#endif
-               );
+                       info->protect[i] ? "RO " : "   ");
        }
        printf ("\n");
-
 }
 
 /*-----------------------------------------------------------------------
@@ -338,7 +358,8 @@ void flash_print_info  (flash_info_t *info)
 
 
 /*-----------------------------------------------------------------------
- */
+
+*/
 
 /*
  * The following code cannot be run from FLASH!
@@ -347,7 +368,7 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
 {
        short i;
        FLASH_WORD_SIZE value;
-       ulong base = (ulong)addr;
+       ulong base;
        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
 
        /* Write auto select command: read Manufacturer ID */
@@ -377,10 +398,10 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
                return (0);                     /* no or unknown flash  */
        }
        value = addr2[1];                       /* device ID            */
-       /*      printf("Device value %x\n",value); */
+       /*      printf("Device value %x\n",value);                  */
        switch (value) {
        case (FLASH_WORD_SIZE)AMD_ID_F040B:
-               info->flash_id += FLASH_AM040;
+               info->flash_id += FLASH_AM040;
                info->sector_count = 8;
                info->size = 0x0080000; /* => 512 ko */
                break;
@@ -419,12 +440,17 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
                info->sector_count = 35;
                info->size = 0x00200000;
                break;                          /* => 2 MB              */
-#if 0  /* enable when device IDs are available */
        case (FLASH_WORD_SIZE)AMD_ID_LV320T:
                info->flash_id += FLASH_AM320T;
                info->sector_count = 67;
                info->size = 0x00400000;
                break;                          /* => 4 MB              */
+       case (FLASH_WORD_SIZE)AMD_ID_LV640U:
+               info->flash_id += FLASH_AM640U;
+               info->sector_count = 128;
+               info->size = 0x00800000;
+               break;                          /* => 8 MB              */
+#if 0  /* enable when device IDs are available */
 
        case (FLASH_WORD_SIZE)AMD_ID_LV320B:
                info->flash_id += FLASH_AM320B;
@@ -455,23 +481,26 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
                return (0);                     /* => no or unknown flash */
 
        }
-
+       /* base address calculation */
+       base=0-info->size;
        /* set up sector start address table */
-  if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
-           (info->flash_id  == FLASH_AM040)){
+       if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
+            (info->flash_id  == FLASH_AM040) ||
+            (info->flash_id  == FLASH_AM640U)){
                for (i = 0; i < info->sector_count; i++)
                        info->start[i] = base + (i * 0x00010000);
-  } else {
+       }
+       else {
                if (info->flash_id & FLASH_BTYPE) {
-               /* set sector offsets for bottom boot block type        */
-               info->start[0] = base + 0x00000000;
-               info->start[1] = base + 0x00004000;
-               info->start[2] = base + 0x00006000;
-               info->start[3] = base + 0x00008000;
-               for (i = 4; i < info->sector_count; i++)
-                       info->start[i] = base + (i * 0x00010000) - 0x00030000;
-         }
-         else {
+                       /* set sector offsets for bottom boot block type        */
+                       info->start[0] = base + 0x00000000;
+                       info->start[1] = base + 0x00004000;
+                       info->start[2] = base + 0x00006000;
+                       info->start[3] = base + 0x00008000;
+                       for (i = 4; i < info->sector_count; i++)
+                               info->start[i] = base + (i * 0x00010000) - 0x00030000;
+               }
+               else {
                        /* set sector offsets for top boot block type           */
                        i = info->sector_count - 1;
                        if(info->sector_count==71) {
@@ -501,75 +530,67 @@ static ulong flash_get_size (vu_long *addr, flash_info_t *info)
                /* read sector protection at sector address, (A7 .. A0) = 0x02 */
                /* D0 = 1 if protected */
                addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
-       if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
-       info->protect[i] = 0;
-      else
-        info->protect[i] = addr2[2] & 1;
+               if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
+                       info->protect[i] = 0;
+               else
+                       info->protect[i] = addr2[2] & 1;
        }
 
        /*
         * Prevent writes to uninitialized FLASH.
         */
        if (info->flash_id != FLASH_UNKNOWN) {
-#if 0 /* test-only */
-#ifdef CONFIG_ADCIOP
-               addr2 = (volatile unsigned char *)info->start[0];
-                addr2[ADDR0] = 0xAA;
-                addr2[ADDR1] = 0x55;
-                addr2[ADDR0] = 0xF0;  /* reset bank */
-#else
                addr2 = (FLASH_WORD_SIZE *)info->start[0];
                *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
-#endif
-#else /* test-only */
-               addr2 = (FLASH_WORD_SIZE *)info->start[0];
-               *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
-#endif /* test-only */
        }
        return (info->size);
 }
 
+
 int wait_for_DQ7(flash_info_t *info, int sect)
 {
        ulong start, now, last;
        volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
 
        start = get_timer (0);
-    last  = start;
-    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
-        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
-            printf ("Timeout\n");
-            return -1;
-        }
-        /* show that we're waiting */
-        if ((now - last) > 1000) {  /* every second */
-                               putc ('.');
-            last = now;
-        }
-    }
-       return 0;
+       last  = start;
+       while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+               if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
+                       printf ("Timeout\n");
+                       return ERR_TIMOUT;
+               }
+               /* show that we're waiting */
+               if ((now - last) > 1000) {  /* every second */
+                       putc ('.');
+                       last = now;
+               }
+       }
+       return ERR_OK;
 }
 
 int intel_wait_for_DQ7(flash_info_t *info, int sect)
 {
-       ulong start, now, last;
+       ulong start, now, last, status;
        volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
 
-               start = get_timer (0);
-    last  = start;
-    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
-        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
-            printf ("Timeout\n");
-            return -1;
-        }
-        /* show that we're waiting */
-        if ((now - last) > 1000) {  /* every second */
-                               putc ('.');
-            last = now;
-        }
-    }
-    addr[0]=(FLASH_WORD_SIZE)0x00500050;
-       return 0;
+       start = get_timer (0);
+       last  = start;
+       while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+               if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) {
+                       printf ("Timeout\n");
+                       return ERR_TIMOUT;
+               }
+               /* show that we're waiting */
+               if ((now - last) > 1000) {  /* every second */
+                       putc ('.');
+                       last = now;
+               }
+       }
+       status = addr[0] & (FLASH_WORD_SIZE)0x00280028;
+       /* clear status register */
+       addr[0] = (FLASH_WORD_SIZE)0x00500050;
+       /* check status for block erase fail and VPP low */
+       return (status == 0 ? ERR_OK : ERR_NOT_ERASED);
 }
 
 /*-----------------------------------------------------------------------
@@ -580,7 +601,7 @@ int flash_erase (flash_info_t *info, int s_first, int s_last)
        volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
        volatile FLASH_WORD_SIZE *addr2;
        int flag, prot, sect, l_sect;
-       int i;
+       int i, rcode = 0;
 
 
        if ((s_first < 0) || (s_first > s_last)) {
@@ -621,7 +642,7 @@ int flash_erase (flash_info_t *info, int s_first, int s_last)
                if (info->protect[sect] == 0) { /* not protected */
                        addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
                        /*  printf("Erasing sector %p\n", addr2); */ /* CLH */
-           if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
+                       if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
                                addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
                                addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
                                addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
@@ -630,16 +651,16 @@ int       flash_erase (flash_info_t *info, int s_first, int s_last)
                                addr2[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
                                for (i=0; i<50; i++)
                                        udelay(1000);  /* wait 1 ms */
-                   wait_for_DQ7(info, sect);
-                 }
-                 else {
-                       if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
+                               rcode |= wait_for_DQ7(info, sect);
+                       }
+                       else {
+                               if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
                                        addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector */
                                        addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
-                           intel_wait_for_DQ7(info, sect);
+                                       intel_wait_for_DQ7(info, sect);
                                        addr2[0] = (FLASH_WORD_SIZE)0x00200020;  /* sector erase */
                                        addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
-                           intel_wait_for_DQ7(info, sect);
+                                       rcode |= intel_wait_for_DQ7(info, sect);
                                }
                                else {
                                        addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
@@ -648,18 +669,18 @@ int       flash_erase (flash_info_t *info, int s_first, int s_last)
                                        addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
                                        addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
                                        addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
-                           wait_for_DQ7(info, sect);
-                               }
-                }
-                l_sect = sect;
-                   /*
-                    * Wait for each sector to complete, it's more
-                    * reliable.  According to AMD Spec, you must
-                    * issue all erase commands within a specified
-                    * timeout.  This has been seen to fail, especially
-                    * if printf()s are included (for debug)!!
-                    */
-                /*   wait_for_DQ7(info, sect); */
+                                       rcode |= wait_for_DQ7(info, sect);
+                               }
+                       }
+                       l_sect = sect;
+                       /*
+                        * Wait for each sector to complete, it's more
+                        * reliable.  According to AMD Spec, you must
+                        * issue all erase commands within a specified
+                        * timeout.  This has been seen to fail, especially
+                        * if printf()s are included (for debug)!!
+                        */
+                       /*   wait_for_DQ7(info, sect); */
                }
        }
 
@@ -684,10 +705,13 @@ DONE:
        addr = (FLASH_WORD_SIZE *)info->start[0];
        addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
 
-       printf (" done\n");
-       return 0;
+       if (!rcode)
+           printf (" done\n");
+
+       return rcode;
 }
 
+
 void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
 {
        int i;
@@ -707,8 +731,6 @@ void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
                i++;
                c-=(info->start[i]-info->start[i-1]);
        }while(c>0);
-
-
 }
 
 
@@ -799,7 +821,7 @@ static int write_word (flash_info_t *info, ulong dest, ulong data)
 {
        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]);
        volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
-       volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
+       volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
        ulong start;
        int flag;
        int i;
@@ -826,7 +848,7 @@ static int write_word (flash_info_t *info, ulong dest, ulong data)
                        udelay(10);
                        while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080)
                        {
-                               if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
+                               if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
                                        return (1);
                        }
                        dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
@@ -847,8 +869,8 @@ static int write_word (flash_info_t *info, ulong dest, ulong data)
                        start = get_timer (0);
                        while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
                                (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
-                               if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
-                                       return (1);
+                               if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
+                                       return (1);
                                }
                        }
                }