X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fcfi.c;h=efa0aeecf00a5c96aca8f43e039e6a1247f90d71;hp=cb05021573f51e66b7067f9b5d30a944557bf57e;hb=61493083bcf02071ff95d0e7c95de0133f53dc0d;hpb=feddedb6db72b81714780fae5d0b3a51dc1ddedc diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index cb05021573..efa0aeecf0 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -19,7 +19,7 @@ * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -46,16 +46,19 @@ #define AT49BV6416 0x00d6 #define AT49BV6416T 0x00d2 -static struct cfi_unlock_addresses cfi_unlock_addresses[] = { +static const struct cfi_unlock_addresses cfi_unlock_addresses[] = { [CFI_UNLOCK_555_2AA] = { .unlock1 = 0x555, .unlock2 = 0x2aa }, [CFI_UNLOCK_5555_2AAA] = { .unlock1 = 0x5555, .unlock2 = 0x2aaa }, }; +static const int cfi_status_poll_mask_dq6_dq7 = CFI_STATUS_POLL_MASK_DQ6_DQ7; + /* CFI fixups forward declarations */ -static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, void *param); -static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, void *param); -static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, void *param); -static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, void *param); +static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param); +static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param); +static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param); +static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param); +static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param); /* fixup after reading cmdset 0002 primary query table */ static const struct cfi_fixup cfi_0002_fixups[] = { @@ -71,6 +74,8 @@ static const struct cfi_fixup cfi_0002_fixups[] = { &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, {CFI_MFR_SST, 0x274b, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_5555_2AAA]}, + {CFI_MFR_SST, 0x235f, cfi_fixup_0002_polling_bits, /* 39VF3201C */ + &cfi_status_poll_mask_dq6_dq7}, {CFI_MFR_SST, 0x236d, cfi_fixup_0002_unlock_addresses, &cfi_unlock_addresses[CFI_UNLOCK_555_2AA]}, {CFI_MFR_ATMEL, 0x00C8, cfi_fixup_reversed_erase_regions, NULL}, @@ -522,6 +527,11 @@ static int cfi_read_spansion_pri_ext(struct flash_bank *bank) if (retval != ERROR_OK) return retval; + /* default values for implementation specific workarounds */ + pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1; + pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2; + pri_ext->_reversed_geometry = 0; + if ((pri_ext->pri[0] != 'P') || (pri_ext->pri[1] != 'R') || (pri_ext->pri[2] != 'I')) { retval = cfi_send_command(bank, 0xf0, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) @@ -590,11 +600,6 @@ static int cfi_read_spansion_pri_ext(struct flash_bank *bank) LOG_DEBUG("WP# protection 0x%x", pri_ext->TopBottom); - /* default values for implementation specific workarounds */ - pri_ext->_unlock1 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock1; - pri_ext->_unlock2 = cfi_unlock_addresses[CFI_UNLOCK_555_2AA].unlock2; - pri_ext->_reversed_geometry = 0; - return ERROR_OK; } @@ -1098,19 +1103,6 @@ static int cfi_protect(struct flash_bank *bank, int set, int first, int last) } } -/* Convert code image to target endian - * FIXME create general block conversion fcts in target.c?) */ -static void cfi_fix_code_endian(struct target *target, uint8_t *dest, - const uint32_t *src, uint32_t count) -{ - uint32_t i; - for (i = 0; i < count; i++) { - target_buffer_set_u32(target, dest, *src); - dest += 4; - src++; - } -} - static uint32_t cfi_command_val(struct flash_bank *bank, uint8_t cmd) { struct target *target = bank->target; @@ -1134,7 +1126,7 @@ static uint32_t cfi_command_val(struct flash_bank *bank, uint8_t cmd) } } -static int cfi_intel_write_block(struct flash_bank *bank, uint8_t *buffer, +static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t address, uint32_t count) { struct target *target = bank->target; @@ -1221,7 +1213,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, uint8_t *buffer, arm_algo.core_state = ARM_STATE_ARM; } else { LOG_ERROR("Unknown architecture"); - return ERROR_FAIL; + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } cfi_intel_clear_status_register(bank); @@ -1259,7 +1251,8 @@ static int cfi_intel_write_block(struct flash_bank *bank, uint8_t *buffer, "Increase CFI_MAX_INTEL_CODESIZE and recompile."); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - cfi_fix_code_endian(target, target_code, target_code_src, target_code_size / 4); + + target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src); /* Get memory for block write handler */ retval = target_alloc_working_area(target, @@ -1386,7 +1379,7 @@ cleanup: return retval; } -static int cfi_spansion_write_block_mips(struct flash_bank *bank, uint8_t *buffer, +static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t *buffer, uint32_t address, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; @@ -1499,7 +1492,8 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, uint8_t *buffe LOG_ERROR("Out of memory"); return ERROR_FAIL; } - cfi_fix_code_endian(target, target_code, target_code_src, target_code_size / 4); + + target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src); /* allocate working area */ retval = target_alloc_working_area(target, target_code_size, @@ -1535,16 +1529,16 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, uint8_t *buffe } ; - init_reg_param(®_params[0], "a0", 32, PARAM_OUT); - init_reg_param(®_params[1], "a1", 32, PARAM_OUT); - init_reg_param(®_params[2], "a2", 32, PARAM_OUT); - init_reg_param(®_params[3], "a3", 32, PARAM_OUT); - init_reg_param(®_params[4], "t0", 32, PARAM_OUT); - init_reg_param(®_params[5], "t1", 32, PARAM_IN); - init_reg_param(®_params[6], "t4", 32, PARAM_OUT); - init_reg_param(®_params[7], "t5", 32, PARAM_OUT); - init_reg_param(®_params[8], "t6", 32, PARAM_OUT); - init_reg_param(®_params[9], "t7", 32, PARAM_OUT); + init_reg_param(®_params[0], "r4", 32, PARAM_OUT); + init_reg_param(®_params[1], "r5", 32, PARAM_OUT); + init_reg_param(®_params[2], "r6", 32, PARAM_OUT); + init_reg_param(®_params[3], "r7", 32, PARAM_OUT); + init_reg_param(®_params[4], "r8", 32, PARAM_OUT); + init_reg_param(®_params[5], "r9", 32, PARAM_IN); + init_reg_param(®_params[6], "r12", 32, PARAM_OUT); + init_reg_param(®_params[7], "r13", 32, PARAM_OUT); + init_reg_param(®_params[8], "r14", 32, PARAM_OUT); + init_reg_param(®_params[9], "r15", 32, PARAM_OUT); while (count > 0) { uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count; @@ -1598,7 +1592,7 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, uint8_t *buffe return retval; } -static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, +static int cfi_spansion_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t address, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; @@ -1695,7 +1689,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, 0xeafffffe /* b 81ac */ }; - /* see contib/loaders/flash/armv7m_cfi_span_16.s for src */ + /* see contrib/loaders/flash/armv7m_cfi_span_16.s for src */ static const uint32_t armv7m_word_16_code[] = { 0x5B02F830, 0x9000F8A8, @@ -1717,7 +1711,36 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, 0x0000BE00 }; - /* see contib/loaders/flash/armv4_5_cfi_span_16_dq7.s for src */ + /* see contrib/loaders/flash/armv7m_cfi_span_16_dq7.s for src */ + static const uint32_t armv7m_word_16_code_dq7only[] = { + /* 00000000 : */ + 0x5B02F830, /* ldrh.w r5, [r0], #2 */ + 0x9000F8A8, /* strh.w r9, [r8] */ + 0xB000F8AA, /* strh.w fp, [sl] */ + 0x3000F8A8, /* strh.w r3, [r8] */ + 0xBF00800D, /* strh r5, [r1, #0] */ + /* nop */ + + /* 00000014 : */ + 0xEA85880E, /* ldrh r6, [r1, #0] */ + /* eor.w r7, r5, r6 */ + 0x40270706, /* ands r7, r4 */ + 0x3A01D1FA, /* bne.n 14 */ + /* subs r2, #1 */ + 0xF101D002, /* beq.n 28 */ + 0xE7EB0102, /* add.w r1, r1, #2 */ + /* b.n 0 */ + + /* 00000028 : */ + 0x0580F04F, /* mov.w r5, #128 */ + 0xBF00E7FF, /* b.n 30 */ + /* nop (for alignment purposes) */ + + /* 00000030 : */ + 0x0000BE00 /* bkpt 0x0000 */ + }; + + /* see contrib/loaders/flash/armv4_5_cfi_span_16_dq7.s for src */ static const uint32_t armv4_5_word_16_code_dq7only[] = { /* : */ 0xe0d050b2, /* ldrh r5, [r0], #2 */ @@ -1741,7 +1764,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, 0xeafffffe /* b 81ac */ }; - /* see contib/loaders/flash/armv4_5_cfi_span_8.s for src */ + /* see contrib/loaders/flash/armv4_5_cfi_span_8.s for src */ static const uint32_t armv4_5_word_8_code[] = { /* 000081b0 : */ 0xe4d05001, /* ldrb r5, [r0], #1 */ @@ -1788,7 +1811,7 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, arm_algo = &armv4_5_algo; } else { LOG_ERROR("Unknown architecture"); - return ERROR_FAIL; + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } int target_code_size = 0; @@ -1817,11 +1840,13 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, } else { /* No DQ5 support. Use DQ7 DATA# polling only. */ if (is_armv7m(target_to_armv7m(target))) { - LOG_ERROR("Unknown ARM architecture"); - return ERROR_FAIL; + /* armv7m target */ + target_code_src = armv7m_word_16_code_dq7only; + target_code_size = sizeof(armv7m_word_16_code_dq7only); + } else { /* armv4_5 target */ + target_code_src = armv4_5_word_16_code_dq7only; + target_code_size = sizeof(armv4_5_word_16_code_dq7only); } - target_code_src = armv4_5_word_16_code_dq7only; - target_code_size = sizeof(armv4_5_word_16_code_dq7only); } break; case 4: @@ -1847,7 +1872,8 @@ static int cfi_spansion_write_block(struct flash_bank *bank, uint8_t *buffer, LOG_ERROR("Out of memory"); return ERROR_FAIL; } - cfi_fix_code_endian(target, target_code, target_code_src, target_code_size / 4); + + target_buffer_set_u32_array(target, target_code, target_code_size / 4, target_code_src); /* allocate working area */ retval = target_alloc_working_area(target, target_code_size, @@ -1976,7 +2002,7 @@ static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t return ERROR_OK; } -static int cfi_intel_write_words(struct flash_bank *bank, uint8_t *word, +static int cfi_intel_write_words(struct flash_bank *bank, const uint8_t *word, uint32_t wordcount, uint32_t address) { int retval; @@ -2096,7 +2122,7 @@ static int cfi_spansion_write_word(struct flash_bank *bank, uint8_t *word, uint3 return ERROR_OK; } -static int cfi_spansion_write_words(struct flash_bank *bank, uint8_t *word, +static int cfi_spansion_write_words(struct flash_bank *bank, const uint8_t *word, uint32_t wordcount, uint32_t address) { int retval; @@ -2189,7 +2215,7 @@ static int cfi_write_word(struct flash_bank *bank, uint8_t *word, uint32_t addre return ERROR_FLASH_OPERATION_FAILED; } -static int cfi_write_words(struct flash_bank *bank, uint8_t *word, +static int cfi_write_words(struct flash_bank *bank, const uint8_t *word, uint32_t wordcount, uint32_t address) { struct cfi_flash_bank *cfi_info = bank->driver_priv; @@ -2271,7 +2297,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u } if (count) { - LOG_INFO("Fixup %d unaligned read tail bytes", count); + LOG_INFO("Fixup %" PRIu32 " unaligned read tail bytes", count); /* read a complete word from flash */ retval = target_read_memory(target, read_p, bank->bus_width, 1, current_word); @@ -2286,7 +2312,7 @@ static int cfi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, u return ERROR_OK; } -static int cfi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) +static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct target *target = bank->target; @@ -2427,7 +2453,7 @@ static int cfi_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, return cfi_reset(bank); } -static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, void *param) +static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, const void *param) { (void) param; struct cfi_flash_bank *cfi_info = bank->driver_priv; @@ -2436,7 +2462,7 @@ static void cfi_fixup_reversed_erase_regions(struct flash_bank *bank, void *para pri_ext->_reversed_geometry = 1; } -static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, void *param) +static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, const void *param) { int i; struct cfi_flash_bank *cfi_info = bank->driver_priv; @@ -2457,16 +2483,24 @@ static void cfi_fixup_0002_erase_regions(struct flash_bank *bank, void *param) } } -static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, void *param) +static void cfi_fixup_0002_unlock_addresses(struct flash_bank *bank, const void *param) { struct cfi_flash_bank *cfi_info = bank->driver_priv; struct cfi_spansion_pri_ext *pri_ext = cfi_info->pri_ext; - struct cfi_unlock_addresses *unlock_addresses = param; + const struct cfi_unlock_addresses *unlock_addresses = param; pri_ext->_unlock1 = unlock_addresses->unlock1; pri_ext->_unlock2 = unlock_addresses->unlock2; } +static void cfi_fixup_0002_polling_bits(struct flash_bank *bank, const void *param) +{ + struct cfi_flash_bank *cfi_info = bank->driver_priv; + const int *status_poll_mask = param; + + cfi_info->status_poll_mask = *status_poll_mask; +} + static int cfi_query_string(struct flash_bank *bank, int address) { @@ -3028,7 +3062,7 @@ static int get_cfi_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, void *param) +static void cfi_fixup_0002_write_buffer(struct flash_bank *bank, const void *param) { struct cfi_flash_bank *cfi_info = bank->driver_priv;