|
|
@ -602,6 +602,63 @@ static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, |
|
|
|
return retcode; |
|
|
|
return retcode; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int use_flash_status_poll(flash_info_t *info) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef CONFIG_SYS_CFI_FLASH_STATUS_POLL |
|
|
|
|
|
|
|
if (info->vendor == CFI_CMDSET_AMD_EXTENDED || |
|
|
|
|
|
|
|
info->vendor == CFI_CMDSET_AMD_STANDARD) |
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int flash_status_poll(flash_info_t *info, void *src, void *dst, |
|
|
|
|
|
|
|
ulong tout, char *prompt) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
#ifdef CONFIG_SYS_CFI_FLASH_STATUS_POLL |
|
|
|
|
|
|
|
ulong start; |
|
|
|
|
|
|
|
int ready; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if CONFIG_SYS_HZ != 1000 |
|
|
|
|
|
|
|
if ((ulong)CONFIG_SYS_HZ > 100000) |
|
|
|
|
|
|
|
tout *= (ulong)CONFIG_SYS_HZ / 1000; /* for a big HZ, avoid overflow */ |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
tout = DIV_ROUND_UP(tout * (ulong)CONFIG_SYS_HZ, 1000); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Wait for command completion */ |
|
|
|
|
|
|
|
start = get_timer(0); |
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
|
|
|
switch (info->portwidth) { |
|
|
|
|
|
|
|
case FLASH_CFI_8BIT: |
|
|
|
|
|
|
|
ready = flash_read8(dst) == flash_read8(src); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FLASH_CFI_16BIT: |
|
|
|
|
|
|
|
ready = flash_read16(dst) == flash_read16(src); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FLASH_CFI_32BIT: |
|
|
|
|
|
|
|
ready = flash_read32(dst) == flash_read32(src); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case FLASH_CFI_64BIT: |
|
|
|
|
|
|
|
ready = flash_read64(dst) == flash_read64(src); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
ready = 0; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (ready) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
if (get_timer(start) > tout) { |
|
|
|
|
|
|
|
printf("Flash %s timeout at address %lx data %lx\n", |
|
|
|
|
|
|
|
prompt, (ulong)dst, (ulong)flash_read8(dst)); |
|
|
|
|
|
|
|
return ERR_TIMOUT; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
udelay(1); /* also triggers watchdog */ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#endif /* CONFIG_SYS_CFI_FLASH_STATUS_POLL */ |
|
|
|
|
|
|
|
return ERR_OK; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
/*-----------------------------------------------------------------------
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) |
|
|
|
static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) |
|
|
@ -749,7 +806,12 @@ static int flash_write_cfiword (flash_info_t * info, ulong dest, |
|
|
|
if (!sect_found) |
|
|
|
if (!sect_found) |
|
|
|
sect = find_sector (info, dest); |
|
|
|
sect = find_sector (info, dest); |
|
|
|
|
|
|
|
|
|
|
|
return flash_full_status_check (info, sect, info->write_tout, "write"); |
|
|
|
if (use_flash_status_poll(info)) |
|
|
|
|
|
|
|
return flash_status_poll(info, &cword, dstaddr, |
|
|
|
|
|
|
|
info->write_tout, "write"); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
return flash_full_status_check(info, sect, |
|
|
|
|
|
|
|
info->write_tout, "write"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE |
|
|
|
#ifdef CONFIG_SYS_FLASH_USE_BUFFER_WRITE |
|
|
@ -911,9 +973,15 @@ static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); |
|
|
|
flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); |
|
|
|
retcode = flash_full_status_check (info, sector, |
|
|
|
if (use_flash_status_poll(info)) |
|
|
|
info->buffer_write_tout, |
|
|
|
retcode = flash_status_poll(info, src - (1 << shift), |
|
|
|
"buffer write"); |
|
|
|
dst - (1 << shift), |
|
|
|
|
|
|
|
info->buffer_write_tout, |
|
|
|
|
|
|
|
"buffer write"); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
retcode = flash_full_status_check(info, sector, |
|
|
|
|
|
|
|
info->buffer_write_tout, |
|
|
|
|
|
|
|
"buffer write"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
@ -935,6 +1003,7 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) |
|
|
|
int rcode = 0; |
|
|
|
int rcode = 0; |
|
|
|
int prot; |
|
|
|
int prot; |
|
|
|
flash_sect_t sect; |
|
|
|
flash_sect_t sect; |
|
|
|
|
|
|
|
int st; |
|
|
|
|
|
|
|
|
|
|
|
if (info->flash_id != FLASH_MAN_CFI) { |
|
|
|
if (info->flash_id != FLASH_MAN_CFI) { |
|
|
|
puts ("Can't erase unknown flash type - aborted\n"); |
|
|
|
puts ("Can't erase unknown flash type - aborted\n"); |
|
|
@ -998,10 +1067,20 @@ int flash_erase (flash_info_t * info, int s_first, int s_last) |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (flash_full_status_check |
|
|
|
if (use_flash_status_poll(info)) { |
|
|
|
(info, sect, info->erase_blk_tout, "erase")) { |
|
|
|
cfiword_t cword = (cfiword_t)0xffffffffffffffffULL; |
|
|
|
|
|
|
|
void *dest; |
|
|
|
|
|
|
|
dest = flash_map(info, sect, 0); |
|
|
|
|
|
|
|
st = flash_status_poll(info, &cword, dest, |
|
|
|
|
|
|
|
info->erase_blk_tout, "erase"); |
|
|
|
|
|
|
|
flash_unmap(info, sect, 0, dest); |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
st = flash_full_status_check(info, sect, |
|
|
|
|
|
|
|
info->erase_blk_tout, |
|
|
|
|
|
|
|
"erase"); |
|
|
|
|
|
|
|
if (st) |
|
|
|
rcode = 1; |
|
|
|
rcode = 1; |
|
|
|
} else if (flash_verbose) |
|
|
|
else if (flash_verbose) |
|
|
|
putc ('.'); |
|
|
|
putc ('.'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|