|
@@ -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,
|
|
|
|
- info->buffer_write_tout,
|
|
|
|
- "buffer write");
|
|
|
|
|
|
+ if (use_flash_status_poll(info))
|
|
|
|
+ retcode = flash_status_poll(info, src - (1 << shift),
|
|
|
|
+ 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
|
|
|
|
- (info, sect, info->erase_blk_tout, "erase")) {
|
|
|
|
|
|
+ if (use_flash_status_poll(info)) {
|
|
|
|
+ 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 ('.');
|
|
}
|
|
}
|
|
}
|
|
}
|