X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fmrvlqspi.c;h=a752f0943c6e493b9a9671870b00cee4e3e1f648;hp=a5cc1ca025c3077e9b1ab05f1eeaec329fbe4ae7;hb=HEAD;hpb=447fb25324f1e9112523ef78825f8dadf3c7ddb7 diff --git a/src/flash/nor/mrvlqspi.c b/src/flash/nor/mrvlqspi.c index a5cc1ca025..4eb6522bea 100644 --- a/src/flash/nor/mrvlqspi.c +++ b/src/flash/nor/mrvlqspi.c @@ -1,21 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + /*************************************************************************** * Copyright (C) 2014 by Mahavir Jain * - * * - * 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, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * * ***************************************************************************/ /* @@ -40,7 +26,7 @@ #define QSPI_W_EN (0x1) #define QSPI_SS_DISABLE (0x0) #define QSPI_SS_ENABLE (0x1) -#define WRITE_DISBALE (0x0) +#define WRITE_DISABLE (0x0) #define WRITE_ENABLE (0x1) #define QSPI_TIMEOUT (1000) @@ -76,7 +62,7 @@ #define DINCNT 0x20 struct mrvlqspi_flash_bank { - int probed; + bool probed; uint32_t reg_base; uint32_t bank_num; const struct flash_device *dev; @@ -161,7 +147,7 @@ static int mrvlqspi_set_ss_state(struct flash_bank *bank, bool state, int timeou mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; - LOG_DEBUG("status: 0x%x", regval); + LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & XFER_RDY) == XFER_RDY) break; if (timeout-- <= 0) { @@ -216,7 +202,7 @@ static int mrvlqspi_stop_transfer(struct flash_bank *bank) mrvlqspi_get_reg(bank, CNTL), ®val); if (retval != ERROR_OK) return retval; - LOG_DEBUG("status: 0x%x", regval); + LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & (XFER_RDY | WFIFO_EMPTY)) == (XFER_RDY | WFIFO_EMPTY)) break; @@ -245,7 +231,7 @@ static int mrvlqspi_stop_transfer(struct flash_bank *bank) mrvlqspi_get_reg(bank, CONF), ®val); if (retval != ERROR_OK) return retval; - LOG_DEBUG("status: 0x%x", regval); + LOG_DEBUG("status: 0x%08" PRIx32, regval); if ((regval & XFER_START) == 0) break; if (timeout-- <= 0) { @@ -286,7 +272,7 @@ static int mrvlqspi_fifo_flush(struct flash_bank *bank, int timeout) mrvlqspi_get_reg(bank, CONF), &val); if (retval != ERROR_OK) return retval; - LOG_DEBUG("status: 0x%x", val); + LOG_DEBUG("status: 0x%08" PRIX32, val); if ((val & FIFO_FLUSH) == 0) break; if (timeout-- <= 0) { @@ -310,7 +296,7 @@ static int mrvlqspi_read_byte(struct flash_bank *bank, uint8_t *data) mrvlqspi_get_reg(bank, CNTL), &val); if (retval != ERROR_OK) return retval; - LOG_DEBUG("status: 0x%x", val); + LOG_DEBUG("status: 0x%08" PRIx32, val); if ((val & RFIFO_EMPTY) == 0) break; usleep(10); @@ -331,7 +317,7 @@ static int mrvlqspi_flash_busy_status(struct flash_bank *bank, int timeout) uint8_t val; int retval; - /* Flush read/write fifo's */ + /* Flush read/write fifos */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; @@ -382,7 +368,7 @@ static int mrvlqspi_set_write_status(struct flash_bank *bank, bool mode) int retval; uint32_t instr; - /* Flush read/write fifo's */ + /* Flush read/write fifos */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; @@ -420,7 +406,7 @@ static int mrvlqspi_read_id(struct flash_bank *bank, uint32_t *id) LOG_DEBUG("Getting ID"); - /* Flush read/write fifo's */ + /* Flush read/write fifos */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; @@ -455,7 +441,8 @@ static int mrvlqspi_read_id(struct flash_bank *bank, uint32_t *id) return retval; } - LOG_DEBUG("ID is 0x%x 0x%x 0x%x", id_buf[0], id_buf[1], id_buf[2]); + LOG_DEBUG("ID is 0x%02" PRIx8 " 0x%02" PRIx8 " 0x%02" PRIx8, + id_buf[0], id_buf[1], id_buf[2]); retval = mrvlqspi_set_ss_state(bank, QSPI_SS_DISABLE, QSPI_TIMEOUT); if (retval != ERROR_OK) return retval; @@ -505,6 +492,9 @@ static int mrvlqspi_bulk_erase(struct flash_bank *bank) int retval; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; + if (mrvlqspi_info->dev->chip_erase_cmd == 0x00) + return ERROR_FLASH_OPER_UNSUPPORTED; + /* Set flash write enable */ retval = mrvlqspi_set_write_status(bank, WRITE_ENABLE); if (retval != ERROR_OK) @@ -526,21 +516,21 @@ static int mrvlqspi_bulk_erase(struct flash_bank *bank) return mrvlqspi_flash_busy_status(bank, CHIP_ERASE_TIMEOUT); } -static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last) +static int mrvlqspi_flash_erase(struct flash_bank *bank, unsigned int first, + unsigned int last) { struct target *target = bank->target; struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; int retval = ERROR_OK; - int sector; - LOG_DEBUG("erase from sector %d to sector %d", first, last); + LOG_DEBUG("erase from sector %u to sector %u", 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; } @@ -550,9 +540,9 @@ static int mrvlqspi_flash_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; } } @@ -562,7 +552,7 @@ static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last) if (first == 0 && last == (bank->num_sectors - 1) && mrvlqspi_info->dev->chip_erase_cmd != mrvlqspi_info->dev->erase_cmd) { - LOG_DEBUG("Chip supports the bulk erase command."\ + LOG_DEBUG("Chip supports the bulk erase command." " Will use bulk erase instead of sector-by-sector erase."); retval = mrvlqspi_bulk_erase(bank); if (retval == ERROR_OK) { @@ -572,7 +562,10 @@ static int mrvlqspi_flash_erase(struct flash_bank *bank, int first, int last) " Falling back to sector-by-sector erase."); } - for (sector = first; sector <= last; sector++) { + if (mrvlqspi_info->dev->erase_cmd == 0x00) + return ERROR_FLASH_OPER_UNSUPPORTED; + + for (unsigned int sector = first; sector <= last; sector++) { retval = mrvlqspi_block_erase(bank, sector * mrvlqspi_info->dev->sectorsize); if (retval != ERROR_OK) @@ -593,7 +586,6 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, struct reg_param reg_params[6]; struct armv7m_algorithm armv7m_info; struct working_area *write_algorithm; - int sector; LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32, offset, count); @@ -609,19 +601,21 @@ static int mrvlqspi_flash_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; } } - page_size = mrvlqspi_info->dev->pagesize; + /* if no valid page_size, use reasonable default */ + page_size = mrvlqspi_info->dev->pagesize ? + mrvlqspi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE; /* See contrib/loaders/flash/mrvlqspi.S for src */ static const uint8_t mrvlqspi_flash_write_code[] = { @@ -675,11 +669,11 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, if (target_alloc_working_area(target, sizeof(mrvlqspi_flash_write_code), &write_algorithm) != ERROR_OK) { - LOG_ERROR("Insufficient working area. You must configure"\ + LOG_ERROR("Insufficient working area. You must configure" " a working area > %zdB in order to write to SPIFI flash.", sizeof(mrvlqspi_flash_write_code)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(mrvlqspi_flash_write_code), @@ -697,15 +691,15 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, * space, free the algorithm */ target_free_working_area(target, write_algorithm); - LOG_ERROR("Insufficient working area. Please allocate at least"\ + LOG_ERROR("Insufficient working area. Please allocate at least" " %zdB of working area to enable flash writes.", sizeof(mrvlqspi_flash_write_code) + 1 ); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } else if (fifo_size < page_size) - LOG_WARNING("Working area size is limited; flash writes may be"\ - " slow. Increase working area size to at least %zdB"\ + LOG_WARNING("Working area size is limited; flash writes may be" + " slow. Increase working area size to at least %zdB" " to reduce write times.", (size_t)(sizeof(mrvlqspi_flash_write_code) + page_size) ); @@ -713,7 +707,7 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) { target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; @@ -756,7 +750,7 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, return retval; } -int mrvlqspi_flash_read(struct flash_bank *bank, uint8_t *buffer, +static int mrvlqspi_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { struct target *target = bank->target; @@ -774,7 +768,7 @@ int mrvlqspi_flash_read(struct flash_bank *bank, uint8_t *buffer, return ERROR_FLASH_BANK_NOT_PROBED; } - /* Flush read/write fifo's */ + /* Flush read/write fifos */ retval = mrvlqspi_fifo_flush(bank, FIFO_FLUSH_TIMEOUT); if (retval != ERROR_OK) return retval; @@ -828,6 +822,7 @@ static int mrvlqspi_probe(struct flash_bank *bank) uint32_t id = 0; int retval; struct flash_sector *sectors; + uint32_t sectorsize; /* If we've already probed, we should be fine to skip this time. */ if (mrvlqspi_info->probed) @@ -838,7 +833,7 @@ static int mrvlqspi_probe(struct flash_bank *bank) return ERROR_TARGET_NOT_HALTED; } - mrvlqspi_info->probed = 0; + mrvlqspi_info->probed = false; mrvlqspi_info->bank_num = bank->bank_number; /* Read flash JEDEC ID */ @@ -854,35 +849,42 @@ static int mrvlqspi_probe(struct flash_bank *bank) } if (!mrvlqspi_info->dev) { - LOG_ERROR("Unknown flash device ID 0x%08x", id); + LOG_ERROR("Unknown flash device ID 0x%08" PRIx32, id); return ERROR_FAIL; } - LOG_INFO("Found flash device \'%s\' ID 0x%08x", + LOG_INFO("Found flash device \'%s\' ID 0x%08" PRIx32, mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id); + /* Set correct size value */ bank->size = mrvlqspi_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 = mrvlqspi_info->dev->sectorsize ? + mrvlqspi_info->dev->sectorsize : mrvlqspi_info->dev->size_in_bytes; /* create and fill sectors array */ - bank->num_sectors = mrvlqspi_info->dev->size_in_bytes / - mrvlqspi_info->dev->sectorsize; + bank->num_sectors = mrvlqspi_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 * mrvlqspi_info->dev->sectorsize; - sectors[sector].size = mrvlqspi_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; - mrvlqspi_info->probed = 1; + mrvlqspi_info->probed = true; return ERROR_OK; } @@ -901,24 +903,17 @@ static int mrvlqspi_flash_erase_check(struct flash_bank *bank) return ERROR_OK; } -static int mrvlqspi_protect_check(struct flash_bank *bank) -{ - /* Not implemented yet */ - return ERROR_OK; -} - -int mrvlqspi_get_info(struct flash_bank *bank, char *buf, int buf_size) +static int mrvlqspi_get_info(struct flash_bank *bank, struct command_invocation *cmd) { struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv; if (!(mrvlqspi_info->probed)) { - snprintf(buf, buf_size, - "\nQSPI flash bank not probed yet\n"); + command_print_sameline(cmd, "\nQSPI flash bank not probed yet\n"); return ERROR_OK; } - snprintf(buf, buf_size, "\nQSPI flash information:\n" - " Device \'%s\' ID 0x%08x\n", + command_print_sameline(cmd, "\nQSPI flash information:\n" + " Device \'%s\' ID 0x%08" PRIx32 "\n", mrvlqspi_info->dev->name, mrvlqspi_info->dev->device_id); return ERROR_OK; @@ -932,7 +927,7 @@ FLASH_BANK_COMMAND_HANDLER(mrvlqspi_flash_bank_command) return ERROR_COMMAND_SYNTAX_ERROR; mrvlqspi_info = malloc(sizeof(struct mrvlqspi_flash_bank)); - if (mrvlqspi_info == NULL) { + if (!mrvlqspi_info) { LOG_ERROR("not enough memory"); return ERROR_FAIL; } @@ -940,21 +935,20 @@ FLASH_BANK_COMMAND_HANDLER(mrvlqspi_flash_bank_command) /* Get QSPI controller register map base address */ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], mrvlqspi_info->reg_base); bank->driver_priv = mrvlqspi_info; - mrvlqspi_info->probed = 0; + mrvlqspi_info->probed = false; return ERROR_OK; } -struct flash_driver mrvlqspi_flash = { +const struct flash_driver mrvlqspi_flash = { .name = "mrvlqspi", .flash_bank_command = mrvlqspi_flash_bank_command, .erase = mrvlqspi_flash_erase, - .protect = NULL, .write = mrvlqspi_flash_write, .read = mrvlqspi_flash_read, .probe = mrvlqspi_probe, .auto_probe = mrvlqspi_auto_probe, .erase_check = mrvlqspi_flash_erase_check, - .protect_check = mrvlqspi_protect_check, .info = mrvlqspi_get_info, + .free_driver_priv = default_flash_free_driver_priv, };