All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Warren <swarren@wwwdotorg.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 4/4] dfu: add SF backend
Date: Wed, 11 Jun 2014 16:03:36 -0600	[thread overview]
Message-ID: <1402524216-9999-4-git-send-email-swarren@wwwdotorg.org> (raw)
In-Reply-To: <1402524216-9999-1-git-send-email-swarren@wwwdotorg.org>

From: Stephen Warren <swarren@nvidia.com>

This allows SPI Flash to be programmed using DFU.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
 drivers/dfu/Makefile |   1 +
 drivers/dfu/dfu.c    |   3 ++
 drivers/dfu/dfu_sf.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h        |  22 ++++++++
 4 files changed, 165 insertions(+)
 create mode 100644 drivers/dfu/dfu_sf.c

diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index def628dcdcc4..5cc535efdd47 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_DFU_FUNCTION) += dfu.o
 obj-$(CONFIG_DFU_MMC) += dfu_mmc.o
 obj-$(CONFIG_DFU_NAND) += dfu_nand.o
 obj-$(CONFIG_DFU_RAM) += dfu_ram.o
+obj-$(CONFIG_DFU_SF) += dfu_sf.o
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 897dfab77be6..6cd3fbb58ae4 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -413,6 +413,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
 	} else if (strcmp(interface, "ram") == 0) {
 		if (dfu_fill_entity_ram(dfu, devstr, s))
 			return -1;
+	} else if (strcmp(interface, "sf") == 0) {
+		if (dfu_fill_entity_sf(dfu, devstr, s))
+			return -1;
 	} else {
 		printf("%s: Device %s not (yet) supported!\n",
 		       __func__,  interface);
diff --git a/drivers/dfu/dfu_sf.c b/drivers/dfu/dfu_sf.c
new file mode 100644
index 000000000000..91f6df220b1d
--- /dev/null
+++ b/drivers/dfu/dfu_sf.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <div64.h>
+#include <dfu.h>
+#include <spi_flash.h>
+
+static long dfu_get_medium_size_sf(struct dfu_entity *dfu)
+{
+	return dfu->data.sf.size;
+}
+
+static int dfu_read_medium_sf(struct dfu_entity *dfu, u64 offset, void *buf,
+		long *len)
+{
+	return spi_flash_read(dfu->data.sf.dev, offset, *len, buf);
+}
+
+static int dfu_write_medium_sf(struct dfu_entity *dfu,
+		u64 offset, void *buf, long *len)
+{
+	int ret;
+
+	ret = spi_flash_erase(dfu->data.sf.dev, offset, *len);
+	if (ret)
+		return ret;
+
+	ret = spi_flash_write(dfu->data.sf.dev, offset, *len, buf);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int dfu_flush_medium_sf(struct dfu_entity *dfu)
+{
+	return 0;
+}
+
+static unsigned int dfu_polltimeout_sf(struct dfu_entity *dfu)
+{
+	return DFU_DEFAULT_POLL_TIMEOUT;
+}
+
+static void dfu_free_entity_sf(struct dfu_entity *dfu)
+{
+	spi_flash_free(dfu->data.sf.dev);
+}
+
+static struct spi_flash *parse_dev(char *devstr)
+{
+	unsigned int bus;
+	unsigned int cs;
+	unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
+	unsigned int mode = CONFIG_SF_DEFAULT_MODE;
+	char *s, *endp;
+	struct spi_flash *dev;
+
+	s = strsep(&devstr, ":");
+	if (!s || !*s || (bus = simple_strtoul(s, &endp, 0), *endp)) {
+		printf("Invalid SPI bus %s\n", s);
+		return NULL;
+	}
+
+	s = strsep(&devstr, ":");
+	if (!s || !*s || (cs = simple_strtoul(s, &endp, 0), *endp)) {
+		printf("Invalid SPI chip-select %s\n", s);
+		return NULL;
+	}
+
+	s = strsep(&devstr, ":");
+	if (s && *s) {
+		speed = simple_strtoul(s, &endp, 0);
+		if (*endp || !speed) {
+			printf("Invalid SPI speed %s\n", s);
+			return NULL;
+		}
+	}
+
+	s = strsep(&devstr, ":");
+	if (s && *s) {
+		mode = simple_strtoul(s, &endp, 0);
+		if (*endp || mode > 3) {
+			printf("Invalid SPI mode %s\n", s);
+			return NULL;
+		}
+	}
+
+	dev = spi_flash_probe(bus, cs, speed, mode);
+	if (!dev) {
+		printf("Failed to create SPI flash at %d:%d:%d:%d\n",
+		       bus, cs, speed, mode);
+		return NULL;
+	}
+
+	return dev;
+}
+
+int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s)
+{
+	char *st;
+
+	dfu->data.sf.dev = parse_dev(devstr);
+	if (!dfu->data.sf.dev)
+		return -ENODEV;
+
+	dfu->dev_type = DFU_DEV_SF;
+	dfu->max_buf_size = dfu->data.sf.dev->sector_size;
+
+	st = strsep(&s, " ");
+	if (!strcmp(st, "raw")) {
+		dfu->layout = DFU_RAW_ADDR;
+		dfu->data.sf.start = simple_strtoul(s, &s, 16);
+		s++;
+		dfu->data.sf.size = simple_strtoul(s, &s, 16);
+	} else {
+		printf("%s: Memory layout (%s) not supported!\n", __func__, st);
+		spi_flash_free(dfu->data.sf.dev);
+		return -1;
+	}
+
+	dfu->get_medium_size = dfu_get_medium_size_sf;
+	dfu->read_medium = dfu_read_medium_sf;
+	dfu->write_medium = dfu_write_medium_sf;
+	dfu->flush_medium = dfu_flush_medium_sf;
+	dfu->poll_timeout = dfu_polltimeout_sf;
+	dfu->free_entity = dfu_free_entity_sf;
+
+	/* initial state */
+	dfu->inited = 0;
+
+	return 0;
+}
diff --git a/include/dfu.h b/include/dfu.h
index 43814b38ec6d..7e0a99908ca4 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -14,6 +14,7 @@
 #include <common.h>
 #include <linux/list.h>
 #include <mmc.h>
+#include <spi_flash.h>
 #include <linux/usb/composite.h>
 
 enum dfu_device_type {
@@ -21,6 +22,7 @@ enum dfu_device_type {
 	DFU_DEV_ONENAND,
 	DFU_DEV_NAND,
 	DFU_DEV_RAM,
+	DFU_DEV_SF,
 };
 
 enum dfu_layout {
@@ -70,6 +72,14 @@ struct ram_internal_data {
 	unsigned int	size;
 };
 
+struct sf_internal_data {
+	struct spi_flash *dev;
+
+	/* RAW programming */
+	u64 start;
+	u64 size;
+};
+
 #define DFU_NAME_SIZE			32
 #define DFU_CMD_BUF_SIZE		128
 #ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE
@@ -97,6 +107,7 @@ struct dfu_entity {
 		struct mmc_internal_data mmc;
 		struct nand_internal_data nand;
 		struct ram_internal_data ram;
+		struct sf_internal_data sf;
 	} data;
 
 	long (*get_medium_size)(struct dfu_entity *dfu);
@@ -182,5 +193,16 @@ static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr,
 }
 #endif
 
+#ifdef CONFIG_DFU_SF
+extern int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s);
+#else
+static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr,
+				     char *s)
+{
+	puts("SF support not available!\n");
+	return -1;
+}
+#endif
+
 int dfu_add(struct usb_configuration *c);
 #endif /* __DFU_ENTITY_H_ */
