* 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 DINCNT 0x20
struct mrvlqspi_flash_bank {
- int probed;
+ bool probed;
uint32_t reg_base;
uint32_t bank_num;
const struct flash_device *dev;
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;
* 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)
);
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 */
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) {
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)
{
struct mrvlqspi_flash_bank *mrvlqspi_info = bank->driver_priv;
/* 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,
};