X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Ffespi.c;h=9191764a96ad1c5bf43db0c2d44b39aca85bfed4;hp=ea47afd23162735260cb5fb23824118625a4414e;hb=HEAD;hpb=c3b90c052acfb7e35a0f4ce22276d53a96d631c7 diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index ea47afd231..9191764a96 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + /*************************************************************************** * Copyright (C) 2010 by Antonio Borneo * * Modified by Megan Wachs from the original stmsmi.c * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * 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, see . * ***************************************************************************/ /* The Freedom E SPI controller is a SPI bus controller @@ -122,7 +111,7 @@ struct fespi_flash_bank { - int probed; + bool probed; target_addr_t ctrl_base; const struct flash_device *dev; }; @@ -136,8 +125,9 @@ struct fespi_target { /* TODO !!! What is the right naming convention here? */ static const struct fespi_target target_devices[] = { /* name, tap_idcode, ctrl_base */ - { "Freedom E300 SPI Flash", 0x10e31913 , 0x10014000 }, - { NULL, 0, 0 } + { "Freedom E310-G000 SPI Flash", 0x10e31913, 0x10014000 }, + { "Freedom E310-G002 SPI Flash", 0x20000913, 0x10014000 }, + { NULL, 0, 0 } }; FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command) @@ -150,18 +140,16 @@ FLASH_BANK_COMMAND_HANDLER(fespi_flash_bank_command) return ERROR_COMMAND_SYNTAX_ERROR; fespi_info = malloc(sizeof(struct fespi_flash_bank)); - if (fespi_info == NULL) { + if (!fespi_info) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } bank->driver_priv = fespi_info; - fespi_info->probed = 0; + fespi_info->probed = false; fespi_info->ctrl_base = 0; if (CMD_ARGC >= 7) { - int temp; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[6], temp); - fespi_info->ctrl_base = (uint32_t) temp; + COMMAND_PARSE_ADDRESS(CMD_ARGV[6], fespi_info->ctrl_base); LOG_DEBUG("ASSUMING FESPI device at ctrl_base = " TARGET_ADDR_FMT, fespi_info->ctrl_base); } @@ -184,13 +172,13 @@ static int fespi_read_reg(struct flash_bank *bank, uint32_t *value, target_addr_ } static int fespi_write_reg(struct flash_bank *bank, target_addr_t address, uint32_t value) -{ \ +{ struct target *target = bank->target; struct fespi_flash_bank *fespi_info = bank->driver_priv; int result = target_write_u32(target, fespi_info->ctrl_base + address, value); if (result != ERROR_OK) { - LOG_ERROR("fespi_write_reg() error writing 0x%x to " TARGET_ADDR_FMT, + LOG_ERROR("fespi_write_reg() error writing 0x%" PRIx32 " to " TARGET_ADDR_FMT, value, fespi_info->ctrl_base + address); return result; } @@ -275,7 +263,7 @@ static int fespi_rx(struct flash_bank *bank, uint8_t *out) break; int64_t now = timeval_ms(); if (now - start > 1000) { - LOG_ERROR("rxfifo didn't go positive (value=0x%x).", value); + LOG_ERROR("rxfifo didn't go positive (value=0x%" PRIx32 ").", value); return ERROR_TARGET_TIMEOUT; } } @@ -338,6 +326,11 @@ static int fespi_erase_sector(struct flash_bank *bank, int sector) if (retval != ERROR_OK) return retval; sector = bank->sectors[sector].offset; + if (bank->size > 0x1000000) { + retval = fespi_tx(bank, sector >> 24); + if (retval != ERROR_OK) + return retval; + } retval = fespi_tx(bank, sector >> 16); if (retval != ERROR_OK) return retval; @@ -360,21 +353,21 @@ static int fespi_erase_sector(struct flash_bank *bank, int sector) return ERROR_OK; } -static int fespi_erase(struct flash_bank *bank, int first, int last) +static int fespi_erase(struct flash_bank *bank, unsigned int first, + unsigned int last) { struct target *target = bank->target; struct fespi_flash_bank *fespi_info = bank->driver_priv; int retval = ERROR_OK; - int sector; - LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last); + LOG_DEBUG("%s: from sector %u to sector %u", __func__, first, last); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } - if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { + if ((last < first) || (last >= bank->num_sectors)) { LOG_ERROR("Flash sector invalid"); return ERROR_FLASH_SECTOR_INVALID; } @@ -384,9 +377,9 @@ static int fespi_erase(struct flash_bank *bank, int first, int last) return ERROR_FLASH_BANK_NOT_PROBED; } - for (sector = first; sector <= last; sector++) { + for (unsigned int sector = first; sector <= last; sector++) { if (bank->sectors[sector].is_protected) { - LOG_ERROR("Flash sector %d protected", sector); + LOG_ERROR("Flash sector %u protected", sector); return ERROR_FAIL; } } @@ -411,7 +404,7 @@ static int fespi_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) goto done; - for (sector = first; sector <= last; sector++) { + for (unsigned int sector = first; sector <= last; sector++) { retval = fespi_erase_sector(bank, sector); if (retval != ERROR_OK) goto done; @@ -426,11 +419,9 @@ done: } static int fespi_protect(struct flash_bank *bank, int set, - int first, int last) + unsigned int first, unsigned int last) { - int sector; - - for (sector = first; sector <= last; sector++) + for (unsigned int sector = first; sector <= last; sector++) bank->sectors[sector].is_protected = set; return ERROR_OK; } @@ -438,32 +429,38 @@ static int fespi_protect(struct flash_bank *bank, int set, static int slow_fespi_write_buffer(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t len) { + struct fespi_flash_bank *fespi_info = bank->driver_priv; uint32_t ii; - if (offset & 0xFF000000) { - LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x", - offset); - return ERROR_FAIL; - } - /* TODO!!! assert that len < page size */ - fespi_tx(bank, SPIFLASH_WRITE_ENABLE); - fespi_txwm_wait(bank); + if (fespi_tx(bank, SPIFLASH_WRITE_ENABLE) != ERROR_OK) + return ERROR_FAIL; + if (fespi_txwm_wait(bank) != ERROR_OK) + return ERROR_FAIL; if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD) != ERROR_OK) return ERROR_FAIL; - fespi_tx(bank, SPIFLASH_PAGE_PROGRAM); + if (fespi_tx(bank, fespi_info->dev->pprog_cmd) != ERROR_OK) + return ERROR_FAIL; - fespi_tx(bank, offset >> 16); - fespi_tx(bank, offset >> 8); - fespi_tx(bank, offset); + if (bank->size > 0x1000000 && fespi_tx(bank, offset >> 24) != ERROR_OK) + return ERROR_FAIL; + if (fespi_tx(bank, offset >> 16) != ERROR_OK) + return ERROR_FAIL; + if (fespi_tx(bank, offset >> 8) != ERROR_OK) + return ERROR_FAIL; + if (fespi_tx(bank, offset) != ERROR_OK) + return ERROR_FAIL; - for (ii = 0; ii < len; ii++) - fespi_tx(bank, buffer[ii]); + for (ii = 0; ii < len; ii++) { + if (fespi_tx(bank, buffer[ii]) != ERROR_OK) + return ERROR_FAIL; + } - fespi_txwm_wait(bank); + if (fespi_txwm_wait(bank) != ERROR_OK) + return ERROR_FAIL; if (fespi_write_reg(bank, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO) != ERROR_OK) return ERROR_FAIL; @@ -473,274 +470,24 @@ static int slow_fespi_write_buffer(struct flash_bank *bank, return ERROR_OK; } -static const uint8_t algorithm_bin[] = { -#include "../../../contrib/loaders/flash/fespi/fespi.inc" +static const uint8_t riscv32_bin[] = { +#include "../../../contrib/loaders/flash/fespi/riscv32_fespi.inc" }; -#define STEP_EXIT 4 -#define STEP_TX 8 -#define STEP_TXWM_WAIT 12 -#define STEP_WRITE_REG 16 -#define STEP_WIP_WAIT 20 -#define STEP_SET_DIR 24 -#define STEP_NOP 0xff - -struct algorithm_steps { - unsigned size; - unsigned used; - uint8_t **steps; -}; - -static struct algorithm_steps *as_new(void) -{ - struct algorithm_steps *as = calloc(1, sizeof(struct algorithm_steps)); - as->size = 8; - as->steps = malloc(as->size * sizeof(as->steps[0])); - return as; -} - -static struct algorithm_steps *as_delete(struct algorithm_steps *as) -{ - for (unsigned step = 0; step < as->used; step++) { - free(as->steps[step]); - as->steps[step] = NULL; - } - free(as->steps); - free(as); - return NULL; -} - -static int as_empty(struct algorithm_steps *as) -{ - for (unsigned s = 0; s < as->used; s++) { - if (as->steps[s][0] != STEP_NOP) - return 0; - } - return 1; -} - -/* Return size of compiled program. */ -static unsigned as_compile(struct algorithm_steps *as, uint8_t *target, - unsigned target_size) -{ - unsigned offset = 0; - bool finish_early = false; - for (unsigned s = 0; s < as->used && !finish_early; s++) { - unsigned bytes_left = target_size - offset; - switch (as->steps[s][0]) { - case STEP_NOP: - break; - case STEP_TX: - { - unsigned size = as->steps[s][1]; - if (size + 3 > bytes_left) { - finish_early = true; - break; - } - memcpy(target + offset, as->steps[s], size + 2); - offset += size + 2; - break; - } - case STEP_WRITE_REG: - if (4 > bytes_left) { - finish_early = true; - break; - } - memcpy(target + offset, as->steps[s], 3); - offset += 3; - break; - case STEP_SET_DIR: - if (3 > bytes_left) { - finish_early = true; - break; - } - memcpy(target + offset, as->steps[s], 2); - offset += 2; - break; - case STEP_TXWM_WAIT: - case STEP_WIP_WAIT: - if (2 > bytes_left) { - finish_early = true; - break; - } - memcpy(target + offset, as->steps[s], 1); - offset += 1; - break; - default: - assert(0); - } - if (!finish_early) - as->steps[s][0] = STEP_NOP; - } - assert(offset + 1 <= target_size); - target[offset++] = STEP_EXIT; - - LOG_DEBUG("%d-byte program:", offset); - for (unsigned i = 0; i < offset;) { - char buf[80]; - for (unsigned x = 0; i < offset && x < 16; x++, i++) - sprintf(buf + x*3, "%02x ", target[i]); - LOG_DEBUG("%s", buf); - } - - return offset; -} -static void as_add_step(struct algorithm_steps *as, uint8_t *step) -{ - if (as->used == as->size) { - as->size *= 2; - as->steps = realloc(as->steps, sizeof(as->steps[0]) * as->size); - LOG_DEBUG("Increased size to 0x%x", as->size); - } - as->steps[as->used] = step; - as->used++; -} - -static void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data) -{ - LOG_DEBUG("count=%d", count); - while (count > 0) { - unsigned step_count = MIN(count, 255); - uint8_t *step = malloc(step_count + 2); - step[0] = STEP_TX; - step[1] = step_count; - memcpy(step + 2, data, step_count); - as_add_step(as, step); - data += step_count; - count -= step_count; - } -} - -static void as_add_tx1(struct algorithm_steps *as, uint8_t byte) -{ - uint8_t data[1]; - data[0] = byte; - as_add_tx(as, 1, data); -} - -static void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data) -{ - uint8_t *step = malloc(3); - step[0] = STEP_WRITE_REG; - step[1] = offset; - step[2] = data; - as_add_step(as, step); -} - -static void as_add_txwm_wait(struct algorithm_steps *as) -{ - uint8_t *step = malloc(1); - step[0] = STEP_TXWM_WAIT; - as_add_step(as, step); -} - -static void as_add_wip_wait(struct algorithm_steps *as) -{ - uint8_t *step = malloc(1); - step[0] = STEP_WIP_WAIT; - as_add_step(as, step); -} - -static void as_add_set_dir(struct algorithm_steps *as, bool dir) -{ - uint8_t *step = malloc(2); - step[0] = STEP_SET_DIR; - step[1] = FESPI_FMT_DIR(dir); - as_add_step(as, step); -} - -/* This should write something less than or equal to a page.*/ -static int steps_add_buffer_write(struct algorithm_steps *as, - const uint8_t *buffer, uint32_t chip_offset, uint32_t len) -{ - if (chip_offset & 0xFF000000) { - LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x", - chip_offset); - return ERROR_FAIL; - } - - as_add_tx1(as, SPIFLASH_WRITE_ENABLE); - as_add_txwm_wait(as); - as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD); - - uint8_t setup[] = { - SPIFLASH_PAGE_PROGRAM, - chip_offset >> 16, - chip_offset >> 8, - chip_offset, - }; - as_add_tx(as, sizeof(setup), setup); - - as_add_tx(as, len, buffer); - as_add_txwm_wait(as); - as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO); - - /* fespi_wip() */ - as_add_set_dir(as, FESPI_DIR_RX); - as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD); - as_add_wip_wait(as); - as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO); - as_add_set_dir(as, FESPI_DIR_TX); - - return ERROR_OK; -} - -static int steps_execute(struct algorithm_steps *as, - struct flash_bank *bank, struct working_area *algorithm_wa, - struct working_area *data_wa) -{ - struct target *target = bank->target; - struct fespi_flash_bank *fespi_info = bank->driver_priv; - uint32_t ctrl_base = fespi_info->ctrl_base; - int xlen = riscv_xlen(target); - - struct reg_param reg_params[2]; - init_reg_param(®_params[0], "a0", xlen, PARAM_OUT); - init_reg_param(®_params[1], "a1", xlen, PARAM_OUT); - buf_set_u64(reg_params[0].value, 0, xlen, ctrl_base); - buf_set_u64(reg_params[1].value, 0, xlen, data_wa->address); - - int retval = ERROR_OK; - while (!as_empty(as)) { - keep_alive(); - uint8_t *data_buf = malloc(data_wa->size); - unsigned bytes = as_compile(as, data_buf, data_wa->size); - retval = target_write_buffer(target, data_wa->address, bytes, - data_buf); - free(data_buf); - if (retval != ERROR_OK) { - LOG_ERROR("Failed to write data to " TARGET_ADDR_FMT ": %d", - data_wa->address, retval); - goto exit; - } - - retval = target_run_algorithm(target, 0, NULL, 2, reg_params, - algorithm_wa->address, algorithm_wa->address + 4, - 10000, NULL); - if (retval != ERROR_OK) { - LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d", - algorithm_wa->address, retval); - goto exit; - } - } - -exit: - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[0]); - return retval; -} +static const uint8_t riscv64_bin[] = { +#include "../../../contrib/loaders/flash/fespi/riscv64_fespi.inc" +}; static int fespi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; struct fespi_flash_bank *fespi_info = bank->driver_priv; - uint32_t cur_count, page_size, page_offset; - int sector; + uint32_t cur_count, page_size; int retval = ERROR_OK; - LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, - __func__, offset, count); + LOG_DEBUG("bank->size=0x%x offset=0x%08" PRIx32 " count=0x%08" PRIx32, + bank->size, offset, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -753,104 +500,169 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer, } /* Check sector protection */ - for (sector = 0; sector < bank->num_sectors; sector++) { + for (unsigned int sector = 0; sector < bank->num_sectors; sector++) { /* Start offset in or before this sector? */ /* End offset in or behind this sector? */ if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && ((offset + count - 1) >= bank->sectors[sector].offset) && bank->sectors[sector].is_protected) { - LOG_ERROR("Flash sector %d protected", sector); + LOG_ERROR("Flash sector %u protected", sector); return ERROR_FAIL; } } - struct working_area *algorithm_wa; - if (target_alloc_working_area(target, sizeof(algorithm_bin), - &algorithm_wa) != ERROR_OK) { - LOG_WARNING("Couldn't allocate %zd-byte working area.", - sizeof(algorithm_bin)); - algorithm_wa = NULL; + struct riscv_info *riscv = riscv_info(target); + if (!is_riscv(riscv)) { + LOG_ERROR("Unexpected target type"); + return ERROR_FAIL; + } + + unsigned int xlen = riscv_xlen(target); + struct working_area *algorithm_wa = NULL; + struct working_area *data_wa = NULL; + const uint8_t *bin; + size_t bin_size; + if (xlen == 32) { + bin = riscv32_bin; + bin_size = sizeof(riscv32_bin); } else { + bin = riscv64_bin; + bin_size = sizeof(riscv64_bin); + } + + unsigned data_wa_size = 0; + if (target_alloc_working_area(target, bin_size, &algorithm_wa) == ERROR_OK) { retval = target_write_buffer(target, algorithm_wa->address, - sizeof(algorithm_bin), algorithm_bin); + bin_size, bin); if (retval != ERROR_OK) { LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d", algorithm_wa->address, retval); target_free_working_area(target, algorithm_wa); algorithm_wa = NULL; - } - } - struct working_area *data_wa = NULL; - unsigned data_wa_size = 2 * count; - while (1) { - if (data_wa_size < 128) { - LOG_WARNING("Couldn't allocate data working area."); - target_free_working_area(target, algorithm_wa); - algorithm_wa = NULL; - } - if (target_alloc_working_area_try(target, data_wa_size, &data_wa) == - ERROR_OK) { - break; + } else { + data_wa_size = MIN(target_get_working_area_avail(target), count); + if (data_wa_size < 128) { + LOG_WARNING("Couldn't allocate data working area."); + target_free_working_area(target, algorithm_wa); + algorithm_wa = NULL; + } else if (target_alloc_working_area(target, data_wa_size, &data_wa) != ERROR_OK) { + target_free_working_area(target, algorithm_wa); + algorithm_wa = NULL; + } } - - data_wa_size /= 2; + } else { + LOG_WARNING("Couldn't allocate %zd-byte working area.", bin_size); + algorithm_wa = NULL; } /* If no valid page_size, use reasonable default. */ page_size = fespi_info->dev->pagesize ? fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE; - fespi_txwm_wait(bank); + if (algorithm_wa) { + struct reg_param reg_params[6]; + init_reg_param(®_params[0], "a0", xlen, PARAM_IN_OUT); + init_reg_param(®_params[1], "a1", xlen, PARAM_OUT); + init_reg_param(®_params[2], "a2", xlen, PARAM_OUT); + init_reg_param(®_params[3], "a3", xlen, PARAM_OUT); + init_reg_param(®_params[4], "a4", xlen, PARAM_OUT); + init_reg_param(®_params[5], "a5", xlen, PARAM_OUT); + + while (count > 0) { + cur_count = MIN(count, data_wa_size); + buf_set_u64(reg_params[0].value, 0, xlen, fespi_info->ctrl_base); + buf_set_u64(reg_params[1].value, 0, xlen, page_size); + buf_set_u64(reg_params[2].value, 0, xlen, data_wa->address); + buf_set_u64(reg_params[3].value, 0, xlen, offset); + buf_set_u64(reg_params[4].value, 0, xlen, cur_count); + buf_set_u64(reg_params[5].value, 0, xlen, + fespi_info->dev->pprog_cmd | (bank->size > 0x1000000 ? 0x100 : 0)); + + retval = target_write_buffer(target, data_wa->address, cur_count, + buffer); + if (retval != ERROR_OK) { + LOG_DEBUG("Failed to write %d bytes to " TARGET_ADDR_FMT ": %d", + cur_count, data_wa->address, retval); + goto err; + } + + LOG_DEBUG("write(ctrl_base=0x%" TARGET_PRIxADDR ", page_size=0x%x, " + "address=0x%" TARGET_PRIxADDR ", offset=0x%" PRIx32 + ", count=0x%" PRIx32 "), buffer=%02x %02x %02x %02x %02x %02x ..." PRIx32, + fespi_info->ctrl_base, page_size, data_wa->address, offset, cur_count, + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); + retval = target_run_algorithm(target, 0, NULL, + ARRAY_SIZE(reg_params), reg_params, + algorithm_wa->address, 0, cur_count * 2, NULL); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d", + algorithm_wa->address, retval); + goto err; + } + + uint64_t algorithm_result = buf_get_u64(reg_params[0].value, 0, xlen); + if (algorithm_result != 0) { + LOG_ERROR("Algorithm returned error %" PRId64, algorithm_result); + retval = ERROR_FAIL; + goto err; + } + + buffer += cur_count; + offset += cur_count; + count -= cur_count; + } - /* Disable Hardware accesses*/ - if (fespi_disable_hw_mode(bank) != ERROR_OK) - return ERROR_FAIL; + target_free_working_area(target, data_wa); + target_free_working_area(target, algorithm_wa); - struct algorithm_steps *as = as_new(); + } else { + fespi_txwm_wait(bank); - /* poll WIP */ - retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT); - if (retval != ERROR_OK) - goto err; - - page_offset = offset % page_size; - /* central part, aligned words */ - while (count > 0) { - /* clip block at page boundary */ - if (page_offset + count > page_size) - cur_count = page_size - page_offset; - else - cur_count = count; - - if (algorithm_wa) - retval = steps_add_buffer_write(as, buffer, offset, cur_count); - else - retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count); + /* Disable Hardware accesses*/ + if (fespi_disable_hw_mode(bank) != ERROR_OK) + return ERROR_FAIL; + + /* poll WIP */ + retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT); if (retval != ERROR_OK) goto err; - page_offset = 0; - buffer += cur_count; - offset += cur_count; - count -= cur_count; - } + uint32_t page_offset = offset % page_size; + /* central part, aligned words */ + while (count > 0) { + /* clip block at page boundary */ + if (page_offset + count > page_size) + cur_count = page_size - page_offset; + else + cur_count = count; - if (algorithm_wa) - retval = steps_execute(as, bank, algorithm_wa, data_wa); + retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count); + if (retval != ERROR_OK) + goto err; -err: - if (algorithm_wa) { - target_free_working_area(target, data_wa); - target_free_working_area(target, algorithm_wa); + page_offset = 0; + buffer += cur_count; + offset += cur_count; + count -= cur_count; + } + + /* Switch to HW mode before return to prompt */ + if (fespi_enable_hw_mode(bank) != ERROR_OK) + return ERROR_FAIL; } - as_delete(as); + return ERROR_OK; + +err: + target_free_working_area(target, data_wa); + target_free_working_area(target, algorithm_wa); /* Switch to HW mode before return to prompt */ if (fespi_enable_hw_mode(bank) != ERROR_OK) return ERROR_FAIL; + return retval; } @@ -920,7 +732,7 @@ static int fespi_probe(struct flash_bank *bank) if (fespi_info->probed) free(bank->sectors); - fespi_info->probed = 0; + fespi_info->probed = false; if (fespi_info->ctrl_base == 0) { for (target_device = target_devices ; target_device->name ; ++target_device) @@ -980,8 +792,6 @@ static int fespi_probe(struct flash_bank *bank) if (bank->size <= (1UL << 16)) LOG_WARNING("device needs 2-byte addresses - not implemented"); - if (bank->size > (1UL << 24)) - LOG_WARNING("device needs paging or 4-byte addresses - not implemented"); /* if no sectors, treat whole bank as single sector */ sectorsize = fespi_info->dev->sectorsize ? @@ -990,12 +800,12 @@ static int fespi_probe(struct flash_bank *bank) /* create and fill sectors array */ bank->num_sectors = fespi_info->dev->size_in_bytes / sectorsize; sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); - if (sectors == NULL) { + if (!sectors) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } - for (int sector = 0; sector < bank->num_sectors; sector++) { + for (unsigned int sector = 0; sector < bank->num_sectors; sector++) { sectors[sector].offset = sector * sectorsize; sectors[sector].size = sectorsize; sectors[sector].is_erased = -1; @@ -1003,7 +813,7 @@ static int fespi_probe(struct flash_bank *bank) } bank->sectors = sectors; - fespi_info->probed = 1; + fespi_info->probed = true; return ERROR_OK; } @@ -1021,24 +831,23 @@ static int fespi_protect_check(struct flash_bank *bank) return ERROR_OK; } -static int get_fespi_info(struct flash_bank *bank, char *buf, int buf_size) +static int get_fespi_info(struct flash_bank *bank, struct command_invocation *cmd) { struct fespi_flash_bank *fespi_info = bank->driver_priv; if (!(fespi_info->probed)) { - snprintf(buf, buf_size, - "\nFESPI flash bank not probed yet\n"); + command_print_sameline(cmd, "\nFESPI flash bank not probed yet\n"); return ERROR_OK; } - snprintf(buf, buf_size, "\nFESPI flash information:\n" + command_print_sameline(cmd, "\nFESPI flash information:\n" " Device \'%s\' (ID 0x%08" PRIx32 ")\n", fespi_info->dev->name, fespi_info->dev->device_id); return ERROR_OK; } -struct flash_driver fespi_flash = { +const struct flash_driver fespi_flash = { .name = "fespi", .flash_bank_command = fespi_flash_bank_command, .erase = fespi_erase,