summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dfu/Kconfig8
-rw-r--r--drivers/dfu/dfu_sf.c52
2 files changed, 60 insertions, 0 deletions
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index 4692736c9d..1cbec81128 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -46,5 +46,13 @@ config DFU_SF
This option enables using DFU to read and write to SPI flash based
storage.
+config DFU_SF_PART
+ bool "MTD partition support for SPI flash back end"
+ depends on DFU_SF && CMD_MTDPARTS
+ default y
+ help
+ This option enables the support of "part" and "partubi" target in
+ SPI flash DFU back end.
+
endif
endmenu
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c
index b78fcfd3a1..0fdbfae434 100644
--- a/drivers/dfu/dfu_sf.c
+++ b/drivers/dfu/dfu_sf.c
@@ -10,6 +10,8 @@
#include <dfu.h>
#include <spi.h>
#include <spi_flash.h>
+#include <jffs2/load_kernel.h>
+#include <linux/mtd/mtd.h>
static int dfu_get_medium_size_sf(struct dfu_entity *dfu, u64 *size)
{
@@ -52,11 +54,33 @@ static int dfu_write_medium_sf(struct dfu_entity *dfu,
static int dfu_flush_medium_sf(struct dfu_entity *dfu)
{
+ u64 off, length;
+
+ if (!CONFIG_IS_ENABLED(DFU_SF_PART) || !dfu->data.sf.ubi)
+ return 0;
+
+ /* in case of ubi partition, erase rest of the partition */
+ off = find_sector(dfu, dfu->data.sf.start, dfu->offset);
+ /* last write ended with unaligned length jump to next */
+ if (off != dfu->data.sf.start + dfu->offset)
+ off += dfu->data.sf.dev->sector_size;
+ length = dfu->data.sf.start + dfu->data.sf.size - off;
+ if (length)
+ return spi_flash_erase(dfu->data.sf.dev, off, length);
+
return 0;
}
static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu)
{
+ /*
+ * Currently, Poll Timeout != 0 is only needed on nand
+ * ubi partition, as sectors which are not used need
+ * to be erased
+ */
+ if (CONFIG_IS_ENABLED(DFU_SF_PART) && dfu->data.sf.ubi)
+ return DFU_MANIFEST_POLL_TIMEOUT;
+
return DFU_DEFAULT_POLL_TIMEOUT;
}
@@ -133,6 +157,34 @@ int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s)
dfu->data.sf.start = simple_strtoul(s, &s, 16);
s++;
dfu->data.sf.size = simple_strtoul(s, &s, 16);
+ } else if (CONFIG_IS_ENABLED(DFU_SF_PART) &&
+ (!strcmp(st, "part") || !strcmp(st, "partubi"))) {
+ char mtd_id[32];
+ struct mtd_device *mtd_dev;
+ u8 part_num;
+ struct part_info *pi;
+ int ret, dev, part;
+
+ dfu->layout = DFU_RAW_ADDR;
+
+ dev = simple_strtoul(s, &s, 10);
+ s++;
+ part = simple_strtoul(s, &s, 10);
+
+ sprintf(mtd_id, "%s%d,%d", "nor", dev, part - 1);
+ printf("using id '%s'\n", mtd_id);
+
+ mtdparts_init();
+
+ ret = find_dev_and_part(mtd_id, &mtd_dev, &part_num, &pi);
+ if (ret != 0) {
+ printf("Could not locate '%s'\n", mtd_id);
+ return -1;
+ }
+ dfu->data.sf.start = pi->offset;
+ dfu->data.sf.size = pi->size;
+ if (!strcmp(st, "partubi"))
+ dfu->data.sf.ubi = 1;
} else {
printf("%s: Memory layout (%s) not supported!\n", __func__, st);
spi_flash_free(dfu->data.sf.dev);