Support NAND devices which NAND ID is not fixed-length

时间:2022-06-12 21:38:21
--- a/mediatek/build/tools/emigen/MT6575/emigen.pl
+++ b/mediatek/build/tools/emigen/MT6575/emigen.pl
@@ -205,6 +205,15 @@ my $is_existed_c             = (-e $CUSTOM_EMI_C)?           1 : 0;
 #****************************************************************************
 open CUSTOM_MEMORY_DEVICE_HDR, "<$CUSTOM_MEMORY_DEVICE_HDR" or &error_handler("$CUSTOM_MEMORY_DEVICE_HDR: file error!", __FILE__, __LINE__);
 
+# CustCS_CustemChips:
+#  the number of part number which customer assigned
+#  in mediatek/custom/$project/preloader/inc/custom_MemoryDevice.h
+# TotalCustemChips:
+#   because one part number may matches multiple emmc/nand ID, the TotalCustemChips >= CustCS_CustemChips
+#   the final number of part number which will use to create emi_setting
+#   in mediatek/custom/$project/preloader/inc/custom_emi.h
+#
+my $CustCS_CustemChips = 0 ;
 my $TotalCustemChips = 0 ;
 
 #
@@ -213,14 +222,31 @@ my $TotalCustemChips = 0 ;
 #   this should be an array of structurs, but it is said perl does not support it.
 #   these are input, except EMI_GEND
 #
-my $CustCS_PART_NUMBER ;
+
+# CustCS_PART_NUMBER:
+#  the content of part number which customer assigned
+#  in mediatek/custom/$project/preloader/inc/custom_MemoryDevice.h
+# Total_PART_NUMBER:
+#   the final part number which will show
+#   in mediatek/custom/$project/preloader/inc/custom_emi.h
+ my $CustCS_PART_NUMBER ;
+my $Total_PART_NUMBER ;
+
 
 ######################################################################################
 my $DEV_TYPE;
 my $DEV_TYPE1;
 my $DEV_TYPE2;
 my $NAND_EMMC_ID;
+my $FW_ID ;
 my $ID_String ;
+my $FW_ID_String ;
+my $Sub_version;
+my $USE_EMMC_ID_LEN=9;
+my $MAX_NAND_EMMC_ID_LEN=12;
+my $MAX_FW_ID_LEN=8;
+#my $ORI_ID_Length;
+my $fw_id_len;
 my $NAND_PAGE_SIZE;
 my $EMI_CONA_VAL;           
 my $DRAMC_DRVCTL0_VAL;      
@@ -290,13 +316,13 @@ while (<CUSTOM_MEMORY_DEVICE_HDR>)
         {
             #print "\nCS0 $2, $3\n" ;
             $CustCS_PART_NUMBER[$2] = $3 ;
-            $TotalCustemChips = $TotalCustemChips + 1 ;
+            $CustCS_CustemChips = $CustCS_CustemChips + 1 ;
             
             print "$CustCS_PART_NUMBER[$2]\n"
         }
     }
 }
-print "\n$TotalCustemChips\n" if ($DebugPrint ==1);
+print "\n$CustCS_CustemChips\n" if ($DebugPrint ==1);
 close CUSTOM_MEMORY_DEVICE_HDR;
 #
 #
@@ -309,13 +335,13 @@ close CUSTOM_MEMORY_DEVICE_HDR;
 #
 #   check if data validate.
 #
-if ($TotalCustemChips > 10)
+if ($CustCS_CustemChips > 10)
 {
-    die "\nTotalCustemChips($TotalCustemChips) > 30\n" ;
+    die "\n[Error]CustCS_CustemChips($CustCS_CustemChips) > 30\n" ;
 }
-if ($TotalCustemChips == 0)
+if ($CustCS_CustemChips == 0)
 {
-    die "\nTotalCustemChips($TotalCustemChips) = 0?\n" ;
+    die "\n[Error]CustCS_CustemChips($CustCS_CustemChips) = 0?\n" ;
 }
 
  
@@ -339,11 +365,15 @@ else
 }
 # select worksheet
 my $Sheet;
-my $eos_flag       = 7; # if this flag counts to '0', it means End Of Sheet
+my $eos_flag       = 4; # if this flag counts to '0', it means End Of Sheet
 my $iter = 0 ;
-    while ($iter<$TotalCustemChips)
+my $CustCS_part_number_iter = 0;
+my $total_part_number_iter = 0;
+
+    while ($iter<$CustCS_CustemChips)
     {
-        &DeviceListParser_LPSDRAM($iter);
+        $eos_flag = 4;
+        $total_part_number_iter = &DeviceListParser_LPSDRAM($iter,$total_part_number_iter);     
         $iter = $iter + 1 ;
     }
     
@@ -352,6 +382,7 @@ my $iter = 0 ;
     my $Discrete_DDR = 0 ;
     my $EMMC_NAND_MCP = "00" ;
     my $Page_size = "0" ;
+    print "TotalCustemChips:$TotalCustemChips\n";
     while ($iter < $TotalCustemChips)
     {
         # only one Discrete is allowed
@@ -363,7 +394,7 @@ my $iter = 0 ;
             }
             else
             {
-                die "more than 1 Discrete DDR used!\n" ;
+                die "[Error]more than 1 Discrete DDR used!\n" ;
             }
         }
         
@@ -374,7 +405,7 @@ my $iter = 0 ;
         }
         elsif ($EMMC_NAND_MCP != $DEV_TYPE1[$iter] && $DEV_TYPE1[$iter] != "00")
         {
-            die "Both NAND and eMMC are used!\n"
+            die "[Error]Both NAND and eMMC are used!\n"
         }
         
         # can't use different page size.
@@ -388,7 +419,7 @@ my $iter = 0 ;
             {
                 if ($Page_size != $NAND_PAGE_SIZE[$iter])
                 {
-                    die "different MCP page size!$Page_size, $NAND_PAGE_SIZE[$iter]\n" ;
+                    die "[Error]different MCP page size!$Page_size, $NAND_PAGE_SIZE[$iter]\n" ;
                 }
             }
         }
@@ -400,11 +431,16 @@ my $iter = 0 ;
         {
             if ($DEV_TYPE1[$iter] != "00")
             {
-                if ( $CustCS_PART_NUMBER[iter] == $CustCS_PART_NUMBER[iter2] )
+                if ($NAND_EMMC_ID[$iter] eq $NAND_EMMC_ID[$iter2])
                 {
-                    if ($NAND_EMMC_ID[iter] != $NAND_EMMC_ID[iter2])
+                     if ( $Total_PART_NUMBER[$iter] ne $Total_PART_NUMBER[$iter2] )
+                    {
+                        die "[Error]Different part number:$Total_PART_NUMBER[$iter],$Total_PART_NUMBER[$iter2] with same NAND/eMMC ID:$NAND_EMMC_ID[$iter]"
+                    }
+                    else
                     {
-                        die "different NAND/eMMC ID with same part number $CustCS_PART_NUMBER[iter] !\n" ;
+                        die "[Error]Two same part number:$Total_PART_NUMBER[$iter],$Total_PART_NUMBER[$iter2] with same NAND/eMMC ID:$NAND_EMMC_ID[$iter]"
+
                     }
                 }
             }
@@ -484,7 +520,7 @@ sub error_handler
 {
 	   my ($error_msg, $file, $line_no) = @_;
 	   
-	   my $final_error_msg = "EMIGEN ERROR: $error_msg at $file line $line_no\n";
+	   my $final_error_msg = "[Error]EMIGEN ERROR: $error_msg at $file line $line_no\n";
 	   print $final_error_msg;
 	   die $final_error_msg;
 }
@@ -736,21 +772,23 @@ __TEMPLATE
 sub DeviceListParser_LPSDRAM
 {
     my ($id) ;
+    my ($CustCS_id) ;
     my ($PartNum) ;
+    my ($iter);
+    my ($num_part_found);
         
-    my ($is_part_found) ;     #  0: No part number is found
-                              #  1: 1 part number is found
-    $is_part_found = 0 ;
-    
-    $id = $_[0] ;
+                              
+    $num_part_found = 0 ;
+    $CustCS_id = $_[0]; # CustCS_CustemChips_iter
+    $id = $_[1] ; # total_part_number_iter 
     
-    $PartNum = $CustCS_PART_NUMBER[$id] ;
+    $PartNum = $CustCS_PART_NUMBER[$CustCS_id] ;
+    print "\nCustCS ID num is $CustCS_id, part number:$CustCS_PART_NUMBER[$CustCS_id]\n" ;
     
-    print "\nnum is $id, nandID is $CustNAND_ID[$id]\n" ;
 
     my $row        = $start_num + 0 ;                    # scan from row 2 when $MEMORY_DEVICE_TYPE eq 'LPSDRAM'
     my $col        = $COLUMN_PART_NUMBER ;               # scan column 2 for Part Number
-    my $EXCEL_ROW ;
+    my $rows_part_found;                                 # stores the part numbers found in MDL
     
     $Sheet = get_sheet("mt6575") ;
     
@@ -775,7 +813,7 @@ sub DeviceListParser_LPSDRAM
         }
         
 
-        $eos_flag   = 7 ;
+        $eos_flag   = 4 ;
 
         # remove leading and tailing spaces
         $scan_idx =~ s/^\s+// if $DebugPrint == 1 ;
@@ -793,255 +831,346 @@ sub DeviceListParser_LPSDRAM
             $boardid = &xls_cell_value($Sheet, $row, $COLUMN_BOARD_ID) ;
             if ($CustBoard_ID eq $boardid)
             {
-                $EXCEL_ROW = $row;
+                $rows_part_found[$num_part_found] = $row;
 
                 print "\nPartNum($PartNum==$scan_idx) found in row $row\n" ;
-
-                $is_part_found = 1 ;
-                last ;
+                $Total_PART_NUMBER[$TotalCustemChips] = $PartNum;
+                $num_part_found += 1 ;
+                $TotalCustemChips += 1;
             }
         }
     }
 
