support multi-byte write mode for certain flash chips

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1390 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Arnim Läuger 16 years ago
parent 0ab386f676
commit 37d72e13f3

@ -1,4 +1,11 @@
2008-12-01 Arnim Laeuger <arniml@users.sourceforge.net>
* include/flash.h, src/flash/amd_flash.c, src/flash/amd.c,
src/flash/intel.c, src/flash/flash.c, configure.ac:
support multi-byte write mode
chips must match the following criteria to qualify
- CFI data specifies multi-byte write mode supported
- handled by amd.c
- 8 or 16 bit interface
* src/bus/prototype.c (prototype_bus_new): consider amode parameter properly
when specified on the command line. pervious version didn't set ASHIFT in

@ -562,6 +562,15 @@ AS_IF([test "x$dmalloc" = xyes], [
])
# Enable flash multi-byte write mode?
AC_ARG_ENABLE(flash_multi_byte,
[AS_HELP_STRING([--enable-flash_multi_byte], [Enable flash multi-byte write mode])],
[multi_byte=$enableval], [multi_byte=yes])
AS_IF([test "x$multi_byte" = xyes], [
AC_DEFINE(MULTI_BYTE, 1, [define for flash multi-byte write mode])
])
AC_OUTPUT
dnl

@ -69,6 +69,7 @@ typedef struct {
int (*erase_block)( cfi_array_t *cfi_array, uint32_t adr );
int (*unlock_block)( cfi_array_t *cfi_array, uint32_t adr );
int (*program)( cfi_array_t *cfi_array, uint32_t adr, uint32_t data );
int (*program_buffer)( cfi_array_t *cfi_array, uint32_t adr, uint32_t *buffer, int count );
void (*readarray)( cfi_array_t *cfi_array );
} flash_driver_t;

