http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / shared / opensource / flash / cfiflash.c
index 6dd8ccc..4a1ec2b 100755 (executable)
@@ -87,7 +87,9 @@
 #define ID_AM29DL800B   0x22CB
 #define ID_AM29LV800T   0x22DA
 #define ID_AM29LV800B   0x225B
-#define ID_AM29LV400B   0x22BA
+#define ID_STM29W320EB 0x2257
+#define ID_STM29W640FB 0x22fd
+//#define ID_AM29LV400B   0x22BA
 #define ID_AM29LV200BT  0x223B
 
 #define ID_AM29LV160B   0x2249
 #define ID_MX29LV320AT  0x22A7
 #define ID_AM29LV320B   0x22F9
 #define ID_MX29LV320AB  0x22A8
-#define ID_MX29LV640BT  0x22C9
+//#define ID_MX29LV640BT  0x22C9
 
 #define ID_AM29LV320M   0x227E
 #define ID_AM29LV320MB  0x2200
 #define ID_AM29LV320MT  0x2201
+#define ID_W19L320SB           0x222A
+#define ID_W19L320ST           0x22BA
+#define ID_K8D3216UB   0x22a2
+#define ID_K8D3216UT   0x22a0
+#define ID_K8D6316UB    0x22e2
+#define ID_K8D1716UB   0x2277
+#define ID_K8D1716UT   0x2275
+
 
 #define ID_SST39VF200A  0x2789
 #define ID_SST39VF400A  0x2780
           {ID_AM29DL800B, "AM29DL800B"},    \
           {ID_AM29LV800T, "AM29LV800T"},    \
           {ID_AM29LV800B, "AM29LV800B"},    \
-          {ID_AM29LV400B, "AM29LV400B"},    \
           {ID_AM29LV200BT, "AM29LV200BT"},  \
           {ID_AM29LV160B, "AM29LV160B"},    \
           {ID_AM29LV160T, "AM29LV160T"},    \
           {ID_AM29LV320M, "AM29LV320M"},    \
           {ID_AM29LV320MB, "AM29LV320MB"},  \
           {ID_AM29LV320MT, "AM29LV320MT"},  \
-          {ID_MX29LV640BT, "MX29LV640BT"},  \
           {ID_SST39VF200A, "SST39VF200A"},  \
           {ID_SST39VF400A, "SST39VF400A"},  \
           {ID_SST39VF800A, "SST39VF800A"},  \
           {ID_I28F320C3T, "I28F320C3T"},    \
           {ID_I28F320C3B, "I28F320C3B"},    \
           {ID_I28F640J3,  "I28F640J3"},     \
+          {ID_W19L320SB,  "W19L320SB"},                \
+                 {ID_W19L320ST,  "W19L320ST"},         \
+                 {ID_K8D3216UB,"K8D3216UB"},           \
+                 {ID_K8D3216UT,"K8D3216UT"},{ID_K8D6316UB,"K8D6316UB"},{ID_K8D1716UB,"K8D1716UB"},             \
+                 {ID_K8D1716UT,"K8D1716UT"},           \
+                 {ID_STM29W320EB,"STM29W320EB"},   \
+                 {ID_STM29W640FB,"STM29W640FB"},   \
           {0, ""}                           \
         }
 
@@ -211,6 +226,11 @@ static unsigned short cfi_flash_get_device_id(void);
 static int cfi_flash_get_cfi(struct cfi_query *query, unsigned short *cfi_struct,
     int flashFamily);
 
+//swda add,06/27/2006
+static int DiagLedBlinking(void);
+#define T200ms                         ((200 * HZ) / 1000)     // ~200 ms
+#define T100ms                         ((100 * HZ) / 1000)     // ~100 ms
+//swda add end
 
 /** Variables. **/
 static flash_device_info_t flash_cfi_dev =
@@ -227,7 +247,8 @@ static flash_device_info_t flash_cfi_dev =
         cfi_flash_get_total_size,
         cfi_flash_get_total_size
     };
-
+unsigned short device_id;
+unsigned short man_id;
 /*********************************************************************/
 /* 'meminfo' should be a pointer, but most C compilers will not      */
 /* allocate static storage for a pointer without calling             */
@@ -297,6 +318,98 @@ static UINT16 cfi_data_struct_26LV800B[] = {
     0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
 };
 
