diff options
Diffstat (limited to 'drivers/dfu')
| -rw-r--r-- | drivers/dfu/dfu.c | 52 | ||||
| -rw-r--r-- | drivers/dfu/dfu_mmc.c | 2 | ||||
| -rw-r--r-- | drivers/dfu/dfu_nand.c | 18 |
3 files changed, 61 insertions, 11 deletions
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 6af6890d0..05217526b 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -20,6 +20,7 @@ */ #include <common.h> +#include <errno.h> #include <malloc.h> #include <mmc.h> #include <fat.h> @@ -41,8 +42,34 @@ static int dfu_find_alt_num(const char *s) return ++i; } -static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE) - dfu_buf[DFU_DATA_BUF_SIZE]; +static unsigned char *dfu_buf; +static unsigned long dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE; + +static unsigned char *dfu_free_buf(void) +{ + free(dfu_buf); + dfu_buf = NULL; + return dfu_buf; +} + +static unsigned char *dfu_get_buf(void) +{ + char *s; + + if (dfu_buf != NULL) + return dfu_buf; + + s = getenv("dfu_bufsiz"); + dfu_buf_size = s ? (unsigned long)simple_strtol(s, NULL, 16) : + CONFIG_SYS_DFU_DATA_BUF_SIZE; + + dfu_buf = memalign(CONFIG_SYS_CACHELINE_SIZE, dfu_buf_size); + if (dfu_buf == NULL) + printf("%s: Could not memalign 0x%lx bytes\n", + __func__, dfu_buf_size); + + return dfu_buf; +} static int dfu_write_buffer_drain(struct dfu_entity *dfu) { @@ -87,8 +114,10 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->offset = 0; dfu->bad_skip = 0; dfu->i_blk_seq_num = 0; - dfu->i_buf_start = dfu_buf; - dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf_start = dfu_get_buf(); + if (dfu->i_buf_start == NULL) + return -ENOMEM; + dfu->i_buf_end = dfu_get_buf() + dfu_buf_size; dfu->i_buf = dfu->i_buf_start; dfu->inited = 1; @@ -148,11 +177,12 @@ int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc); /* clear everything */ + dfu_free_buf(); dfu->crc = 0; dfu->offset = 0; dfu->i_blk_seq_num = 0; dfu->i_buf_start = dfu_buf; - dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf_end = dfu_buf; dfu->i_buf = dfu->i_buf_start; dfu->inited = 0; @@ -218,7 +248,11 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf); if (!dfu->inited) { - ret = dfu->read_medium(dfu, 0, buf, &dfu->r_left); + dfu->i_buf_start = dfu_get_buf(); + if (dfu->i_buf_start == NULL) + return -ENOMEM; + + ret = dfu->read_medium(dfu, 0, dfu->i_buf_start, &dfu->r_left); if (ret != 0) { debug("%s: failed to get r_left\n", __func__); return ret; @@ -229,8 +263,7 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) dfu->i_blk_seq_num = 0; dfu->crc = 0; dfu->offset = 0; - dfu->i_buf_start = dfu_buf; - dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf_end = dfu_get_buf() + dfu_buf_size; dfu->i_buf = dfu->i_buf_start; dfu->b_left = 0; @@ -257,11 +290,12 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, dfu->crc); puts("\nUPLOAD ... done\nCtrl+C to exit ...\n"); + dfu_free_buf(); dfu->i_blk_seq_num = 0; dfu->crc = 0; dfu->offset = 0; dfu->i_buf_start = dfu_buf; - dfu->i_buf_end = dfu_buf + sizeof(dfu_buf); + dfu->i_buf_end = dfu_buf; dfu->i_buf = dfu->i_buf_start; dfu->b_left = 0; diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index e2f397840..e7ee0770c 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -98,6 +98,8 @@ static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu, op == DFU_OP_READ ? "load" : "write", dfu->data.mmc.dev, dfu->data.mmc.part, (unsigned int) buf, dfu->name); + if (op == DFU_OP_WRITE) + sprintf(cmd_buf + strlen(cmd_buf), " %ld", *len); break; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, diff --git a/drivers/dfu/dfu_nand.c b/drivers/dfu/dfu_nand.c index 7dc89b2f2..07dee8981 100644 --- a/drivers/dfu/dfu_nand.c +++ b/drivers/dfu/dfu_nand.c @@ -63,12 +63,26 @@ static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu, nand = &nand_info[nand_curr_device]; - if (op == DFU_OP_READ) + if (op == DFU_OP_READ) { ret = nand_read_skip_bad(nand, start, &count, &actual, lim, buf); - else + } else { + nand_erase_options_t opts; + + memset(&opts, 0, sizeof(opts)); + opts.offset = start; + opts.length = count; + opts.spread = 1; + opts.quiet = 1; + opts.lim = lim; + /* first erase */ + ret = nand_erase_opts(nand, &opts); + if (ret) + return ret; + /* then write */ ret = nand_write_skip_bad(nand, start, &count, &actual, lim, buf, 0); + } if (ret != 0) { printf("%s: nand_%s_skip_bad call failed at %llx!\n", |