@ -275,7 +275,7 @@ amd_flash_print_info( cfi_array_t *cfi_array )
switch (mid) {
case 0x0001:
printf( "AMD" );
printf( _("\n\tChip: ") );
printf( _("\n\tChip: ") );
switch (cid) {
case 0x0049:
printf( "AM29LV160DB" );
@ -294,7 +294,7 @@ amd_flash_print_info( cfi_array_t *cfi_array )
break;
case 0x227E: /* 16-bit mode */
case 0x007E: /* 8-bit mode */
printf( "S92GL" );
printf( "S92GLxxxN" );
break;
default:
printf ( _("Unknown (ID 0x%04x)"), cid );
@ -303,7 +303,7 @@ amd_flash_print_info( cfi_array_t *cfi_array )
break;
case 0x001f:
printf( "Atmel" );
printf( _("\n\tChip: ") );
printf( _("\n\tChip: ") );
switch (cid) {
case 0x01d2:
printf( "AT49BW642DT" );
@ -318,7 +318,7 @@ amd_flash_print_info( cfi_array_t *cfi_array )
break;
case 0x0020:
printf( "ST/Samsung" );
printf( _("\n\tChip: ") );
printf( _("\n\tChip: ") );
switch (cid) {
case 0x00ca:
printf( "M29W320DT" );
@ -336,7 +336,7 @@ amd_flash_print_info( cfi_array_t *cfi_array )
break;
case 0x00C2:
printf( "Macronix" );
printf( _("\n\tChip: ") );
printf( _("\n\tChip: ") );
switch (cid) {
case 0x2249:
printf( "MX29LV160B" );
@ -413,6 +413,67 @@ amd_flash_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data )
return !status;
}
static int
amd_program_buffer_status( cfi_array_t *cfi_array, uint32_t adr, uint32_t data )
{
bus_t *bus = cfi_array->bus;
int timeout;
const uint32_t dq7mask = (1 << 7);
const uint32_t dq5mask = (1 << 5);
uint32_t bit7 = data & dq7mask;
uint32_t data1;
for (timeout = 0; timeout < 7000; timeout++) {
data1 = bus_read( bus, adr );
if (dbg)
printf( "amd_program_buffer_status %d: %04X (%04X) = %04X\n", timeout, data1, (data1 & dq7mask), bit7 );
if ((data1 & dq7mask) == bit7)
return 1;
if ((data1 & dq5mask) == dq5mask)
break;
usleep( 100 );
}
data1 = bus_read( bus, adr );
if ((data1 & dq7mask) == bit7)
return 1;
return 0;
}
static int
amd_flash_program_buffer( cfi_array_t *cfi_array, uint32_t adr, uint32_t *buffer, int count )
{
int status;
bus_t *bus = cfi_array->bus;
int o = amd_flash_address_shift( cfi_array );
int idx;
uint32_t sa = adr;
if (dbg)
printf("\nflash_program_buffer 0x%08X, count 0x%08X\n", adr, count);
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00aa00aa );
bus_write( bus, cfi_array->address + (0x02aa << o), 0x00550055 );
bus_write( bus, adr, 0x00250025 );
bus_write( bus, sa, count-1 );
/* write payload to write buffer */
for (idx = 0; idx < count; idx++) {
bus_write( bus, adr, buffer[idx] );
adr += cfi_array->bus_width;
}
/* program buffer to flash */
bus_write( bus, sa, 0x00290029 );
status = amd_program_buffer_status( cfi_array, adr - cfi_array->bus_width, buffer[idx - 1] );
/* amd_flash_read_array(ps); */
return !status;
}
static void
amd_flash_read_array( cfi_array_t *cfi_array )
{
@ -429,29 +490,32 @@ flash_driver_t amd_32_flash_driver = {
amd_flash_erase_block,
amd_flash_unlock_block,
amd_flash_program,
NULL,
amd_flash_read_array,
};
flash_driver_t amd_16_flash_driver = {
2, /* buswidth */
N_("AMD/Fujitsu Standard Command Set"),
N_("supported: AMD 29LV800B; 1x16 Bit"),
N_("supported: AMD 29LV800B, S92GLxxxN; 1x16 Bit"),
amd_flash_autodetect16,
amd_flash_print_info,
amd_flash_erase_block,
amd_flash_unlock_block,
amd_flash_program,
amd_flash_program_buffer,
amd_flash_read_array,
};
flash_driver_t amd_8_flash_driver = {
1, /* buswidth */
N_("AMD/Fujitsu Standard Command Set"),
N_("supported: AMD 29LV160, AMD 29LV065D, AMD 29LV040B; 1x8 Bit"),
N_("supported: AMD 29LV160, AMD 29LV065D, AMD 29LV040B, S92GLxxxN; 1x8 Bit"),
amd_flash_autodetect8,
amd_flash_print_info,
amd_flash_erase_block,
amd_flash_unlock_block,
amd_flash_program,
amd_flash_program_buffer,
amd_flash_read_array,
};

@ -350,5 +350,6 @@ flash_driver_t amd_29xx040_flash_driver = {
amd_29xx040_erase_block,
amd_29xx040_unlock_block,
amd_29xx040_program,
NULL,
amd_29xx040_read_array,
};

@ -250,6 +250,9 @@ flashmem( bus_t *bus, FILE *f, uint32_t addr )
int neb;
int bus_width;
int chip_width;
uint32_t *write_buffer = NULL;
uint32_t write_buffer_adr = 0;
int write_buffer_count, cfi_max_entries;
set_flash_driver();
if (!cfi_array || !flash_driver) {
@ -264,6 +267,20 @@ flashmem( bus_t *bus, FILE *f, uint32_t addr )
for (i = 0, neb = 0; i < cfi->device_geometry.number_of_erase_regions; i++)
neb += cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks;
/* prepare multi-byte write */
#ifdef MULTI_BYTE
cfi_max_entries = flash_driver->program_buffer ? cfi->device_geometry.max_bytes_write / flash_driver->bus_width : 0;
#else
cfi_max_entries = 0;
#endif
if (cfi_max_entries > 0) {
write_buffer = (uint32_t *)calloc( cfi_max_entries, sizeof( uint32_t ) );
if (!write_buffer) {
printf( _("Out of memory!\n") );
return;
}
}
erased = malloc( neb * sizeof *erased );
if (!erased) {
printf( _("Out of memory!\n") );
@ -274,6 +291,7 @@ flashmem( bus_t *bus, FILE *f, uint32_t addr )
printf( _("program:\n") );
adr = addr;
write_buffer_count = 0;
while (!feof( f )) {
uint32_t data;
#define BSIZE 4096
@ -306,13 +324,47 @@ flashmem( bus_t *bus, FILE *f, uint32_t addr )
else
data |= b[bc + j] << (j * 8);
if (flash_driver->program( cfi_array, adr, data )) {
if (cfi_max_entries > 0) {
/* handle multi-byte writes via write buffer */
if (write_buffer_count == 0)
write_buffer_adr = adr; /* note address of first entry that goes into write buffer */
write_buffer[write_buffer_count++] = data;
if ((write_buffer_count == cfi_max_entries) ||
((adr + flash_driver->bus_width) % (cfi_max_entries * flash_driver->bus_width) == 0)) {
/* program buffer to flash conditions matched:
a) write buffer is full (cfi_max_bytes_write bytes entered)
b) next adr will leave current page */
if (flash_driver->program_buffer( cfi_array, write_buffer_adr, write_buffer, write_buffer_count )) {
printf( _("\nflash error\n") );
return;
}
write_buffer_count = 0;
}
} else {
/* single word write */
if (flash_driver->program( cfi_array, adr, data )) {
printf( _("\nflash error\n") );
return;
}
}
adr += flash_driver->bus_width;
}
}
/* flush partly filled write buffer */
if (cfi_max_entries > 0) {
if (write_buffer_count > 0) {
if (flash_driver->program_buffer( cfi_array, write_buffer_adr, write_buffer, write_buffer_count )) {
free( write_buffer );
printf( _("\nflash error\n") );
return;
}
adr += flash_driver->bus_width;
}
free( write_buffer );
}
printf( _("addr: 0x%08X\n"), adr - flash_driver->bus_width);
flash_driver->readarray( cfi_array );

@ -362,6 +362,7 @@ flash_driver_t intel_32_flash_driver = {
intel_flash_erase_block32,
intel_flash_unlock_block32,
intel_flash_program32,
NULL,
intel_flash_readarray32,
};
@ -374,6 +375,7 @@ flash_driver_t intel_16_flash_driver = {
intel_flash_erase_block,
intel_flash_unlock_block,
intel_flash_program,
NULL,
intel_flash_readarray,
};
@ -386,5 +388,6 @@ flash_driver_t intel_8_flash_driver = {
intel_flash_erase_block,
intel_flash_unlock_block,
intel_flash_program,
NULL,
intel_flash_readarray,
};

Loading…
Cancel
Save