static int em357_mass_erase(struct flash_bank *bank) { struct target *target = bank->target; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* unlock option flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* mass erase flash memory */ retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_MER | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 100); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; }
static int em357_erase(struct flash_bank *bank, int first, int last) { struct target *target = bank->target; int i; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first == 0) && (last == (bank->num_sectors - 1))) return em357_mass_erase(bank); /* Enable FPEC clock */ target_write_u32(target, EM357_FPEC_CLK, 0x00000001); /* unlock flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; for (i = first; i <= last; i++) { retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_AR, bank->base + bank->sectors[i].offset); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PER | FLASH_STRT); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 100); if (retval != ERROR_OK) return retval; bank->sectors[i].is_erased = 1; } retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; }
static int em357_erase_options(struct flash_bank *bank) { struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; em357_info = bank->driver_priv; /* read current options */ em357_read_options(bank); /* unlock flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2); if (retval != ERROR_OK) return retval; /* erase option bytes */ retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* clear readout protection and complementary option bytes * this will also force a device unlock if set */ em357_info->option_bytes.RDP = 0x5AA5; return ERROR_OK; }
static int em357_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; uint32_t words_remaining = (count / 2); uint32_t bytes_remaining = (count & 0x00000001); uint32_t address = bank->base + offset; uint32_t bytes_written = 0; int retval; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (offset & 0x1) { LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } /* unlock flash registers */ retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; target_write_u32(target, EM357_FPEC_CLK, 0x00000001); /* multiple half words (2-byte) to be programmed? */ if (words_remaining > 0) { /* try using a block write */ retval = em357_write_block(bank, buffer, offset, words_remaining); if (retval != ERROR_OK) { if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single dword accesses */ LOG_WARNING( "couldn't use block writes, falling back to single memory accesses"); } } else { buffer += words_remaining * 2; address += words_remaining * 2; words_remaining = 0; } } if ((retval != ERROR_OK) && (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)) return retval; while (words_remaining > 0) { uint16_t value; memcpy(&value, buffer + bytes_written, sizeof(uint16_t)); retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, address, value); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 5); if (retval != ERROR_OK) return retval; bytes_written += 2; words_remaining--; address += 2; } if (bytes_remaining) { uint16_t value = 0xffff; memcpy(&value, buffer + bytes_written, bytes_remaining); retval = target_write_u32(target, EM357_FLASH_CR, FLASH_PG); if (retval != ERROR_OK) return retval; retval = target_write_u16(target, address, value); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 5); if (retval != ERROR_OK) return retval; } return target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); }
static int em357_write_options(struct flash_bank *bank) { struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; em357_info = bank->driver_priv; /* unlock flash registers */ int retval = target_write_u32(target, EM357_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; /* unlock option flash registers */ retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_OPTKEYR, KEY2); if (retval != ERROR_OK) return retval; /* program option bytes */ retval = target_write_u32(target, EM357_FLASH_CR, FLASH_OPTPG | FLASH_OPTWRE); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 1 */ retval = target_write_u16(target, EM357_OB_WRP0, em357_info->option_bytes.protection[0]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 2 */ retval = target_write_u16(target, EM357_OB_WRP1, em357_info->option_bytes.protection[1]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write protection byte 3 */ retval = target_write_u16(target, EM357_OB_WRP2, em357_info->option_bytes.protection[2]); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; /* write readout protection bit */ retval = target_write_u16(target, EM357_OB_RDP, em357_info->option_bytes.RDP); if (retval != ERROR_OK) return retval; retval = em357_wait_status_busy(bank, 10); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, EM357_FLASH_CR, FLASH_LOCK); if (retval != ERROR_OK) return retval; return ERROR_OK; }