+#if defined (CONFIG_BCM96338) 
+unsigned long get_flash_base(unsigned long size)
+{
+       static unsigned long flash_base = FLASH_BASE;
+       if (size > 0x10000000) {
+               flash_base = size;
+       }
+       else if (size) {
+               unsigned long fsize = 8 * 1024;
+               unsigned long fbase = 0x20000000;
+               unsigned long frmap;
+
+               for (frmap = 0; frmap < 17; frmap++) {
+                       if (size == fsize) {
+                               fbase -= fsize;
+                               if (fbase > 0x1fc00000) fbase = 0x1fc00000;
+                               *(volatile unsigned long *)0xfffe3160 = fbase | frmap;
+                               flash_base = (unsigned long)(fbase|0xa0000000);
+                               break;
+                       }
+                       fsize <<= 1;
+               }
+       }
+
+       return flash_base;
+}
+#endif 
+
+#if defined (CONFIG_BCM96348) 
+/* denny 08/17/04' add, reconfigure and obtin flash base address */
+unsigned long get_flash_base(unsigned long size)
+{
+       static unsigned long flash_base = FLASH_BASE; 
+       
+       if (size > 0x10000000) {
+               flash_base = size;
+       }
+       else if (size) {
+               unsigned long fsize = 8 * 1024;
+               unsigned long fbase = 0x20000000;
+               unsigned long frmap;
+
+               for (frmap = 0; frmap < 17; frmap++) {
+                       if (size == fsize) {
+                               fbase -= fsize;
+                               if (fbase > 0x1fc00000) fbase = 0x1fc00000;
+                               *(volatile unsigned long *)MPI_BASE = fbase | frmap;
+                               flash_base = (unsigned long)(fbase|0xa0000000);
+                               break;
+                       }
+                       fsize <<= 1;
+               }
+       }
+
+       return flash_base;
+}
+#endif
+
+#ifdef CONFIG_CS1 
+unsigned long get_flash2_base(unsigned long size)
+{
+       static unsigned long flash2_base = FLASH_BASE;
+
+       if (size == -1) {
+               *(volatile unsigned long *)0xfffe2008 = 0;
+               *(volatile unsigned long *)0xfffe200c = 0;
+               flash2_base = FLASH_BASE;
+       }    
+       else if (size > 0xa0000000) {
+               flash2_base = size;
+       }
+       else if (size) {
+               unsigned long fsize = 8 * 1024;
+               unsigned long fbase = *(volatile unsigned long *)0xfffe2000 & ~0xf;
+               unsigned long frmap;
+
+               for (frmap = 0; frmap < 17; frmap++) {
+                       if (size == fsize) {
+                               fbase -= fsize;
+                               *(volatile unsigned long *)0xfffe200c = *(volatile unsigned long *)0xfffe2004;
+                               *(volatile unsigned long *)0xfffe2008 = fbase | frmap;
+                               flash2_base = (unsigned long)(fbase|0xa0000000);
+                               break;
+                       }
+                       fsize <<= 1;
+               }
+       }
+
+       return flash2_base;
+}
+#endif
+/* end */
 
 /*********************************************************************/
 /* Init_flash is used to build a sector table from the information   */
@@ -323,7 +436,6 @@ int cfi_flash_init(flash_device_info_t **flash_info)
     struct flash_name_from_id *fnfi_ptr;
     int i=0, j=0, count=0;
     int basecount=0L;
-    unsigned short device_id;
     int flipCFIGeometry = FALSE;
 
     *flash_info = &flash_cfi_dev;
@@ -359,7 +471,7 @@ int cfi_flash_init(flash_device_info_t **flash_info)
             break;
         case ID_AM29DL800B:
         case ID_AM29LV800B:
-        case ID_AM29LV400B:   
+//        case ID_AM29LV400B:   
         case ID_AM29LV160B:
         case ID_AM29LV320B:
         case ID_MX29LV320AB:
@@ -370,8 +482,16 @@ int cfi_flash_init(flash_device_info_t **flash_info)
         case ID_AM29LV320T:
         case ID_MX29LV320AT:
         case ID_AM29LV320MT:
-        case ID_AM29LV200BT:
-        case ID_MX29LV640BT:
+        case ID_W19L320ST:
+        case ID_W19L320SB:
+        case ID_K8D3216UB:
+        case ID_K8D6316UB:
+        case ID_K8D1716UB:
+        case ID_K8D1716UT:
+        case ID_K8D3216UT:
+        case ID_STM29W320EB:
+        case ID_STM29W640FB:
+        case 0x43:
             flashFamily = FLASH_AMD;
             break;
         case ID_SST39VF200A:
@@ -403,13 +523,84 @@ int cfi_flash_init(flash_device_info_t **flash_info)
             return FLASH_API_ERROR;           
         }
     }
+#if defined (CONFIG_BCM96338) 
+       volatile unsigned int *cs = (volatile unsigned int *)0xfffe3160;
+       /* reconfigure CS0 and flash base */
+       get_flash_base(query.device_size);
+       
+       printk("Flash Config: ");
+       printk("CS0(%x,%x),", cs[0], cs[1]);
+       printk("Base(%x),", (unsigned int)get_flash_base(0));
+       printk("Size(%dMB)\n", (query.device_size)>>20);
+#endif
+
+#if defined (CONFIG_BCM96348) || defined (CONFIG_BCM96358) 
+
+/* denny 08/17/04' add, reconfigure the CS0 and CS1 for flash */
+    {
+       volatile unsigned int *cs = (volatile unsigned int *)MPI_BASE;
+        if (device_id == ID_AM29LV320MB || device_id == ID_AM29LV320MT)
+            *(volatile unsigned int*)(MPI_BASE+4) |= 0x0000000e; /* if spansion flash CS0 wait time -> Three */
+   
+#if defined (CONFIG_BCM96348)
+       /* reconfigure CS0 and flash base */
+       get_flash_base(query.device_size);
+
+#ifdef CONFIG_CS1
+         struct cfi_query query2;
+       /* try to detection CS1 for flash base */
+       get_flash_base(get_flash2_base(0x100000));
+       if (flash_get_cfi(&query2, 0,flashFamily) == -1) {
+               get_flash2_base(-1);
+               get_flash_base(query.device_size);
+       }
+       else {
+               /* reconfigure CS0 and flash base */
+               get_flash_base(query.device_size);
+               /* set flash base value */
+               get_flash_base(get_flash2_base(query2.device_size));
+           #if DEBUG_FLASH 
+               printk("query.num_erase_blocks = %x\n", query.num_erase_blocks);
+               printk("query.device_size = %x\n", query.device_size);
+               printk("query2.num_erase_blocks = %x\n", query2.num_erase_blocks);
+               printk("query2.device_size = %x\n", query2.device_size);
+               printk("flash_base = %x\n", get_flash_base(0));
+               #endif
+               for (i=0; i<query.num_erase_blocks; i++)
+                       memcpy(&query.erase_block[i+query2.num_erase_blocks], &query.erase_block[i], sizeof(query.erase_block[0]));
+               for (i=0; i<query2.num_erase_blocks; i++)
+                       memcpy(&query.erase_block[i], &query2.erase_block[i], sizeof(query.erase_block[0]));
+               query.num_erase_blocks += query2.num_erase_blocks;
+               query.device_size += query2.device_size;
+       }
+#endif /* CS1 */
+#endif /* 6348 */
+#endif /* 6348 || 6358 */
+#if defined (CONFIG_BCM96348) || defined (CONFIG_BCM96358) 
+
+       #if DEBUG_FLASH  
+       printk("query.num_erase_blocks = %x\n", query.num_erase_blocks);
+       printk("query.device_size = %x\n", query.device_size);
+       printk("flash_base = %x\n", get_flash_base(0));
+       #endif
+       printk("Flash Config: ");
+       printk("CS0(%x,%x),", cs[0], cs[1]);
+#if defined (CONFIG_BCM96348)
+       if (cs[2]) printk("CS1(%x,%x) ", cs[2], cs[3]);
+       printk("Base(%x),", (unsigned int)get_flash_base(0));
+#endif
+       printk("Size(%dMB)\n", (query.device_size)>>20);
+    }
+/* end */
 
