OSDN Git Service

Prepare for ADFE-FlashWriter 1.0.4
authorMasaki Muranaka <monaka at monami-software.com>
Wed, 15 Jul 2009 08:51:54 +0000 (17:51 +0900)
committerMasaki Muranaka <monaka at monami-software.com>
Wed, 15 Jul 2009 08:51:54 +0000 (17:51 +0900)
jtag/src/flash/amd_flash.c

index a3c56ba..22de3ec 100644 (file)
@@ -24,6 +24,8 @@
  * Documentation:
  * [1] Spansion, Am29F040B Data Sheet
  * [2] Spansion, Am29LV040B Data Sheet
+ * [3] Spansion, Am29LV081B Data Sheet
+ * [4] Spansion, Am29LV400D Data Sheet
 */
 
 #include "sysdep.h"
 #define AMD_UNDEFINED_MODE
 
 #define FLASH_ERASE_ERROR                      -5
-#define ERASE_FLASH_SUCCESS                    1
+#define FLASH_ERASE_SUCCESS                    0
 
-#define AMD_29xx040B   1
+#define AMD_UNKNOWN_DEVICE     0
+#define AMD_29xx040B           1
+#define AMD_29xx081B           (0x38)
+#define AMD_29LV400B_TOP       (0xB9)
+#define AMD_29LV400B_BOTTOM    (0xBA)
 
 #define AMD_BYPASS_UNLOCK_ALGORITHM            1
 #define AMD_STANDARD_WRITE_ALGORITHM           0
@@ -72,19 +78,88 @@ struct
        unsigned short algorithm;
        unsigned short unlock_bypass;
 }
-var_forced_detection;
+  var_forced_detection = { AMD_UNKNOWN_DEVICE, 0, 0};
 
 int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array );
 static int amd_29xx040_autodetect( cfi_array_t *cfi_array );
 static int amd_29xx040_status( bus_t *bus, uint32_t adr, unsigned short data );
 static void amd_29xx040_print_info( cfi_array_t *cfi_array );
 static void amd_29xx040_read_array( cfi_array_t *cfi_array );
+static int _amd_29xx040_erase( cfi_array_t *cfi_array, uint32_t adr, int eraseall );
 static int amd_29xx040_erase_all( cfi_array_t *cfi_array );
 static int amd_29xx040_erase_block( cfi_array_t *cfi_array, uint32_t adr );
 static int amd_29xx040_program_single( cfi_array_t *cfi_array, uint32_t adr, uint32_t data );
 static int amd_29xx040_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t *buffer, int count );
 static int amd_29xx040_unlock_block( cfi_array_t *cfi_array, uint32_t adr );
 
