#endif
#include "imp.h"
+#include <helper/binarybuffer.h>
#include <helper/bits.h>
#include <helper/time_support.h>
#include <target/algorithm.h>
#undef SPIFLASH_READ
#undef SPIFLASH_PAGE_PROGRAM
-#define READ_REG(a) \
-({ \
- uint32_t _result; \
- \
- retval = target_read_u32(target, io_base + (a), &_result); \
- (retval == ERROR_OK) ? _result : 0x0; \
-})
-
/* saved mode settings */
#define QSPI_MODE (stmqspi_info->saved_ccr & \
(0xF0000000U | QSPI_DCYC_MASK | QSPI_4LINE_MODE | QSPI_ALTB_MODE | QSPI_ADDR4))
#define OPI_CMD(cmd) ((OPI_MODE ? ((((uint16_t)(cmd)) << 8) | (~(cmd) & 0xFFU)) : (cmd)))
-#define OCTOSPI_CMD(mode, ccr, ir) \
-({ \
- retval = target_write_u32(target, io_base + OCTOSPI_CR, \
- OCTOSPI_MODE | (mode)); \
- if (retval == ERROR_OK) \
- retval = target_write_u32(target, io_base + OCTOSPI_TCR, \
- (stmqspi_info->saved_tcr & ~OCTOSPI_DCYC_MASK) | \
- ((OPI_MODE && ((mode) == OCTOSPI_READ_MODE)) ? \
- (OPI_DUMMY << OCTOSPI_DCYC_POS) : 0)); \
- if (retval == ERROR_OK) \
- retval = target_write_u32(target, io_base + OCTOSPI_CCR, ccr); \
- if (retval == ERROR_OK) \
- retval = target_write_u32(target, io_base + OCTOSPI_IR, \
- OPI_CMD(ir)); \
- retval; \
-})
-
/* convert uint32_t into 4 uint8_t in little endian byte order */
static inline uint32_t h_to_le_32(uint32_t val)
{
bool octo;
struct flash_device dev;
uint32_t io_base;
- uint32_t saved_cr; /* in particalar FSEL, DFM bit mask in QUADSPI_CR *AND* OCTOSPI_CR */
+ uint32_t saved_cr; /* in particular FSEL, DFM bit mask in QUADSPI_CR *AND* OCTOSPI_CR */
uint32_t saved_ccr; /* different meaning for QUADSPI and OCTOSPI */
uint32_t saved_tcr; /* only for OCTOSPI */
uint32_t saved_ir; /* only for OCTOSPI */
unsigned int sfdp_dummy2; /* number of dummy bytes for SFDP read for flash2 */
};
+static inline int octospi_cmd(struct flash_bank *bank, uint32_t mode,
+ uint32_t ccr, uint32_t ir)
+{
+ struct target *target = bank->target;
+ const struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
+ const uint32_t io_base = stmqspi_info->io_base;
+
+ int retval = target_write_u32(target, io_base + OCTOSPI_CR,
+ OCTOSPI_MODE | mode);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, io_base + OCTOSPI_TCR,
+ (stmqspi_info->saved_tcr & ~OCTOSPI_DCYC_MASK) |
+ ((OPI_MODE && (mode == OCTOSPI_READ_MODE)) ?
+ (OPI_DUMMY << OCTOSPI_DCYC_POS) : 0));
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = target_write_u32(target, io_base + OCTOSPI_CCR, ccr);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ return target_write_u32(target, io_base + OCTOSPI_IR, OPI_CMD(ir));
+}
+
FLASH_BANK_COMMAND_HANDLER(stmqspi_flash_bank_command)
{
struct stmqspi_flash_bank *stmqspi_info;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], io_base);
stmqspi_info = malloc(sizeof(struct stmqspi_flash_bank));
- if (stmqspi_info == NULL) {
+ if (!stmqspi_info) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
uint32_t io_base = stmqspi_info->io_base;
- uint32_t spi_sr;
- int retval;
long long endtime;
endtime = timeval_ms() + timeout;
do {
- spi_sr = READ_REG(SPI_SR);
- if ((spi_sr & BIT(SPI_BUSY)) == 0) {
- if (retval == ERROR_OK) {
- /* Clear transmit finished flag */
- retval = target_write_u32(target, io_base + SPI_FCR, BIT(SPI_TCF));
- }
+ uint32_t spi_sr;
+ int retval = target_read_u32(target, io_base + SPI_SR, &spi_sr);
+
+ if (retval != ERROR_OK)
return retval;
+
+ if ((spi_sr & BIT(SPI_BUSY)) == 0) {
+ /* Clear transmit finished flag */
+ return target_write_u32(target, io_base + SPI_FCR, BIT(SPI_TCF));
} else
LOG_DEBUG("busy: 0x%08X", spi_sr);
alive_sleep(1);
return ERROR_FLASH_OPERATION_FAILED;
}
+static int stmqspi_abort(struct flash_bank *bank)
+{
+ struct target *target = bank->target;
+ const struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
+ const uint32_t io_base = stmqspi_info->io_base;
+ uint32_t cr;
+
+ int retval = target_read_u32(target, io_base + SPI_CR, &cr);
+
+ if (retval != ERROR_OK)
+ cr = 0;
+
+ return target_write_u32(target, io_base + SPI_CR, cr | BIT(SPI_ABORT));
+}
+
/* Set to memory-mapped mode, e.g. after an error */
static int set_mm_mode(struct flash_bank *bank)
{
return retval;
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
int count, retval;
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
/* Read status */
if (IS_OCTOSPI) {
- retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_STATUS, SPIFLASH_READ_STATUS);
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_STATUS,
+ SPIFLASH_READ_STATUS);
if (OPI_MODE) {
/* Dummy address 0, only required for 8-line mode */
retval = target_write_u32(target, io_base + SPI_AR, 0);
*status = 0;
/* for debugging only */
- (void)READ_REG(SPI_SR);
+ uint32_t dummy;
+ (void)target_read_u32(target, io_base + SPI_SR, &dummy);
for ( ; count > 0; --count) {
if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH)))
int retval;
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
/* Send write enable command */
if (IS_OCTOSPI) {
- retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE, OCTOSPI_CCR_WRITE_ENABLE, SPIFLASH_WRITE_ENABLE);
+ retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE, OCTOSPI_CCR_WRITE_ENABLE,
+ SPIFLASH_WRITE_ENABLE);
if (OPI_MODE) {
/* Dummy address 0, only required for 8-line mode */
retval = target_write_u32(target, io_base + SPI_AR, 0);
return ERROR_COMMAND_SYNTAX_ERROR;
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
stmqspi_info = bank->driver_priv;
/* Send Mass Erase command */
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE, OCTOSPI_CCR_MASS_ERASE,
+ retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE, OCTOSPI_CCR_MASS_ERASE,
stmqspi_info->dev.chip_erase_cmd);
else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_MASS_ERASE);
retval = wait_till_ready(bank, SPI_MASS_ERASE_TIMEOUT);
duration_measure(&bench);
- if (retval == ERROR_OK) {
- /* set all sectors as erased */
- for (sector = 0; sector < bank->num_sectors; sector++)
- bank->sectors[sector].is_erased = 1;
-
+ if (retval == ERROR_OK)
command_print(CMD, "stmqspi mass erase completed in %fs (%0.3f KiB/s)",
duration_elapsed(&bench),
duration_kbps(&bench, bank->size));
- } else {
+ else
command_print(CMD, "stmqspi mass erase not completed even after %fs",
duration_elapsed(&bench));
- }
err:
/* Switch to memory mapped mode before return to prompt */
return ERROR_COMMAND_SYNTAX_ERROR;
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, index++, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
target = bank->target;
bank->size = stmqspi_info->dev.size_in_bytes << dual;
io_base = stmqspi_info->io_base;
- fsize = (READ_REG(SPI_DCR) >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
+
+ uint32_t dcr;
+ retval = target_read_u32(target, io_base + SPI_DCR, &dcr);
+
if (retval != ERROR_OK)
return retval;
+ fsize = (dcr >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
+
LOG_DEBUG("FSIZE = 0x%04x", fsize);
if (bank->size == BIT(fsize + 1))
LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1.");
bank->num_sectors =
stmqspi_info->dev.size_in_bytes / stmqspi_info->dev.sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- if (sectors == NULL) {
+ if (!sectors) {
LOG_ERROR("not enough memory");
return ERROR_FAIL;
}
}
retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
- if (ERROR_OK != retval)
+ if (retval != ERROR_OK)
return retval;
target = bank->target;
}
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
goto err;
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE,
+ retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE,
(OCTOSPI_MODE_CCR & OCTOSPI_NO_ALTB & OCTOSPI_NO_ADDR &
((num_write == 1) ? OCTOSPI_NO_DATA : ~0U)), cmd_byte);
else
if (retval != ERROR_OK)
goto err;
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_READ_MODE,
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
(OCTOSPI_MODE_CCR & OCTOSPI_NO_DDTR & OCTOSPI_NO_ALTB & ~OCTOSPI_ADDR4 &
((num_write == 1) ? OCTOSPI_NO_ADDR : ~0U)) |
(((num_write - 2) & 0x3U) << SPI_ADSIZE_POS), cmd_byte);
/* Send Sector Erase command */
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_WRITE_MODE, OCTOSPI_CCR_SECTOR_ERASE,
+ retval = octospi_cmd(bank, OCTOSPI_WRITE_MODE, OCTOSPI_CCR_SECTOR_ERASE,
stmqspi_info->dev.erase_cmd);
else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_SECTOR_ERASE);
{
struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
- uint32_t io_base = stmqspi_info->io_base;
struct duration bench;
struct reg_param reg_params[2];
struct armv7m_algorithm armv7m_info;
}
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
{
struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
- uint32_t io_base = stmqspi_info->io_base;
int retval;
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
}
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
{
struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
- uint32_t io_base = stmqspi_info->io_base;
unsigned int dual, sector;
bool octal_dtr;
int retval;
}
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
{
struct target *target = bank->target;
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
- uint32_t io_base = stmqspi_info->io_base;
unsigned int dual;
bool octal_dtr;
int retval;
}
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
/* Read SFDP block */
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_SFDP(len),
- SPIFLASH_READ_SFDP);
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
+ OCTOSPI_CCR_READ_SFDP(len), SPIFLASH_READ_SFDP);
else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP);
if (retval != ERROR_OK)
err:
/* Abort operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
return retval;
}
/* Read SFDP block */
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_SFDP(len),
- SPIFLASH_READ_SFDP);
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
+ OCTOSPI_CCR_READ_SFDP(len), SPIFLASH_READ_SFDP);
else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_SFDP);
if (retval != ERROR_OK)
/* SPIFLASH_READ_MID causes device in octal mode to go berserk, so don't use in this case */
for (type = (IS_OCTOSPI && OPI_MODE) ? 1 : 0; type < 2 ; type++) {
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
goto err;
switch (type) {
case 0:
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_MID, SPIFLASH_READ_MID);
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
+ OCTOSPI_CCR_READ_MID, SPIFLASH_READ_MID);
else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_MID);
break;
case 1:
if (IS_OCTOSPI)
- retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, OCTOSPI_CCR_READ_ID, SPIFLASH_READ_ID);
+ retval = octospi_cmd(bank, OCTOSPI_READ_MODE,
+ OCTOSPI_CCR_READ_ID, SPIFLASH_READ_ID);
else
retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_READ_ID);
break;
}
/* for debugging only */
- (void)READ_REG(SPI_SR);
+ uint32_t dummy;
+ (void)target_read_u32(target, io_base + SPI_SR, &dummy);
/* Read ID from Data Register */
for (len1 = 0, len2 = 0; count > 0; --count) {
}
/* Abort any previous operation */
- retval = target_write_u32(target, io_base + SPI_CR,
- READ_REG(SPI_CR) | BIT(SPI_ABORT));
+ retval = stmqspi_abort(bank);
if (retval != ERROR_OK)
return retval;
if (data == magic) {
LOG_DEBUG("QSPI_ABR register present");
stmqspi_info->octo = false;
- } else if (READ_REG(OCTOSPI_MAGIC) == OCTO_MAGIC_ID) {
- LOG_DEBUG("OCTOSPI_MAGIC present");
- stmqspi_info->octo = true;
} else {
- LOG_ERROR("No QSPI, no OCTOSPI at 0x%08" PRIx32, io_base);
- stmqspi_info->probed = false;
- stmqspi_info->dev.name = "none";
- return ERROR_FAIL;
+ uint32_t magic_id;
+
+ retval = target_read_u32(target, io_base + OCTOSPI_MAGIC, &magic_id);
+
+ if (retval == ERROR_OK && magic_id == OCTO_MAGIC_ID) {
+ LOG_DEBUG("OCTOSPI_MAGIC present");
+ stmqspi_info->octo = true;
+ } else {
+ LOG_ERROR("No QSPI, no OCTOSPI at 0x%08" PRIx32, io_base);
+ stmqspi_info->probed = false;
+ stmqspi_info->dev.name = "none";
+ return ERROR_FAIL;
+ }
}
/* save current FSEL and DFM bits in QSPI/OCTOSPI_CR, current QSPI/OCTOSPI_CCR value */
- stmqspi_info->saved_cr = READ_REG(SPI_CR);
+ retval = target_read_u32(target, io_base + SPI_CR, &stmqspi_info->saved_cr);
if (retval == ERROR_OK)
- stmqspi_info->saved_ccr = READ_REG(SPI_CCR);
+ retval = target_read_u32(target, io_base + SPI_CCR, &stmqspi_info->saved_ccr);
if (IS_OCTOSPI) {
- uint32_t mtyp;
+ uint32_t dcr1;
+
+ retval = target_read_u32(target, io_base + OCTOSPI_DCR1, &dcr1);
- mtyp = ((READ_REG(OCTOSPI_DCR1) & OCTOSPI_MTYP_MASK)) >> OCTOSPI_MTYP_POS;
if (retval == ERROR_OK)
- stmqspi_info->saved_tcr = READ_REG(OCTOSPI_TCR);
+ retval = target_read_u32(target, io_base + OCTOSPI_TCR,
+ &stmqspi_info->saved_tcr);
+
if (retval == ERROR_OK)
- stmqspi_info->saved_ir = READ_REG(OCTOSPI_IR);
+ retval = target_read_u32(target, io_base + OCTOSPI_IR,
+ &stmqspi_info->saved_ir);
+
+ if (retval != ERROR_OK) {
+ LOG_ERROR("No OCTOSPI at io_base 0x%08" PRIx32, io_base);
+ stmqspi_info->probed = false;
+ stmqspi_info->dev.name = "none";
+ return ERROR_FAIL;
+ }
+
+ const uint32_t mtyp = (dcr1 & OCTOSPI_MTYP_MASK) >> OCTOSPI_MTYP_POS;
+
if ((mtyp != 0x0) && (mtyp != 0x1)) {
- retval = ERROR_FAIL;
LOG_ERROR("Only regular SPI protocol supported in OCTOSPI");
- }
- if (retval == ERROR_OK) {
- LOG_DEBUG("OCTOSPI at 0x%08" PRIx64 ", io_base at 0x%08" PRIx32 ", OCTOSPI_CR 0x%08"
- PRIx32 ", OCTOSPI_CCR 0x%08" PRIx32 ", %d-byte addr", bank->base, io_base,
- stmqspi_info->saved_cr, stmqspi_info->saved_ccr, SPI_ADSIZE);
- } else {
- LOG_ERROR("No OCTOSPI at io_base 0x%08" PRIx32, io_base);
stmqspi_info->probed = false;
stmqspi_info->dev.name = "none";
return ERROR_FAIL;
}
+
+ LOG_DEBUG("OCTOSPI at 0x%08" PRIx64 ", io_base at 0x%08" PRIx32 ", OCTOSPI_CR 0x%08"
+ PRIx32 ", OCTOSPI_CCR 0x%08" PRIx32 ", %d-byte addr", bank->base, io_base,
+ stmqspi_info->saved_cr, stmqspi_info->saved_ccr, SPI_ADSIZE);
} else {
if (retval == ERROR_OK) {
LOG_DEBUG("QSPI at 0x%08" PRIx64 ", io_base at 0x%08" PRIx32 ", QSPI_CR 0x%08"
/* Set correct size value */
bank->size = stmqspi_info->dev.size_in_bytes << dual;
- fsize = ((READ_REG(SPI_DCR) >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1));
+ uint32_t dcr;
+ retval = target_read_u32(target, io_base + SPI_DCR, &dcr);
+
if (retval != ERROR_OK)
goto err;
+ fsize = (dcr >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1);
+
LOG_DEBUG("FSIZE = 0x%04x", fsize);
if (bank->size == BIT((fsize + 1)))
LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1.");
/* create and fill sectors array */
bank->num_sectors = stmqspi_info->dev.size_in_bytes / stmqspi_info->dev.sectorsize;
sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
- if (sectors == NULL) {
+ if (!sectors) {
LOG_ERROR("not enough memory");
retval = ERROR_FAIL;
goto err;
return ERROR_OK;
}
-static int get_stmqspi_info(struct flash_bank *bank, char *buf, int buf_size)
+static int get_stmqspi_info(struct flash_bank *bank, struct command_invocation *cmd)
{
struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv;
if (!(stmqspi_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_FLASH_BANK_NOT_PROBED;
}
- snprintf(buf, buf_size, "flash%s%s \'%s\', device id = 0x%06" PRIx32
+ command_print_sameline(cmd, "flash%s%s \'%s\', device id = 0x%06" PRIx32
", flash size = %" PRIu32 "%sbytes\n(page size = %" PRIu32
", read = 0x%02" PRIx8 ", qread = 0x%02" PRIx8
", pprog = 0x%02" PRIx8 ", mass_erase = 0x%02" PRIx8