Skip to contentSkip to conversation

Implement NAND dfu support

PATCH New Pantelis Antoniou 4 participants 9 messages Dec 10, 2012 – Dec 12, 2012

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Implement NAND dfu support

Introduce on-the fly DFU NAND support.

---
 drivers/dfu/Makefile   |   1 +
 drivers/dfu/dfu.c      |   7 ++
 drivers/dfu/dfu_nand.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h          |  23 ++++++
 4 files changed, 225 insertions(+)
 create mode 100644 drivers/dfu/dfu_nand.c
drivers/dfu/Makefile +1 -0
index 7b717bc..153095d 100644
@@ -27,6 +27,7 @@ LIB	= $(obj)libdfu.o
 
 COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
 COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
+COBJS-$(CONFIG_DFU_NAND) += dfu_nand.o
 
 SRCS    := $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
drivers/dfu/dfu.c +7 -0
index fb9b417..1972b17 100644
@@ -234,6 +234,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
 		dfu->i_buf = dfu->i_buf_start;
 		dfu->b_left = 0;
 
+		dfu->bad_skip = 0;
+
 		dfu->inited = 1;
 	}
 
@@ -263,6 +265,8 @@ int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
 		dfu->i_buf = dfu->i_buf_start;
 		dfu->b_left = 0;
 
+		dfu->bad_skip = 0;
+
 		dfu->inited = 0;
 	}
 
@@ -285,6 +289,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
 	if (strcmp(interface, "mmc") == 0) {
 		if (dfu_fill_entity_mmc(dfu, s))
 			return -1;
+	} else if (strcmp(interface, "nand") == 0) {
+		if (dfu_fill_entity_nand(dfu, s))
+			return -1;
 	} else {
 		printf("%s: Device %s not (yet) supported!\n",
 		       __func__,  interface);
drivers/dfu/dfu_nand.c new file +194 -0

194 lines not on this page · raw message

include/dfu.h +23 -0
index 2847ef8..0454762 100644
@@ -52,6 +52,15 @@ struct mmc_internal_data {
 	unsigned int part;
 };
 
+struct nand_internal_data {
+	/* RAW programming */
+	u64 start;
+	u64 size;
+
+	unsigned int dev;
+	unsigned int part;
+};
+
 static inline unsigned int get_mmc_blk_size(int dev)
 {
 	return find_mmc_device(dev)->read_bl_len;
@@ -71,6 +80,7 @@ struct dfu_entity {
 
 	union {
 		struct mmc_internal_data mmc;
+		struct nand_internal_data nand;
 	} data;
 
 	int (*read_medium)(struct dfu_entity *dfu,
@@ -91,6 +101,8 @@ struct dfu_entity {
 	long r_left;
 	long b_left;
 
+	u32 bad_skip;	/* for nand use */
+
 	unsigned int inited : 1;
 };
 
@@ -115,4 +127,15 @@ static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
 	return -1;
 }
 #endif
+
+#ifdef CONFIG_DFU_NAND
+extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s);
+#else
+static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *s)
+{
+	puts("NAND support not available!\n");
+	return -1;
+}
+#endif
+
 #endif /* __DFU_ENTITY_H_ */
Signature · 1 line
1.7.12
#1 lore raw

PATCH 1/1 Implement NAND dfu support

Quoted 11 lines · Pantelis Antoniou

Introduce on-the fly DFU NAND support.

---
 drivers/dfu/Makefile   |   1 +
 drivers/dfu/dfu.c      |   7 ++
 drivers/dfu/dfu_nand.c | 194  
+++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h          |  23 ++++++
 4 files changed, 225 insertions(+)
 create mode 100644 drivers/dfu/dfu_nand.c

What is DFU? I don't see anything in README or doc/, despite there already being CONFIG symbols for it.

Quoted 25 lines
drivers/dfu/dfu_nand.c new file +25 -0
+static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
+			u64 offset, void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+	u64 start, count;
+	int ret;
+	int dev;
+	loff_t actual;
+
+	/* if buf == NULL return total size of the area */
+	if (buf == NULL) {
+		*len = dfu->data.nand.size;
+		return 0;
+	}
+
+	start = dfu->data.nand.start + offset + dfu->bad_skip;
+	count = *len;
+	if (start + count >
+			dfu->data.nand.start + dfu->data.nand.size) {
+		printf("%s: block_op out of bounds\n", __func__);
+		return -1;
+	}
+	dev = nand_curr_device;
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+		!nand_info[dev].name) {

drivers/dfu/dfu_nand.c line 73

Quoted 10 lines
drivers/dfu/dfu_nand.c new file +10 -0
+		printf("%s: invalid nand device\n", __func__);
+		return -1;
+	}
+
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