-    if ($is_part_found != 1)
+    if ($num_part_found == 0)
     {
-        die "\nunsupported part number $PartNum\n" ;
+        die "\n[Error]unsupported part number $PartNum\n" ;
     }
     
-    $_ = $row ;
-    
-    $VENDOR[$id] = &xls_cell_value($Sheet, $_, $COLUMN_VENDOR) ;
-    
-    $DENSITY[$id] = &xls_cell_value($Sheet, $_, $COLUMN_DENSITY) ;
-    
+    $iter = 0;
+    while ($iter<$num_part_found)
+    {
 
-    # find the correct platform
-    my $platform_scan_idx = $COLUMN_PLATFORM ; #First EMI controller
-    
-    my $tmp_platform = &xls_cell_value($Sheet, $start_num, $platform_scan_idx) ;
-    
+        $_ = $rows_part_found[$iter] ;
+        $iter ++;
+
+        $VENDOR[$id] = &xls_cell_value($Sheet, $_, $COLUMN_VENDOR) ;
+
+        $DENSITY[$id] = &xls_cell_value($Sheet, $_, $COLUMN_DENSITY) ;
+
+
+        # find the correct platform
+        my $platform_scan_idx = $COLUMN_PLATFORM ; #First EMI controller
+
+        my $tmp_platform = &xls_cell_value($Sheet, $start_num, $platform_scan_idx) ;
+
+        while (!($tmp_platform =~ $PLATFORM))
+        {
+            $platform_scan_idx++;
+            $tmp_platform = &xls_cell_value($Sheet, $start_num, $platform_scan_idx);
+        }
+
+        &error_handler("$CUSTOM_MEMORY_DEVICE_HDR: $PLATFORM not support LPSDRAM!", __FILE__, __LINE__) if ($platform_scan_idx > $COLUMN_PLATFORM);
+
+        $DEV_TYPE[$id]                       = &xls_cell_value($Sheet, $_, $COLUMN_TYPE) ;
+        $NAND_EMMC_ID[$id]                   = &xls_cell_value($Sheet, $_, $COLUMN_NAND_EMMC_ID) ;
+        $NAND_PAGE_SIZE[$id]                 = &xls_cell_value($Sheet, $_, $COLUMN_NAND_PAGE_SIZE) ;
+
+        $EMI_CONA_VAL[$id]                   = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_DRVCTL0_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_DRVCTL1_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_DLE_VAL[$id]                  = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_ACTIM_VAL[$id]                = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_GDDR3CTL1_VAL[$id]            = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_CONF1_VAL[$id]                = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_DDR2CTL_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_TEST2_3_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_CONF2_VAL[$id]                = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_PD_CTRL_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_PADCTL3_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_DQODLY_VAL[$id]               = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_ADDR_OUTPUT_DLY[$id]          = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        $DRAMC_CLK_OUTPUT_DLY[$id]           = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+
+
+        $DDR1_2_3[$id]                        = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+
+        #  openoffice saved file workaround
+
+        if ($DEV_TYPE[$id] =~ /DDR1/)
+        {
+            $DDR1_2_3[$id] = 'DDR1';
+        }
+        elsif ($DEV_TYPE[$id] =~ /DDR2/)
+        {
+            $DDR1_2_3[$id] = 'DDR2';
+        }
+        elsif ($DEV_TYPE[$id] =~ /DDR3/)
+        {
+            $DDR1_2_3[$id] = 'DDR3';
+        }
 
-    while (!($tmp_platform =~ $PLATFORM))
-    {
-        $platform_scan_idx++;
-        $tmp_platform = &xls_cell_value($Sheet, $start_num, $platform_scan_idx);
-    }
-    
-    
-    &error_handler("$CUSTOM_MEMORY_DEVICE_HDR: $PLATFORM not support LPSDRAM!", __FILE__, __LINE__) if ($platform_scan_idx > $COLUMN_PLATFORM);
-    
-    $DEV_TYPE[$id]                       = &xls_cell_value($Sheet, $_, $COLUMN_TYPE) ;
-    $NAND_EMMC_ID[$id]                   = &xls_cell_value($Sheet, $_, $COLUMN_NAND_EMMC_ID) ;
-    $NAND_PAGE_SIZE[$id]                 = &xls_cell_value($Sheet, $_, $COLUMN_NAND_PAGE_SIZE) ;
-    
-    $EMI_CONA_VAL[$id]                   = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_DRVCTL0_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_DRVCTL1_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_DLE_VAL[$id]                  = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_ACTIM_VAL[$id]                = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_GDDR3CTL1_VAL[$id]            = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_CONF1_VAL[$id]                = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_DDR2CTL_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_TEST2_3_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_CONF2_VAL[$id]                = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_PD_CTRL_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_PADCTL3_VAL[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_DQODLY_VAL[$id]               = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_ADDR_OUTPUT_DLY[$id]          = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    $DRAMC_CLK_OUTPUT_DLY[$id]           = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-
-
-    $DDR1_2_3[id]                        = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-
-   #  openoffice saved file workaround
-
-    if ($DEV_TYPE[$id] =~ /DDR1/)
-    {
-        $DDR1_2_3[id] = 'DDR1';
-    }
-    elsif ($DEV_TYPE[$id] =~ /DDR2/)
-    {
-        $DDR1_2_3[id] = 'DDR2';
-    }
-    elsif ($DEV_TYPE[$id] =~ /DDR3/)
-    {
-        $DDR1_2_3[id] = 'DDR3';
-    }
-    
 #union
 #1 DDR2
-    if ($DDR1_2_3[id] eq "DDR2")
-    {
-        $DDR2_MODE_REG1[$id]             = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR2_MODE_REG2[$id]             = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR2_MODE_REG3[$id]             = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR2_MODE_REG10[$id]            = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR2_MODE_REG63[$id]            = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    }
+        if ($DDR1_2_3[$id] eq "DDR2")
+        {
+            $DDR2_MODE_REG1[$id]             = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR2_MODE_REG2[$id]             = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR2_MODE_REG3[$id]             = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR2_MODE_REG10[$id]            = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR2_MODE_REG63[$id]            = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        }
 #2 DDR1
-    elsif ($DDR1_2_3[id] eq "DDR1")
-    {
-        $DDR1_MODE_REG[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR1_EXT_MODE_REG[$id]          = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    }
+        elsif ($DDR1_2_3[$id] eq "DDR1")
+        {
+            $DDR1_MODE_REG[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR1_EXT_MODE_REG[$id]          = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        }
 #3 DDR3    
-    elsif ($DDR1_2_3[id] eq "DDR3")
-    {
-        $DDR3_MODE_REG0[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR3_MODE_REG1[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR3_MODE_REG2[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-        $DDR3_MODE_REG3[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
-    }
+        elsif ($DDR1_2_3[$id] eq "DDR3")
+        {
+            $DDR3_MODE_REG0[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR3_MODE_REG1[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR3_MODE_REG2[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+            $DDR3_MODE_REG3[$id]              = &xls_cell_value($Sheet, $_, $platform_scan_idx++) ;
+        }
+        if ($DENSITY[$id] eq "4096+4096")
+        {
+            $DRAM_RANK0_SIZE[$id] = "0x20000000";
+            $DRAM_RANK1_SIZE[$id] = "0x20000000";
+        }
+        elsif ($DENSITY[$id] eq "2048+2048")
+        {
+            $DRAM_RANK0_SIZE[$id] = "0x10000000";
+            $DRAM_RANK1_SIZE[$id] = "0x10000000";
+        }
+        elsif ($DENSITY[$id] eq "4096+2048")
+        {
+            $DRAM_RANK0_SIZE[$id] = "0x20000000";
+            $DRAM_RANK1_SIZE[$id] = "0x10000000";
+        }
+        elsif ($DENSITY[$id] eq "8192")
+        {
+            $DRAM_RANK0_SIZE[$id] = "0x40000000";
+            $DRAM_RANK1_SIZE[$id] = "0";
+        }
+        elsif ($DENSITY[$id] eq "4096")
+        {
+            $DRAM_RANK0_SIZE[$id] = "0x20000000";
+            $DRAM_RANK1_SIZE[$id] = "0";
+        }
+        elsif ($DENSITY[$id] eq "2048")
+        {
+            $DRAM_RANK0_SIZE[$id] = "0x10000000";
+            $DRAM_RANK1_SIZE[$id] = "0";
+        }
 
-	if ($DENSITY[$id] eq "4096+4096")
-	{
-		$DRAM_RANK0_SIZE[$id] = "0x20000000";
-		$DRAM_RANK1_SIZE[$id] = "0x20000000";
-	}
-	elsif ($DENSITY[$id] eq "2048+2048")
-	{
-		$DRAM_RANK0_SIZE[$id] = "0x10000000";
-		$DRAM_RANK1_SIZE[$id] = "0x10000000";
-	}
-	elsif ($DENSITY[$id] eq "4096+2048")
-	{
-		$DRAM_RANK0_SIZE[$id] = "0x20000000";
-		$DRAM_RANK1_SIZE[$id] = "0x10000000";
-	}
-	elsif ($DENSITY[$id] eq "8192")
-	{
-		$DRAM_RANK0_SIZE[$id] = "0x40000000";
-		$DRAM_RANK1_SIZE[$id] = "0";
-	}
-	elsif ($DENSITY[$id] eq "4096")
-	{
-		$DRAM_RANK0_SIZE[$id] = "0x20000000";
-		$DRAM_RANK1_SIZE[$id] = "0";
-	}
-	elsif ($DENSITY[$id] eq "2048")
-	{
-		$DRAM_RANK0_SIZE[$id] = "0x10000000";
-		$DRAM_RANK1_SIZE[$id] = "0";
-	}
-
-    if ($DEV_TYPE[$id] eq "Discrete DDR1")
-    {
-        $DEV_TYPE1[$id] = "00" ;
-        $DEV_TYPE2[$id] = "01" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "Discrete DDR2")
-    {
-        $DEV_TYPE1[$id] = "00" ;
-        $DEV_TYPE2[$id] = "02" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "Discrete DDR3")
-    {
-        $DEV_TYPE1[$id] = "00" ;
-        $DEV_TYPE2[$id] = "03" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "MCP(NAND+DDR1)")
-    {
-        $DEV_TYPE1[$id] = "01" ;
-        $DEV_TYPE2[$id] = "01" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "MCP(NAND+DDR2)")
-    {
-        $DEV_TYPE1[$id] = "01" ;
-        $DEV_TYPE2[$id] = "02" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "MCP(NAND+DDR3)")
-    {
-        $DEV_TYPE1[$id] = "01" ;
-        $DEV_TYPE2[$id] = "03" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "MCP(eMMC+DDR1)")
-    {
-        $DEV_TYPE1[$id] = "02" ;
-        $DEV_TYPE2[$id] = "01" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "MCP(eMMC+DDR2)")
-    {
-        $DEV_TYPE1[$id] = "02" ;
-        $DEV_TYPE2[$id] = "02" ;
-    }
-    elsif ($DEV_TYPE[$id] eq "MCP(eMMC+DDR3)")
-    {
-        $DEV_TYPE1[$id] = "02" ;
-        $DEV_TYPE2[$id] = "03" ;
-    }
-    else
-    {
-        die "unknown mcp type $DEV_TYPE[$id] \n" ;
-    }
+        if ($DEV_TYPE[$id] eq "Discrete DDR1")
+        {
+            $DEV_TYPE1[$id] = "00" ;
+            $DEV_TYPE2[$id] = "01" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "Discrete DDR2")
+        {
+            $DEV_TYPE1[$id] = "00" ;
+            $DEV_TYPE2[$id] = "02" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "Discrete DDR3")
+        {
+            $DEV_TYPE1[$id] = "00" ;
+            $DEV_TYPE2[$id] = "03" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "MCP(NAND+DDR1)")
+        {
+            $DEV_TYPE1[$id] = "01" ;
+            $DEV_TYPE2[$id] = "01" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "MCP(NAND+DDR2)")
+        {
+            $DEV_TYPE1[$id] = "01" ;
+            $DEV_TYPE2[$id] = "02" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "MCP(NAND+DDR3)")
+        {
+            $DEV_TYPE1[$id] = "01" ;
+            $DEV_TYPE2[$id] = "03" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "MCP(eMMC+DDR1)")
+        {
+            $DEV_TYPE1[$id] = "02" ;
+            $DEV_TYPE2[$id] = "01" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "MCP(eMMC+DDR2)")
+        {
+            $DEV_TYPE1[$id] = "02" ;
+            $DEV_TYPE2[$id] = "02" ;
+        }
+        elsif ($DEV_TYPE[$id] eq "MCP(eMMC+DDR3)")
+        {
+            $DEV_TYPE1[$id] = "02" ;
+            $DEV_TYPE2[$id] = "03" ;
+        }
+        else
+        {
+            die "[Error]unknown mcp type $DEV_TYPE[$id] \n" ;
+        }
 
 
-    $_ = $NAND_EMMC_ID[$id] ;
-    $ID_String[$id] = "{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}" ;
-    if ($DEV_TYPE1[$id] == "01" ) 
-    {
-        if (/([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])/)
+        $_ = $NAND_EMMC_ID[$id] ;
+        print "NAND_EMMC_ID:$NAND_EMMC_ID[$id]\n";
+        # To parse NAND_EMMC_ID, we only support 12 bytes ID
+        if (length($NAND_EMMC_ID[$id]) % 2) 
         {
-            $ID_String[$id] = "{0x$1,0x$2,0x$3,0x$4,0x$5,0x0,0x0,0x0,0x0,0x0,0x0,0x0}" ;
-            print "$ID_String[$id]\n" ;
+            die "[Error] The wrong NAND_EMMC_ID: $NAND_EMMC_ID[$id] !!"; 
         }
-    }
-    elsif ($DEV_TYPE1[$id] == "02" ) 
-    {
-        if(/([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])([\dA-Fa-f][\dA-Fa-f])/)
+        $ID_String[$id] = "{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}" ;
+        $FW_ID_String[$id] = "{0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}" ;
+        $ID_Length[$id] = (length($NAND_EMMC_ID[$id])-2)/2; 
+        my @NAND_VECTOR = ($NAND_EMMC_ID[$id] =~ m/([\dA-Fa-f]{2})/gs);
+        my @FW_ID_VECTOR;
+        my $fw_id_len=0;
+        my $nand_emmc_id_len=0;
+	my $i;
+
+
+        print "To parse EMMC ID & FW ID:$DEV_TYPE1[$id],$ID_Length[$id]\n";
+        if ($DEV_TYPE1[$id] == "00" || $DEV_TYPE1[$id] == "01") 
         {
-            $ID_String[$id] = "{0x$1,0x$2,0x$3,0x$4,0x$5,0x$6,0x$7,0x$8,0x$9,0x0,0x0,0x0}" ;
-            print "$ID_String[$id]\n" ;
+            # Do nothing for NAND FW ID
+            $nand_emmc_id_len = $ID_Length[$id];
+            $fw_id_len = 0;
+            @FW_ID_VECTOR = "";
+            # The sub_version will be 1 once we have id_length
+            if($ID_Length[$id] == 9)
+            {
+                $Sub_version[$id] = "0x0";
+            }
+            else
+            {
+                $Sub_version[$id] = "0x1";
+            }
         }
-    }
-    
-    $EMI_SETTINGS[$id] = "\n\t//$PartNum\n\t{\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . "0x" . $DEV_TYPE1[$id] . $DEV_TYPE2[$id] . ",\t\t/* TYPE */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $ID_String[$id] . ",\t\t/* NAND_EMMC_ID */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $EMI_CONA_VAL[$id] . ",\t\t/* EMI_CONA_VAL */\n\t\t" ;
-    
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DRVCTL0_VAL[$id] . ",\t\t/* DRAMC_DRVCTL0_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DRVCTL1_VAL[$id] . ",\t\t/* DRAMC_DRVCTL1_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DLE_VAL[$id] . ",\t\t/* DRAMC_DLE_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_ACTIM_VAL[$id] . ",\t\t/* DRAMC_ACTIM_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_GDDR3CTL1_VAL[$id] . ",\t\t/* DRAMC_GDDR3CTL1_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_CONF1_VAL[$id] . ",\t\t/* DRAMC_CONF1_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DDR2CTL_VAL[$id] . ",\t\t/* DRAMC_DDR2CTL_VAL */\n\t\t" ;    
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_TEST2_3_VAL[$id] . ",\t\t/* DRAMC_TEST2_3_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_CONF2_VAL[$id] . ",\t\t/* DRAMC_CONF2_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_PD_CTRL_VAL[$id] . ",\t\t/* DRAMC_PD_CTRL_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_PADCTL3_VAL[$id] . ",\t\t/* DRAMC_PADCTL3_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DQODLY_VAL[$id] . ",\t\t/* DRAMC_DQODLY_VAL */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_ADDR_OUTPUT_DLY[$id] . ",\t\t/* DRAMC_ADDR_OUTPUT_DLY */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_CLK_OUTPUT_DLY[$id] . ",\t\t/* DRAMC_CLK_OUTPUT_DLY */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . "{" . $DRAM_RANK0_SIZE[$id] . "," .  $DRAM_RANK1_SIZE[$id] . ",0,0},\t\t/* DRAM RANK SIZE */\n\t\t" ;
-    $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . "{0,0,0,0,0,0},\t\t/* reserved 6 */\n\t\t" ;
-    
+        elsif ($DEV_TYPE1[$id] == "02" ) 
+        {
+            $nand_emmc_id_len = $USE_EMMC_ID_LEN;
+            $fw_id_len = $ID_Length[$id] - $nand_emmc_id_len;
+            @FW_ID_VECTOR = @NAND_VECTOR[$USE_EMMC_ID_LEN...($ID_Length[$id]-1)];
+            foreach(1...$fw_id_len)
+            {
+                pop(@NAND_VECTOR);
+            } 
+            print "EMMC_FW_ID:@FW_ID_VECTOR\n" ;
+            # for previous emmc version only check 9 bytes.
+            if($ID_Length[$id] == 9)
+            {
+                $Sub_version[$id] = "0x0";
+            }
+            else
+            {
+                $Sub_version[$id] = "0x1";
+            }
+        }
+        if ($fw_id_len > $MAX_FW_ID_LEN)
+        {
+            die("[ERROR] The FW ID number is larger then 8.");
+        }
+        #create NAND_EMMC_ID string
+        $last = pop(@NAND_VECTOR);
+        $ID_String[$id] = "{";
+        foreach $a (@NAND_VECTOR)
+        {
+            $ID_String[$id] .= "0x$a,";
+        }
+        $ID_String[$id] .= "0x$last";
+        # To add ZERO in the end
+        if ($nand_emmc_id_len < $MAX_NAND_EMMC_ID_LEN)
+        {
+            for($i = 0; $i <($MAX_NAND_EMMC_ID_LEN - $nand_emmc_id_len); $i++)
+            {
+                $ID_String[$id].= ",0x0" 
+            }
+        }
+        $ID_String[$id] .= "}";
+
+        print "$ID_String[$id]\n" ;
+
+        #create FW ID string
+        $last = pop(@FW_ID_VECTOR);
+        if ($fw_id_len != 0)
+        {
+            $FW_ID_String[$id] = "{";
+            foreach $a (@FW_ID_VECTOR)
+            {
+                $FW_ID_String[$id] .= "0x$a,";
+            }
+            $FW_ID_String[$id] .= "0x$last";
+            # To add ZERO in the end
+            if ($fw_id_len < $MAX_FW_ID_LEN)
+            {
+                for($i = 0; $i <($MAX_FW_ID_LEN - $fw_id_len); $i++)
+                {
+                    $FW_ID_String[$id].= ",0x0" 
+                }
+            }
+            $FW_ID_String[$id] .= "}";
+        }
+        print "$FW_ID_String[$id]\n" ;
+
+        $EMI_SETTINGS[$id] = "\n\t//$PartNum\n\t{\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . "0x" . $DEV_TYPE1[$id] . $DEV_TYPE2[$id] . ",\t\t/* TYPE */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $ID_String[$id] . ",\t\t/* NAND_EMMC_ID */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $EMI_CONA_VAL[$id] . ",\t\t/* EMI_CONA_VAL */\n\t\t" ;
+
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DRVCTL0_VAL[$id] . ",\t\t/* DRAMC_DRVCTL0_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DRVCTL1_VAL[$id] . ",\t\t/* DRAMC_DRVCTL1_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DLE_VAL[$id] . ",\t\t/* DRAMC_DLE_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_ACTIM_VAL[$id] . ",\t\t/* DRAMC_ACTIM_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_GDDR3CTL1_VAL[$id] . ",\t\t/* DRAMC_GDDR3CTL1_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_CONF1_VAL[$id] . ",\t\t/* DRAMC_CONF1_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DDR2CTL_VAL[$id] . ",\t\t/* DRAMC_DDR2CTL_VAL */\n\t\t" ;    
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_TEST2_3_VAL[$id] . ",\t\t/* DRAMC_TEST2_3_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_CONF2_VAL[$id] . ",\t\t/* DRAMC_CONF2_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_PD_CTRL_VAL[$id] . ",\t\t/* DRAMC_PD_CTRL_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_PADCTL3_VAL[$id] . ",\t\t/* DRAMC_PADCTL3_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_DQODLY_VAL[$id] . ",\t\t/* DRAMC_DQODLY_VAL */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_ADDR_OUTPUT_DLY[$id] . ",\t\t/* DRAMC_ADDR_OUTPUT_DLY */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DRAMC_CLK_OUTPUT_DLY[$id] . ",\t\t/* DRAMC_CLK_OUTPUT_DLY */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . "{" . $DRAM_RANK0_SIZE[$id] . "," .  $DRAM_RANK1_SIZE[$id] . ",0,0},\t\t/* DRAM RANK SIZE */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . "{0,0},\t\t/* reserved 2 */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $FW_ID_String[$id] . ",\t\t/* EMMC FW ID */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $ID_Length[$id] . ",\t\t/* EMMC ID/FW ID checking length */\n\t\t" ;
+        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $Sub_version[$id] . ",\t\t/* sub_version */\n\t\t" ;
+
 #union
 #1 DDR2
-    if ($DDR1_2_3[id] eq "DDR2")
-    {    
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG1[$id] . ",\t\t/* DDR2_MODE_REG1 */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG2[$id] . ",\t\t/* DDR2_MODE_REG2 */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG3[$id] . ",\t\t/* DDR2_MODE_REG3 */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG10[$id] . ",\t\t/* DDR2_MODE_REG10 */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG63[$id] . "\t\t/* DDR2_MODE_REG63 */\n\t}" ;
-    }
+        if ($DDR1_2_3[$id] eq "DDR2")
+        {    
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG1[$id] . ",\t\t/* DDR2_MODE_REG1 */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG2[$id] . ",\t\t/* DDR2_MODE_REG2 */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG3[$id] . ",\t\t/* DDR2_MODE_REG3 */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG10[$id] . ",\t\t/* DDR2_MODE_REG10 */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR2_MODE_REG63[$id] . "\t\t/* DDR2_MODE_REG63 */\n\t}" ;
+        }
 #2 DDR1
-    elsif ($DDR1_2_3[id] eq "DDR1")
-    {
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR1_MODE_REG[$id] . ",\t\t/* DDR1_MODE_REG */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR1_EXT_MODE_REG[$id] . "\t\t/* DDR1_EXT_MODE_REG */\n\t}" ;
-    }
+        elsif ($DDR1_2_3[$id] eq "DDR1")
+        {
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR1_MODE_REG[$id] . ",\t\t/* DDR1_MODE_REG */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR1_EXT_MODE_REG[$id] . "\t\t/* DDR1_EXT_MODE_REG */\n\t}" ;
+        }
 #3 DDR3    
-     elsif ($DDR1_2_3[id] eq "DDR3")
-    {
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG0[$id] . ",\t\t/* DDR3_MODE_REG0 */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG1[$id] . ",\t\t/* DDR3_MODE_REG1 */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG2[$id] . ",\t\t/* DDR3_MODE_REG2 */\n\t\t" ;
-        $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG3[$id] . ",\t\t/* DDR3_MODE_REG3 */\n\t}" ;
-    }   
-    print  $EMI_SETTINGS[$id] ;
-    print "\n\n" ;
+        elsif ($DDR1_2_3[$id] eq "DDR3")
+        {
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG0[$id] . ",\t\t/* DDR3_MODE_REG0 */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG1[$id] . ",\t\t/* DDR3_MODE_REG1 */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG2[$id] . ",\t\t/* DDR3_MODE_REG2 */\n\t\t" ;
+            $EMI_SETTINGS[$id] = $EMI_SETTINGS[$id] . $DDR3_MODE_REG3[$id] . ",\t\t/* DDR3_MODE_REG3 */\n\t}" ;
+        }   
+        print  $EMI_SETTINGS[$id] ;
+        print "\n\n" ;
+        $id ++;
+    }
+    # return total_part_number_iter
+    return $id;
+    
 }
 
 
@@ -1056,7 +1185,7 @@ sub OsName {
     $os = "linux";
   } 
   else {
-    die "does not support windows now!!" ;
+    die "[Error]does not support windows now!!" ;
     $os = "windows";
   }
 }
@@ -1131,7 +1260,7 @@ sub lin_xls_cell_value
 {
   my ($Sheet, $row, $col) = @_;
   my $cell = $Sheet->get_cell($row, $col);
-  exit 1 unless (defined $cell);
+  return "" unless (defined $cell);
   my $value = $cell->Value();
 
 }
@@ -1282,11 +1411,24 @@ sub write_tag_one_element()
     print FILE pack ("L", hex ("0")) ;
     print FILE pack ("L", hex ("0")) ;
     print FILE pack ("L", hex ("0")) ;
-    print FILE pack ("L", hex ("0")) ;
-    print FILE pack ("L", hex ("0")) ;
-    print FILE pack ("L", hex ("0")) ;
-    print FILE pack ("L", hex ("0")) ;
-    $fs = $fs + 40 ;
+    $fs = $fs + 24 ;
+    $_ = $FW_ID_String[$id] ;
+    if (/(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+),(\w+)/)
+    {
+        print FILE pack ("C", hex ($1)) ;            #fw id
+        print FILE pack ("C", hex ($2)) ;
+        print FILE pack ("C", hex ($3)) ;
+        print FILE pack ("C", hex ($4)) ;
+        print FILE pack ("C", hex ($5)) ;
+        print FILE pack ("C", hex ($6)) ;
+        print FILE pack ("C", hex ($7)) ;
+        print FILE pack ("C", hex ($8)) ;
+        $fs = $fs + 8 ;
+    }
+
+    print FILE pack ("L", scalar($ID_Length[$id])) ;        # EMMC ID/FW ID checking length
+    print FILE pack ("L", hex (lc($Sub_version[$id]))) ;        # Sub_version checking for flash tool
+    $fs = $fs + 8 ;
     
     
     if ($DEV_TYPE2[$id] == "02")
--- a/mediatek/platform/mt6577/preloader/check_size.sh
+++ b/mediatek/platform/mt6577/preloader/check_size.sh
@@ -1,5 +1,5 @@
 PL_MAX_RAM_SIZE=32768
-PL_MAX_ROM_SIZE=111800
+PL_MAX_ROM_SIZE=118000
 
 ROM_RPT_SIZE=500
 RAM_RPT_SIZE=500



--- a/mediatek/platform/mt6577/preloader/src/drivers/inc/mt6577_emi.h
+++ b/mediatek/platform/mt6577/preloader/src/drivers/inc/mt6577_emi.h
@@ -75,7 +75,10 @@ typedef struct
     int   DRAMC_ADDR_OUTPUT_DLY;  // for E1 DDR2 only
     int   DRAMC_CLK_OUTPUT_DLY;   // for E1 DDR2 only
     int   DRAM_RANK_SIZE[4];
-    int   reserved[6];
+    int   reserved[2];
+    char  fw_id[8];               // To save fw id
+    int   id_length;              // EMMC and NAND ID/FW ID checking length
+    int   sub_version;            // sub_version: 0x1 for new version
 
     union
     {


--- a/mediatek/platform/mt6577/preloader/src/drivers/mt6577_emi.c
+++ b/mediatek/platform/mt6577/preloader/src/drivers/mt6577_emi.c
@@ -735,8 +735,10 @@ static int mt6577_get_mdl_number (void)
                         if ((emi_settings[i].type & 0xF00) == 0x100)
                         {
                             /* NAND */
-                            if (memcmp(id, emi_settings[i].ID, 5) == 0)
+                            if (memcmp(id, emi_settings[i].ID, emi_settings[i].id_length) == 0){
+                                memset(id + emi_settings[i].id_length, 0, sizeof(id) - emi_settings[i].id_length);                                
                                 break; /* found */
+                            }
                         }
                         else
                         {
@@ -895,6 +897,11 @@ void mt6577_set_emi (void)
     *(volatile unsigned int *)0xC0003150 = 0x00000830;
     else if (mt6577_get_dram_type() == 3)
         *(volatile unsigned int *)0xC0003150 = 0x00000845;
+
+#ifdef MTK_DISPLAY_HIGH_RESOLUTION
+    *(volatile unsigned int *)0xC0003158 = 0x00004000;
+#endif
+ 
     *(volatile unsigned int*) 0xC00030F0 = 0x04080008;
     if (platform_chip_ver() == CHIP_VER_E1) {
         *(volatile unsigned int *)0xC00030F8 = 0x90000000; 


--- a/mediatek/platform/mt6577/preloader/src/drivers/nand.c
+++ b/mediatek/platform/mt6577/preloader/src/drivers/nand.c
@@ -146,6 +146,7 @@ uint8 ext_id1, ext_id2, ext_id3;
 static u32 g_u4ChipVer;
 static u32 g_i4ErrNum;
 static BOOL g_bInitDone;
+BOOL g_bHwEcc=TRUE;
 
 /*
 struct nand_oobinfo mt6577_nand_oob = {
@@ -554,7 +555,7 @@ static void ECC_Config (void)
         ECC_CNFG_ECC4 | ENC_CNFG_NFI |
         (u4ENCODESize << ENC_CNFG_MSG_SHIFT));
 
-#ifdef USE_AHB_MODE
+#ifndef MANUAL_CORRECT
     NFI_SET_REG32 (ECC_DECCNFG_REG32, DEC_CNFG_CORRECT);
 #else
     NFI_SET_REG32 (ECC_DECCNFG_REG32, DEC_CNFG_EL);
@@ -588,13 +589,12 @@ static bool mt6577_nand_check_bch_error (u8 * pDataBuf, u32 u4SecIndex, u32 u4Pa
     u32 u4ErrorNumDebug, i, u4ErrNum;
     u32 timeout = 0xFFFF;
 
-#if !USE_AHB_MODE
+#ifdef MANUAL_CORRECT
     u32 au4ErrBitLoc[6];
     u32 u4ErrByteLoc, u4BitOffset;
     u32 u4ErrBitLoc1th, u4ErrBitLoc2nd;
 #endif
 
-    //4 // Wait for Decode Done
     while (0 == (u2SectorDoneMask & DRV_Reg16 (ECC_DECDONE_REG16)))
     {
         timeout--;
@@ -603,7 +603,7 @@ static bool mt6577_nand_check_bch_error (u8 * pDataBuf, u32 u4SecIndex, u32 u4Pa
             return FALSE;
         }
     }
-#if (USE_AHB_MODE)
+#ifndef MANUAL_CORRECT
     u4ErrorNumDebug = DRV_Reg32 (ECC_DECENUM_REG32);
     if (0 != (u4ErrorNumDebug & 0xFFFF))
     {
@@ -613,20 +613,17 @@ static bool mt6577_nand_check_bch_error (u8 * pDataBuf, u32 u4SecIndex, u32 u4Pa
             u4ErrNum &= 0xF;
             if (0xF == u4ErrNum)
             {
-                //mtd->ecc_stats.failed++;
                 bRet = FALSE;
-                MSG (INIT, "UnCorrectable at PageAddr=%d, Sector=%d\n",
-                    u4PageAddr, i);
+                printf("UnCorrectable at PageAddr=%d, Sector=%d with ECC_DECENUM=%x\n", u4PageAddr, i,u4ErrNum);
             }
             else
             {
-                //mtd->ecc_stats.corrected++;
-                MSG (INIT, "Correct at PageAddr=%d, Sector=%d\n",
-                    u4ErrNum, u4PageAddr, i);
+                printf( "Correct %d bit error at PageAddr=%d, Sector=%d\n",u4ErrNum, u4PageAddr, i);
             }
         }
     }
 #else
+/* We will manually correct the error bits in the last sector, not all the sectors of the page!*/
     //memset(au4ErrBitLoc, 0x0, sizeof(au4ErrBitLoc));
     u4ErrorNumDebug = DRV_Reg32 (ECC_DECENUM_REG32);
     u4ErrNum = DRV_Reg32 (ECC_DECENUM_REG32) >> (u4SecIndex << 2);
@@ -924,10 +921,13 @@ static u8 mt6577_nand_read_byte (void)
     return DRV_Reg8 (NFI_DATAR_REG32);
 }
 
-bool getflashid(u8 *id)
+bool getflashid(u8 *nand_id, int longest_id_number)
 {
 	u8 maf_id=0;
 	u8 dev_id=0;
+        int i=0;
+        u8 *id=nand_id;
+
 	PDN_Power_CONA_DOWN (PDN_PERI_NFI, FALSE);
 
 	DRV_WriteReg32 (NFI_ACCCON_REG32, NFI_DEFAULT_ACCESS_TIMING);
@@ -947,14 +947,12 @@ bool getflashid(u8 *id)
 	}
 	//*id= (dev_id<<8)|maf_id;
     //    *id= (maf_id<<8)|dev_id;
-    id[0] = maf_id;
+        id[0] = maf_id;
 	id[1] = dev_id;
-	id[2] = mt6577_nand_read_byte ();
-	id[3] = mt6577_nand_read_byte ();
-	id[4] = mt6577_nand_read_byte ();
-#ifdef DBG_PRELOADER	
-	MSG (INIT, "getflashID %x %x %x %x %x successful!!!\n",id[0],id[1],id[2],id[3],id[4]);
-#endif
+        
+        for(i = 2; i < longest_id_number; i++)
+            id[i] = mt6577_nand_read_byte ();
+
 	return TRUE;
 }
 
@@ -1185,14 +1183,20 @@ int mt6577_nand_init (void)
 static void mt6577_nand_stop_read (void)
 {
     NFI_CLN_REG16 (NFI_CON_REG16, CON_NFI_BRD);
-    ECC_Decode_End ();
+    if(g_bHwEcc)
+    {
+        ECC_Decode_End ();
+    }
 }
 
 //-----------------------------------------------------------------------------
 static void mt6577_nand_stop_write (void)
 {
     NFI_CLN_REG16 (NFI_CON_REG16, CON_NFI_BWR);
-    ECC_Encode_End ();
+    if(g_bHwEcc)
+    {
+        ECC_Encode_End ();
+    }
 }
 
 //-----------------------------------------------------------------------------
@@ -1219,25 +1223,10 @@ static bool mt6577_nand_read_page_data (u32 * buf)
     u32 i;
     u32 *pBuf32;
 
-    /* Infinity. No need since it's set in initialization stage */
-    /*
-    NFI_SET_REG16 (NFI_PAGEFMT_REG16,
-        (PAGEFMT_SPARE_16 << PAGEFMT_SPARE_SHIFT) | PAGEFMT_2K);
-    */
-
 #if (USE_AHB_MODE)
     pBuf32 = (u32 *) buf;
     NFI_CLN_REG16 (NFI_CNFG_REG16, CNFG_BYTE_RW);
-    // DRV_WriteReg32 (NFI_STRADDR_REG32, pBuf32);
-#if 0
-    if (i4Interrupt)
-    {
-        init_completion (&g_comp_AHB_Done);
-        DRV_Reg16 (NFI_INTR_REG16);
-        DRV_WriteReg16 (NFI_INTR_EN_REG16, INTR_AHB_DONE_EN);
-    }
-    dmac_inv_range (pDataBuf, pDataBuf + u4Size);
-#endif
+
     DRV_Reg16 (NFI_INTR_REG16);
     DRV_WriteReg16 (NFI_INTR_EN_REG16, INTR_AHB_DONE_EN);
     NFI_SET_REG16 (NFI_CON_REG16, CON_NFI_BRD);
@@ -1261,29 +1250,9 @@ static bool mt6577_nand_read_page_data (u32 * buf)
         }
     }
 
-#if 0
-    if (i4Interrupt)
-    {
-        wait_for_completion (&g_comp_AHB_Done);
-    }
-    else
-    {
-        // while (u4Size > DRV_Reg16 (NFI_BYTELEN_REG16))
-        while ( (u4Size >> 9) > ((DRV_Reg16(NFI_BYTELEN_REG16) & 0xf000) >> 12) )
-        {
-            timeout--;
-            if (0 == timeout)
-            {
-                return FALSE;     //4  // AHB Mode Time Out!
-            }
-        }
-#endif
-#if 0
-    }
-#endif
 #else
     NFI_CLN_REG16 (NFI_CNFG_REG16, CNFG_BYTE_RW);
-    DRV_WriteReg32 (NFI_STRADDR_REG32, 0);
+    //DRV_WriteReg32 (NFI_STRADDR_REG32, 0);
     NFI_SET_REG16 (NFI_CON_REG16, CON_NFI_BRD);
 
     //pBuf32 = (u32*)g_nand_buf;
@@ -1291,7 +1260,6 @@ static bool mt6577_nand_read_page_data (u32 * buf)
 
     for (i = 0; (i < (u4Size >> 2)) && (timeout > 0);)
     {
-        //if (FIFO_RD_REMAIN (DRV_Reg16 (NFI_FIFOSTA_REG16)) >= 4)
 	if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1)
         {
             *pBuf32++ = DRV_Reg32 (NFI_DATAR_REG32);
@@ -1321,16 +1289,7 @@ static bool mt6577_nand_write_page_data (u32 * buf)
     pBuf32 = (u32 *) buf;
 
     NFI_CLN_REG16 (NFI_CNFG_REG16, CNFG_BYTE_RW);
-    // DRV_WriteReg32 (NFI_STRADDR_REG32, pBuf32);
-#if 0
-    if (i4Interrupt)
-    {
-        init_completion (&g_comp_AHB_Done);
-        DRV_Reg16 (NFI_INTR_REG16);
-        DRV_WriteReg16 (NFI_INTR_EN_REG16, INTR_AHB_DONE_EN);
-    }
-    dmac_clean_range (pDataBuf, pDataBuf + u4Size);
-#endif
+
     DRV_Reg16 (NFI_INTR_REG16);
     DRV_WriteReg16 (NFI_INTR_EN_REG16, INTR_AHB_DONE_EN);
     NFI_SET_REG16 (NFI_CON_REG16, CON_NFI_BWR);
@@ -1342,26 +1301,7 @@ static bool mt6577_nand_write_page_data (u32 * buf)
             return FALSE;     //4  // AHB Mode Time Out!
         }
     }
-#if 0
-    if (i4Interrupt)
-    {
-        wait_for_completion (&g_comp_AHB_Done);
-    }
-    else
-    {
-        // while (u4Size > DRV_Reg16 (NFI_BYTELEN_REG16))
-        while ( (u4Size >> 9) > ((DRV_Reg16(NFI_BYTELEN_REG16) & 0xf000) >> 12) )
-        {
-            timeout--;
-            if (0 == timeout)
-            {
-                return FALSE;     //4  // AHB Mode Time Out!
-            }
-        }
-#endif
-#if 0
-    }
-#endif
+
 #else
     u32 i;
     u32 *pBuf32;
@@ -1372,7 +1312,8 @@ static bool mt6577_nand_write_page_data (u32 * buf)
 
     for (i = 0; (i < (u4Size >> 2)) && (timeout > 0);)
     {
-        if (FIFO_WR_REMAIN (DRV_Reg16 (NFI_FIFOSTA_REG16)) <= 12)
+        //if (FIFO_WR_REMAIN (DRV_Reg16 (NFI_FIFOSTA_REG16)) <= 12)
+			if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1)
         {
             DRV_WriteReg32 (NFI_DATAW_REG32, *pBuf32++);
             i++;
@@ -1402,10 +1343,8 @@ static void mt6577_nand_read_fdm_data (u32 u4SecNum, u8 * spare_buf)
     for (i = 0; i < u4SecNum; ++i)
     {
         *pBuf32++ = DRV_Reg32 (NFI_FDM0L_REG32 + (i << 3));
-        //MSG(ERASE, "NFI_FDM%dL_REG32 (0x%x) = 0x%x\n", i, (NFI_FDM0L_REG32 + (i<<3)), DRV_Reg32(NFI_FDM0L_REG32 + (i<<3)));
         *pBuf32++ = DRV_Reg32 (NFI_FDM0M_REG32 + (i << 3));
-        //MSG(ERASE, "NFI_FDM%dM_REG32 (0x%x) = 0x%x\n", i, (NFI_FDM0M_REG32 + (i<<3)), DRV_Reg32(NFI_FDM0M_REG32 + (i<<3)));
-    }
+        }
 }
 
 //-----------------------------------------------------------------------------
@@ -1417,12 +1356,8 @@ mt6577_nand_write_fdm_data (u32 u4SecNum, u8 *oob)
 
     for (i = 0; i < u4SecNum; ++i)
     {
-        //MSG(ERASE, "g_nand_spare %d : 0x%x\n", i, *pBuf32);
         DRV_WriteReg32 (NFI_FDM0L_REG32 + (i << 3), *pBuf32++);
-        //MSG(ERASE, "NFI_FDM%dL_REG32 (0x%x) = 0x%x\n", i, (NFI_FDM0L_REG32 + (i<<3)), DRV_Reg32(NFI_FDM0L_REG32 + (i<<3)));
-        //MSG(ERASE, "g_nand_spare %d : 0x%x\n", i, *pBuf32);
         DRV_WriteReg32 (NFI_FDM0M_REG32 + (i << 3), *pBuf32++);
-        //MSG(ERASE, "NFI_FDM%dM_REG32 (0x%x) = 0x%x\n", i, (NFI_FDM0M_REG32 + (i<<3)), DRV_Reg32(NFI_FDM0M_REG32 + (i<<3)));
     }
 }
 
@@ -1448,15 +1383,22 @@ static bool mt6577_nand_ready_for_read (u32 page_addr, u32 sec_num, u8 *buf)
 
 #if USE_AHB_MODE
     NFI_SET_REG16 (NFI_CNFG_REG16, CNFG_AHB);
-    DRV_WriteReg32(NFI_STRADDR_REG32, buf);
 #else
     NFI_CLN_REG16 (NFI_CNFG_REG16, CNFG_AHB);
 #endif
+    DRV_WriteReg32(NFI_STRADDR_REG32, buf);
+    if(g_bHwEcc)
+    {
+	NFI_SET_REG16 (NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+    }else{
+	NFI_CLN_REG16 (NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+    }
 
-    NFI_SET_REG16 (NFI_CNFG_REG16, CNFG_HW_ECC_EN);
     mt6577_nand_set_autoformat (TRUE);
-    ECC_Decode_Start ();
-
+    if(g_bHwEcc)
+    {
+        ECC_Decode_Start ();
+    }
     if (!mt6577_nand_set_command (NAND_CMD_READ0))
     {
         goto cleanup;
@@ -1511,11 +1453,17 @@ static bool mt6577_nand_ready_for_write (u32 page_addr, u32 sec_num, u8 *buf)
     NFI_CLN_REG16 (NFI_CNFG_REG16, CNFG_AHB);
 #endif
 
-    NFI_SET_REG16 (NFI_CNFG_REG16, CNFG_HW_ECC_EN);
-
+    if(g_bHwEcc)
+    {
+        NFI_SET_REG16 (NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+    }else{
+	NFI_CLN_REG16 (NFI_CNFG_REG16, CNFG_HW_ECC_EN);
+    }
     mt6577_nand_set_autoformat (TRUE);
-
-    ECC_Encode_Start ();
+    if(g_bHwEcc)
+    {
+	ECC_Encode_Start ();
+    }
 
     if (!mt6577_nand_set_command (NAND_CMD_SEQIN))
     {
@@ -1595,22 +1543,22 @@ int mt6577_nand_read_page_hw (u32 page, u8 *dat, u8 *oob)
         {
             bRet = FALSE;
         }
-
-        if (!mt6577_nand_check_dececc_done (u4SecNum))
+	if(g_bHwEcc)
         {
-            bRet = FALSE;
-        }
-
-        //mt6577_nand_read_fdm_data(u4SecNum, (char*)(buf + 2048));
+            if (!mt6577_nand_check_dececc_done (u4SecNum) )
+            {
+                bRet = FALSE;
+            }
+	}
         mt6577_nand_read_fdm_data (u4SecNum, oob);
-        //mt6577_nand_read_fdm_data(u4SecNum);
-
-        if (!mt6577_nand_check_bch_error(pPageBuf, u4SecNum - 1, page))
+	if(g_bHwEcc)
         {
-        MSG(ERASE, "check bch error !\n");
-        bRet = FALSE;
+            if (!mt6577_nand_check_bch_error(pPageBuf, u4SecNum - 1, page))
+            {
+                MSG(ERASE, "check bch error !\n");
+                bRet = FALSE;
+            }
         }
-
         mt6577_nand_stop_read ();
     }
 #if 0
@@ -1668,7 +1616,6 @@ int mt6577_nand_write_page_hwecc (unsigned int logical_addr, char *buf)
     // write bad index into oob
     if (mapped_block != block)
     {
-        // MSG(INIT, "page: 0x%x\n", page_in_block);
         set_bad_index_to_oob(g_nand_spare, block);
     }
     else 
@@ -1696,19 +1643,7 @@ int mt6577_nand_write_page_hw(u32 page, u8 *dat, u8 *oob)
     int i, j, start, len;
     bool empty = TRUE;
     u8 oob_checksum = 0;
-    // u32 page_addr = PAGE_NUM (logical_addr);
-
-
-#if 0
-    MSG (WRITE, "Dump spare data :\n");
-    for (i = 0; i < 32; i++)
-    {
-        MSG (WRITE, "g_nand_spare [%d] : 0x%x, usb spare [%d] : 0x%x\n", i,
-            *(g_nand_spare + i), i, *(buf + 2048 + i));
-    }
-#endif
-
-    // MSG (WRITE, "write page addr is 0x%x\n", page_addr);
+ 
     for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && nand_oob->oobfree[i].length; i++)
     {
         /* Set the reserved bytes to 0xff */


--- a/mediatek/platform/mt6577/preloader/src/drivers/nand_common_inter.c
+++ b/mediatek/platform/mt6577/preloader/src/drivers/nand_common_inter.c
@@ -40,6 +40,9 @@
 #include "blkdev.h"
 #include "nand.h"
 #include "nand_common_inter.h"
+#include "part.h"
+#include "partition_define.h"
+
 
 /**************************************************************************
 *  DEBUG CONTROL
@@ -116,9 +119,51 @@ static int nand_bwrite(blkdev_t *bdev, u32 blknr, u32 blks, u8 *buf)
     return 0;
 }
 
+void Invert_Bits(u8* buff_ptr, u32 bit_pos)
+{
+    u32 byte_pos   = 0;
+    u8  byte_val   = 0;
+   u8  temp_val   = 0;
+    u32 invert_bit = 0;
+
+    byte_pos = bit_pos >> 3;
+    invert_bit = bit_pos & ((1<<3)-1);
+    byte_val = buff_ptr[byte_pos];    
+    temp_val = byte_val & (1 << invert_bit);
+    
+    if(temp_val > 0)
+        byte_val &= ~temp_val;
+    else
+        byte_val |= (1 << invert_bit);
+    buff_ptr[byte_pos] = byte_val;    
+}
+void compare_page(u8 * testbuff, u8 * sourcebuff,u32 length,char *s){
+	u32 errnum=0;
+	u32 ii=0;
+	u32 index;
+	printf("%s",s);
+	for(index=0;index<length;index++){				
+		if(testbuff[index]!=sourcebuff[index]){
+			u8 t=sourcebuff[index]^testbuff[index];
+			for(ii=0;ii<8;ii++){
+				if((t>>ii)&0x1==1){
+					errnum++;
+				}
+			}
+			printf(" ([%d]=%x) != ([%d]=%x )",index,sourcebuff[index],index,testbuff[index]);
+		}
+
+	}
+	if(errnum>0){
+		printf(": page have %d mismatch bits\n",errnum);
+	}else{
+		printf(" :the two buffers are same!\n");
+	}
+}
 // ==========================================================
 // NAND Common Interface - Init
 // ==========================================================
+//#define TEST_PIO_ECC
 u32 nand_init_device(void)
 {
     if (!blkdev_get(BOOTDEV_NAND)) {
@@ -137,6 +182,97 @@ u32 nand_init_device(void)
         g_nand_bdev.blkbuf  = (u8*)STORAGE_BUFFER_ADDR;
         g_nand_bdev.type    = BOOTDEV_NAND;
 
+#ifdef TEST_PIO_ECC
+	#define NAND_MAX_PAGE_LENGTH (g_nand_chip.page_size+128)
+	
+	int ecc_level=4,sec_index,curr_error_bit,err_bits_per_sec;
+	int sec_num=g_nand_chip.page_size>>9;
+	u32 sec_size=g_nand_chip.page_size/sec_num;
+	u8 *testbuff=malloc(NAND_MAX_PAGE_LENGTH);
+	u8 *sourcebuff=malloc(NAND_MAX_PAGE_LENGTH);
+	//part_t *part = part_get(PART_UBOOT);
+  	//u32 offset = (part->startblk) * g_nand_chip.erasesize;
+	//printf("(part->startblk) =%d * g_nand_chip.erasesize=%d",(part->startblk),g_nand_chip.erasesize);
+	u32 offset=0x620000;
+	u32 page_idx=0;
+	u32 chk_bit_len= sec_size<<3;
+	u32 errbits=0;
+	u32 index=0;
+	u32 page_per_blk=g_nand_chip.erasesize/g_nand_chip.page_size;
+
+	for(err_bits_per_sec=1;err_bits_per_sec<=ecc_level;err_bits_per_sec++){
+		offset+=g_nand_chip.erasesize*(err_bits_per_sec-1);
+		printf("~~~start test ecc correct in ");
+		#if USE_AHB_MODE
+		printf(" AHB mode");
+		#else
+		printf(" MCU mode");
+		#endif
+		printf(", every sector have %d bit error~~~\n",err_bits_per_sec);
+		curr_error_bit=0;
+		for(page_idx = 0 ; page_idx < page_per_blk; page_idx++){
+			printf("~~~start test ecc correct in Page %d \n",offset/g_nand_chip.page_size+page_idx);
+			g_bHwEcc=TRUE;
+			nand_read_data(sourcebuff,offset+page_idx*g_nand_chip.page_size);
+			memcpy(testbuff, sourcebuff, NAND_MAX_PAGE_LENGTH);
+			for(sec_index = 0 ; sec_index < sec_num && curr_error_bit < chk_bit_len ; sec_index++){
+				//printf("insert err bit @ page %d:sector %d : bit ",page_idx+offset/g_nand_chip.page_size,sec_index);
+				for(errbits=0;errbits<err_bits_per_sec;errbits++){
+					Invert_Bits(((u8 *)testbuff)+sec_index*sec_size, curr_error_bit);	
+					//printf("%d, ",curr_error_bit);
+					curr_error_bit++;
+				}
+				//printf("\n");
+			}
+			g_bHwEcc=FALSE;
+			nand_write_data (testbuff,offset+page_idx*g_nand_chip.page_size);
+			compare_page(testbuff, sourcebuff,NAND_MAX_PAGE_LENGTH,"source and test buff check ");
+			g_bHwEcc=TRUE;
+			nand_read_data(testbuff,offset+page_idx*g_nand_chip.page_size);
+			compare_page(testbuff, sourcebuff,NAND_MAX_PAGE_LENGTH,"read back check ");
+		}
+	}
+
+  //part_t *part2 = part_get(PART_BOOTIMG);
+  //offset = (part2->startblk) * g_nand_chip.erasesize;
+	offset=0x680000;
+
+  for(err_bits_per_sec=1;err_bits_per_sec<=ecc_level;err_bits_per_sec++){
+	  offset+=g_nand_chip.erasesize*(err_bits_per_sec-1);
+	  printf("~~~start test ecc correct in ");
+	#if USE_AHB_MODE
+	  printf(" AHB mode");
+	#else
+	  printf(" MCU mode");
+	#endif
+	  printf(", every sector have %d bit error~~~\n",err_bits_per_sec);
+	  curr_error_bit=0;
+	  for(page_idx = 0 ; page_idx < page_per_blk; page_idx++){
+		  printf("~~~start test ecc correct in Page %d \n",offset/g_nand_chip.page_size+page_idx);
+		  g_bHwEcc=TRUE;
+		  nand_read_data(sourcebuff,offset+page_idx*g_nand_chip.page_size);
+		  memcpy(testbuff, sourcebuff, NAND_MAX_PAGE_LENGTH);
+		  for(sec_index = 0 ; sec_index < sec_num && curr_error_bit < chk_bit_len ; sec_index++){
+			  //printf("insert err bit @ page %d:sector %d : bit ",page_idx+offset/g_nand_chip.page_size,sec_index);
+			  for(errbits=0;errbits<err_bits_per_sec;errbits++){
+				  Invert_Bits(((u8 *)testbuff)+sec_index*sec_size, curr_error_bit);   
+				  //printf("%d, ",curr_error_bit);
+				  curr_error_bit++;
+			  }
+			  //printf("\n");
+		  }
+		  g_bHwEcc=FALSE;
+		  nand_write_data (testbuff,offset+page_idx*g_nand_chip.page_size);
+		  compare_page(testbuff, sourcebuff,NAND_MAX_PAGE_LENGTH,"source and test buff check ");
+		  g_bHwEcc=TRUE;
+		  nand_read_data(testbuff,offset+page_idx*g_nand_chip.page_size);
+		  compare_page(testbuff, sourcebuff,NAND_MAX_PAGE_LENGTH,"read back check ");
+	  }
+  }
+
+	
+  #endif
+
         blkdev_register(&g_nand_bdev);
     }
     
@@ -145,12 +281,12 @@ u32 nand_init_device(void)
 
 u32 nand_get_device_id(u8 *id, u32 len)
 {
-    u8 buf[5];
+    u8 buf[16];
     
-    if (TRUE != getflashid(buf))
+    if (TRUE != getflashid(buf, len))
         return -1;
 
-    len = len > 5 ? 5 : len;
+    len = len > 16 ? 16 : len;
 
     memcpy (id, buf, len);
 
@@ -215,7 +351,7 @@ u32 nand_read_data (u8 * buf, u32 offset)
     if (mt6577_nand_read_page_hwecc (offset, buf) == FALSE)
     {     
         print ("nand_read_data fail\n");
-        ASSERT (0);
+        return -1;
     }
 
     return offset;
@@ -238,7 +374,7 @@ u32 nand_write_data (u8 * buf, u32 offset)
     return offset;
 }
 
-#if CFG_LEGACY_USB_DOWNLOAD
+
 // ==========================================================
 // NAND Common Interface - Erase Function
 // ==========================================================
@@ -295,6 +431,7 @@ bool nand_erase_data (u32 offset, u32 offset_limit, u32 size)
 
     return TRUE;
 }
+#if CFG_LEGACY_USB_DOWNLOAD
 
 // ==========================================================
 // NAND Common Interface - Check If Device Is Ready To Use