diff options
author | Tom Rini <trini@konsulko.com> | 2015-09-07 08:56:23 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2015-09-07 08:56:23 -0400 |
commit | cdc7732f3737f2bb97b77eb3d7c9da344bb73612 (patch) | |
tree | 5d3a3567a1a58335ed2f38d8228cf24483f79b14 /drivers | |
parent | a6003397f7b74f7af6c21954073e046de08f43c9 (diff) | |
parent | 49b4c5c700077e387fef61a7225f92d190ee0c45 (diff) |
Merge git://git.denx.de/u-boot-usb
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dfu/Kconfig | 10 | ||||
-rw-r--r-- | drivers/dfu/Makefile | 1 | ||||
-rw-r--r-- | drivers/dfu/dfu.c | 39 | ||||
-rw-r--r-- | drivers/dfu/dfu_tftp.c | 65 | ||||
-rw-r--r-- | drivers/usb/gadget/f_thor.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/f_thor.h | 3 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 7 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 1 |
8 files changed, 132 insertions, 3 deletions
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; |