drivers/dfu/dfu_nand.c line 77

Quoted 4 lines
(quoted diff) +2 -0
+	/* find out how much actual bytes have been written */
+	/* the difference is the amount of skip we must add from now on  

*/

drivers/dfu/dfu_nand.c new file +1 -0
+	actual = nand_extent_skip_bad(&nand_info[dev], start, count);

...especially since you already need to interact with it here?

-Scott

#2 lore raw

PATCH 1/1 Implement NAND dfu support

Quoted 13 lines · Scott Wood
Quoted 11 lines · Pantelis Antoniou

Introduce on-the fly DFU NAND support.

---

drivers/dfu/Makefile   |   1 +
drivers/dfu/dfu.c      |   7 ++
drivers/dfu/dfu_nand.c | 194
+++++++++++++++++++++++++++++++++++++++++++++++++
include/dfu.h          |  23 ++++++
4 files changed, 225 insertions(+)

create mode 100644 drivers/dfu/dfu_nand.c

Quoted 2 lines

What is DFU? I don't see anything in README or doc/, despite there already being CONFIG symbols for it.

Pah... Yes, we let that one slip past. DFU is USB Device Firmware Upgrade, something from the openmoko folks (roughly) that various devices support for sending payload via USB to be written to $flash.

Quoted 38 lines
Quoted 25 lines
drivers/dfu/dfu_nand.c new file +25 -0
+static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
+			u64 offset, void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+	u64 start, count;
+	int ret;
+	int dev;
+	loff_t actual;
+
+	/* if buf == NULL return total size of the area */
+	if (buf == NULL) {
+		*len = dfu->data.nand.size;
+		return 0;
+	}
+
+	start = dfu->data.nand.start + offset + dfu->bad_skip;
+	count = *len;
+	if (start + count >
+			dfu->data.nand.start + dfu->data.nand.size) {
+		printf("%s: block_op out of bounds\n", __func__);
+		return -1;
+	}
+	dev = nand_curr_device;
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+		!nand_info[dev].name) {

drivers/dfu/dfu_nand.c line 73

Quoted 10 lines
drivers/dfu/dfu_nand.c new file +10 -0
+		printf("%s: invalid nand device\n", __func__);
+		return -1;
+	}
+
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

Quoted 6 lines

drivers/dfu/dfu_nand.c line 77

Quoted 4 lines
(quoted diff) +2 -0
+	/* find out how much actual bytes have been written */
+	/* the difference is the amount of skip we must add from now on

*/

drivers/dfu/dfu_nand.c new file +1 -0
+	actual = nand_extent_skip_bad(&nand_info[dev], start, count);

...especially since you already need to interact with it here?

I've been talking with Pantelis about this as well and in short, this series adds NAND support ala MMC (which is to say, (ab)using the command interface). I think he was thinking we need a bit more generic help to avoid having to duplicate the code the command interface also uses (state, sanity checking), iirc.

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20121210/d8edb0a1/attachment.pgp>
#3 lore raw

PATCH 1/1 Implement NAND dfu support

Quoted 18 lines · Tom Rini
Quoted 10 lines · Scott Wood

drivers/dfu/dfu_nand.c line 73

Quoted 6 lines · Pantelis Antoniou
drivers/dfu/dfu_nand.c new file +6 -0
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

Quoted 6 lines

drivers/dfu/dfu_nand.c line 77

Quoted 4 lines
(quoted diff) +2 -0
+	/* find out how much actual bytes have been written */
+	/* the difference is the amount of skip we must add from now on

*/

drivers/dfu/dfu_nand.c new file +1 -0
+	actual = nand_extent_skip_bad(&nand_info[dev], start, count);

...especially since you already need to interact with it here?

Quoted 7 lines

I've been talking with Pantelis about this as well and in short, this series adds NAND support ala MMC (which is to say, (ab)using the command
interface). I think he was thinking we need a bit more generic help to
avoid having to duplicate the code the command interface also uses (state, sanity checking), iirc.

Some elaboration on what exactly he's relying on from the command line interface would be nice.

-Scott

#4 lore raw

