drivers: spi_flash_at45: Fix erasing of first two sectors

Most available AT45 flash chips have their first two sectors shorter
than the consecutive ones. Usually, the first sector is marked as 0a
and has its size equal to eight pages (one block) and the second one
(usually 0b) is the complement to the size of a regular sector.
This commits modifies the driver so that erasing of these first two
sectors is performed correctly. This modified behavior is configurable
with a new DT property so that it is still possible to also use legacy
AT45 chips that do not feature such sector split. Such legacy chips
usually also do not support the chip erase and sector erase commands,
so two more DT properties are introduced to cover that.

Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
This commit is contained in:
Andrzej Głąbek 2023-04-26 15:18:38 +02:00 committed by Carles Cufí
parent 81c9795023
commit 0b573a1f38
3 changed files with 53 additions and 10 deletions

View file

@ -394,6 +394,8 @@ Drivers and Sensors
* flash_simulator: A memory region can now be used as the storage area for the
flash simulator. Using the memory region allows the flash simulator to keep
its contents over a device reboot.
* spi_flash_at45: Fixed erase procedure to properly handle chips that have
their initial sector split into two parts (usually marked as 0a and 0b).
* FPGA

View file

@ -74,8 +74,11 @@ struct spi_flash_at45_config {
#endif
uint32_t chip_size;
uint32_t sector_size;
uint32_t sector_0a_size;
uint16_t block_size;
uint16_t page_size;
bool no_chip_erase;
bool no_sector_erase;
uint16_t t_enter_dpd; /* in microseconds */
uint16_t t_exit_dpd; /* in microseconds */
bool use_udpd;
@ -454,16 +457,28 @@ static int spi_flash_at45_erase(const struct device *dev, off_t offset,
}
#endif
if (size == cfg->chip_size) {
if (!cfg->no_chip_erase && size == cfg->chip_size) {
err = perform_chip_erase(dev);
} else {
while (size) {
if (is_erase_possible(cfg->sector_size,
size_t sector_size = cfg->sector_size;
if (cfg->sector_0a_size) {
if (offset < cfg->sector_0a_size) {
sector_size = cfg->sector_0a_size;
} else if (offset < cfg->sector_size) {
/* Sector 0b. Calculate its size. */
sector_size -= cfg->sector_0a_size;
}
}
if (!cfg->no_sector_erase &&
is_erase_possible(sector_size,
offset, size)) {
err = perform_erase_op(dev, CMD_SECTOR_ERASE,
offset);
offset += cfg->sector_size;
size -= cfg->sector_size;
offset += sector_size;
size -= sector_size;
} else if (is_erase_possible(cfg->block_size,
offset, size)) {
err = perform_erase_op(dev, CMD_BLOCK_ERASE,
@ -681,14 +696,18 @@ static const struct flash_driver_api spi_flash_at45_api = {
.pages_count = INST_##idx##_PAGES, \
.pages_size = DT_INST_PROP(idx, page_size), \
},)) \
.chip_size = INST_##idx##_BYTES, \
.sector_size = DT_INST_PROP(idx, sector_size), \
.block_size = DT_INST_PROP(idx, block_size), \
.page_size = DT_INST_PROP(idx, page_size), \
.t_enter_dpd = DIV_ROUND_UP( \
.chip_size = INST_##idx##_BYTES, \
.sector_size = DT_INST_PROP(idx, sector_size), \
.sector_0a_size = DT_INST_PROP(idx, sector_0a_pages) \
* DT_INST_PROP(idx, page_size), \
.block_size = DT_INST_PROP(idx, block_size), \
.page_size = DT_INST_PROP(idx, page_size), \
.no_chip_erase = DT_INST_PROP(idx, no_chip_erase), \
.no_sector_erase = DT_INST_PROP(idx, no_sector_erase), \
.t_enter_dpd = DIV_ROUND_UP( \
DT_INST_PROP(idx, enter_dpd_delay), \
NSEC_PER_USEC), \
.t_exit_dpd = DIV_ROUND_UP( \
.t_exit_dpd = DIV_ROUND_UP( \
DT_INST_PROP(idx, exit_dpd_delay), \
NSEC_PER_USEC), \
.use_udpd = DT_INST_PROP(idx, use_udpd), \

View file

@ -23,6 +23,18 @@ properties:
required: true
description: Flash sector size in bytes.
sector-0a-pages:
type: int
default: 8
description: |
Most available AT45 flash chips have their first two sectors shorter
than the consecutive ones. Usually, the first sector is marked as 0a
and has its size equal to eight pages (one block) and the second one
(usually 0b) is the complement to the size of a regular sector.
This property allows specifying the size (in pages) of that first sector
and defaults to the commonly used value of eight pages.
Value of zero means that the flash chip has all sectors of equal size.
block-size:
type: int
required: true
@ -33,6 +45,16 @@ properties:
required: true
description: Flash page size in bytes.
no-chip-erase:
type: boolean
description: |
If set, indicates that the chip does not support the chip erase command.
no-sector-erase:
type: boolean
description: |
If set, indicates that the chip does not support the sector erase command.
use-udpd:
type: boolean
description: |