X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fdfu%2Fdfu_nand.c;h=0bfdbf942898d391e993213573153dd4ec96c436;hb=f3f2af3bdf2af89d0621aa0fbd94a918e4447081;hp=ccdbef6b75f26fe78fe5fc52438d797bad5b3b46;hpb=c534d2fdcf7aa80230a0f1ed54d5e3164ba595eb;p=u-boot diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c index ccdbef6b75..0bfdbf9428 100644 --- a/drivers/dfu/dfu_nand.c +++ b/drivers/dfu/dfu_nand.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * dfu_nand.c -- DFU for NAND routines. * @@ -6,8 +7,6 @@ * Based on dfu_mmc.c which is: * Copyright (C) 2012 Samsung Electronics * author: Lukasz Majewski - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -25,7 +24,7 @@ static int nand_block_op(enum dfu_op op, struct dfu_entity *dfu, loff_t start, lim; size_t count, actual; int ret; - nand_info_t *nand; + struct mtd_info *mtd; /* if buf == NULL return total size of the area */ if (buf == NULL) { @@ -37,18 +36,18 @@ static int nand_block_op(enum dfu_op op, struct dfu_entity *dfu, lim = dfu->data.nand.start + dfu->data.nand.size - start; count = *len; + mtd = get_nand_dev_by_index(nand_curr_device); + if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || - !nand_info[nand_curr_device].name) { + !mtd) { printf("%s: invalid nand device\n", __func__); return -1; } - nand = &nand_info[nand_curr_device]; - if (op == DFU_OP_READ) { - ret = nand_read_skip_bad(nand, start, &count, &actual, - lim, buf); + ret = nand_read_skip_bad(mtd, start, &count, &actual, + lim, buf); } else { nand_erase_options_t opts; @@ -59,12 +58,12 @@ static int nand_block_op(enum dfu_op op, struct dfu_entity *dfu, opts.quiet = 1; opts.lim = lim; /* first erase */ - ret = nand_erase_opts(nand, &opts); + ret = nand_erase_opts(mtd, &opts); if (ret) return ret; /* then write */ - ret = nand_write_skip_bad(nand, start, &count, &actual, - lim, buf, 0); + ret = nand_write_skip_bad(mtd, start, &count, &actual, + lim, buf, WITH_WR_VERIFY); } if (ret != 0) { @@ -114,6 +113,13 @@ static int dfu_write_medium_nand(struct dfu_entity *dfu, return ret; } +int dfu_get_medium_size_nand(struct dfu_entity *dfu, u64 *size) +{ + *size = dfu->data.nand.size; + + return 0; +} + static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf, long *len) { @@ -121,7 +127,6 @@ static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf, switch (dfu->layout) { case DFU_RAW_ADDR: - *len = dfu->data.nand.size; ret = nand_block_read(dfu, offset, buf, len); break; default: @@ -135,27 +140,35 @@ static int dfu_read_medium_nand(struct dfu_entity *dfu, u64 offset, void *buf, static int dfu_flush_medium_nand(struct dfu_entity *dfu) { int ret = 0; + u64 off; /* in case of ubi partition, erase rest of the partition */ if (dfu->data.nand.ubi) { - nand_info_t *nand; + struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device); nand_erase_options_t opts; if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || - !nand_info[nand_curr_device].name) { + !mtd) { printf("%s: invalid nand device\n", __func__); return -1; } - nand = &nand_info[nand_curr_device]; - memset(&opts, 0, sizeof(opts)); - opts.offset = dfu->data.nand.start + dfu->offset + + off = dfu->offset; + if ((off & (mtd->erasesize - 1)) != 0) { + /* + * last write ended with unaligned length + * sector is erased, jump to next + */ + off = off & ~((mtd->erasesize - 1)); + off += mtd->erasesize; + } + opts.offset = dfu->data.nand.start + off + dfu->bad_skip; opts.length = dfu->data.nand.start + dfu->data.nand.size - opts.offset; - ret = nand_erase_opts(nand, &opts); + ret = nand_erase_opts(mtd, &opts); if (ret != 0) printf("Failure erase: %d\n", ret); } @@ -175,7 +188,7 @@ unsigned int dfu_polltimeout_nand(struct dfu_entity *dfu) return DFU_DEFAULT_POLL_TIMEOUT; } -int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s) +int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s) { char *st; int ret, dev, part; @@ -220,6 +233,7 @@ int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s) return -1; } + dfu->get_medium_size = dfu_get_medium_size_nand; dfu->read_medium = dfu_read_medium_nand; dfu->write_medium = dfu_write_medium_nand; dfu->flush_medium = dfu_flush_medium_nand;