summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile3
-rw-r--r--common/dfu.c92
-rw-r--r--common/spl/Makefile1
-rw-r--r--common/spl/spl.c10
-rw-r--r--common/spl/spl_dfu.c57
5 files changed, 162 insertions, 1 deletions
diff --git a/common/Makefile b/common/Makefile
index 9a9a065..ecc23e6 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -89,6 +89,8 @@ obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
endif # !CONFIG_SPL_BUILD
ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_DFU_SUPPORT) += dfu.o
+obj-$(CONFIG_SPL_DFU_SUPPORT) += cli_hush.o
obj-$(CONFIG_SPL_HASH_SUPPORT) += hash.o
obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o
obj-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
@@ -171,6 +173,7 @@ obj-$(CONFIG_CMDLINE) += cli_simple.o
obj-y += cli.o
obj-$(CONFIG_CMDLINE) += cli_readline.o
+obj-$(CONFIG_CMD_DFU) += dfu.o
obj-y += command.o
obj-y += s_record.o
obj-y += xyzModem.o
diff --git a/common/dfu.c b/common/dfu.c
new file mode 100644
index 0000000..4c529f7
--- /dev/null
+++ b/common/dfu.c
@@ -0,0 +1,92 @@
+/*
+ * 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>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <dfu.h>
+#include <console.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <net.h>
+
+int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
+{
+ bool dfu_reset = false;
+ int ret, i = 0;
+
+ board_usb_init(usbctrl_index, USB_INIT_DEVICE);
+ g_dnl_clear_detach();
+ ret = g_dnl_register(usb_dnl_gadget);
+ if (ret) {
+ error("g_dnl_register failed");
+ return CMD_RET_FAILURE;
+ }
+
+ while (1) {
+ if (g_dnl_detach()) {
+ /*
+ * Check if USB bus reset is performed after detach,
+ * which indicates that -R switch has been passed to
+ * dfu-util. In this case reboot the device
+ */
+ if (dfu_usb_get_reset()) {
+ dfu_reset = true;
+ goto exit;
+ }
+
+ /*
+ * This extra number of usb_gadget_handle_interrupts()
+ * calls is necessary to assure correct transmission
+ * completion with dfu-util
+ */
+ if (++i == 10000)
+ goto exit;
+ }
+
+ if (ctrlc())
+ goto exit;
+
+ if (dfu_get_defer_flush()) {
+ /*
+ * Call to usb_gadget_handle_interrupts() is necessary
+ * to act on ZLP OUT transaction from HOST PC after
+ * transmitting the whole file.
+ *
+ * If this ZLP OUT packet is NAK'ed, the HOST libusb
+ * function fails after timeout (by default it is set to
+ * 5 seconds). In such situation the dfu-util program
+ * exits with error message.
+ */
+ usb_gadget_handle_interrupts(usbctrl_index);
+ ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0);
+ dfu_set_defer_flush(NULL);
+ if (ret) {
+ error("Deferred dfu_flush() failed!");
+ goto exit;
+ }
+ }
+
+ WATCHDOG_RESET();
+ usb_gadget_handle_interrupts(usbctrl_index);
+ }
+exit:
+ g_dnl_unregister();
+ board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE);
+
+ if (dfu_reset)
+ run_command("reset", 0);
+
+ g_dnl_clear_detach();
+
+ return ret;
+}
diff --git a/common/spl/Makefile b/common/spl/Makefile
index b15f0f6..5bd0b18 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -24,4 +24,5 @@ obj-$(CONFIG_SPL_USB_SUPPORT) += spl_usb.o
obj-$(CONFIG_SPL_FAT_SUPPORT) += spl_fat.o
obj-$(CONFIG_SPL_EXT_SUPPORT) += spl_ext.o
obj-$(CONFIG_SPL_SATA_SUPPORT) += spl_sata.o
+obj-$(CONFIG_SPL_DFU_SUPPORT) += spl_dfu.o
endif
diff --git a/common/spl/spl.c b/common/spl/spl.c
index e14ec80..57b73af 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -174,7 +174,7 @@ __weak void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
# define CONFIG_SPL_LOAD_FIT_ADDRESS 0
#endif
-#ifdef CONFIG_SPL_RAM_DEVICE
+#if defined(CONFIG_SPL_RAM_DEVICE) || defined(CONFIG_SPL_DFU_SUPPORT)
static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector,
ulong count, void *buf)
{
@@ -312,6 +312,9 @@ struct boot_device_name boot_name_table[] = {
#ifdef CONFIG_SPL_USB_SUPPORT
{ BOOT_DEVICE_USB, "USB" },
#endif
+#ifdef CONFIG_SPL_DFU_SUPPORT
+ { BOOT_DEVICE_DFU, "USB DFU" },
+#endif
#ifdef CONFIG_SPL_SATA_SUPPORT
{ BOOT_DEVICE_SATA, "SATA" },
#endif
@@ -398,6 +401,11 @@ static int spl_load_image(u32 boot_device)
case BOOT_DEVICE_USB:
return spl_usb_load_image();
#endif
+#ifdef CONFIG_SPL_DFU_SUPPORT
+ case BOOT_DEVICE_DFU:
+ spl_dfu_cmd(0, "dfu_alt_info_ram", "ram", "0");
+ return spl_ram_load_image();
+#endif
#ifdef CONFIG_SPL_SATA_SUPPORT
case BOOT_DEVICE_SATA:
return spl_sata_load_image();
diff --git a/common/spl/spl_dfu.c b/common/spl/spl_dfu.c
new file mode 100644
index 0000000..e8d0ba1
--- /dev/null
+++ b/common/spl/spl_dfu.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2016
+ * Texas Instruments, <www.ti.com>
+ *
+ * Ravi B <ravibabu@ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <spl.h>
+#include <linux/compiler.h>
+#include <errno.h>
+#include <watchdog.h>
+#include <console.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <dfu.h>
+#include <environment.h>
+
+static int run_dfu(int usb_index, char *interface, char *devstring)
+{
+ int ret;
+
+ ret = dfu_init_env_entities(interface, devstring);
+ if (ret) {
+ dfu_free_entities();
+ goto exit;
+ }
+
+ run_usb_dnl_gadget(usb_index, "usb_dnl_dfu");
+exit:
+ dfu_free_entities();
+ return ret;
+}
+
+int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr)
+{
+ char *str_env;
+ int ret;
+
+ /* set default environment */
+ set_default_env(0);
+ str_env = getenv(dfu_alt_info);
+ if (!str_env) {
+ error("\"dfu_alt_info\" env variable not defined!\n");
+ return -EINVAL;
+ }
+
+ ret = setenv("dfu_alt_info", str_env);
+ if (ret) {
+ error("unable to set env variable \"dfu_alt_info\"!\n");
+ return -EINVAL;
+ }
+
+ /* invoke dfu command */
+ return run_dfu(usbctrl, interface, devstr);
+}