+static void amd_29xx040b_init_cfi( cfi_query_structure_t *cfi )
+{
+       cfi_erase_block_region_t *region;
+
+       region = malloc( sizeof (cfi_erase_block_region_t) );
+       cfi->device_geometry.erase_block_regions = region;
+       if (region == NULL) {
+               return;
+       }
+       cfi->device_geometry.number_of_erase_regions = 1;
+       region->erase_block_size = 64 * 1024;
+       region->number_of_erase_blocks = 8;
+}
+
+static void amd_29xx081b_init_cfi( cfi_query_structure_t *cfi )
+{
+       cfi_erase_block_region_t *region;
+
+       region = malloc( sizeof (cfi_erase_block_region_t) );
+       cfi->device_geometry.erase_block_regions = region;
+       if (region == NULL) {
+               return;
+       }
+       cfi->device_geometry.number_of_erase_regions = 1;
+       region->erase_block_size = 64 * 1024;
+       region->number_of_erase_blocks = 16;
+}
+
+static void amd_29lv400b_top_init_cfi( cfi_query_structure_t *cfi )
+{
+       cfi_erase_block_region_t *region;
+       const int region_number = 4;
+       region = malloc( sizeof (cfi_erase_block_region_t) * region_number);
+       cfi->device_geometry.erase_block_regions = region;
+       if (region == NULL) {
+               return;
+       }
+       cfi->device_geometry.number_of_erase_regions = region_number;
+       region[0].erase_block_size = 64 * 1024;
+       region[0].number_of_erase_blocks = 8;
+       region[1].erase_block_size = 32 * 1024;
+       region[1].number_of_erase_blocks = 1;
+       region[2].erase_block_size = 8 * 1024;
+       region[2].number_of_erase_blocks = 2;
+       region[3].erase_block_size = 16 * 1024;
+       region[3].number_of_erase_blocks = 1;
+}
+
+static void amd_29lv400b_bottom_init_cfi( cfi_query_structure_t *cfi )
+{
+       cfi_erase_block_region_t *region;
+       const int region_number = 4;
+       region = malloc( sizeof (cfi_erase_block_region_t) * region_number);
+       cfi->device_geometry.erase_block_regions = region;
+       if (region == NULL) {
+               return;
+       }
+       cfi->device_geometry.number_of_erase_regions = region_number;
+       region[0].erase_block_size = 16 * 1024;
+       region[0].number_of_erase_blocks = 1;
+       region[1].erase_block_size = 8 * 1024;
+       region[1].number_of_erase_blocks = 2;
+       region[2].erase_block_size = 32 * 1024;
+       region[2].number_of_erase_blocks = 1;
+       region[3].erase_block_size = 64 * 1024;
+       region[3].number_of_erase_blocks = 8;
+}
+
 int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
 {
        int mid;
@@ -111,8 +186,14 @@ int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
        if (mid != 0x01)
                return -1;
 
-       switch(did)
+       switch(did & 0xff)
        {
+               case 0xB9:
+                       var_forced_detection.flash = AMD_29LV400B_TOP;
+                       break;
+               case 0xBA:
+                       var_forced_detection.flash = AMD_29LV400B_BOTTOM;
+                       break;
                case 0xA4:
                        var_forced_detection.flash = AMD_29xx040B;
                        break;
@@ -120,13 +201,16 @@ int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
                        var_forced_detection.flash = AMD_29xx040B;
                        var_forced_detection.algorithm = AMD_BYPASS_UNLOCK_ALGORITHM;
                        break;
+               case 0x38:
+                       var_forced_detection.flash = AMD_29xx081B;
+                       break;
                default:
                        break;
        }
 
         (*cfi_array)->bus = bus;
-        (*cfi_array)->address = 0;
-        if (bus_area( bus, adr+0, &area ) != URJTAG_STATUS_OK)
+        (*cfi_array)->address = adr;
+        if (bus_area( bus, adr, &area ) != URJTAG_STATUS_OK)
                 return -8;              /* bus width detection failed */
         unsigned int bw = area.width;
        int ba,i;
@@ -152,14 +236,24 @@ int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
                cfi->device_geometry.device_size = 512*1024;
                cfi->device_geometry.device_interface = 0;      // x 8
                cfi->device_geometry.max_bytes_write = 32;      //not used
-               cfi->device_geometry.number_of_erase_regions = 1;
-               cfi->device_geometry.erase_block_regions =
-               malloc( cfi->device_geometry.number_of_erase_regions * sizeof (cfi_erase_block_region_t) );
+               switch (var_forced_detection.flash) {
+               case AMD_29xx040B:
+                 amd_29xx040b_init_cfi(cfi);
+                 break;
+               case AMD_29xx081B:
+                 amd_29xx081b_init_cfi(cfi);
+                 break;
+               case AMD_29LV400B_TOP:
+                 amd_29lv400b_top_init_cfi(cfi);
+                 break;
+               case AMD_29LV400B_BOTTOM:
+                 amd_29lv400b_bottom_init_cfi(cfi);
+                 break;
+               }
+
                if (!cfi->device_geometry.erase_block_regions)
-                       return -2;      /* out of memory */
+                       return -2;      /* out of memory, or unsupported flash. */
 
-               cfi->device_geometry.erase_block_regions[i].erase_block_size = 64 * 1024;
-               cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks = 8;
                //Add other details for info
        }
        return 0;
@@ -168,7 +262,7 @@ int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
 
 static int amd_29xx040_autodetect( cfi_array_t *cfi_array )
 {
-       return(var_forced_detection.flash == AMD_29xx040B); //Non-CFI Am29xx040B flash
+       return (var_forced_detection.flash != AMD_UNKNOWN_DEVICE);
 }
 
 static int amd_29xx040_status( bus_t *bus, uint32_t adr, unsigned short data )
@@ -181,7 +275,7 @@ static int amd_29xx040_status( bus_t *bus, uint32_t adr, unsigned short data )
        dq5mask = (1 << 5);
        dq7bit = data & dq7mask;
 
