summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/spl/spl_nand.c5
-rw-r--r--drivers/mtd/nand/raw/nand_spl_loaders.c28
-rw-r--r--include/nand.h1
3 files changed, 33 insertions, 1 deletions
diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c
index 48c97549eb..1e6f2dce56 100644
--- a/common/spl/spl_nand.c
+++ b/common/spl/spl_nand.c
@@ -42,8 +42,11 @@ static int spl_nand_load_image(struct spl_image_info *spl_image,
static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
ulong size, void *dst)
{
+ ulong sector;
int ret;
+ sector = *(int *)load->priv;
+ offs = sector + nand_spl_adjust_offset(sector, offs - sector);
ret = nand_spl_load_image(offs, size, dst);
if (!ret)
return size;
@@ -66,7 +69,7 @@ static int spl_nand_load_element(struct spl_image_info *spl_image,
debug("Found FIT\n");
load.dev = NULL;
- load.priv = NULL;
+ load.priv = &offset;
load.filename = NULL;
load.bl_len = 1;
load.read = spl_nand_fit_read;
diff --git a/drivers/mtd/nand/raw/nand_spl_loaders.c b/drivers/mtd/nand/raw/nand_spl_loaders.c
index 177c12b581..4befc75c04 100644
--- a/drivers/mtd/nand/raw/nand_spl_loaders.c
+++ b/drivers/mtd/nand/raw/nand_spl_loaders.c
@@ -41,6 +41,34 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
return 0;
}
+/**
+ * nand_spl_adjust_offset - Adjust offset from a starting sector
+ * @sector: Address of the sector
+ * @offs: Offset starting from @sector
+ *
+ * If one or more bad blocks are in the address space between @sector
+ * and @sector + @offs, @offs is increased by the NAND block size for
+ * each bad block found.
+ */
+u32 nand_spl_adjust_offset(u32 sector, u32 offs)
+{
+ unsigned int block, lastblock;
+
+ block = sector / CONFIG_SYS_NAND_BLOCK_SIZE;
+ lastblock = (sector + offs) / CONFIG_SYS_NAND_BLOCK_SIZE;
+
+ while (block <= lastblock) {
+ if (nand_is_bad_block(block)) {
+ offs += CONFIG_SYS_NAND_BLOCK_SIZE;
+ lastblock++;
+ }
+
+ block++;
+ }
+
+ return offs;
+}
+
#ifdef CONFIG_SPL_UBI
/*
* Temporary storage for non NAND page aligned and non NAND page sized
diff --git a/include/nand.h b/include/nand.h
index 93cbe1e25d..80dd6469bc 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -120,6 +120,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length,
int allexcept);
int nand_get_lock_status(struct mtd_info *mtd, loff_t offset);
+u32 nand_spl_adjust_offset(u32 sector, u32 offs);
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst);
int nand_spl_read_block(int block, int offset, int len, void *dst);
void nand_deselect(void);