diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 3 | ||||
-rw-r--r-- | common/dfu.c | 92 | ||||
-rw-r--r-- | common/spl/Makefile | 1 | ||||
-rw-r--r-- | common/spl/spl.c | 10 | ||||
-rw-r--r-- | common/spl/spl_dfu.c | 57 |
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); +} |