aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini2015-09-07 08:56:23 -0400
committerTom Rini2015-09-07 08:56:23 -0400
commitcdc7732f3737f2bb97b77eb3d7c9da344bb73612 (patch)
tree5d3a3567a1a58335ed2f38d8228cf24483f79b14
parenta6003397f7b74f7af6c21954073e046de08f43c9 (diff)
parent49b4c5c700077e387fef61a7225f92d190ee0c45 (diff)
Merge git://git.denx.de/u-boot-usb
-rw-r--r--board/h2200/h2200.c12
-rw-r--r--common/Makefile1
-rw-r--r--common/cmd_dfu.c20
-rw-r--r--common/cmd_fitupd.c2
-rw-r--r--common/main.c2
-rw-r--r--common/update.c58
-rw-r--r--configs/am335x_boneblack_defconfig1
-rw-r--r--doc/README.dfutftp114
-rw-r--r--doc/README.update7
-rw-r--r--drivers/dfu/Kconfig10
-rw-r--r--drivers/dfu/Makefile1
-rw-r--r--drivers/dfu/dfu.c39
-rw-r--r--drivers/dfu/dfu_tftp.c65
-rw-r--r--drivers/usb/gadget/f_thor.c9
-rw-r--r--drivers/usb/gadget/f_thor.h3
-rw-r--r--drivers/usb/host/ehci-hcd.c7
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--include/configs/bcm28155_ap.h19
-rw-r--r--include/dfu.h41
-rw-r--r--include/net.h14
-rw-r--r--include/net/tftp.h (renamed from net/tftp.h)0
-rw-r--r--net/bootp.c2
-rw-r--r--net/net.c2
-rw-r--r--net/rarp.c2
-rw-r--r--net/tftp.c2
-rw-r--r--test/dfu/README9
-rwxr-xr-xtest/dfu/dfu_gadget_test.sh18
27 files changed, 426 insertions, 35 deletions
diff --git a/board/h2200/h2200.c b/board/h2200/h2200.c
index 66ae4b6906b..01f8e67be14 100644
--- a/board/h2200/h2200.c
+++ b/board/h2200/h2200.c
@@ -59,3 +59,15 @@ int dram_init(void)
gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
return 0;
}
+
+#ifdef CONFIG_USB_GADGET_PXA2XX
+int board_usb_init(int index, enum usb_init_type init)
+{
+ return 0;
+}
+
+int board_usb_cleanup(int index, enum usb_init_type init)
+{
+ return 0;
+}
+#endif
diff --git a/common/Makefile b/common/Makefile
index f4ba8782f54..556fb075929 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -210,6 +210,7 @@ obj-$(CONFIG_LYNXKDI) += lynxkdi.o
obj-$(CONFIG_MENU) += menu.o
obj-$(CONFIG_MODEM_SUPPORT) += modem.o
obj-$(CONFIG_UPDATE_TFTP) += update.o
+obj-$(CONFIG_DFU_TFTP) += update.o
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
obj-$(CONFIG_CMD_DFU) += cmd_dfu.o
obj-$(CONFIG_CMD_GPT) += cmd_gpt.o
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
index 857148f8afe..f060db75c6c 100644
--- a/common/cmd_dfu.c
+++ b/common/cmd_dfu.c
@@ -1,6 +1,9 @@
/*
* cmd_dfu.c -- dfu command
*
+ * Copyright (C) 2015
+ * Lukasz Majewski <l.majewski@majess.pl>
+ *
* Copyright (C) 2012 Samsung Electronics
* authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
* Lukasz Majewski <l.majewski@samsung.com>
@@ -13,6 +16,7 @@
#include <dfu.h>
#include <g_dnl.h>
#include <usb.h>
+#include <net.h>
static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
@@ -26,6 +30,15 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
char *devstring = argv[3];
int ret, i = 0;
+#ifdef CONFIG_DFU_TFTP
+ unsigned long addr = 0;
+ if (!strcmp(argv[1], "tftp")) {
+ if (argc == 5)
+ addr = simple_strtoul(argv[4], NULL, 0);
+
+ return update_tftp(addr, interface, devstring);
+ }
+#endif
ret = dfu_init_env_entities(interface, devstring);
if (ret)
@@ -89,4 +102,11 @@ U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
" on device <dev>, attached to interface\n"
" <interface>\n"
" [list] - list available alt settings\n"
+#ifdef CONFIG_DFU_TFTP
+ "dfu tftp <interface> <dev> [<addr>]\n"
+ " - device firmware upgrade via TFTP\n"
+ " on device <dev>, attached to interface\n"
+ " <interface>\n"
+ " [<addr>] - address where FIT image has been stored\n"
+#endif
);
diff --git a/common/cmd_fitupd.c b/common/cmd_fitupd.c
index b0459744d98..78b8747336a 100644
--- a/common/cmd_fitupd.c
+++ b/common/cmd_fitupd.c
@@ -23,7 +23,7 @@ static int do_fitupd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (argc == 2)
addr = simple_strtoul(argv[1], NULL, 16);
- return update_tftp(addr);
+ return update_tftp(addr, NULL, NULL);
}
U_BOOT_CMD(fitupd, 2, 0, do_fitupd,
diff --git a/common/main.c b/common/main.c
index 2979fbed630..ead0cd17aa8 100644
--- a/common/main.c
+++ b/common/main.c
@@ -75,7 +75,7 @@ void main_loop(void)
run_preboot_environment_command();
#if defined(CONFIG_UPDATE_TFTP)
- update_tftp(0UL);
+ update_tftp(0UL, NULL, NULL);
#endif /* CONFIG_UPDATE_TFTP */
s = bootdelay_process();
diff --git a/common/update.c b/common/update.c
index 1c6aa186d0d..1da80b70f2d 100644
--- a/common/update.c
+++ b/common/update.c
@@ -13,8 +13,8 @@
#error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature"
#endif
-#if defined(CONFIG_SYS_NO_FLASH)
-#error "CONFIG_SYS_NO_FLASH defined, but FLASH is required for auto-update feature"
+#if defined(CONFIG_UPDATE_TFTP) && defined(CONFIG_SYS_NO_FLASH)
+#error "CONFIG_UPDATE_TFTP and CONFIG_SYS_NO_FLASH needed for legacy behaviour"
#endif
#include <command.h>
@@ -22,6 +22,8 @@
#include <net.h>
#include <net/tftp.h>
#include <malloc.h>
+#include <dfu.h>
+#include <errno.h>
/* env variable holding the location of the update file */
#define UPDATE_FILE_ENV "updatefile"
@@ -41,11 +43,11 @@
extern ulong tftp_timeout_ms;
extern int tftp_timeout_count_max;
-extern flash_info_t flash_info[];
extern ulong load_addr;
-
+#ifndef CONFIG_SYS_NO_FLASH
+extern flash_info_t flash_info[];
static uchar *saved_prot_info;
-
+#endif
static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
{
int size, rv;
@@ -94,6 +96,7 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
return rv;
}
+#ifndef CONFIG_SYS_NO_FLASH
static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
{
uchar *sp_info_ptr;
@@ -165,9 +168,11 @@ static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
return 0;
}
+#endif
static int update_flash(ulong addr_source, ulong addr_first, ulong size)
{
+#ifndef CONFIG_SYS_NO_FLASH
ulong addr_last = addr_first + size - 1;
/* round last address to the sector boundary */
@@ -203,7 +208,7 @@ static int update_flash(ulong addr_source, ulong addr_first, ulong size)
printf("Error: could not protect flash sectors\n");
return 1;
}
-
+#endif
return 0;
}
@@ -223,13 +228,24 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
return 0;
}
-int update_tftp(ulong addr)
+int update_tftp(ulong addr, char *interface, char *devstring)
{
- char *filename, *env_addr;
- int images_noffset, ndepth, noffset;
+ char *filename, *env_addr, *fit_image_name;
ulong update_addr, update_fladdr, update_size;
- void *fit;
+ int images_noffset, ndepth, noffset;
+ bool update_tftp_dfu;
int ret = 0;
+ void *fit;
+
+ if (interface == NULL && devstring == NULL) {
+ update_tftp_dfu = false;
+ } else if (interface && devstring) {
+ update_tftp_dfu = true;
+ } else {
+ error("Interface: %s and devstring: %s not supported!\n",
+ interface, devstring);
+ return -EINVAL;
+ }
/* use already present image */
if (addr)
@@ -278,8 +294,8 @@ got_update_file:
if (ndepth != 1)
goto next_node;
- printf("Processing update '%s' :",
- fit_get_name(fit, noffset, NULL));
+ fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
+ printf("Processing update '%s' :", fit_image_name);
if (!fit_image_verify(fit, noffset)) {
printf("Error: invalid update hash, aborting\n");
@@ -295,10 +311,20 @@ got_update_file:
ret = 1;
goto next_node;
}
- if (update_flash(update_addr, update_fladdr, update_size)) {
- printf("Error: can't flash update, aborting\n");
- ret = 1;
- goto next_node;
+
+ if (!update_tftp_dfu) {
+ if (update_flash(update_addr, update_fladdr,
+ update_size)) {
+ printf("Error: can't flash update, aborting\n");
+ ret = 1;
+ goto next_node;
+ }
+ } else if (fit_image_check_type(fit, noffset,
+ IH_TYPE_FIRMWARE)) {
+ ret = dfu_tftp_write(fit_image_name, update_addr,
+ update_size, interface, devstring);
+ if (ret)
+ return ret;
}
next_node:
noffset = fdt_next_node(fit, noffset, &ndepth);
diff --git a/configs/am335x_boneblack_defconfig b/configs/am335x_boneblack_defconfig
index 60339c8725e..f1ff65fa835 100644
--- a/configs/am335x_boneblack_defconfig
+++ b/configs/am335x_boneblack_defconfig
@@ -8,3 +8,4 @@ CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT"
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_SETEXPR is not set
CONFIG_SPI_FLASH=y
+CONFIG_DFU_TFTP=y
diff --git a/doc/README.dfutftp b/doc/README.dfutftp
new file mode 100644
index 00000000000..0257f0d5037
--- /dev/null
+++ b/doc/README.dfutftp
@@ -0,0 +1,114 @@
+Device Firmware Upgrade (DFU) - extension to use TFTP
+=====================================================
+
+Why?
+----
+
+* Update TFTP (CONFIG_UPDATE_TFTP) only supports writing
+code to NAND memory via TFTP.
+* DFU supports writing data to the variety of mediums (NAND,
+eMMC, SD, partitions, RAM, etc) via USB.
+
+Combination of both solves their shortcomings!
+
+
+Overview
+--------
+
+This document briefly describes how to use DFU for
+upgrading firmware (e.g. kernel, u-boot, rootfs, etc.)
+via TFTP protocol.
+
+By using Ethernet (TFTP protocol to be precise) it is
+possible to overcome the major problem of USB based DFU -
+the relatively low transfer speed for large files.
+This was caused by DFU standard, which imposed utilization
+of only EP0 for transfer. By using Ethernet we can circumvent
+this shortcoming.
+
+Beagle Bone Black rev. C (BBB) powered by TI's am335x CPU has
+been used as a demo board.
+
+To utilize this feature, one needs to first enable support
+for USB based DFU (CONFIG_DFU_*) and DFU TFTP update
+(CONFIG_DFU_TFTP) described in ./doc/README.update.
+
+The "dfu" command has been extended to support transfer via TFTP - one
+needs to type for example "dfu tftp 0 mmc 0"
+
+This feature does not depend on "fitupd" command enabled.
+
+As of this writing (SHA1:8d77576371381ade83de475bb639949b44941e8c v2015.10-rc2)
+the update.c code is not enabled (CONFIG_UPDATE_TFTP) by any board in the
+contemporary u-boot tree.
+
+
+Environment variables
+---------------------
+
+The "dfu tftp" command can be used in the "preboot" environment variable
+(when it is enabled by defining CONFIG_PREBOOT).
+This is the preferable way of using this command in the early boot stage
+as opposed to legacy update_tftp() function invocation.
+
+
+Beagle Bone Black (BBB) setup
+-----------------------------
+
+1. Setup tftp env variables:
+ * select desired eth device - 'ethact' variable ["ethact=cpsw"]
+ (use "bdinfo" to check current setting)
+ * setup "serverip" and "ipaddr" variables
+ * set "loadaddr" as a fixed buffer where incoming data is placed
+ ["loadaddr=0x81000000"]
+
+#########
+# BONUS #
+#########
+It is possible to use USB interface to emulate ETH connection by setting
+"ethact=usb_ether". In this way one can have very fast DFU transfer via USB.
+
+For 33MiB test image the transfer rate was 1MiB/s for ETH over USB and 200KiB/s
+for pure DFU USB transfer.
+
+2. Setup update_tftp variables:
+ * set "updatefile" - the file name to be downloaded via TFTP (stored on
+ the HOST at e.g. /srv/tftp)
+
+3. If required, to update firmware on boot, put the "dfu tftp 0 mmc 0" in the
+ "preboot" env variable. Otherwise use this command from u-boot prompt.
+
+4. Inspect "dfu" specific variables:
+ * "dfu_alt_info" - information about available DFU entities
+ * "dfu_bufsiz" - variable to set buffer size [in bytes] - when it is not
+ possible to set large enough default buffer (8 MiB @ BBB)
+
+
+
+FIT image format for download
+-----------------------------
+
+To create FIT image for download one should follow the update tftp README file
+(./doc/README.update) with one notable difference:
+
+The original snippet of ./doc/uImage.FIT/update_uboot.its
+
+ images {
+ update@1 {
+ description = "U-Boot binary";
+
+should look like
+
+ images {
+ u-boot.bin@1 {
+ description = "U-Boot binary";
+
+where "u-boot.bin" is the DFU entity name to be stored.
+
+
+
+To do
+-----
+
+* Extend dfu-util command to support TFTP based transfers
+* Upload support (via TFTP)
diff --git a/doc/README.update b/doc/README.update
index a7f4d9ebe5d..eab124ce1d9 100644
--- a/doc/README.update
+++ b/doc/README.update
@@ -93,3 +93,10 @@ Example .its files
An example containing three updates. It can be used to update Linux kernel,
ramdisk and FDT blob stored in Flash. The procedure for preparing the update
file is similar to the example above.
+
+TFTP update via DFU
+-------------------
+
+- It is now possible to update firmware (bootloader, kernel, rootfs, etc.) via
+ TFTP by using DFU (Device Firmware Upgrade). More information can be found in
+ ./doc/README.dfutftp documentation entry.
diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig
index e69de29bb2d..4fe22193b14 100644
--- a/drivers/dfu/Kconfig
+++ b/drivers/dfu/Kconfig
@@ -0,0 +1,10 @@
+menu "DFU support"
+
+config DFU_TFTP
+ bool "DFU via TFTP"
+ help
+ This option allows performing update of DFU managed medium with data
+ send via TFTP boot.
+ Detailed description of this feature can be found at ./doc/README.dfutftp
+
+endmenu
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index cebea30ac3c..61f2b71f918 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -10,3 +10,4 @@ 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
+obj-$(CONFIG_DFU_TFTP) += dfu_tftp.o
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
index 675162d927d..6cf240de22d 100644
--- a/drivers/dfu/dfu.c
+++ b/drivers/dfu/dfu.c
@@ -76,7 +76,7 @@ int dfu_init_env_entities(char *interface, char *devstr)
}
static unsigned char *dfu_buf;
-static unsigned long dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE;
+static unsigned long dfu_buf_size;
unsigned char *dfu_free_buf(void)
{
@@ -568,3 +568,40 @@ int dfu_get_alt(char *name)
return -ENODEV;
}
+
+int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size)
+{
+ unsigned long dfu_buf_size, write, left = size;
+ int i, ret = 0;
+ void *dp = buf;
+
+ /*
+ * Here we must call dfu_get_buf(dfu) first to be sure that dfu_buf_size
+ * has been properly initialized - e.g. if "dfu_bufsiz" has been taken
+ * into account.
+ */
+ dfu_get_buf(dfu);
+ dfu_buf_size = dfu_get_buf_size();
+ debug("%s: dfu buf size: %lu\n", __func__, dfu_buf_size);
+
+ for (i = 0; left > 0; i++) {
+ write = min(dfu_buf_size, left);
+
+ debug("%s: dp: 0x%p left: %lu write: %lu\n", __func__,
+ dp, left, write);
+ ret = dfu_write(dfu, dp, write, i);
+ if (ret) {
+ error("DFU write failed\n");
+ return ret;
+ }
+
+ dp += write;
+ left -= write;
+ }
+
+ ret = dfu_flush(dfu, NULL, 0, i);
+ if (ret)
+ error("DFU flush failed!");
+
+ return ret;
+}
diff --git a/drivers/dfu/dfu_tftp.c b/drivers/dfu/dfu_tftp.c
new file mode 100644
index 00000000000..cd71708231f
--- /dev/null
+++ b/drivers/dfu/dfu_tftp.c
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2015
+ * Lukasz Majewski <l.majewski@majess.pl>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <dfu.h>
+
+int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
+ char *interface, char *devstring)
+{
+ char *s, *sb;
+ int alt_setting_num, ret;
+ struct dfu_entity *dfu;
+
+ debug("%s: name: %s addr: 0x%x len: %d device: %s:%s\n", __func__,
+ dfu_entity_name, addr, len, interface, devstring);
+
+ ret = dfu_init_env_entities(interface, devstring);
+ if (ret)
+ goto done;
+
+ /*
+ * We need to copy name pointed by *dfu_entity_name since this text
+ * is the integral part of the FDT image.
+ * Any implicit modification (i.e. done by strsep()) will corrupt
+ * the FDT image and prevent other images to be stored.
+ */
+ s = strdup(dfu_entity_name);
+ sb = s;
+ if (!s) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ strsep(&s, "@");
+ debug("%s: image name: %s strlen: %d\n", __func__, sb, strlen(sb));
+
+ alt_setting_num = dfu_get_alt(sb);
+ free(sb);
+ if (alt_setting_num < 0) {
+ error("Alt setting [%d] to write not found!",
+ alt_setting_num);
+ ret = -ENODEV;
+ goto done;
+ }
+
+ dfu = dfu_get_entity(alt_setting_num);
+ if (!dfu) {
+ error("DFU entity for alt: %d not found!", alt_setting_num);
+ ret = -ENODEV;
+ goto done;
+ }
+
+ ret = dfu_write_from_mem_addr(dfu, (void *)addr, len);
+
+done:
+ dfu_free_entities();
+
+ return ret;
+}
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index 6346370cd67..06139ee04d2 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -123,6 +123,9 @@ static int process_rqt_cmd(const struct rqt_box *rqt)
send_rsp(rsp);
g_dnl_unregister();
dfu_free_entities();
+#ifdef CONFIG_THOR_RESET_OFF
+ return RESET_DONE;
+#endif
run_command("reset", 0);
break;
case RQT_CMD_POWEROFF:
@@ -728,6 +731,10 @@ int thor_handle(void)
if (ret > 0) {
ret = process_data();
+#ifdef CONFIG_THOR_RESET_OFF
+ if (ret == RESET_DONE)
+ break;
+#endif
if (ret < 0)
return ret;
} else {
@@ -768,7 +775,7 @@ static int thor_func_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
}
dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
- gadget->ep0->maxpacket);
+ THOR_PACKET_SIZE);
if (!dev->req->buf) {
status = -ENOMEM;
goto fail;
diff --git a/drivers/usb/gadget/f_thor.h b/drivers/usb/gadget/f_thor.h
index 833a9d24ae7..83412851dd1 100644
--- a/drivers/usb/gadget/f_thor.h
+++ b/drivers/usb/gadget/f_thor.h
@@ -121,4 +121,7 @@ struct f_thor {
#define F_NAME_BUF_SIZE 32
#define THOR_PACKET_SIZE SZ_1M /* 1 MiB */
#define THOR_STORE_UNIT_SIZE SZ_32M /* 32 MiB */
+#ifdef CONFIG_THOR_RESET_OFF
+#define RESET_DONE 0xFFFFFFFF
+#endif
#endif /* _USB_THOR_H_ */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 3a0d32ee2ba..88b670b7f8a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1645,8 +1645,10 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
ctrl->hcor = hcor;
ctrl->priv = ctrl;
- if (init == USB_INIT_DEVICE)
+ ctrl->init = init;
+ if (ctrl->init == USB_INIT_DEVICE)
goto done;
+
ret = ehci_reset(ctrl);
if (ret)
goto err;
@@ -1666,6 +1668,9 @@ int ehci_deregister(struct udevice *dev)
{
struct ehci_ctrl *ctrl = dev_get_priv(dev);
+ if (ctrl->init == USB_INIT_DEVICE)
+ return 0;
+
ehci_shutdown(ctrl);
return 0;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 3379c293c4d..b41c04a8b30 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -242,6 +242,7 @@ struct ehci_ops {
};
struct ehci_ctrl {
+ enum usb_init_type init;
struct ehci_hccr *hccr; /* R/O registers, not need for volatile */
struct ehci_hcor *hcor;
int rootdev;
diff --git a/include/configs/bcm28155_ap.h b/include/configs/bcm28155_ap.h
index b7c5716eae4..7b48875d638 100644
--- a/include/configs/bcm28155_ap.h
+++ b/include/configs/bcm28155_ap.h
@@ -153,4 +153,23 @@
#define CONFIG_G_DNL_PRODUCT_NUM 0x0d02 /* nexus one */
#define CONFIG_G_DNL_MANUFACTURER "Broadcom Corporation"
+/* Fastboot and USB OTG */
+#define CONFIG_USB_FUNCTION_FASTBOOT
+#define CONFIG_CMD_FASTBOOT
+#define CONFIG_FASTBOOT_FLASH
+#define CONFIG_FASTBOOT_FLASH_MMC_DEV 0
+#define CONFIG_SYS_CACHELINE_SIZE 64
+#define CONFIG_USB_FASTBOOT_BUF_SIZE (CONFIG_SYS_SDRAM_SIZE - SZ_1M)
+#define CONFIG_USB_FASTBOOT_BUF_ADDR CONFIG_SYS_SDRAM_BASE
+#define CONFIG_USB_GADGET
+#define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_VBUS_DRAW 0
+#define CONFIG_USB_GADGET_S3C_UDC_OTG
+#define CONFIG_USB_GADGET_BCM_UDC_OTG_PHY
+#define CONFIG_USB_GADGET_DOWNLOAD
+#define CONFIG_USBID_ADDR 0x34052c46
+#define CONFIG_G_DNL_VENDOR_NUM 0x18d1 /* google */
+#define CONFIG_G_DNL_PRODUCT_NUM 0x0d02 /* nexus one */
+#define CONFIG_G_DNL_MANUFACTURER "Broadcom Corporation"
+
#endif /* __BCM28155_AP_H */
diff --git a/include/dfu.h b/include/dfu.h
index 7d31abdf337..6118dc27b95 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -162,6 +162,21 @@ bool dfu_usb_get_reset(void);
int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+
+/**
+ * dfu_write_from_mem_addr - write data from memory to DFU managed medium
+ *
+ * This function adds support for writing data starting from fixed memory
+ * address (like $loadaddr) to dfu managed medium (e.g. NAND, MMC, file system)
+ *
+ * @param dfu - dfu entity to which we want to store data
+ * @param buf - fixed memory addres from where data starts
+ * @param size - number of bytes to write
+ *
+ * @return - 0 on success, other value on failure
+ */
+int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size);
+
/* Device specific */
#ifdef CONFIG_DFU_MMC
extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s);
@@ -207,5 +222,31 @@ static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr,
}
#endif
+/**
+ * dfu_tftp_write - Write TFTP data to DFU medium
+ *
+ * This function is storing data received via TFTP on DFU supported medium.
+ *
+ * @param dfu_entity_name - name of DFU entity to write
+ * @param addr - address of data buffer to write
+ * @param len - number of bytes
+ * @param interface - destination DFU medium (e.g. "mmc")
+ * @param devstring - instance number of destination DFU medium (e.g. "1")
+ *
+ * @return 0 on success, otherwise error code
+ */
+#ifdef CONFIG_DFU_TFTP
+int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
+ char *interface, char *devstring);
+#else
+static inline int dfu_tftp_write(char *dfu_entity_name, unsigned int addr,
+ unsigned int len, char *interface,
+ char *devstring)
+{
+ puts("TFTP write support for DFU not available!\n");
+ return -ENOSYS;
+}
+#endif
+
int dfu_add(struct usb_configuration *c);
#endif /* __DFU_ENTITY_H_ */
diff --git a/include/net.h b/include/net.h
index d09bec9de15..f1671e38dea 100644
--- a/include/net.h
+++ b/include/net.h
@@ -813,8 +813,18 @@ void copy_filename(char *dst, const char *src, int size);
/* get a random source port */
unsigned int random_port(void);
-/* Update U-Boot over TFTP */
-int update_tftp(ulong addr);
+/**
+ * update_tftp - Update firmware over TFTP (via DFU)
+ *
+ * This function updates board's firmware via TFTP
+ *
+ * @param addr - memory address where data is stored
+ * @param interface - the DFU medium name - e.g. "mmc"
+ * @param devstring - the DFU medium number - e.g. "1"
+ *
+ * @return - 0 on success, other value on failure
+ */
+int update_tftp(ulong addr, char *interface, char *devstring);
/**********************************************************************/
diff --git a/net/tftp.h b/include/net/tftp.h
index c411c9b2e65..c411c9b2e65 100644
--- a/net/tftp.h
+++ b/include/net/tftp.h
diff --git a/net/bootp.c b/net/bootp.c
index 43466af2f39..b2f8ad4ded9 100644
--- a/net/bootp.c
+++ b/net/bootp.c
@@ -11,8 +11,8 @@
#include <common.h>
#include <command.h>
#include <net.h>
+#include <net/tftp.h>
#include "bootp.h"
-#include "tftp.h"
#include "nfs.h"
#ifdef CONFIG_STATUS_LED
#include <status_led.h>
diff --git a/net/net.c b/net/net.c
index 2a6efd85eae..a115ce28927 100644
--- a/net/net.c
+++ b/net/net.c
@@ -86,6 +86,7 @@
#include <environment.h>
#include <errno.h>
#include <net.h>
+#include <net/tftp.h>
#if defined(CONFIG_STATUS_LED)
#include <miiphy.h>
#include <status_led.h>
@@ -105,7 +106,6 @@
#if defined(CONFIG_CMD_SNTP)
#include "sntp.h"
#endif
-#include "tftp.h"
DECLARE_GLOBAL_DATA_PTR;
diff --git a/net/rarp.c b/net/rarp.c
index 4ce2f37a8a6..1fa11b690d2 100644
--- a/net/rarp.c
+++ b/net/rarp.c
@@ -8,10 +8,10 @@
#include <common.h>
#include <command.h>
#include <net.h>
+#include <net/tftp.h>
#include "nfs.h"
#include "bootp.h"
#include "rarp.h"
-#include "tftp.h"
#define TIMEOUT 5000UL /* Milliseconds before trying BOOTP again */
#ifndef CONFIG_NET_RETRY_COUNT
diff --git a/net/tftp.c b/net/tftp.c
index 18ce84c2021..181f0f363e7 100644
--- a/net/tftp.c
+++ b/net/tftp.c
@@ -10,7 +10,7 @@
#include <command.h>
#include <mapmem.h>
#include <net.h>
-#include "tftp.h"
+#include <net/tftp.h>
#include "bootp.h"
#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
#include <flash.h>
diff --git a/test/dfu/README b/test/dfu/README
index 5176aba632c..408d5594219 100644
--- a/test/dfu/README
+++ b/test/dfu/README
@@ -26,12 +26,19 @@ Example usage:
setenv dfu_alt_info dfu_test.bin fat 0 6\;dfudummy.bin fat 0 6
dfu 0 mmc 0
2. On the host:
- test/dfu/dfu_gadget_test.sh X Y [test file name]
+ test/dfu/dfu_gadget_test.sh X Y [test file name] [usb device vendor:product]
e.g. test/dfu/dfu_gadget_test.sh 0 1
or
e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img
+ or
+ e.g. test/dfu/dfu_gadget_test.sh 0 1 0451:d022
+ or
+ e.g. test/dfu/dfu_gadget_test.sh 0 1 ./dat_960.img 0451:d022
... where X and Y are dfu_test.bin's and dfudummy.bin's alt setting numbers.
They can be obtained from dfu-util -l or $dfu_alt_info.
It is also possible to pass optional [test file name] to force the script to
test one particular file.
+If many DFU devices are connected, it may be useful to filter on USB
+vendor/product ID (0451:d022).
+One can get them by running "lsusb" command on a host PC.
diff --git a/test/dfu/dfu_gadget_test.sh b/test/dfu/dfu_gadget_test.sh
index 2f5b7db58d4..9c7942257b4 100755
--- a/test/dfu/dfu_gadget_test.sh
+++ b/test/dfu/dfu_gadget_test.sh
@@ -45,18 +45,18 @@ dfu_test_file () {
printf "$COLOUR_GREEN ========================================================================================= $COLOUR_DEFAULT\n"
printf "File:$COLOUR_GREEN %s $COLOUR_DEFAULT\n" $1
- dfu-util -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
+ dfu-util $USB_DEV -D $1 -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
echo -n "TX: "
calculate_md5sum $1
MD5_TX=$MD5SUM
- dfu-util -D ${DIR}/dfudummy.bin -a $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $?
+ dfu-util $USB_DEV -D ${DIR}/dfudummy.bin -a $TARGET_ALT_SETTING_B >> $LOG_FILE 2>&1 || die $?
N_FILE=$DIR$RCV_DIR${1:2}"_rcv"
- dfu-util -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
+ dfu-util $USB_DEV -U $N_FILE -a $TARGET_ALT_SETTING >> $LOG_FILE 2>&1 || die $?
echo -n "RX: "
calculate_md5sum $N_FILE
@@ -89,13 +89,17 @@ fi
TARGET_ALT_SETTING=$1
TARGET_ALT_SETTING_B=$2
-if [ -n "$3" ]
+file=$3
+[[ $3 == *':'* ]] && USB_DEV="-d $3" && file=""
+[ $# -eq 4 ] && USB_DEV="-d $4"
+
+if [ -n "$file" ]
then
- dfu_test_file $3
+ dfu_test_file $file
else
- for file in $DIR*.$SUFFIX
+ for f in $DIR*.$SUFFIX
do
- dfu_test_file $file
+ dfu_test_file $f
done
fi