* 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. *
- * *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
/*
#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)
#define DINCNT 0x20
struct mrvlqspi_flash_bank {
- int probed;
+ bool probed;
uint32_t reg_base;
uint32_t bank_num;
const struct flash_device *dev;
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) {
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;
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) {
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) {
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);
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;
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;
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;
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;
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)
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;
}
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;
}
}
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) {
" 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)
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);
}
/* 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[] = {
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),
* 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)
);
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;
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;
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;
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)
return ERROR_TARGET_NOT_HALTED;
}
- mrvlqspi_info->probed = 0;
+ mrvlqspi_info->probed = false;
mrvlqspi_info->bank_num = bank->bank_number;
/* Read flash JEDEC ID */
}
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;
}
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;
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;
}
/* 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,
};