drivers: flash: stm32l5: use write-block-size when writing

STM32L5 have a write block size of 8, but STM32U5 and STM32H5 have a
write block size of 16. Convert write_dword() and
flash_stm32_write_range() to write write-block-size data at a time.

Fixes #60724

Signed-off-by: Florian Vaussard <florian.vaussard@gmail.com>
This commit is contained in:
Florian Vaussard 2023-07-25 22:47:16 +02:00 committed by Fabio Baltieri
commit 4c9e42925e

View file

@ -155,13 +155,15 @@ bool flash_stm32_valid_range(const struct device *dev, off_t offset,
return flash_stm32_range_exists(dev, offset, len);
}
static int write_dword(const struct device *dev, off_t offset, uint64_t val)
static int write_nwords(const struct device *dev, off_t offset, const uint32_t *buff, size_t n)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
volatile uint32_t *flash = (uint32_t *)(offset
+ CONFIG_FLASH_BASE_ADDRESS);
bool full_zero = true;
uint32_t tmp;
int rc;
int i;
/* if the non-secure control register is locked,do not fail silently */
if (regs->NSCR & FLASH_STM32_NSLOCK) {
@ -175,16 +177,26 @@ static int write_dword(const struct device *dev, off_t offset, uint64_t val)
return rc;
}
/* Check if this double word is erased and value isn't 0.
/* Check if this double/quad word is erased and value isn't 0.
*
* It is allowed to write only zeros over an already written dword
* It is allowed to write only zeros over an already written dword / qword
* See 6.3.7 in STM32L5 reference manual.
* See 7.3.7 in STM32U5 reference manual.
* See 7.3.5 in STM32H5 reference manual.
*/
if ((flash[0] != 0xFFFFFFFFUL ||
flash[1] != 0xFFFFFFFFUL) && val != 0UL) {
LOG_ERR("Word at offs %ld not erased", (long)offset);
return -EIO;
for (i = 0; i < n; i++) {
if (buff[i] != 0) {
full_zero = false;
break;
}
}
if (!full_zero) {
for (i = 0; i < n; i++) {
if (flash[i] != 0xFFFFFFFFUL) {
LOG_ERR("Word at offs %ld not erased", (long)(offset + i));
return -EIO;
}
}
}
/* Set the NSPG bit */
@ -194,8 +206,9 @@ static int write_dword(const struct device *dev, off_t offset, uint64_t val)
tmp = regs->NSCR;
/* Perform the data write operation at the desired memory address */
flash[0] = (uint32_t)val;
flash[1] = (uint32_t)(val >> 32);
for (i = 0; i < n; i++) {
flash[i] = buff[i];
}
/* Wait until the NSBSY bit is cleared */
rc = flash_stm32_wait_flash_idle(dev);
@ -343,8 +356,9 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
}
}
for (i = 0; i < len; i += 8, offset += 8) {
rc = write_dword(dev, offset, ((const uint64_t *) data)[i>>3]);
for (i = 0; i < len; i += FLASH_STM32_WRITE_BLOCK_SIZE) {
rc = write_nwords(dev, offset + i, ((const uint32_t *) data + (i>>2)),
FLASH_STM32_WRITE_BLOCK_SIZE / 4);
if (rc < 0) {
break;
}