retval = ((flash_read16(addr) & cword.w) == cword.w);
break;
case FLASH_CFI_32BIT:
- retval = ((flash_read16(addr) & cword.l) == cword.l);
+ retval = ((flash_read32(addr) & cword.l) == cword.l);
break;
case FLASH_CFI_64BIT:
retval = ((flash_read64(addr) & cword.ll) == cword.ll);
}
if (!flag) {
unmap_physmem(dstaddr, info->portwidth);
- return 2;
+ return ERR_NOT_ERASED;
}
/* Disable interrupts which might cause a timeout here */
int retcode;
void *src = cp;
void *dst = map_physmem(dest, len, MAP_NOCACHE);
+ void *dst2 = dst;
+ int flag = 0;
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ cnt = len;
+ break;
+ case FLASH_CFI_16BIT:
+ cnt = len >> 1;
+ break;
+ case FLASH_CFI_32BIT:
+ cnt = len >> 2;
+ break;
+ case FLASH_CFI_64BIT:
+ cnt = len >> 3;
+ break;
+ default:
+ retcode = ERR_INVAL;
+ goto out_unmap;
+ }
+
+ while ((cnt-- > 0) && (flag == 0)) {
+ switch (info->portwidth) {
+ case FLASH_CFI_8BIT:
+ flag = ((flash_read8(dst2) & flash_read8(src)) ==
+ flash_read8(src));
+ src += 1, dst2 += 1;
+ break;
+ case FLASH_CFI_16BIT:
+ flag = ((flash_read16(dst2) & flash_read16(src)) ==
+ flash_read16(src));
+ src += 2, dst2 += 2;
+ break;
+ case FLASH_CFI_32BIT:
+ flag = ((flash_read32(dst2) & flash_read32(src)) ==
+ flash_read32(src));
+ src += 4, dst2 += 4;
+ break;
+ case FLASH_CFI_64BIT:
+ flag = ((flash_read64(dst2) & flash_read64(src)) ==
+ flash_read64(src));
+ src += 8, dst2 += 8;
+ break;
+ }
+ }
+ if (!flag) {
+ retcode = ERR_NOT_ERASED;
+ goto out_unmap;
+ }
+
+ src = cp;
sector = find_sector (info, dest);
switch (info->vendor) {
return;
}
+/*-----------------------------------------------------------------------
+ * This is used in a few places in write_buf() to show programming
+ * progress. Making it a function is nasty because it needs to do side
+ * effect updates to digit and dots. Repeated code is nasty too, so
+ * we define it once here.
+ */
+#ifdef CONFIG_FLASH_SHOW_PROGRESS
+#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub) \
+ dots -= dots_sub; \
+ if ((scale > 0) && (dots <= 0)) { \
+ if ((digit % 5) == 0) \
+ printf ("%d", digit / 5); \
+ else \
+ putc ('.'); \
+ digit--; \
+ dots += scale; \
+ }
+#else
+#define FLASH_SHOW_PROGRESS(scale, dots, digit, dots_sub)
+#endif
+
/*-----------------------------------------------------------------------
* Copy memory to flash, returns:
* 0 - OK
int aln;
cfiword_t cword;
int i, rc;
-
#ifdef CFG_FLASH_USE_BUFFER_WRITE
int buffered_size;
#endif
+#ifdef CONFIG_FLASH_SHOW_PROGRESS
+ int digit = CONFIG_FLASH_SHOW_PROGRESS;
+ int scale = 0;
+ int dots = 0;
+
+ /*
+ * Suppress if there are fewer than CONFIG_FLASH_SHOW_PROGRESS writes.
+ */
+ if (cnt >= CONFIG_FLASH_SHOW_PROGRESS) {
+ scale = (int)((cnt + CONFIG_FLASH_SHOW_PROGRESS - 1) /
+ CONFIG_FLASH_SHOW_PROGRESS);
+ }
+#endif
+
/* get lower aligned address */
wp = (addr & ~(info->portwidth - 1));
return rc;
wp += i;
+ FLASH_SHOW_PROGRESS(scale, dots, digit, i);
}
/* handle the aligned part */
wp += i;
src += i;
cnt -= i;
+ FLASH_SHOW_PROGRESS(scale, dots, digit, i);
}
#else
while (cnt >= info->portwidth) {
return rc;
wp += info->portwidth;
cnt -= info->portwidth;
+ FLASH_SHOW_PROGRESS(scale, dots, digit, info->portwidth);
}
#endif /* CFG_FLASH_USE_BUFFER_WRITE */
+
if (cnt == 0) {
return (0);
}
cmdset_amd_read_jedec_ids(info);
flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
- /* check if flash geometry needs reversal */
- if (qry->num_erase_regions > 1) {
- /* reverse geometry if top boot part */
- if (info->cfi_version < 0x3131) {
- /* CFI < 1.1, try to guess from device id */
- if ((info->device_id & 0x80) != 0)
- cfi_reverse_geometry(qry);
- } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
- /* CFI >= 1.1, deduct from top/bottom flag */
- /* note: ext_addr is valid since cfi_version > 0 */
- cfi_reverse_geometry(qry);
- }
- }
-
return 0;
}
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
case CFI_CMDSET_INTEL_EXTENDED:
- flash_read_jedec_ids_intel(info);
+ cmdset_intel_read_jedec_ids(info);
break;
case CFI_CMDSET_AMD_STANDARD:
case CFI_CMDSET_AMD_EXTENDED:
- flash_read_jedec_ids_amd(info);
+ cmdset_amd_read_jedec_ids(info);
break;
default:
break;
{
int cfi_offset;
- flash_write_cmd (info, 0, 0, info->cmd_reset);
+ /* We do not yet know what kind of commandset to use, so we issue
+ the reset command in both Intel and AMD variants, in the hope
+ that AMD flash roms ignore the Intel command. */
+ flash_write_cmd (info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
+
for (cfi_offset=0;
cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint);
cfi_offset++) {
return 0;
}
+/*
+ * Manufacturer-specific quirks. Add workarounds for geometry
+ * reversal, etc. here.
+ */
+static void flash_fixup_amd(flash_info_t *info, struct cfi_qry *qry)
+{
+ /* check if flash geometry needs reversal */
+ if (qry->num_erase_regions > 1) {
+ /* reverse geometry if top boot part */
+ if (info->cfi_version < 0x3131) {
+ /* CFI < 1.1, try to guess from device id */
+ if ((info->device_id & 0x80) != 0)
+ cfi_reverse_geometry(qry);
+ } else if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) {
+ /* CFI >= 1.1, deduct from top/bottom flag */
+ /* note: ext_addr is valid since cfi_version > 0 */
+ cfi_reverse_geometry(qry);
+ }
+ }
+}
+
+static void flash_fixup_atmel(flash_info_t *info, struct cfi_qry *qry)
+{
+ int reverse_geometry = 0;
+
+ /* Check the "top boot" bit in the PRI */
+ if (info->ext_addr && !(flash_read_uchar(info, info->ext_addr + 6) & 1))
+ reverse_geometry = 1;
+
+ /* AT49BV6416(T) list the erase regions in the wrong order.
+ * However, the device ID is identical with the non-broken
+ * AT49BV642D since u-boot only reads the low byte (they
+ * differ in the high byte.) So leave out this fixup for now.
+ */
+#if 0
+ if (info->device_id == 0xd6 || info->device_id == 0xd2)
+ reverse_geometry = !reverse_geometry;
+#endif
+
+ if (reverse_geometry)
+ cfi_reverse_geometry(qry);
+}
+
/*
* The following code cannot be run from FLASH!
*
return 0;
}
+ /* Do manufacturer-specific fixups */
+ switch (info->manufacturer_id) {
+ case 0x0001:
+ flash_fixup_amd(info, &qry);
+ break;
+ case 0x001f:
+ flash_fixup_atmel(info, &qry);
+ break;
+ }
+
debug ("manufacturer is %d\n", info->vendor);
debug ("manufacturer id is 0x%x\n", info->manufacturer_id);
debug ("device id is 0x%x\n", info->device_id);