+#endif
     // need to determine if it top or bottom boot here
     switch (device_id)
     {
         case ID_AM29DL800B:
         case ID_AM29LV800B:
-        case ID_AM29LV400B:   
+//      case ID_AM29LV400B:   
         case ID_AM29LV160B:
         case ID_AM29LV320B:
         case ID_MX29LV320AB:
@@ -419,11 +610,19 @@ int cfi_flash_init(flash_device_info_t **flash_info)
         case ID_I28F640J3:
         case ID_I28F160C3T:
         case ID_I28F320C3T:
-        case ID_SST39VF3201:
-        case ID_SST39VF6401:
         case ID_SST39VF200A:
         case ID_SST39VF400A:
         case ID_SST39VF800A:
+        case ID_K8D1716UB:
+        case ID_K8D3216UB:
+        case ID_K8D6316UB:
+        case ID_STM29W320EB:
+        case ID_STM29W640FB:
+       case ID_SST39VF1601:
+       case ID_SST39VF3201:
+        case ID_SST39VF6401:
+        case ID_W19L320SB:
+        case 0x43: // for Toshiba 58FVB160FT-85
             flipCFIGeometry = FALSE;
             break;
         case ID_AM29DL800T:
@@ -433,11 +632,14 @@ int cfi_flash_init(flash_device_info_t **flash_info)
         case ID_MX29LV320AT:
         case ID_AM29LV320MT:
         case ID_AM29LV200BT:
-        case ID_SST39VF1601:
-        case ID_MX29LV640BT:
+//        case ID_MX29LV640BT:
+        case ID_K8D1716UT:
+        case ID_K8D3216UT:
+        case ID_W19L320ST:
             flipCFIGeometry = TRUE;
             break;
         default:
+            printk("Flash memory not supported!  Device id = %x\n", device_id);
             return FLASH_API_ERROR;           
     }
 
@@ -477,6 +679,7 @@ int cfi_flash_init(flash_device_info_t **flash_info)
                 break;
             }
         }
+        if (fnfi_ptr->fnfi_id == 0) strcpy(flash_cfi_dev.flash_device_name,"UNKNOWN");
     }
 
     return (FLASH_API_OK);
@@ -602,8 +805,14 @@ static int cfi_flash_get_sector_size(unsigned short sector)
 /*********************************************************************/
 static unsigned char *cfi_flash_get_memptr(unsigned short sector)
 {
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)      
+    unsigned char *memptr = (unsigned char*)
+        (get_flash_base(0) + meminfo.sec[sector].base);
+#endif
+#if defined (CONFIG_BCM96358)
     unsigned char *memptr = (unsigned char*)
         (FLASH_BASE + meminfo.sec[sector].base);
+#endif
 
     return (memptr);
 }
