struct jtagspi_flash_bank {
struct jtag_tap *tap;
const struct flash_device *dev;
- int probed;
+ bool probed;
uint32_t ir;
};
return ERROR_COMMAND_SYNTAX_ERROR;
info = malloc(sizeof(struct jtagspi_flash_bank));
- if (info == NULL) {
+ if (!info) {
LOG_ERROR("no memory for flash bank info");
return ERROR_FAIL;
}
bank->driver_priv = info;
info->tap = NULL;
- info->probed = 0;
+ info->probed = false;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], info->ir);
return ERROR_OK;
{
struct jtagspi_flash_bank *info = bank->driver_priv;
struct scan_field field;
- uint8_t buf[4];
+ uint8_t buf[4] = { 0 };
LOG_DEBUG("loading jtagspi ir");
buf_set_u32(buf, 0, info->tap->ir_length, info->ir);
lenb = DIV_ROUND_UP(len, 8);
data_buf = malloc(lenb);
if (lenb > 0) {
- if (data_buf == NULL) {
+ if (!data_buf) {
LOG_ERROR("no memory for spi buffer");
return ERROR_FAIL;
}
jtagspi_set_ir(bank);
/* passing from an IR scan to SHIFT-DR clears BYPASS registers */
jtag_add_dr_scan(info->tap, n, fields, TAP_IDLE);
- jtag_execute_queue();
+ int retval = jtag_execute_queue();
if (is_read)
flip_u8(data_buf, data, lenb);
free(data_buf);
- return ERROR_OK;
+ return retval;
}
static int jtagspi_probe(struct flash_bank *bank)
struct jtagspi_flash_bank *info = bank->driver_priv;
struct flash_sector *sectors;
uint8_t in_buf[3];
- uint32_t id;
+ uint32_t id, sectorsize;
if (info->probed)
free(bank->sectors);
- info->probed = 0;
+ info->probed = false;
- if (bank->target->tap == NULL) {
+ if (!bank->target->tap) {
LOG_ERROR("Target has no JTAG tap");
return ERROR_FAIL;
}
/* Set correct size value */
bank->size = info->dev->size_in_bytes;
+ 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 = info->dev->sectorsize ?
+ info->dev->sectorsize : info->dev->size_in_bytes;
/* create and fill sectors array */
- bank->num_sectors =
- info->dev->size_in_bytes / info->dev->sectorsize;
+ bank->num_sectors = 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++) {
- sectors[sector].offset = sector * info->dev->sectorsize;
- sectors[sector].size = info->dev->sectorsize;
+ for (unsigned int sector = 0; sector < bank->num_sectors; sector++) {
+ sectors[sector].offset = sector * sectorsize;
+ sectors[sector].size = sectorsize;
sectors[sector].is_erased = -1;
sectors[sector].is_protected = 0;
}
bank->sectors = sectors;
- info->probed = 1;
+ info->probed = true;
return ERROR_OK;
}
-static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
+static int jtagspi_read_status(struct flash_bank *bank, uint32_t *status)
{
uint8_t buf;
- if (jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8) == ERROR_OK) {
+ int err = jtagspi_cmd(bank, SPIFLASH_READ_STATUS, NULL, &buf, -8);
+ if (err == ERROR_OK) {
*status = buf;
/* LOG_DEBUG("status=0x%08" PRIx32, *status); */
}
+
+ return err;
}
static int jtagspi_wait(struct flash_bank *bank, int timeout_ms)
do {
dt = timeval_ms() - t0;
- jtagspi_read_status(bank, &status);
+
+ int retval = jtagspi_read_status(bank, &status);
+ if (retval != ERROR_OK)
+ return retval;
+
if ((status & SPIFLASH_BSY_BIT) == 0) {
LOG_DEBUG("waited %" PRId64 " ms", dt);
return ERROR_OK;
uint32_t status;
jtagspi_cmd(bank, SPIFLASH_WRITE_ENABLE, NULL, NULL, 0);
- jtagspi_read_status(bank, &status);
+
+ int retval = jtagspi_read_status(bank, &status);
+ if (retval != ERROR_OK)
+ return retval;
+
if ((status & SPIFLASH_WE_BIT) == 0) {
LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, status);
return ERROR_FAIL;
int retval;
int64_t t0 = timeval_ms();
+ if (info->dev->chip_erase_cmd == 0x00)
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+
retval = jtagspi_write_enable(bank);
if (retval != ERROR_OK)
return retval;
return retval;
}
-static int jtagspi_sector_erase(struct flash_bank *bank, int sector)
+static int jtagspi_sector_erase(struct flash_bank *bank, unsigned int sector)
{
struct jtagspi_flash_bank *info = bank->driver_priv;
int retval;
return retval;
jtagspi_cmd(bank, info->dev->erase_cmd, &bank->sectors[sector].offset, NULL, 0);
retval = jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT);
- LOG_INFO("sector %d took %" PRId64 " ms", sector, timeval_ms() - t0);
+ LOG_INFO("sector %u took %" PRId64 " ms", sector, timeval_ms() - t0);
return retval;
}
-static int jtagspi_erase(struct flash_bank *bank, int first, int last)
+static int jtagspi_erase(struct flash_bank *bank, unsigned int first,
+ unsigned int last)
{
- int sector;
struct jtagspi_flash_bank *info = bank->driver_priv;
int retval = ERROR_OK;
- LOG_DEBUG("erase from sector %d to sector %d", first, last);
+ LOG_DEBUG("erase from sector %u to sector %u", first, last);
- 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;
}
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;
}
}
LOG_WARNING("Bulk flash erase failed. Falling back to sector erase.");
}
- for (sector = first; sector <= last; sector++) {
+ if (info->dev->erase_cmd == 0x00)
+ return ERROR_FLASH_OPER_UNSUPPORTED;
+
+ for (unsigned int sector = first; sector <= last; sector++) {
retval = jtagspi_sector_erase(bank, sector);
if (retval != ERROR_OK) {
LOG_ERROR("Sector erase failed.");
return retval;
}
-static int jtagspi_protect(struct flash_bank *bank, int set, int first, int last)
+static int jtagspi_protect(struct flash_bank *bank, int set, unsigned int first,
+ unsigned int last)
{
- int sector;
-
- if ((first < 0) || (last < first) || (last >= bank->num_sectors)) {
- LOG_ERROR("Flash sector invalid");
- return ERROR_FLASH_SECTOR_INVALID;
- }
-
- for (sector = first; sector <= last; sector++)
+ for (unsigned int sector = first; sector <= last; sector++)
bank->sectors[sector].is_protected = set;
return ERROR_OK;
}
-static int jtagspi_protect_check(struct flash_bank *bank)
-{
- return ERROR_OK;
-}
-
static int jtagspi_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
{
struct jtagspi_flash_bank *info = bank->driver_priv;
{
struct jtagspi_flash_bank *info = bank->driver_priv;
int retval;
- uint32_t n;
+ uint32_t n, pagesize;
if (!(info->probed)) {
LOG_ERROR("Flash bank not yet probed.");
return ERROR_FLASH_BANK_NOT_PROBED;
}
- for (n = 0; n < count; n += info->dev->pagesize) {
+ /* if no write pagesize, use reasonable default */
+ pagesize = info->dev->pagesize ? info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
+
+ for (n = 0; n < count; n += pagesize) {
retval = jtagspi_page_write(bank, buffer + n, offset + n,
- MIN(count - n, info->dev->pagesize));
+ MIN(count - n, pagesize));
if (retval != ERROR_OK) {
LOG_ERROR("page write error");
return retval;
return ERROR_OK;
}
-static int jtagspi_info(struct flash_bank *bank, char *buf, int buf_size)
+static int jtagspi_info(struct flash_bank *bank, struct command_invocation *cmd)
{
struct jtagspi_flash_bank *info = bank->driver_priv;
if (!(info->probed)) {
- snprintf(buf, buf_size, "\nJTAGSPI flash bank not probed yet\n");
+ command_print_sameline(cmd, "\nJTAGSPI flash bank not probed yet\n");
return ERROR_OK;
}
- snprintf(buf, buf_size, "\nSPIFI flash information:\n"
+ command_print_sameline(cmd, "\nSPIFI flash information:\n"
" Device \'%s\' (ID 0x%08" PRIx32 ")\n",
info->dev->name, info->dev->device_id);
return ERROR_OK;
}
-struct flash_driver jtagspi_flash = {
+const struct flash_driver jtagspi_flash = {
.name = "jtagspi",
.flash_bank_command = jtagspi_flash_bank_command,
.erase = jtagspi_erase,
.probe = jtagspi_probe,
.auto_probe = jtagspi_probe,
.erase_check = default_flash_blank_check,
- .protect_check = jtagspi_protect_check,
.info = jtagspi_info,
.free_driver_priv = default_flash_free_driver_priv,
};