-- 
1.8.1.5

  parent reply	other threads:[~2014-06-11 22:03 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-11 22:03 [U-Boot] [PATCH 1/4] dfu: defer parsing of device string to IO backend Stephen Warren
2014-06-11 22:03 ` [U-Boot] [PATCH 2/4] dfu: allow backend to specify a maximum buffer size Stephen Warren
2014-06-20  7:54   ` Lukasz Majewski
2014-06-11 22:03 ` [U-Boot] [PATCH 3/4] dfu: add free_entity() to struct dfu_entity Stephen Warren
2014-06-20  7:55   ` Lukasz Majewski
2014-06-11 22:03 ` Stephen Warren [this message]
2014-06-20  7:55   ` [U-Boot] [PATCH 4/4] dfu: add SF backend Lukasz Majewski
2015-09-21 17:13   ` Fabio Estevam
2015-09-21 17:31     ` Stephen Warren
2015-09-21 17:37       ` Fabio Estevam
2015-09-22  1:50         ` Fabio Estevam
2015-09-22  2:55           ` Fabio Estevam
2015-09-22  3:23             ` Stephen Warren
2015-09-22  3:37               ` Fabio Estevam
2015-09-22  7:23                 ` Lukasz Majewski
2014-06-20  7:54 ` [U-Boot] [PATCH 1/4] dfu: defer parsing of device string to IO backend Lukasz Majewski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1402524216-9999-4-git-send-email-swarren@wwwdotorg.org \
    --to=swarren@wwwdotorg.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.