static int stm32lx_lock_program_memory(struct flash_bank *bank) { struct target *target = bank->target; int retval; uint32_t reg32; /* To lock the program memory, simply set the lock bit and lock PECR */ retval = target_read_u32(target, FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__PRGLOCK; retval = target_write_u32(target, FLASH_PECR, reg32); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__PELOCK; retval = target_write_u32(target, FLASH_PECR, reg32); if (retval != ERROR_OK) return retval; return ERROR_OK; }
static int stm32x_read_options(struct flash_bank *bank) { uint32_t optiondata; struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* read current option bytes */ int retval = target_read_u32(target, STM32_FLASH_OBR, &optiondata); if (retval != ERROR_OK) return retval; stm32x_info->option_bytes.user_options = (uint16_t)0xFFF8 | ((optiondata >> 2) & 0x07); stm32x_info->option_bytes.RDP = (optiondata & (1 << OPT_READOUT)) ? 0xFFFF : 0x5AA5; if (optiondata & (1 << OPT_READOUT)) LOG_INFO("Device Security Bit Set"); /* each bit refers to a 4bank protection */ retval = target_read_u32(target, STM32_FLASH_WRPR, &optiondata); if (retval != ERROR_OK) return retval; stm32x_info->option_bytes.protection[0] = (uint16_t)optiondata; stm32x_info->option_bytes.protection[1] = (uint16_t)(optiondata >> 8); stm32x_info->option_bytes.protection[2] = (uint16_t)(optiondata >> 16); stm32x_info->option_bytes.protection[3] = (uint16_t)(optiondata >> 24); return ERROR_OK; }
static int nrf5_protect_check(struct flash_bank *bank) { int res; uint32_t clenr0; /* UICR cannot be write protected so just return early */ if (bank->base == NRF5_UICR_BASE) return ERROR_OK; struct nrf5_info *chip = bank->driver_priv; assert(chip != NULL); res = target_read_u32(chip->target, NRF5_FICR_CLENR0, &clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code region 0 size[FICR]"); return res; } if (clenr0 == 0xFFFFFFFF) { res = target_read_u32(chip->target, NRF5_UICR_CLENR0, &clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code region 0 size[UICR]"); return res; } } for (int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = clenr0 != 0xFFFFFFFF && bank->sectors[i].offset < clenr0; return ERROR_OK; }
static int stm32lx_enable_write_half_page(struct flash_bank *bank) { struct target *target = bank->target; int retval; uint32_t reg32; /** * Unlock the program memory, then set the FPRG bit in the PECR register. */ retval = stm32lx_unlock_program_memory(bank); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__FPRG; retval = target_write_u32(target, FLASH_PECR, reg32); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; reg32 |= FLASH_PECR__PROG; retval = target_write_u32(target, FLASH_PECR, reg32); return retval; }
static int mrvlqspi_fifo_flush(struct flash_bank *bank, int timeout) { int retval; uint32_t val; struct target *target = bank->target; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), &val); if (retval != ERROR_OK) return retval; val |= FIFO_FLUSH; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), val); if (retval != ERROR_OK) return retval; /* wait for fifo_flush to clear */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), &val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIX32, val); if ((val & FIFO_FLUSH) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } return ERROR_OK; }
static int stm32x_read_options(struct flash_bank *bank) { uint32_t optiondata; struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* read current option bytes */ int retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata); if (retval != ERROR_OK) return retval; stm32x_info->option_bytes.user_options = optiondata & 0xec; stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff; stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xfff; if (stm32x_info->has_large_mem) { retval = target_read_u32(target, STM32_FLASH_OPTCR1, &optiondata); if (retval != ERROR_OK) return retval; /* append protection bits */ stm32x_info->option_bytes.protection |= (optiondata >> 4) & 0x00fff000; }
static int stm32x_unlock_option_reg(struct target *target) { uint32_t ctrl; int retval = target_read_u32(target, STM32_FLASH_OPTCR, &ctrl); if (retval != ERROR_OK) return retval; if ((ctrl & OPTCR_LOCK) == 0) return ERROR_OK; /* unlock option registers */ retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_OPTKEYR, OPTKEY2); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, STM32_FLASH_OPTCR, &ctrl); if (retval != ERROR_OK) return retval; if (ctrl & OPTCR_LOCK) { LOG_ERROR("options not unlocked STM32_FLASH_OPTCR: %" PRIx32, ctrl); return ERROR_TARGET_FAILURE; } return ERROR_OK; }
int mips32_configure_break_unit(struct target *target) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); int retval; uint32_t dcr, bpinfo; int i; if (mips32->bp_scanned) return ERROR_OK; /* get info about breakpoint support */ retval = target_read_u32(target, EJTAG_DCR, &dcr); if (retval != ERROR_OK) return retval; if (dcr & EJTAG_DCR_IB) { /* get number of inst breakpoints */ retval = target_read_u32(target, EJTAG_IBS, &bpinfo); if (retval != ERROR_OK) return retval; mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F; mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints; mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(struct mips32_comparator)); for (i = 0; i < mips32->num_inst_bpoints; i++) mips32->inst_break_list[i].reg_address = EJTAG_IBA1 + (0x100 * i); /* clear IBIS reg */ retval = target_write_u32(target, EJTAG_IBS, 0); if (retval != ERROR_OK) return retval; }
static int mrvlqspi_read_byte(struct flash_bank *bank, uint8_t *data) { int retval; uint32_t val; struct target *target = bank->target; /* wait for rfifo_empty to reset */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), &val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, val); if ((val & RFIFO_EMPTY) == 0) break; usleep(10); } retval = target_read_u32(target, mrvlqspi_get_reg(bank, DIN), &val); if (retval != ERROR_OK) return retval; *data = val & 0xFF; return ERROR_OK; }
static int stm32x_unlock_reg(struct target *target) { uint32_t ctrl; /* first check if not already unlocked * otherwise writing on STM32_FLASH_KEYR will fail */ int retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; if ((ctrl & FLASH_LOCK) == 0) return ERROR_OK; /* unlock flash registers */ retval = target_write_u32(target, STM32_FLASH_KEYR, KEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, STM32_FLASH_KEYR, KEY2); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, STM32_FLASH_CR, &ctrl); if (retval != ERROR_OK) return retval; if (ctrl & FLASH_LOCK) { LOG_ERROR("flash not unlocked STM32_FLASH_CR: %" PRIx32, ctrl); return ERROR_TARGET_FAILURE; } return ERROR_OK; }
static int mrvlqspi_stop_transfer(struct flash_bank *bank) { int retval; uint32_t regval; struct target *target = bank->target; int timeout = QSPI_TIMEOUT; /* wait for xfer_ready and wfifo_empty to set */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & (XFER_RDY | WFIFO_EMPTY)) == (XFER_RDY | WFIFO_EMPTY)) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; regval |= XFER_STOP; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), regval); if (retval != ERROR_OK) return retval; /* wait for xfer_start to reset */ for (;;) { retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & XFER_START) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; return ERROR_OK; }
/* Static methods implementation */ static int stm32lx_unlock_program_memory(struct flash_bank *bank) { struct target *target = bank->target; int retval; uint32_t reg32; /* * Unlocking the program memory is done by unlocking the PECR, * then by writing the 2 PRGKEY to the PRGKEYR register */ /* check flash is not already unlocked */ retval = target_read_u32(target, FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; if ((reg32 & FLASH_PECR__PRGLOCK) == 0) return ERROR_OK; /* To unlock the PECR write the 2 PEKEY to the PEKEYR register */ retval = target_write_u32(target, FLASH_PEKEYR, PEKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, FLASH_PEKEYR, PEKEY2); if (retval != ERROR_OK) return retval; /* Make sure it worked */ retval = target_read_u32(target, FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; if (reg32 & FLASH_PECR__PELOCK) { LOG_ERROR("PELOCK is not cleared :("); return ERROR_FLASH_OPERATION_FAILED; } retval = target_write_u32(target, FLASH_PRGKEYR, PRGKEY1); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, FLASH_PRGKEYR, PRGKEY2); if (retval != ERROR_OK) return retval; /* Make sure it worked */ retval = target_read_u32(target, FLASH_PECR, ®32); if (retval != ERROR_OK) return retval; if (reg32 & FLASH_PECR__PRGLOCK) { LOG_ERROR("PRGLOCK is not cleared :("); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; }
static int nrf5_protect(struct flash_bank *bank, int set, int first, int last) { int res; uint32_t clenr0, ppfc; struct nrf5_info *chip; /* UICR cannot be write protected so just bail out early */ if (bank->base == NRF5_UICR_BASE) return ERROR_FAIL; res = nrf5_get_probed_chip_if_halted(bank, &chip); if (res != ERROR_OK) return res; if (first != 0) { LOG_ERROR("Code region 0 must start at the begining of the bank"); return ERROR_FAIL; } res = target_read_u32(chip->target, NRF5_FICR_PPFC, &ppfc); if (res != ERROR_OK) { LOG_ERROR("Couldn't read PPFC register"); return res; } if ((ppfc & 0xFF) == 0x00) { LOG_ERROR("Code region 0 size was pre-programmed at the factory, can't change flash protection settings"); return ERROR_FAIL; } res = target_read_u32(chip->target, NRF5_UICR_CLENR0, &clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code region 0 size[UICR]"); return res; } if (clenr0 == 0xFFFFFFFF) { res = target_write_u32(chip->target, NRF5_UICR_CLENR0, clenr0); if (res != ERROR_OK) { LOG_ERROR("Couldn't write code region 0 size[UICR]"); return res; } } else { LOG_ERROR("You need to perform chip erase before changing the protection settings"); } nrf5_protect_check(bank); return ERROR_OK; }
static int mrvlqspi_start_transfer(struct flash_bank *bank, bool rw_mode) { int retval; uint32_t regval; struct target *target = bank->target; retval = mrvlqspi_set_ss_state(bank, QSPI_SS_ENABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; if (rw_mode) regval |= RW_EN; else regval &= ~(RW_EN); regval |= XFER_START; retval = target_write_u32(target, mrvlqspi_get_reg(bank, CONF), regval); if (retval != ERROR_OK) return retval; return ERROR_OK; }
/* The probe routine for the nuc. Only recognizes the nuc120 right now. */ static int nuc1x_probe(struct flash_bank *bank) { struct target *target = bank->target; struct nuc1x_flash_bank *nuc1x_info = bank->driver_priv; int i; uint16_t num_pages; uint32_t device_id; int page_size; uint32_t base_address = 0x00000000; nuc1x_info->probed = 0; /* read nuc1x device id register */ int retval = target_read_u32(target, 0x50000000, &device_id); if (retval != ERROR_OK) return retval; page_size = 512; /* all nuc parts has 512 byte per sector */ /* search part numbers */ for (i = 0; NuMicroParts[i].partno; i++) { if (NuMicroParts[i].partno == (device_id & 0x0FFFFFFF)) { num_pages = NuMicroParts[i].num_page; break; } } if (!(NuMicroParts[i].partno == 0x00000000)) { LOG_INFO("DeviceID : 0x%08" PRIx32 "", device_id); LOG_INFO("Detect %s%cN!", NuMicroParts[i].partname, (char)('A'+(device_id>>28))); } else {
static int mips32_configure_dbs(struct target *target) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; int retval, i; uint32_t bpinfo; /* get number of data breakpoints */ retval = target_read_u32(target, ejtag_info->ejtag_dbs_addr, &bpinfo); if (retval != ERROR_OK) return retval; mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F; mips32->num_data_bpoints_avail = mips32->num_data_bpoints; mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(struct mips32_comparator)); for (i = 0; i < mips32->num_data_bpoints; i++) mips32->data_break_list[i].reg_address = ejtag_info->ejtag_dba0_addr + (ejtag_info->ejtag_dba_step_size * i); /* clear DBIS reg */ retval = target_write_u32(target, ejtag_info->ejtag_dbs_addr, 0); return retval; }
static int sam4l_protect_check(struct flash_bank *bank) { int res; uint32_t st; struct sam4l_info *chip = (struct sam4l_info *)bank->driver_priv; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!chip->probed) { if (sam4l_probe(bank) != ERROR_OK) return ERROR_FLASH_BANK_NOT_PROBED; } res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FSR, &st); if (res != ERROR_OK) return res; st >>= 16; /* There are 16 lock region bits in the upper half word */ for (int i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = !!(st & (1<<i)); return ERROR_OK; }
static int sam4l_check_page_erased(struct flash_bank *bank, uint32_t pn, bool *is_erased_p) { int res; uint32_t st; /* Issue a quick page read to verify that we've erased this page */ res = sam4l_flash_command(bank->target, SAM4L_FCMD_QPR, pn); if (res != ERROR_OK) { LOG_ERROR("Quick page read %d failed", pn); return res; } /* Retrieve the flash status */ res = target_read_u32(bank->target, SAM4L_FLASHCALW + SAM4L_FSR, &st); if (res != ERROR_OK) { LOG_ERROR("Couldn't read erase status"); return res; } /* Is the page in question really erased? */ *is_erased_p = !!(st & (1<<5)); return ERROR_OK; }
int s3c2440_read_block_data(struct nand_device *nand, uint8_t *data, int data_size) { struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv; struct target *target = nand->target; uint32_t nfdata = s3c24xx_info->data; uint32_t tmp; LOG_INFO("%s: reading data: %p, %p, %d", __func__, nand, data, data_size); if (target->state != TARGET_HALTED) { LOG_ERROR("target must be halted to use S3C24XX NAND flash controller"); return ERROR_NAND_OPERATION_FAILED; } while (data_size >= 4) { target_read_u32(target, nfdata, &tmp); data[0] = tmp; data[1] = tmp >> 8; data[2] = tmp >> 16; data[3] = tmp >> 24; data_size -= 4; data += 4; } while (data_size > 0) { target_read_u8(target, nfdata, data); data_size -= 1; data += 1; } return ERROR_OK; }
static int em357_protect_check(struct flash_bank *bank) { struct target *target = bank->target; struct em357_flash_bank *em357_info = bank->driver_priv; uint32_t protection; int i, s; int num_bits; int set; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* each bit refers to a 4bank protection (bit 0-23) */ int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection); if (retval != ERROR_OK) return retval; /* each protection bit is for 4 * 2K pages */ num_bits = (bank->num_sectors / em357_info->ppage_size); for (i = 0; i < num_bits; i++) { set = 1; if (protection & (1 << i)) set = 0; for (s = 0; s < em357_info->ppage_size; s++) bank->sectors[(i * em357_info->ppage_size) + s].is_protected = set; } return ERROR_OK; }
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank) { struct target *target = bank->target; uint32_t status; int retval = ERROR_OK; int timeout = 100; /* wait for busy to clear */ for (;;) { retval = target_read_u32(target, FLASH_SR, &status); if (retval != ERROR_OK) return retval; if ((status & FLASH_SR__BSY) == 0) break; if (timeout-- <= 0) { LOG_ERROR("timed out waiting for flash"); return ERROR_FAIL; } alive_sleep(1); } if (status & FLASH_SR__WRPERR) { LOG_ERROR("access denied / write protected"); retval = ERROR_FAIL; } if (status & FLASH_SR__PGAERR) { LOG_ERROR("invalid program address"); retval = ERROR_FAIL; } return retval; }
static int str7x_protect_check(struct flash_bank *bank) { struct str7x_flash_bank *str7x_info = bank->driver_priv; struct target *target = bank->target; int i; uint32_t flash_flags; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } int retval; retval = target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), &flash_flags); if (retval != ERROR_OK) return retval; for (i = 0; i < bank->num_sectors; i++) { if (flash_flags & str7x_info->sector_bits[i]) bank->sectors[i].is_protected = 0; else bank->sectors[i].is_protected = 1; } return ERROR_OK; }
/* read a long (32bit) from the netx to the pc */ int fn_read_data32(void *pvHandle, unsigned long ulNetxAddress, unsigned long *pulData) { command_context_t *cmd_ctx; target_t *target; int iResult; /* cast the handle to the command context */ cmd_ctx = (command_context_t*)pvHandle; /* get the target from the command context */ target = get_current_target(cmd_ctx); /* read the data from the netX */ iResult = target_read_u32(target, ulNetxAddress, (u32*)pulData); if( iResult==ERROR_OK ) { iResult = 0; } else { iResult = 1; } wxMilliSleep(1); return iResult; }
int mips32_enable_interrupts(struct target *target, int enable) { int retval; int update = 0; uint32_t dcr; /* read debug control register */ retval = target_read_u32(target, EJTAG_DCR, &dcr); if (retval != ERROR_OK) return retval; if (enable) { if (!(dcr & EJTAG_DCR_INTE)) { /* enable interrupts */ dcr |= EJTAG_DCR_INTE; update = 1; } } else { if (dcr & EJTAG_DCR_INTE) { /* disable interrupts */ dcr &= ~EJTAG_DCR_INTE; update = 1; } } if (update) { retval = target_write_u32(target, EJTAG_DCR, dcr); if (retval != ERROR_OK) return retval; } return ERROR_OK; }
/* Protection checking - examines the lock bit. */ static int nuc1x_protect_check(struct flash_bank *bank) { uint32_t is_protected, set; struct target *target = bank->target; int i; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Check to see if Nuc is unlocked or not */ int retval = target_read_u32(target, NUC1X_SYS_WRPROT, &is_protected); if (retval != ERROR_OK) return retval; LOG_INFO("is_protected = 0x%08" PRIx32 "", is_protected); if (is_protected == 0) { /* means protected */ set = 1; } else { set = 0; } for (i = 0; i < bank->num_sectors; i++) bank->sectors[i].is_protected = set; return ERROR_OK; }
static int stm32x_read_options(struct flash_bank *bank) { uint32_t optiondata; struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; stm32x_info = bank->driver_priv; /* read current option bytes */ int retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata); if (retval != ERROR_OK) return retval; /* caution: F2 implements 5 bits (WDG_SW only) * whereas F7 6 bits (IWDG_SW and WWDG_SW) in user_options */ stm32x_info->option_bytes.user_options = optiondata & 0xfc; stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff; stm32x_info->option_bytes.protection = (optiondata >> 16) & (~(0xffff << stm32x_info->protection_bits) & 0xffff); if (stm32x_info->has_extra_options) { /* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */ stm32x_info->option_bytes.user_options |= (optiondata >> 20) & ((0xf00 << (stm32x_info->protection_bits - 12)) & 0xf00); }
/** * Reads a page from an AT91SAM9 NAND controller and verifies using 1-bit ECC * controller on chip. This makes an attempt to correct any errors that are * encountered while reading the page of data. * * @param nand NAND device to read from * @param page Page to be read. * @param data Pointer to where data should be read to. * @param data_size Size of the data to be read. * @param oob Pointer to where OOB data should be read to. * @param oob_size Size of the OOB data to be read. * @return Success or failure of reading the NAND page. */ static int at91sam9_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size) { int retval; struct at91sam9_nand *info = nand->controller_priv; struct target *target = nand->target; uint8_t *oob_data; uint32_t status; retval = at91sam9_ecc_init(target, info); if (ERROR_OK != retval) return retval; retval = nand_page_command(nand, page, NAND_CMD_READ0, !data); if (ERROR_OK != retval) return retval; if (data) { retval = nand_read_data_page(nand, data, data_size); if (ERROR_OK != retval) return retval; } oob_data = at91sam9_oob_init(nand, oob, &oob_size); retval = nand_read_data_page(nand, oob_data, oob_size); if (ERROR_OK == retval && data) { target_read_u32(target, info->ecc + AT91C_ECCx_SR, &status); if (status & 1) { LOG_ERROR("Error detected!"); if (status & 4) LOG_ERROR("Multiple errors encountered; unrecoverable!"); else { /* attempt recovery */ uint32_t parity; target_read_u32(target, info->ecc + AT91C_ECCx_PR, &parity); uint32_t word = (parity & 0x0000FFF0) >> 4; uint32_t bit = parity & 0x0F; data[word] ^= (0x1) << bit; LOG_INFO("Data word %d, bit %d corrected.", (unsigned) word, (unsigned) bit); } }
static int s6e2cc_probe(struct flash_bank *bank) { struct target *target = bank->target; struct fm4_flash_bank *fm4_bank = bank->driver_priv; uint32_t u32_value; uint32_t flash_addr = bank->base; int i, retval, num_sectors, num_extra_sectors; retval = target_read_u32(target, DFCTRLR, &u32_value); if (retval != ERROR_OK) return retval; if (u32_value & DFCTRLR_DFE) { LOG_WARNING("Dual Flash mode is not implemented."); return ERROR_FLASH_OPER_UNSUPPORTED; } switch (fm4_bank->variant) { case s6e2cx8: num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 0; break; case s6e2cx9: num_sectors = (fm4_bank->macro_nr == 0) ? 20 : 12; break; case s6e2cxa: num_sectors = 20; break; default: return ERROR_FLASH_OPER_UNSUPPORTED; } num_extra_sectors = (fm4_bank->macro_nr == 0) ? 1 : 4; bank->num_sectors = num_sectors + num_extra_sectors; LOG_DEBUG("%d sectors", bank->num_sectors); bank->sectors = calloc(bank->num_sectors, sizeof(struct flash_sector)); for (i = 0; i < num_sectors; i++) { int sa = 4 + i; bank->sectors[i].offset = flash_addr - bank->base; s6e2cc_init_sector(&bank->sectors[i], sa); bank->size += bank->sectors[i].size; flash_addr += bank->sectors[i].size; } flash_addr = (fm4_bank->macro_nr == 0) ? 0x00406000 : 0x00408000; for (; i < bank->num_sectors; i++) { int sa = 4 - num_extra_sectors + (i - num_sectors); bank->sectors[i].offset = flash_addr - bank->base; s6e2cc_init_sector(&bank->sectors[i], sa); /* * Don't increase bank->size for these sectors * to avoid an overlap between Flash Macros #0 and #1. */ flash_addr += bank->sectors[i].size; } return ERROR_OK; }
static int xmc4xxx_erase_sector(struct flash_bank *bank, uint32_t address, bool user_config) { int res; uint32_t status; /* See reference manual table 8.4: Command Sequences for Flash Control */ struct xmc4xxx_command_seq erase_cmd_seq[6] = { {FLASH_CMD_ERASE_1, 0xAA}, {FLASH_CMD_ERASE_2, 0x55}, {FLASH_CMD_ERASE_3, 0x80}, {FLASH_CMD_ERASE_4, 0xAA}, {FLASH_CMD_ERASE_5, 0x55}, {0xFF, 0xFF} /* Needs filled in */ }; /* We need to fill in the base address of the sector we'll be * erasing, as well as the magic code that determines whether * this is a standard flash sector or a user configuration block */ erase_cmd_seq[5].address = address; if (user_config) { /* Removing flash protection requires the addition of * the base address */ erase_cmd_seq[5].address += bank->base; erase_cmd_seq[5].magic = 0xC0; } else { erase_cmd_seq[5].magic = 0x30; } res = xmc4xxx_write_command_sequence(bank, erase_cmd_seq, ARRAY_SIZE(erase_cmd_seq)); if (res != ERROR_OK) return res; /* Read the flash status register */ res = target_read_u32(bank->target, FLASH_REG_FLASH0_FSR, &status); if (res != ERROR_OK) { LOG_ERROR("Cannot read flash status register."); return res; } /* Check for a sequence error */ if (status & FSR_SQER_MASK) { LOG_ERROR("Error with flash erase sequence"); return ERROR_FAIL; } /* Make sure a flash erase was triggered */ if (!(status & FSR_ERASE_MASK)) { LOG_ERROR("Flash failed to erase"); return ERROR_FAIL; } /* Now we must wait for the erase operation to end */ res = xmc4xxx_wait_status_busy(bank, FLASH_OP_TIMEOUT); return res; }
static int em357_protect(struct flash_bank *bank, int set, int first, int last) { struct em357_flash_bank *em357_info = NULL; struct target *target = bank->target; uint16_t prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; int i, reg, bit; int status; uint32_t protection; em357_info = bank->driver_priv; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if ((first % em357_info->ppage_size) != 0) { LOG_WARNING("aligned start protect sector to a %d sector boundary", em357_info->ppage_size); first = first - (first % em357_info->ppage_size); } if (((last + 1) % em357_info->ppage_size) != 0) { LOG_WARNING("aligned end protect sector to a %d sector boundary", em357_info->ppage_size); last++; last = last - (last % em357_info->ppage_size); last--; } /* each bit refers to a 4bank protection */ int retval = target_read_u32(target, EM357_FLASH_WRPR, &protection); if (retval != ERROR_OK) return retval; prot_reg[0] = (uint16_t)protection; prot_reg[1] = (uint16_t)(protection >> 8); prot_reg[2] = (uint16_t)(protection >> 16); for (i = first; i <= last; i++) { reg = (i / em357_info->ppage_size) / 8; bit = (i / em357_info->ppage_size) - (reg * 8); LOG_WARNING("reg, bit: %d, %d", reg, bit); if (set) prot_reg[reg] &= ~(1 << bit); else prot_reg[reg] |= (1 << bit); } status = em357_erase_options(bank); if (retval != ERROR_OK) return status; em357_info->option_bytes.protection[0] = prot_reg[0]; em357_info->option_bytes.protection[1] = prot_reg[1]; em357_info->option_bytes.protection[2] = prot_reg[2]; return em357_write_options(bank); }