diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c index 44b001e35bf81e1ba2fb7e55a06d14d2908dbefa..9f0331ad739537aa70cbcb807f63e0231c089605 100644 --- a/drivers/mtd/nand/core.c +++ b/drivers/mtd/nand/core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -112,6 +112,47 @@ int nand_read(unsigned int offset, uintptr_t buffer, size_t length, return 0; } +int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset) +{ + unsigned int block; + unsigned int offset_block; + unsigned int max_block; + int is_bad; + size_t count_bb = 0U; + + block = base / nand_dev.block_size; + + if (offset != 0U) { + offset_block = (base + offset - 1U) / nand_dev.block_size; + } else { + offset_block = block; + } + + max_block = nand_dev.size / nand_dev.block_size; + + while (block <= offset_block) { + if (offset_block >= max_block) { + return -EIO; + } + + is_bad = nand_dev.mtd_block_is_bad(block); + if (is_bad < 0) { + return is_bad; + } + + if (is_bad == 1) { + count_bb++; + offset_block++; + } + + block++; + } + + *extra_offset = count_bb * nand_dev.block_size; + + return 0; +} + struct nand_device *get_nand_device(void) { return &nand_dev; diff --git a/include/drivers/nand.h b/include/drivers/nand.h index 1dbb008f9c280407a2a874b58ace092d2b0a82b3..1b78ad41b15cf891f3c723fa5b13ac2a76f52477 100644 --- a/include/drivers/nand.h +++ b/include/drivers/nand.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -45,6 +45,16 @@ struct nand_device { int nand_read(unsigned int offset, uintptr_t buffer, size_t length, size_t *length_read); +/* + * Look for an extra offset to be added in case of bad blocks + * + * @base: Base address of the area + * @offset: Byte offset to read from in device + * @extra_offset: [out] Extra offset to be added if bad blocks are found + * Return: 0 on success, a negative errno on failure + */ +int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset); + /* * Get NAND device instance *