PATCH 1/1 Implement NAND dfu support

Quoted 27 lines · Scott Wood
Quoted 18 lines · Tom Rini
Quoted 10 lines · Scott Wood

drivers/dfu/dfu_nand.c line 73

Quoted 6 lines · Pantelis Antoniou
drivers/dfu/dfu_nand.c new file +6 -0
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

Quoted 6 lines

drivers/dfu/dfu_nand.c line 77

Quoted 4 lines
(quoted diff) +2 -0
+	/* find out how much actual bytes have been written */
+	/* the difference is the amount of skip we must add from now on

*/

drivers/dfu/dfu_nand.c new file +1 -0
+	actual = nand_extent_skip_bad(&nand_info[dev], start, count);

...especially since you already need to interact with it here?

Quoted 7 lines

I've been talking with Pantelis about this as well and in short, this series adds NAND support ala MMC (which is to say, (ab)using the command
interface). I think he was thinking we need a bit more generic help to
avoid having to duplicate the code the command interface also uses (state, sanity checking), iirc.

Quoted 2 lines

Some elaboration on what exactly he's relying on from the command line interface would be nice.

My gmane-fu is failing me, but the actual 4/7 parts of
http://search.gmane.org/?query=dfu+mmc+%224%2F7%22&author=&group=gmane.comp.boot-loaders.u-boot&sort=revdate&DEFAULTOP=and&%3E=Next&xP=Zdfu%09Zmmc%094%097&xFILTERS=Gcomp.boot-loaders.u-boot---A
show the discussion. In short, for MMC writing it's more complex because we have a number of layouts we need to deal with (raw, FAT, other), but yes, we should in the end migrate things to using the API rather than abusing the command infrastructure.

Signature · 8 lines
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20121211/74ba1782/attachment.pgp>
#5 lore raw

PATCH 1/1 Implement NAND dfu support

In reply to Scott Wood

Hi Scott,

Quoted 13 lines · Pantelis Antoniou
Quoted 11 lines

Introduce on-the fly DFU NAND support.

---
 drivers/dfu/Makefile   |   1 +
 drivers/dfu/dfu.c      |   7 ++
 drivers/dfu/dfu_nand.c | 194  
+++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h          |  23 ++++++
 4 files changed, 225 insertions(+)
 create mode 100644 drivers/dfu/dfu_nand.c
Quoted 2 lines

What is DFU? I don't see anything in README or doc/, despite there already being CONFIG symbols for it.

DFU means Device Firmware Upgrade. It is a relatively simple protocol to update firmware on the target (mainly with small files - e.g. uImage).

For more information please skim:
http://www.usb.org/developers/devclass_docs/usbdfu10.pdf

Quoted 32 lines
Quoted 32 lines

+static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,

drivers/dfu/dfu_nand.c new file +18 -0
+			u64 offset, void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+	u64 start, count;
+	int ret;
+	int dev;
+	loff_t actual;
+
+	/* if buf == NULL return total size of the area */
+	if (buf == NULL) {
+		*len = dfu->data.nand.size;
+		return 0;
+	}
+
+	start = dfu->data.nand.start + offset + dfu->bad_skip;
+	count = *len;
+	if (start + count >
+			dfu->data.nand.start +

dfu->data.nand.size) {

drivers/dfu/dfu_nand.c new file +10 -0
+		printf("%s: block_op out of bounds\n", __func__);
+		return -1;
+	}
+	dev = nand_curr_device;
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+		!nand_info[dev].name) {
+		printf("%s: invalid nand device\n", __func__);
+		return -1;
+	}
+
Quoted 8 lines

drivers/dfu/dfu_nand.c line 73

Quoted 6 lines
drivers/dfu/dfu_nand.c new file +6 -0
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

We also support there eMMC (both with raw and file systems). Moreover we had this discussion some time ago (if we shall use "command" or native C API).

Quoted 10 lines
Quoted 6 lines
(quoted diff) +2 -0
+	/* find out how much actual bytes have been written */
+	/* the difference is the amount of skip we must add from

now on */

(quoted diff) +1 -0
+	actual = nand_extent_skip_bad(&nand_info[dev], start,

count);

...especially since you already need to interact with it here?

-Scott

Signature · 5 lines
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group
#6 lore raw

PATCH 1/1 Implement NAND dfu support

Quoted 12 lines · Lukasz Majewski

Hi Scott,

Quoted 9 lines · Pantelis Antoniou

