#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)
{
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;
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);
/* 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);
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.");
}
/* 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.");