@@ -616,8 +825,13 @@ static int cfi_flash_get_blk(int addr)
 {
     int blk_start, i;
     int last_blk = cfi_flash_get_numsectors();
-    int relative_addr = addr - (int) FLASH_BASE;
 
+#if defined (CONFIG_BCM96348) || defined(CONFIG_BCM96338)       
+    int relative_addr = addr - (int) get_flash_base(0);
+#endif
+#if defined (CONFIG_BCM96358)
+    int relative_addr = addr - (int) FLASH_BASE;
+#endif
     for(blk_start=0, i=0; i < relative_addr && blk_start < last_blk; blk_start++)
         i += cfi_flash_get_sector_size(blk_start);
 
@@ -804,9 +1018,183 @@ static int cfi_flash_write(unsigned short sector, int offset, unsigned char *buf
     if ((nbytes | offset) & 1) {
         return FLASH_API_ERROR;
     }
+if (device_id == 0x43) {
+       volatile UINT16* flashptr;
+       volatile UINT16* dst;
+       int stat = STATUS_READY ;
+       int retry = 0, retried = 0;
+       
+       flashptr = (UINT16 *)flash_get_memptr(sector);
+
+   dst = &flashptr[offset/2];   /* (byte offset) */
+   
+again:
+
+#if 0    
+    /* Check to see if we're in unlock bypass mode */
+    flashptr[0] = 0xF0;  /* reset device to read mode */
+    
+       if ((stat=flash_wait(sector)) != STATUS_READY) {
+         printk("1.error\n");
+        return (byte*)src - buf;
+    }
+#else
+       /* reset device to read mode */
+       cfi_flash_command(FLASH_RESET, 0, 0, 0);
+#endif
+    
+    while (nbytes > 0) {
+       
+               //swda add,06/27/2006
+               if ( (nbytes%1024) == 0 ) {
+                       DiagLedBlinking();
+               }
+               //swda add end    
+                  
+        flashptr[0x555] = 0xAA;      /* unlock 1 */
+        flashptr[0x2AA] = 0x55;      /* unlock 2 */
+
+        flashptr[0x555] = 0xA0;
+        *dst = *src;
+
+        if ((stat=cfi_flash_wait(sector, offset, *src)) != STATUS_READY) {
+             printk("2.error\n");
+            break;
+        }
+        dst++;
+        src++;
+        nbytes -= 2;
+        offset += 2;
+    }
+
+    if (stat != STATUS_READY || nbytes != 0) {
+        if (retry-- > 0) {
+            ++retried;
+#if 0
+            --dst, --src;   /* back up */
+#endif
+            goto again;     /* and retry the last word */
+        }
+      
+     cfi_flash_command(FLASH_RESET,sector,0,0);
+    }
+      
+
+} else if (device_id == ID_AM29LV320MB && ((man_id & 0x00ff) != 0xda)) { 
+       
+       volatile UINT16* flashptr;
+       volatile UINT16* dst;
+       int stat = STATUS_READY ;
+       UINT16 d1;
+       UINT16* retrydst;
+       UINT16* retrysrc;
+       int i=0, k=0 ,retryoffset ;
+       //printk("\nsector %d write %d bytes to offset %d\n",sector,nbytes,offset);
+       //printk("...........................\n");
+       //printk("..\n");
+
+       flashptr = (UINT16 *)flash_get_memptr(sector);
+
+       dst = &flashptr[offset/2];   /* (byte offset) */
+   
+       cfi_flash_command(FLASH_RESET, 0, 0, 0);
+   
+       while (nbytes > 0) {
+
+        retrydst = (UINT16 *)dst;
+        retrysrc = src;
+        retryoffset = offset;
+               
+               //swda add,06/27/2006
+               if ( (nbytes%1024) == 0 ) {
+                       DiagLedBlinking();
+               }
+               //swda add end       
+                     
+        flashptr[0x555] = 0xAA;      /* unlock 1 */
+        flashptr[0x2AA] = 0x55;      /* unlock 2 */
+       
+        flashptr[0] = 0x25;
+        k = (nbytes>32) ? 15 : nbytes/2-1;
+
+        flashptr[0] = k;        
+        for ( i=0; i < k; i++) { *dst=*src; dst++;src++; offset+=2; } /*total k write*/
+        *dst = *src; /*k+1 write, src,dst,offset point to current pos should be written */
+        
+        flashptr[0] = 0x29; /* program to flash confirm */
+        //udelay(5);   
+#if 1
+       do {
+            d1 = flashptr[offset/2];    /* read data */
+            if ((d1 & 0x80) == (*src & 0x80)) {   /* check DQ7 ok */
+                stat = STATUS_READY;
+                goto next;
+            }
+            i++;
+        } while ( ((d1 & 0x20)!=0x20) && ((d1 & 0x02)!=0x02) );
+
+        d1 = flashptr[offset/2];    /* read data */
+        if ((d1 & 0x80) != (*src & 0x80))   /* check DQ7 ok */
+           {
+            printk("CHECK Time_Out\n");
+            stat = STATUS_TIMEOUT;
+            break;
+           }
+        else stat = STATUS_READY;
+#else
+        do {
+            d1 = *flashptr;        /* read data */
+            d2 = d1 ^ *flashptr;   /* read it again and see what toggled */
+            if (d2 == 0) {          /* no toggles, nothing's happening */
+                stat = STATUS_READY;
+                goto next;
+            }
+        } while (!(d2 & 0x20));
+
+        d1 = *flashptr;        /* read data */
+        d2 = d1 ^ *flashptr;   /* read it again and see what toggled */
 
+        if (d2 != 0) {
+            stat=STATUS_TIMEOUT;
+            break;
+        }
+#endif        
+next:                          
+        dst++; /* next batch start to write */
+        src++; /* next batch start to read  */
+        nbytes -= 32;
+        offset += 2 ;
+       }
+
+       if (stat != STATUS_READY || nbytes > 0) {
+          UINT16 data;
+          data = flashptr[offset/2];
+          if ((data & 0x02) == 0x02) { 
+             flashptr[0x555] = 0xaa;
+             flashptr[0x2aa] = 0x55;
+             flashptr[0x555] = 0xf0;
+             printk("abort to write to buffer @ 0x%lx =0x%x\n", offset,data);
+           }
+           else {
+             cfi_flash_command(FLASH_RESET,sector,0,0);
+             printk("fail to write to buffer @ 0x%lx =0x%x\n", offset,data);
+          }  
+       }
+       else { cfi_flash_command(FLASH_RESET,sector,0,0);}
+      
+            
+    
+    } 
+else {
     cfi_flash_command(FLASH_UB, 0, 0, 0);
     while (nbytes > 0) {
+       
+               //swda add,06/27/2006
+               if ( (nbytes%1024) == 0 ) {
+                       DiagLedBlinking();
+               }
+               //swda add end       
+               
         cfi_flash_command(FLASH_PROG, sector, offset, *src);
         if (cfi_flash_wait(sector, offset, *src) != STATUS_READY)
             break;
@@ -815,7 +1203,7 @@ static int cfi_flash_write(unsigned short sector, int offset, unsigned char *buf
         src++;
     }
     cfi_flash_command(FLASH_UBRESET, 0, 0, 0);
-    
+}    
     return (unsigned char*)src - buf;
 }
 
@@ -829,6 +1217,7 @@ static int cfi_flash_wait(unsigned short sector, int offset, unsigned short data
 {
     volatile unsigned short *flashptr; /* flash window */
     unsigned short d1;
+    int i1 = 0;//swda add,06/27/2006
 
     flashptr = (unsigned short *) cfi_flash_get_memptr(sector);
 
@@ -839,6 +1228,13 @@ static int cfi_flash_wait(unsigned short sector, int offset, unsigned short data
             d1 = flashptr[offset/2];
             if (d1 == data)
                 return STATUS_READY;
+                       //swda add,06/27/2006
+                       i1++;
+                       if ( (i1%1024) == 0 ) {
+                               DiagLedBlinking();
+                               i1 = 0;
+                       }
+                       //swda add end  
         } while (!(d1 & 0x20));
 
         d1 = flashptr[offset/2];
@@ -854,6 +1250,11 @@ static int cfi_flash_wait(unsigned short sector, int offset, unsigned short data
                 if (d1 == data)
                     return STATUS_READY;
                 CFI_USLEEP(10);
+                               //swda add,06/27/2006
+                               if ( (i%1024) == 0 ) {
+                                       DiagLedBlinking();
+                               }
+                               //swda add end  
             }
 
             d1 = flashptr[offset/2];
@@ -869,6 +1270,13 @@ static int cfi_flash_wait(unsigned short sector, int offset, unsigned short data
             d1 ^= *flashptr;   /* read it again and see what toggled */
             if (d1 == 0)       /* no toggles, nothing's happening */
                 return STATUS_READY;
+                       //swda add,06/27/2006
+                       i1++;
+                       if ( (i1%1024) == 0 ) {
+                               DiagLedBlinking();
+                               i1 = 0;
+                       }
+                       //swda add end  
         } while (!(d1 & 0x20));
 
         d1 = *flashptr;        /* read data */
@@ -881,8 +1289,18 @@ static int cfi_flash_wait(unsigned short sector, int offset, unsigned short data
 #endif
     } else if (flashFamily == FLASH_INTEL) {
         flashptr[0] = 0x70;
+#if 0  //swda modify,06/27/2006
         /* Wait for completion */
         while(!(*flashptr & 0x80));
+#else
+               while(!(*flashptr & 0x80)) {
+                       i1++;
+                       if ( (i1%1024) == 0 ) {
+                               DiagLedBlinking();
+                               i1 = 0;
+                       }
+               }
+#endif //swda modify end
         if (*flashptr & 0x30) {
             flashptr[0] = 0x50;
             cfi_flash_command(FLASH_RESET, 0, 0, 0);
@@ -908,6 +1326,7 @@ static unsigned short cfi_flash_get_device_id(void)
     fwp = (unsigned short *) cfi_flash_get_memptr(0);
     
     cfi_flash_command(FLASH_READ_ID, 0, 0, 0);
+     man_id = *(fwp);
     answer = *(fwp + 1);
     if (answer == ID_AM29LV320M) {
         answer = *(fwp + 0xe);
@@ -973,3 +1392,35 @@ static int cfi_flash_get_cfi(struct cfi_query *query, unsigned short *cfi_struct
     return(FLASH_API_OK);
 }
 
+//swda add,06/27/2006
+static int DiagLedBlinking(void)
+{
+       static int diag_led = 0;
+       static int curr_time = 0;
+       static int prev_time = 0;
+       static int UpgradeState = 0;
+       static int blink_interval = T200ms;
+       
+       UpgradeState = kerSysGetUpgradeState();
+       if ( !UpgradeState ) 
+               return 0;//not update image or not update configuration, so do nothing
+       
+       if ( UpgradeState == 2 ) {      //update configuration
+               blink_interval = T100ms;
+       } else {        //update image
+               blink_interval = T200ms;
+       } 
+       curr_time = jiffies;    
+       if ( (curr_time - prev_time) >= blink_interval ) {
+               prev_time = curr_time;
+               if (diag_led) {
+                       kerSysLedCtrl(kLedDiag, kLedStateOff);
+                       diag_led = 0;
+               } else {
+                       kerSysLedCtrl(kLedDiag, kLedStateOn);
+                       diag_led = 1;
+               }
+       }
+       return 0;
+}
+//swda add end