-       for (timeout = 0; timeout < 1000; timeout++)    //typical sector erase time = 0.7 sec
+       for (timeout = 0; timeout < 70000; timeout++)   //typical sector erase time = 0.7 sec
        {
                data1 = (unsigned short)(bus_read( bus, adr ) & 0xFF);
                if((data1 & dq7mask) == dq7bit)
@@ -212,7 +306,6 @@ static void amd_29xx040_print_info( cfi_array_t *cfi_array )
        int mid, did, prot;
        bus_t *bus = cfi_array->bus;
 
-
        bus_write( bus, cfi_array->address + 0x0, 0xf0 );
        bus_write( bus, cfi_array->address + 0x555, 0xaa );
        bus_write( bus, cfi_array->address + 0x2AA, 0x55 );
@@ -236,6 +329,14 @@ static void amd_29xx040_print_info( cfi_array_t *cfi_array )
        }
        printf( _("\n\tChip: ") );
        switch (did) {
+               case 0xB9:
+                       printf( "Am29LV400B\t-\t" );
+                       printf( _("Top Boot Block\n") );
+                       break;
+               case 0xBA:
+                       printf( "Am29LV400B\t-\t" );
+                       printf( _("Bottom Boot Block\n") );
+                       break;
                case 0xA4:
                        printf( "Am29C040B\t-\t" );
                        printf( _("5V Flash\n") );
@@ -244,6 +345,10 @@ static void amd_29xx040_print_info( cfi_array_t *cfi_array )
                        printf( "Am29LV040B\t-\t" );
                        printf( _("3V Flash\n") );
                        break;
+               case 0x38:
+                       printf( "Am29LV081B\t-\t" );
+                       printf( _("3V Flash\n") );
+                       break;
                default:
                        printf ( _("Unknown (ID 0x%04x)"), did );
                        break;
@@ -266,12 +371,10 @@ static void amd_29xx040_read_array( cfi_array_t *cfi_array )
 
 
 
-static int amd_29xx040_erase_block( cfi_array_t *cfi_array, uint32_t adr )
+static int _amd_29xx040_erase( cfi_array_t *cfi_array, uint32_t adr, int eraseall )
 {
        bus_t *bus = cfi_array->bus;
 
-       printf("flash_erase_block 0x%08X\n", adr);
-
        /*      printf("protected: %d\n", amdisprotected(ps, adr)); */
 
        if(var_forced_detection.unlock_bypass == AMD_BYPASS_UNLOCK_MODE)
@@ -288,14 +391,16 @@ static int amd_29xx040_erase_block( cfi_array_t *cfi_array, uint32_t adr )
        bus_write( bus, cfi_array->address + 0x555, 0x80 );
        bus_write( bus, cfi_array->address + 0x555, 0xaa );
        bus_write( bus, cfi_array->address + 0x2AA, 0x55 );
-//     bus_write( bus, cfi_array->address + 0x555, 0x10 );     //Chip Erase
-       bus_write( bus, adr, 0x30 );    //Sector erase
-
+       if (eraseall) {
+               bus_write( bus, cfi_array->address + 0x555, 0x10 );     //Chip Erase
+       } else {
+               bus_write( bus, adr, 0x30 );    //Sector erase
+       }
 
        if (amd_29xx040_status( bus, adr, 0xff )) {
                printf( "flash_erase_block 0x%08X DONE\n", adr );
                amd_29xx040_read_array( cfi_array );    /* AMD reset */
-               return ERASE_FLASH_SUCCESS;
+               return FLASH_ERASE_SUCCESS;
        }
        printf( "flash_erase_block 0x%08X FAILED\n", adr );
        /* Read Array */
@@ -304,6 +409,22 @@ static int amd_29xx040_erase_block( cfi_array_t *cfi_array, uint32_t adr )
        return FLASH_ERASE_ERROR;
 }
 
+static int amd_29xx040_erase_block( cfi_array_t *cfi_array, uint32_t adr)
+{
+       printf("flash_erase_block 0x%08X\n", adr);
+       return _amd_29xx040_erase( cfi_array, adr, 0 /* false */ );
+}
+
+static int amd_29xx040_erase_all( cfi_array_t *cfi_array)
+{
+       uint32_t adr;
+       adr = cfi_array->address;
+       printf("flash_erase_all 0x%08X\n", adr);
+       return _amd_29xx040_erase( cfi_array, adr, 1 /* true */ );
+}
+
+
+
 static int amd_29xx040_program_single( cfi_array_t *cfi_array, uint32_t adr, uint32_t data )
 {
        int status;
@@ -357,19 +478,10 @@ static int amd_29xx040_unlock_block( cfi_array_t *cfi_array, uint32_t adr )
        return 0;
 }
 
-static int
-amd_29xx040_erase_all( cfi_array_t *cfi_array )
-{
-        printf("Error: not implemented.");
-       return FLASH_ERROR_UNKNOWN;
-}
-
-
-
 flash_driver_t amd_29xx040_flash_driver = {
        1, /* buswidth */
        N_("AMD Standard Command Set"),
-       N_("supported: AMD 29LV040B, 29C040B, 1x8 Bit"),
+       N_("supported: AMD 29LV040B, 29C040B, 29LV081B, 29LV400B 1x8 Bit"),
        amd_29xx040_autodetect,
        amd_29xx040_print_info,
        amd_29xx040_erase_all,