summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-03-04 12:19:05 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2016-04-08 13:35:32 +0200
commitf6f7bccaa1f79d8e79621c9658f1b1c9fc417dc3 (patch)
tree7641265ba0667675b55c349b74b72841e4da60a2
parentc5532a2d36f326577b1bd2743c79fc00b6a41402 (diff)
downloadbarebox-f6f7bccaa1f79d8e79621c9658f1b1c9fc417dc3.tar.gz
imx-bbu-nand-fcb: Use mtd-peb API to write firmware
With this patch we verify the firmware written to the NAND and thus can react on write failures. We torture the block and if it went bad we mark it as bad. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-rw-r--r--common/imx-bbu-nand-fcb.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index 26b0b29..f1fc4040 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -33,6 +33,7 @@
#include <linux/mtd/mtd.h>
#include <linux/stat.h>
#include <io.h>
+#include <mtd/mtd-peb.h>
struct dbbt_block {
uint32_t Checksum;
@@ -300,6 +301,27 @@ static int imx_bbu_erase(struct mtd_info *mtd)
return 0;
}
+static int mtd_peb_write_block(struct mtd_info *mtd, void *buf, int block, int len)
+{
+ int ret;
+ int retries = 0;
+
+ if (mtd_peb_is_bad(mtd, block))
+ return -EINVAL;
+again:
+ ret = mtd_peb_write(mtd, buf, block, 0, len);
+ if (!ret)
+ return 0;
+
+ if (ret == -EBADMSG) {
+ ret = mtd_peb_torture(mtd, block);
+ if (!ret && retries++ < 3)
+ goto again;
+ }
+
+ return ret;
+}
+
/**
* imx_bbu_firmware_max_blocks - get max number of blocks for firmware
* @mtd: The mtd device
@@ -332,10 +354,8 @@ static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned num, void *buf,
size_t len)
{
int ret;
- size_t written;
int num_blocks = imx_bbu_firmware_max_blocks(mtd);
int block = imx_bbu_firmware_start_block(mtd, num);
- uint64_t offset = block * mtd->erasesize;
pr_info("writing firmware %d to block %d (ofs 0x%08x)\n",
num, block, block * mtd->erasesize);
@@ -346,21 +366,27 @@ static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned num, void *buf,
if (!num_blocks)
return -ENOSPC;
- pr_debug("writing %p at 0x%08llx, left 0x%08x\n",
- buf, offset, len);
+ pr_debug("writing %p peb %d, left 0x%08x\n",
+ buf, block, len);
- if (mtd_block_isbad(mtd, offset)) {
- pr_debug("write skip block @ 0x%08llx\n", offset);
- offset += mtd->erasesize;
+ if (mtd_peb_is_bad(mtd, block)) {
+ pr_debug("skipping block %d\n", block);
+ num_blocks--;
+ block++;
+ continue;
+ }
+
+ ret = mtd_peb_write_block(mtd, buf, block, now);
+
+ if (ret == -EIO) {
block++;
+ num_blocks--;
continue;
}
- ret = mtd_write(mtd, offset, now, &written, buf);
if (ret)
return ret;
- offset += now;
len -= now;
buf += now;
block++;