static void cfi_fixup_atmel_reversed_erase_regions(flash_bank_t *flash, void *param);
/* fixup after reading cmdset 0002 primary query table */
-static cfi_fixup_t cfi_0002_fixups[] = {
+static const cfi_fixup_t cfi_0002_fixups[] = {
{CFI_MFR_SST, 0x00D4, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_SST, 0x00D5, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
{CFI_MFR_SST, 0x00D6, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]},
};
/* fixup after reading cmdset 0001 primary query table */
-static cfi_fixup_t cfi_0001_fixups[] = {
+static const cfi_fixup_t cfi_0001_fixups[] = {
{0, 0, NULL, NULL}
};
-static void cfi_fixup(flash_bank_t *bank, cfi_fixup_t *fixups)
+static void cfi_fixup(flash_bank_t *bank, const cfi_fixup_t *fixups)
{
cfi_flash_bank_t *cfi_info = bank->driver_priv;
- cfi_fixup_t *f;
+ const cfi_fixup_t *f;
for (f = fixups; f->fixup; f++)
{
uint8_t i;
for (i = 0;i < 2;i++)
target_read_memory(target, flash_address(bank, sector, offset + i), bank->bus_width, 1,
- &data[i*bank->bus_width] );
+ &data[i*bank->bus_width]);
}
else
target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 2, data);
uint8_t i;
for (i = 0;i < 4;i++)
target_read_memory(target, flash_address(bank, sector, offset + i), bank->bus_width, 1,
- &data[i*bank->bus_width] );
+ &data[i*bank->bus_width]);
}
else
target_read_memory(target, flash_address(bank, sector, offset), bank->bus_width, 4, data);
pri_ext->suspend_cmd_support = cfi_query_u8(bank, 0, cfi_info->pri_addr + 9);
pri_ext->blk_status_reg_mask = cfi_query_u16(bank, 0, cfi_info->pri_addr + 0xa);
- LOG_DEBUG("feature_support: 0x%" PRIx32 ", suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x",
- pri_ext->feature_support,
- pri_ext->suspend_cmd_support,
+ LOG_DEBUG("feature_support: 0x%" PRIx32 ", suspend_cmd_support: 0x%x, blk_status_reg_mask: 0x%x",
+ pri_ext->feature_support,
+ pri_ext->suspend_cmd_support,
pri_ext->blk_status_reg_mask);
pri_ext->vcc_optimal = cfi_query_u8(bank, 0, cfi_info->pri_addr + 0xc);
/* flash write code */
if (!cfi_info->write_algorithm)
{
- if ( target_code_size > sizeof(target_code) )
+ if (target_code_size > sizeof(target_code))
{
LOG_WARNING("Internal error - target code buffer to small. Increase CFI_MAX_INTEL_CODESIZE and recompile.");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
busy_pattern_val = cfi_command_val(bank, 0x80);
error_pattern_val = cfi_command_val(bank, 0x7e);
- LOG_INFO("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, source->address, buffer_size );
+ LOG_INFO("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, source->address, buffer_size);
/* Programming main loop */
while (count > 0)
buf_set_u32(reg_params[5].value, 0, 32, busy_pattern_val);
buf_set_u32(reg_params[6].value, 0, 32, error_pattern_val);
- LOG_INFO("Write 0x%04" PRIx32 " bytes to flash at 0x%08" PRIx32 , thisrun_count, address );
+ LOG_INFO("Write 0x%04" PRIx32 " bytes to flash at 0x%08" PRIx32 , thisrun_count, address);
/* Execute algorithm, assume breakpoint for last instruction */
retval = target_run_algorithm(target, 0, NULL, 7, reg_params,
0xeafffffe /* b 81ac <sp_16_done> */
};
+ static const uint32_t word_16_code_dq7only[] = {
+ /* <sp_16_code>: */
+ 0xe0d050b2, /* ldrh r5, [r0], #2 */
+ 0xe1c890b0, /* strh r9, [r8] */
+ 0xe1cab0b0, /* strh r11, [r10] */
+ 0xe1c830b0, /* strh r3, [r8] */
+ 0xe1c150b0, /* strh r5, [r1] */
+ 0xe1a00000, /* nop (mov r0,r0) */
+ /* */
+ /* <sp_16_busy>: */
+ 0xe1d160b0, /* ldrh r6, [r1] */
+ 0xe0257006, /* eor r7, r5, r6 */
+ 0xe2177080, /* ands r7, #0x80 */
+ 0x1afffffb, /* bne 8168 <sp_16_busy> */
+ /* */
+ 0xe2522001, /* subs r2, r2, #1 ; 0x1 */
+ 0x03a05080, /* moveq r5, #128 ; 0x80 */
+ 0x0a000001, /* beq 81ac <sp_16_done> */
+ 0xe2811002, /* add r1, r1, #2 ; 0x2 */
+ 0xeafffff0, /* b 8158 <sp_16_code> */
+ /* */
+ /* 000081ac <sp_16_done>: */
+ 0xeafffffe /* b 81ac <sp_16_done> */
+ };
+
static const uint32_t word_8_code[] = {
/* 000081b0 <sp_16_code_end>: */
0xe4d05001, /* ldrb r5, [r0], #1 */
armv4_5_info.core_state = ARMV4_5_STATE_ARM;
/* flash write code */
+ int target_code_size = 0;
if (!cfi_info->write_algorithm)
{
uint8_t *target_code;
- int target_code_size;
const uint32_t *src;
/* convert bus-width dependent algorithm code to correct endiannes */
target_code_size = sizeof(word_8_code);
break;
case 2:
- src = word_16_code;
- target_code_size = sizeof(word_16_code);
+ /* Check for DQ5 support */
+ if( cfi_info->status_poll_mask & (1 << 5) )
+ {
+ src = word_16_code;
+ target_code_size = sizeof(word_16_code);
+ }
+ else
+ {
+ /* No DQ5 support. Use DQ7 DATA# polling only. */
+ src = word_16_code_dq7only;
+ target_code_size = sizeof(word_16_code_dq7only);
+ }
break;
case 4:
src = word_32_code;
retval = target_run_algorithm(target, 0, NULL, 10, reg_params,
cfi_info->write_algorithm->address,
- cfi_info->write_algorithm->address + ((24 * 4) - 4),
+ cfi_info->write_algorithm->address + ((target_code_size) - 4),
10000, &armv4_5_info);
status = buf_get_u32(reg_params[5].value, 0, 32);
count -= thisrun_count;
}
- target_free_working_area(target, source);
+ target_free_all_working_areas(target);
destroy_reg_param(®_params[0]);
destroy_reg_param(®_params[1]);
/* Check for valid range */
if (address & buffermask)
{
- LOG_ERROR("Write address at base 0x%" PRIx32 ", address %" PRIx32 " not aligned to 2^%d boundary",
+ LOG_ERROR("Write address at base 0x%" PRIx32 ", address %" PRIx32 " not aligned to 2^%d boundary",
bank->base, address, cfi_info->max_buf_write_size);
return ERROR_FLASH_OPERATION_FAILED;
}
write_p = address & ~(bank->bus_width - 1);
if ((align = address - write_p) != 0)
{
- LOG_INFO("Fixup %d unaligned head bytes", align );
+ LOG_INFO("Fixup %d unaligned head bytes", align);
for (i = 0; i < bank->bus_width; i++)
current_word[i] = 0;
/* handle unaligned tail bytes */
if (count > 0)
{
- LOG_INFO("Fixup %" PRId32 " unaligned tail bytes", count );
+ LOG_INFO("Fixup %" PRId32 " unaligned tail bytes", count);
copy_p = write_p;
for (i = 0; i < bank->bus_width; i++)
{
return retval;
}
- if ((retval = target_read_u16(target, flash_address(bank, 0, 0x02), &cfi_info->device_id)) != ERROR_OK)
+ if ((retval = target_read_u16(target, flash_address(bank, 0, 0x01), &cfi_info->device_id)) != ERROR_OK)
{
return retval;
}
for (i = 0; i < cfi_info->num_erase_regions; i++)
{
cfi_info->erase_region_info[i] = cfi_query_u32(bank, 0, 0x2d + (4 * i));
- LOG_DEBUG("erase region[%i]: %" PRIu32 " blocks of size 0x%" PRIx32 "",
- i,
- (cfi_info->erase_region_info[i] & 0xffff) + 1,
+ LOG_DEBUG("erase region[%i]: %" PRIu32 " blocks of size 0x%" PRIx32 "",
+ i,
+ (cfi_info->erase_region_info[i] & 0xffff) + 1,
(cfi_info->erase_region_info[i] >> 16) * 256);
}
}
sector++;
}
}
- if (offset != cfi_info->dev_size)
+ if (offset != (cfi_info->dev_size * bank->bus_width / bank->chip_width))
{
- LOG_WARNING("CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32 "", cfi_info->dev_size, offset);
+ LOG_WARNING("CFI size is 0x%" PRIx32 ", but total sector size is 0x%" PRIx32 "", \
+ (cfi_info->dev_size * bank->bus_width / bank->chip_width), offset);
}
}