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:
parent
81c9795023
commit
0b573a1f38
|
@ -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
|
||||
|
||||
|
|
|
@ -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), \
|
||||
|
|
|
@ -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: |
|
||||
|
|
Loading…
Reference in a new issue