mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-28 02:35:28 +00:00
flash: Only erase flash block that contain data
It wastes time to erase blocks that are already erased and it is faster on stm32 to check first. Add a check in flash_physical_erase() on all chips, using a common flash_is_erased() function. BUG=none BRANCH=snow,link TEST=manual Do software sync in U-Boot and see that it succeeds. This tests that we can still erase and then boot a written image. It typically saves a second on a full sync over i2c. SMDK5250 # cros_test swsync -f SF: Detected W25Q32 with page size 4 KiB, total 4 MiB Flashing RW EC image: erasing, writing, done Flashing RO EC image: erasing, writing, done Full software sync completed in 22.949s SMDK5250 # Also see that second erase is faster: SMDK5250 # time mkbp erase rw time: 0.952 seconds, 952 ticks SMDK5250 # time mkbp erase rw time: 0.054 seconds, 54 ticks SMDK5250 # Change-Id: I3699577217fdbb2f212d20d150d3ca15fdff03eb Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/30851 Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
@@ -227,11 +227,17 @@ int flash_physical_write(int offset, int size, const char *data)
|
||||
int flash_physical_erase(int offset, int size)
|
||||
{
|
||||
LM4_FLASH_FCMISC = LM4_FLASH_FCRIS; /* Clear previous error status */
|
||||
LM4_FLASH_FMA = offset;
|
||||
|
||||
for ( ; size > 0; size -= CONFIG_FLASH_ERASE_SIZE) {
|
||||
for ( ; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
|
||||
offset += CONFIG_FLASH_ERASE_SIZE) {
|
||||
int t;
|
||||
|
||||
/* Do nothing if already erased */
|
||||
if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
|
||||
continue;
|
||||
|
||||
LM4_FLASH_FMA = offset;
|
||||
|
||||
#ifdef CONFIG_TASK_WATCHDOG
|
||||
/* Reload the watchdog timer, so that erasing many flash pages
|
||||
* doesn't cause a watchdog reset. May not need this now that
|
||||
@@ -253,8 +259,6 @@ int flash_physical_erase(int offset, int size)
|
||||
* protection error */
|
||||
if (LM4_FLASH_FCRIS & 0x0a01)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
LM4_FLASH_FMA += CONFIG_FLASH_ERASE_SIZE;
|
||||
}
|
||||
|
||||
return EC_SUCCESS;
|
||||
|
||||
@@ -349,7 +349,6 @@ exit_wr:
|
||||
|
||||
int flash_physical_erase(int offset, int size)
|
||||
{
|
||||
uint32_t address;
|
||||
int res = EC_SUCCESS;
|
||||
|
||||
if (unlock(PRG_LOCK) != EC_SUCCESS)
|
||||
@@ -361,13 +360,16 @@ int flash_physical_erase(int offset, int size)
|
||||
/* set PER bit */
|
||||
STM32_FLASH_CR |= PER;
|
||||
|
||||
for (address = CONFIG_FLASH_BASE + offset ;
|
||||
size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
|
||||
address += CONFIG_FLASH_ERASE_SIZE) {
|
||||
for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
|
||||
offset += CONFIG_FLASH_ERASE_SIZE) {
|
||||
timestamp_t deadline;
|
||||
|
||||
/* Do nothing if already erased */
|
||||
if (flash_is_erased(offset, CONFIG_FLASH_ERASE_SIZE))
|
||||
continue;
|
||||
|
||||
/* select page to erase */
|
||||
STM32_FLASH_AR = address;
|
||||
STM32_FLASH_AR = CONFIG_FLASH_BASE + offset;
|
||||
|
||||
/* set STRT bit : start erase */
|
||||
STM32_FLASH_CR |= STRT;
|
||||
|
||||
@@ -235,6 +235,12 @@ int flash_physical_erase(int offset, int size)
|
||||
address += CONFIG_FLASH_ERASE_SIZE / sizeof(uint32_t)) {
|
||||
timestamp_t deadline;
|
||||
|
||||
/*
|
||||
* crosbug.com/p/13066
|
||||
* We can't do the flash_is_erased() trick on stm32l since
|
||||
* bits erase to 0, not 1. Will address later if needed.
|
||||
*/
|
||||
|
||||
/* Start erase */
|
||||
*address = 0x00000000;
|
||||
|
||||
|
||||
@@ -26,6 +26,23 @@ int flash_dataptr(int offset, int size_req, int align, char **ptrp)
|
||||
return CONFIG_FLASH_SIZE - offset;
|
||||
}
|
||||
|
||||
/* crosbug.com/p/13066 - not supported on STM32L */
|
||||
#ifndef CHIP_VARIANT_stm32l15x
|
||||
int flash_is_erased(uint32_t offset, int size)
|
||||
{
|
||||
uint32_t *ptr;
|
||||
|
||||
if (flash_dataptr(offset, size, sizeof(uint32_t), (char **)&ptr) < 0)
|
||||
return 0;
|
||||
|
||||
for (size /= sizeof(uint32_t); size > 0; size -= 4, ptr++)
|
||||
if (*ptr != -1U)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int flash_write(int offset, int size, const char *data)
|
||||
{
|
||||
if (flash_dataptr(offset, size, CONFIG_FLASH_WRITE_SIZE, NULL) < 0)
|
||||
|
||||
@@ -31,6 +31,17 @@ static inline char *flash_physical_dataptr(int offset)
|
||||
return (char *)(CONFIG_FLASH_BASE + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a region of flash is erased
|
||||
*
|
||||
* It is assumed that an erased region has all bits set to 1.
|
||||
*
|
||||
* @param offset Flash offset to check
|
||||
* @param size Number of bytes to check (word-aligned)
|
||||
* @return 1 if erased, 0 if not erased
|
||||
*/
|
||||
int flash_is_erased(uint32_t offset, int size);
|
||||
|
||||
/**
|
||||
* Write to physical flash.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user