drivers/dfu/dfu_nand.c line 73

Quoted 6 lines
drivers/dfu/dfu_nand.c new file +6 -0
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

Quoted 3 lines

We also support there eMMC (both with raw and file systems). Moreover we had this discussion some time ago (if we shall use "command" or native C API).

I don't see how "nand %s %p %llx %llx" supports anything that the NAND C API doesn't support.

I can't follow every discussion that happens on this list, on the off chance it might eventually become relevant to NAND. "Some time ago" is not an easily followed reference to the archives.

-Scott

#7 lore raw

PATCH 1/1 Implement NAND dfu support

Hi Scott,

Quoted 17 lines · Lukasz Majewski
Quoted 12 lines

Hi Scott,

Quoted 9 lines · Pantelis Antoniou

drivers/dfu/dfu_nand.c line 73

Quoted 6 lines
drivers/dfu/dfu_nand.c new file +6 -0
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

Quoted 3 lines

We also support there eMMC (both with raw and file systems). Moreover we had this discussion some time ago (if we shall use "command" or native C API).

Quoted 6 lines

I don't see how "nand %s %p %llx %llx" supports anything that the NAND C API doesn't support.

I can't follow every discussion that happens on this list, on the off chance it might eventually become relevant to NAND. "Some time ago" is not an easily followed reference to the archives.

I understand. Please consult following thread:
http://thread.gmane.org/gmane.comp.boot-loaders.u-boot/134397

Quoted 2 lines

-Scott

Signature · 5 lines
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group
#8 lore raw

PATCH 1/1 Implement NAND dfu support

In reply to Scott Wood

Hi Scott,

Quoted 11 lines · Scott Wood
Quoted 9 lines · Pantelis Antoniou

Introduce on-the fly DFU NAND support.

---

drivers/dfu/Makefile   |   1 +
drivers/dfu/dfu.c      |   7 ++
drivers/dfu/dfu_nand.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++
include/dfu.h          |  23 ++++++
4 files changed, 225 insertions(+)

create mode 100644 drivers/dfu/dfu_nand.c

Quoted 2 lines

What is DFU? I don't see anything in README or doc/, despite there already being CONFIG symbols for it.

This gets answered by a following email.

Quoted 29 lines
Quoted 29 lines
drivers/dfu/dfu_nand.c new file +29 -0
+static int nand_block_op(enum dfu_nand_op op, struct dfu_entity *dfu,
+			u64 offset, void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+	u64 start, count;
+	int ret;
+	int dev;
+	loff_t actual;
+
+	/* if buf == NULL return total size of the area */
+	if (buf == NULL) {
+		*len = dfu->data.nand.size;
+		return 0;
+	}
+
+	start = dfu->data.nand.start + offset + dfu->bad_skip;
+	count = *len;
+	if (start + count >
+			dfu->data.nand.start + dfu->data.nand.size) {
+		printf("%s: block_op out of bounds\n", __func__);
+		return -1;
+	}
+	dev = nand_curr_device;
+	if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+		!nand_info[dev].name) {
+		printf("%s: invalid nand device\n", __func__);
+		return -1;
+	}
+
Quoted 8 lines

drivers/dfu/dfu_nand.c line 73

Quoted 6 lines
drivers/dfu/dfu_nand.c new file +6 -0
+	sprintf(cmd_buf, "nand %s %p %llx %llx",
+		op == DFU_OP_READ ? "read" : "write",
+		 buf, start, count);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	ret = run_command(cmd_buf, 0);

Why not use the C interface to NAND?

Sigh. That's what I'm working on right now. The original implementation for mmc uses the user facing cmd api, so that's what I'm using for nand too.

The problem is that I see, is that by using this method (dfu_mmc|dfu_nand|dfu_foo) this piece of code gets duplicated for each different dfu target.

I was told that Device Model will fix everything, eventually, so I abandoned anything more generic than that. I will follow up with a patch that uses the C interface, and hope that sometime in the future we can consolidate. Maybe.

Quoted 8 lines

drivers/dfu/dfu_nand.c line 77

Quoted 4 lines
drivers/dfu/dfu_nand.c new file +3 -0
+	/* find out how much actual bytes have been written */
+	/* the difference is the amount of skip we must add from now on */
+	actual = nand_extent_skip_bad(&nand_info[dev], start, count);

...especially since you already need to interact with it here?

-Scott

Regards

-- Pantelis