summaryrefslogtreecommitdiffstats
path: root/common/imx-bbu-nand-fcb.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-03-04 12:53:48 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2016-04-08 13:35:32 +0200
commit678617ecaf30d04a7ce15295e0816122320ba498 (patch)
treed3baa3636e7e0abacd01570c0b272db2c62b509a /common/imx-bbu-nand-fcb.c
parent14fd7e9478e53be751bdd568c294623e908b90c1 (diff)
downloadbarebox-678617ecaf30d04a7ce15295e0816122320ba498.tar.gz
imx-bbu-nand-fcb: erase on demand
Instead of erasing the whole partition on update entry, erase the areas separately when we actually want to write them. This is done as a step towards robust update. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'common/imx-bbu-nand-fcb.c')
-rw-r--r--common/imx-bbu-nand-fcb.c47
1 files changed, 14 insertions, 33 deletions
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 492dd92..3dc9274 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -272,34 +272,6 @@ static int fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
return 0;
}
-static int imx_bbu_erase(struct mtd_info *mtd)
-{
- uint64_t offset = 0;
- struct erase_info erase;
- int ret;
-
- while (offset < mtd->size) {
- pr_debug("erasing at 0x%08llx\n", offset);
- if (mtd_block_isbad(mtd, offset)) {
- pr_debug("erase skip block @ 0x%08llx\n", offset);
- offset += mtd->erasesize;
- continue;
- }
-
- memset(&erase, 0, sizeof(erase));
- erase.addr = offset;
- erase.len = mtd->erasesize;
-
- ret = mtd_erase(mtd, &erase);
- if (ret)
- return ret;
-
- offset += mtd->erasesize;
- }
-
- return 0;
-}
-
static int mtd_peb_write_block(struct mtd_info *mtd, void *buf, int block, int len)
{
int ret;
@@ -352,13 +324,22 @@ static int imx_bbu_firmware_start_block(struct mtd_info *mtd, int num)
static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned num, void *buf,
size_t len)
{
- int ret;
+ int ret, i;
int num_blocks = imx_bbu_firmware_max_blocks(mtd);
int block = imx_bbu_firmware_start_block(mtd, num);
pr_info("writing firmware %d to block %d (ofs 0x%08x)\n",
num, block, block * mtd->erasesize);
+ for (i = 0; i < num_blocks; i++) {
+ if (mtd_peb_is_bad(mtd, block + i))
+ continue;
+
+ ret = mtd_peb_erase(mtd, block + i);
+ if (ret && ret != -EIO)
+ return ret;
+ }
+
while (len > 0) {
int now = min(len, mtd->erasesize);
@@ -470,6 +451,10 @@ again:
if (cpu_is_mx28())
imx28_dbbt_create(dbbt, *n_bad_blocksp);
+ ret = mtd_peb_erase(mtd, block);
+ if (ret)
+ return ret;
+
ret = raw_write_page(mtd, fcb_raw_page, block * mtd->erasesize);
if (ret) {
pr_err("Writing FCB on block %d failed with %s\n",
@@ -629,10 +614,6 @@ static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *dat
if (ret)
goto out;
- ret = imx_bbu_erase(mtd);
- if (ret)
- goto out;
-
ret = imx_bbu_write_firmware(mtd, 0, fw, fw_size);
if (ret < 0)
goto out;