X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fmdr.c;h=3796259948a5f25124dc49672cd076c8f38e9049;hp=650abfd62d650e6c313ad4d8a0e5d3e7fa83d270;hb=a7479fa89def9d8b1854d629dfdaa0ba17132617;hpb=facd0e7827926d0639260be40e9cc4c595794194 diff --git a/src/flash/nor/mdr.c b/src/flash/nor/mdr.c index 650abfd62d..3796259948 100644 --- a/src/flash/nor/mdr.c +++ b/src/flash/nor/mdr.c @@ -22,9 +22,7 @@ * GNU General Public License for more details. * * * * 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., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -88,11 +86,6 @@ FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command) return ERROR_OK; } -static int mdr_protect_check(struct flash_bank *bank) -{ - return ERROR_OK; -} - static int mdr_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; @@ -173,7 +166,8 @@ static int mdr_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) goto reset_pg_and_lock; - if ((first == 0) && (last == (bank->num_sectors - 1))) { + if ((first == 0) && (last == (bank->num_sectors - 1)) && + !mdr_info->mem_type) { retval = mdr_mass_erase(bank); goto reset_pg_and_lock; } @@ -218,12 +212,7 @@ reset_pg_and_lock: return retval; } -static int mdr_protect(struct flash_bank *bank, int set, int first, int last) -{ - return ERROR_OK; -} - -static int mdr_write_block(struct flash_bank *bank, uint8_t *buffer, +static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; @@ -255,7 +244,7 @@ static int mdr_write_block(struct flash_bank *bank, uint8_t *buffer, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code); @@ -274,7 +263,7 @@ static int mdr_write_block(struct flash_bank *bank, uint8_t *buffer, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; + } init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (32bit) */ @@ -314,7 +303,7 @@ static int mdr_write_block(struct flash_bank *bank, uint8_t *buffer, return retval; } -static int mdr_write(struct flash_bank *bank, uint8_t *buffer, +static int mdr_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; @@ -345,7 +334,7 @@ static int mdr_write(struct flash_bank *bank, uint8_t *buffer, LOG_INFO("odd number of bytes to write, padding with 0xff"); buffer = memcpy(new_buffer, buffer, count); while (rem--) - buffer[count++] = 0xff; + new_buffer[count++] = 0xff; } uint32_t flash_cmd, cur_per_clock; @@ -471,6 +460,107 @@ free_buffer: if (new_buffer) free(new_buffer); + /* read some bytes bytes to flush buffer in flash accelerator. + * See errata for 1986VE1T and 1986VE3. Error 0007 */ + if ((retval == ERROR_OK) && (!mdr_info->mem_type)) { + uint32_t tmp; + target_checksum_memory(bank->target, bank->base, 64, &tmp); + } + + return retval; +} + +static int mdr_read(struct flash_bank *bank, uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct mdr_flash_bank *mdr_info = bank->driver_priv; + int retval, retval2; + + if (!mdr_info->mem_type) + return default_flash_read(bank, buffer, offset, count); + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset & 0x3) { + LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + if (count & 0x3) { + LOG_ERROR("count 0x%" PRIx32 " breaks required 4-byte alignment", count); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + uint32_t flash_cmd, cur_per_clock; + + retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock); + if (retval != ERROR_OK) + goto err; + + if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) { + /* Something's very wrong if the RST_CLK module is not clocked */ + LOG_ERROR("Target needs reset before flash operations"); + retval = ERROR_FLASH_OPERATION_FAILED; + goto err; + } + + retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM); + if (retval != ERROR_OK) + goto err; + + retval = target_write_u32(target, FLASH_KEY, KEY); + if (retval != ERROR_OK) + goto err; + + retval = target_read_u32(target, FLASH_CMD, &flash_cmd); + if (retval != ERROR_OK) + goto err_lock; + + /* Switch on register access */ + flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON | FLASH_IFREN; + retval = target_write_u32(target, FLASH_CMD, flash_cmd); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + for (uint32_t i = 0; i < count; i += 4) { + retval = target_write_u32(target, FLASH_ADR, offset + i); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + retval = target_write_u32(target, FLASH_CMD, flash_cmd | + FLASH_XE | FLASH_YE | FLASH_SE); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + uint32_t buf; + retval = target_read_u32(target, FLASH_DO, &buf); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + buf_set_u32(buffer, i * 8, 32, buf); + + retval = target_write_u32(target, FLASH_CMD, flash_cmd); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + } + +reset_pg_and_lock: + flash_cmd &= FLASH_DELAY_MASK; + retval2 = target_write_u32(target, FLASH_CMD, flash_cmd); + if (retval == ERROR_OK) + retval = retval2; + +err_lock: + retval2 = target_write_u32(target, FLASH_KEY, 0); + if (retval == ERROR_OK) + retval = retval2; + +err: return retval; } @@ -482,6 +572,11 @@ static int mdr_probe(struct flash_bank *bank) page_count = mdr_info->page_count; page_size = bank->size / page_count; + if (bank->sectors) { + free(bank->sectors); + bank->sectors = NULL; + } + bank->num_sectors = page_count; bank->sectors = malloc(sizeof(struct flash_sector) * page_count); @@ -514,16 +609,17 @@ static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -struct flash_driver mdr_flash = { +const struct flash_driver mdr_flash = { .name = "mdr", + .usage = "flash bank mdr 0 0 \n" + ": 0 for main memory, 1 for info memory", .flash_bank_command = mdr_flash_bank_command, .erase = mdr_erase, - .protect = mdr_protect, .write = mdr_write, - .read = default_flash_read, + .read = mdr_read, .probe = mdr_probe, .auto_probe = mdr_auto_probe, .erase_check = default_flash_blank_check, - .protect_check = mdr_protect_check, .info = get_mdr_info, + .free_driver_priv = default_flash_free_driver_priv, };