diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 347 | ||||
-rw-r--r-- | drivers/usb/gadget/f_thor.c | 65 | ||||
-rw-r--r-- | drivers/usb/host/xhci-rcar.c | 5 | ||||
-rw-r--r-- | drivers/usb/host/xhci-rockchip.c | 16 | ||||
-rw-r--r-- | drivers/usb/host/xhci-zynqmp.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 14 |
6 files changed, 85 insertions, 364 deletions
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 3acadae8b1..3ad4346f2d 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -18,16 +18,7 @@ #include <linux/usb/gadget.h> #include <linux/usb/composite.h> #include <linux/compiler.h> -#include <version.h> #include <g_dnl.h> -#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV -#include <fb_mmc.h> -#endif -#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV -#include <fb_nand.h> -#endif - -#define FASTBOOT_VERSION "0.4" #define FASTBOOT_INTERFACE_CLASS 0xff #define FASTBOOT_INTERFACE_SUB_CLASS 0x42 @@ -58,8 +49,6 @@ static inline struct f_fastboot *func_to_fastboot(struct usb_function *f) } static struct f_fastboot *fastboot_func; -static unsigned int download_size; -static unsigned int download_bytes; static struct usb_endpoint_descriptor fs_ep_in = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -147,22 +136,6 @@ static struct usb_gadget_strings *fastboot_strings[] = { }; static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); -static int strcmp_l1(const char *s1, const char *s2); - - -static char *fb_response_str; - -void fastboot_fail(const char *reason) -{ - strncpy(fb_response_str, "FAIL\0", 5); - strncat(fb_response_str, reason, FASTBOOT_RESPONSE_LEN - 4 - 1); -} - -void fastboot_okay(const char *reason) -{ - strncpy(fb_response_str, "OKAY\0", 5); - strncat(fb_response_str, reason, FASTBOOT_RESPONSE_LEN - 4 - 1); -} static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) { @@ -372,90 +345,9 @@ static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) do_reset(NULL, 0, 0, NULL); } -int __weak fb_set_reboot_flag(void) -{ - return -ENOSYS; -} - -static void cb_reboot(struct usb_ep *ep, struct usb_request *req) -{ - char *cmd = req->buf; - if (!strcmp_l1("reboot-bootloader", cmd)) { - if (fb_set_reboot_flag()) { - fastboot_tx_write_str("FAILCannot set reboot flag"); - return; - } - } - fastboot_func->in_req->complete = compl_do_reset; - fastboot_tx_write_str("OKAY"); -} - -static int strcmp_l1(const char *s1, const char *s2) -{ - if (!s1 || !s2) - return -1; - return strncmp(s1, s2, strlen(s1)); -} - -static void cb_getvar(struct usb_ep *ep, struct usb_request *req) -{ - char *cmd = req->buf; - char response[FASTBOOT_RESPONSE_LEN]; - const char *s; - size_t chars_left; - - strcpy(response, "OKAY"); - chars_left = sizeof(response) - strlen(response) - 1; - - strsep(&cmd, ":"); - if (!cmd) { - pr_err("missing variable"); - fastboot_tx_write_str("FAILmissing var"); - return; - } - - if (!strcmp_l1("version", cmd)) { - strncat(response, FASTBOOT_VERSION, chars_left); - } else if (!strcmp_l1("bootloader-version", cmd)) { - strncat(response, U_BOOT_VERSION, chars_left); - } else if (!strcmp_l1("downloadsize", cmd) || - !strcmp_l1("max-download-size", cmd)) { - char str_num[12]; - - sprintf(str_num, "0x%08x", CONFIG_FASTBOOT_BUF_SIZE); - strncat(response, str_num, chars_left); - } else if (!strcmp_l1("serialno", cmd)) { - s = env_get("serial#"); - if (s) - strncat(response, s, chars_left); - else - strcpy(response, "FAILValue not set"); - } else { - char *envstr; - - envstr = malloc(strlen("fastboot.") + strlen(cmd) + 1); - if (!envstr) { - fastboot_tx_write_str("FAILmalloc error"); - return; - } - - sprintf(envstr, "fastboot.%s", cmd); - s = env_get(envstr); - if (s) { - strncat(response, s, chars_left); - } else { - printf("WARNING: unknown variable: %s\n", cmd); - strcpy(response, "FAILVariable not implemented"); - } - - free(envstr); - } - fastboot_tx_write_str(response); -} - static unsigned int rx_bytes_expected(struct usb_ep *ep) { - int rx_remain = download_size - download_bytes; + int rx_remain = fastboot_data_remaining(); unsigned int rem; unsigned int maxpacket = ep->maxpacket; @@ -477,14 +369,12 @@ static unsigned int rx_bytes_expected(struct usb_ep *ep) return rx_remain; } -#define BYTES_PER_DOT 0x20000 static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) { - char response[FASTBOOT_RESPONSE_LEN]; - unsigned int transfer_size = download_size - download_bytes; + char response[FASTBOOT_RESPONSE_LEN] = {0}; + unsigned int transfer_size = fastboot_data_remaining(); const unsigned char *buffer = req->buf; unsigned int buffer_size = req->actual; - unsigned int pre_dot_num, now_dot_num; if (req->status != 0) { printf("Bad status: %d\n", req->status); @@ -494,33 +384,19 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) if (buffer_size < transfer_size) transfer_size = buffer_size; - memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + download_bytes, - buffer, transfer_size); - - pre_dot_num = download_bytes / BYTES_PER_DOT; - download_bytes += transfer_size; - now_dot_num = download_bytes / BYTES_PER_DOT; - - if (pre_dot_num != now_dot_num) { - putc('.'); - if (!(now_dot_num % 74)) - putc('\n'); - } + fastboot_data_download(buffer, transfer_size, response); + if (response[0]) { + fastboot_tx_write_str(response); + } else if (!fastboot_data_remaining()) { + fastboot_data_complete(response); - /* Check if transfer is done */ - if (download_bytes >= download_size) { /* - * Reset global transfer variable, keep download_bytes because - * it will be used in the next possible flashing command + * Reset global transfer variable */ - download_size = 0; req->complete = rx_handler_command; req->length = EP_BUFFER_SIZE; - strcpy(response, "OKAY"); fastboot_tx_write_str(response); - - printf("\ndownloading of %d bytes finished\n", download_bytes); } else { req->length = rx_bytes_expected(ep); } @@ -529,204 +405,55 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) usb_ep_queue(ep, req, 0); } -static void cb_download(struct usb_ep *ep, struct usb_request *req) -{ - char *cmd = req->buf; - char response[FASTBOOT_RESPONSE_LEN]; - - strsep(&cmd, ":"); - download_size = simple_strtoul(cmd, NULL, 16); - download_bytes = 0; - - printf("Starting download of %d bytes\n", download_size); - - if (0 == download_size) { - strcpy(response, "FAILdata invalid size"); - } else if (download_size > CONFIG_FASTBOOT_BUF_SIZE) { - download_size = 0; - strcpy(response, "FAILdata too large"); - } else { - sprintf(response, "DATA%08x", download_size); - req->complete = rx_handler_dl_image; - req->length = rx_bytes_expected(ep); - } - fastboot_tx_write_str(response); -} - -static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) -{ - char boot_addr_start[12]; - char *bootm_args[] = { "bootm", boot_addr_start, NULL }; - - puts("Booting kernel..\n"); - - sprintf(boot_addr_start, "0x%lx", (long)CONFIG_FASTBOOT_BUF_ADDR); - do_bootm(NULL, 0, 2, bootm_args); - - /* This only happens if image is somehow faulty so we start over */ - do_reset(NULL, 0, 0, NULL); -} - -static void cb_boot(struct usb_ep *ep, struct usb_request *req) -{ - fastboot_func->in_req->complete = do_bootm_on_complete; - fastboot_tx_write_str("OKAY"); -} - static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req) { g_dnl_trigger_detach(); } -static void cb_continue(struct usb_ep *ep, struct usb_request *req) +static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) { - fastboot_func->in_req->complete = do_exit_on_complete; - fastboot_tx_write_str("OKAY"); + fastboot_boot(); + do_exit_on_complete(ep, req); } -#ifdef CONFIG_FASTBOOT_FLASH -static void cb_flash(struct usb_ep *ep, struct usb_request *req) +static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) { - char *cmd = req->buf; - char response[FASTBOOT_RESPONSE_LEN]; + char *cmdbuf = req->buf; + char response[FASTBOOT_RESPONSE_LEN] = {0}; + int cmd = -1; - strsep(&cmd, ":"); - if (!cmd) { - pr_err("missing partition name"); - fastboot_tx_write_str("FAILmissing partition name"); + if (req->status != 0 || req->length == 0) return; - } - - /* initialize the response buffer */ - fb_response_str = response; - - fastboot_fail("no flash device defined"); -#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV - fb_mmc_flash_write(cmd, (void *)CONFIG_FASTBOOT_BUF_ADDR, - download_bytes); -#endif -#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV - fb_nand_flash_write(cmd, - (void *)CONFIG_FASTBOOT_BUF_ADDR, - download_bytes); -#endif - fastboot_tx_write_str(response); -} -#endif -static void cb_oem(struct usb_ep *ep, struct usb_request *req) -{ - char *cmd = req->buf; -#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV - if (strncmp("format", cmd + 4, 6) == 0) { - char cmdbuf[32]; - sprintf(cmdbuf, "gpt write mmc %x $partitions", - CONFIG_FASTBOOT_FLASH_MMC_DEV); - if (run_command(cmdbuf, 0)) - fastboot_tx_write_str("FAIL"); - else - fastboot_tx_write_str("OKAY"); - } else -#endif - if (strncmp("unlock", cmd + 4, 8) == 0) { - fastboot_tx_write_str("FAILnot implemented"); - } - else { - fastboot_tx_write_str("FAILunknown oem command"); + if (req->actual < req->length) { + cmdbuf[req->actual] = '\0'; + cmd = fastboot_handle_command(cmdbuf, response); + } else { + pr_err("buffer overflow"); + fastboot_fail("buffer overflow", response); } -} - -#ifdef CONFIG_FASTBOOT_FLASH -static void cb_erase(struct usb_ep *ep, struct usb_request *req) -{ - char *cmd = req->buf; - char response[FASTBOOT_RESPONSE_LEN]; - strsep(&cmd, ":"); - if (!cmd) { - pr_err("missing partition name"); - fastboot_tx_write_str("FAILmissing partition name"); - return; + if (!strncmp("DATA", response, 4)) { + req->complete = rx_handler_dl_image; + req->length = rx_bytes_expected(ep); } - /* initialize the response buffer */ - fb_response_str = response; - - fastboot_fail("no flash device defined"); -#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV - fb_mmc_erase(cmd); -#endif -#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV - fb_nand_erase(cmd); -#endif fastboot_tx_write_str(response); -} -#endif - -struct cmd_dispatch_info { - char *cmd; - void (*cb)(struct usb_ep *ep, struct usb_request *req); -}; - -static const struct cmd_dispatch_info cmd_dispatch_info[] = { - { - .cmd = "reboot", - .cb = cb_reboot, - }, { - .cmd = "getvar:", - .cb = cb_getvar, - }, { - .cmd = "download:", - .cb = cb_download, - }, { - .cmd = "boot", - .cb = cb_boot, - }, { - .cmd = "continue", - .cb = cb_continue, - }, -#ifdef CONFIG_FASTBOOT_FLASH - { - .cmd = "flash", - .cb = cb_flash, - }, { - .cmd = "erase", - .cb = cb_erase, - }, -#endif - { - .cmd = "oem", - .cb = cb_oem, - }, -}; - -static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) -{ - char *cmdbuf = req->buf; - void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL; - int i; - if (req->status != 0 || req->length == 0) - return; + if (!strncmp("OKAY", response, 4)) { + switch (cmd) { + case FASTBOOT_COMMAND_BOOT: + fastboot_func->in_req->complete = do_bootm_on_complete; + break; - for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) { - if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) { - func_cb = cmd_dispatch_info[i].cb; + case FASTBOOT_COMMAND_CONTINUE: + fastboot_func->in_req->complete = do_exit_on_complete; break; - } - } - if (!func_cb) { - pr_err("unknown command: %.*s", req->actual, cmdbuf); - fastboot_tx_write_str("FAILunknown command"); - } else { - if (req->actual < req->length) { - u8 *buf = (u8 *)req->buf; - buf[req->actual] = 0; - func_cb(ep, req); - } else { - pr_err("buffer overflow"); - fastboot_tx_write_str("FAILbuffer overflow"); + case FASTBOOT_COMMAND_REBOOT: + case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: + fastboot_func->in_req->complete = compl_do_reset; + break; } } diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index c8eda05832..1aa6be44bb 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -620,22 +620,6 @@ static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request *req) status, req->actual, req->length); } -static struct usb_request *thor_start_ep(struct usb_ep *ep) -{ - struct usb_request *req; - - req = alloc_ep_req(ep, THOR_PACKET_SIZE); - debug("%s: ep:%p req:%p\n", __func__, ep, req); - - if (!req) - return NULL; - - memset(req->buf, 0, req->length); - req->complete = thor_rx_tx_complete; - - return req; -} - static void thor_setup_complete(struct usb_ep *ep, struct usb_request *req) { if (req->status || req->actual != req->length) @@ -752,6 +736,13 @@ int thor_handle(void) return 0; } +static void free_ep_req(struct usb_ep *ep, struct usb_request *req) +{ + if (req->buf) + free(req->buf); + usb_ep_free_request(ep, req); +} + static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_gadget *gadget = c->cdev->gadget; @@ -860,21 +851,18 @@ static int thor_func_bind(struct usb_configuration *c, struct usb_function *f) return 0; fail: + if (dev->req) + free_ep_req(gadget->ep0, dev->req); free(dev); return status; } -static void free_ep_req(struct usb_ep *ep, struct usb_request *req) -{ - free(req->buf); - usb_ep_free_request(ep, req); -} - static void thor_unbind(struct usb_configuration *c, struct usb_function *f) { struct f_thor *f_thor = func_to_thor(f); struct thor_dev *dev = f_thor->dev; + free_ep_req(dev->gadget->ep0, dev->req); free(dev); memset(thor_func, 0, sizeof(*thor_func)); thor_func = NULL; @@ -895,8 +883,6 @@ static void thor_func_disable(struct usb_function *f) } if (dev->out_ep->driver_data) { - free(dev->out_req->buf); - dev->out_req->buf = NULL; usb_ep_free_request(dev->out_ep, dev->out_req); usb_ep_disable(dev->out_ep); dev->out_ep->driver_data = NULL; @@ -924,16 +910,17 @@ static int thor_eps_setup(struct usb_function *f) result = usb_ep_enable(ep, d); if (result) - goto exit; + goto err; ep->driver_data = cdev; /* claim */ - req = thor_start_ep(ep); + req = alloc_ep_req(ep, THOR_PACKET_SIZE); if (!req) { - usb_ep_disable(ep); result = -EIO; - goto exit; + goto err_disable_in_ep; } + memset(req->buf, 0, req->length); + req->complete = thor_rx_tx_complete; dev->in_req = req; ep = dev->out_ep; d = ep_desc(gadget, &hs_out_desc, &fs_out_desc); @@ -941,22 +928,34 @@ static int thor_eps_setup(struct usb_function *f) result = usb_ep_enable(ep, d); if (result) - goto exit; + goto err_free_in_req; ep->driver_data = cdev; /* claim */ - req = thor_start_ep(ep); + req = usb_ep_alloc_request(ep, 0); if (!req) { - usb_ep_disable(ep); result = -EIO; - goto exit; + goto err_disable_out_ep; } + req->complete = thor_rx_tx_complete; dev->out_req = req; /* ACM control EP */ ep = dev->int_ep; ep->driver_data = cdev; /* claim */ - exit: + return 0; + + err_disable_out_ep: + usb_ep_disable(dev->out_ep); + + err_free_in_req: + free_ep_req(dev->in_ep, dev->in_req); + dev->in_req = NULL; + + err_disable_in_ep: + usb_ep_disable(dev->in_ep); + + err: return result; } diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index a837afc483..f2e91ef0fe 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -117,12 +117,15 @@ err_clk: static int xhci_rcar_deregister(struct udevice *dev) { + int ret; struct rcar_xhci_platdata *plat = dev_get_platdata(dev); + ret = xhci_deregister(dev); + clk_disable(&plat->clk); clk_free(&plat->clk); - return xhci_deregister(dev); + return ret; } static int xhci_rcar_ofdata_to_platdata(struct udevice *dev) diff --git a/drivers/usb/host/xhci-rockchip.c b/drivers/usb/host/xhci-rockchip.c index 060a6c4309..f19bea3a91 100644 --- a/drivers/usb/host/xhci-rockchip.c +++ b/drivers/usb/host/xhci-rockchip.c @@ -17,7 +17,6 @@ struct rockchip_xhci_platdata { fdt_addr_t hcd_base; - fdt_addr_t phy_base; struct udevice *vbus_supply; }; @@ -35,7 +34,6 @@ struct rockchip_xhci { static int xhci_usb_ofdata_to_platdata(struct udevice *dev) { struct rockchip_xhci_platdata *plat = dev_get_platdata(dev); - struct udevice *child; int ret = 0; /* @@ -47,20 +45,6 @@ static int xhci_usb_ofdata_to_platdata(struct udevice *dev) return -ENXIO; } - /* Get the base address for usbphy from the device node */ - for (device_find_first_child(dev, &child); child; - device_find_next_child(&child)) { - if (!device_is_compatible(child, "rockchip,rk3399-usb3-phy")) - continue; - plat->phy_base = devfdt_get_addr(child); - break; - } - - if (plat->phy_base == FDT_ADDR_T_NONE) { - pr_err("Can't get the usbphy register address\n"); - return -ENXIO; - } - /* Vbus regulator */ ret = device_get_supply_regulator(dev, "vbus-supply", &plat->vbus_supply); diff --git a/drivers/usb/host/xhci-zynqmp.c b/drivers/usb/host/xhci-zynqmp.c index 7fe54281c3..e44e1ae1d9 100644 --- a/drivers/usb/host/xhci-zynqmp.c +++ b/drivers/usb/host/xhci-zynqmp.c @@ -13,7 +13,7 @@ #include <dm.h> #include <usb.h> #include <linux/errno.h> -#include <asm/arch-zynqmp/hardware.h> +#include <asm/arch/hardware.h> #include <linux/compat.h> #include <linux/usb/dwc3.h> #include "xhci.h" diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3adb0028f2..9ded14cc3c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -536,7 +536,7 @@ static int xhci_set_configuration(struct usb_device *udev) /* slot context */ xhci_slot_copy(ctrl, in_ctx, out_ctx); slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(LAST_CTX_MASK); + slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); @@ -1424,7 +1424,7 @@ static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev) ctrl_ctx = xhci_get_input_control_ctx(in_ctx); /* Initialize the input context control */ - ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); ctrl_ctx->drop_flags = 0; xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); @@ -1435,8 +1435,15 @@ static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev) /* Update hub related fields */ slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); - if (hub->tt.multi && udev->speed == USB_SPEED_HIGH) + /* + * refer to section 6.2.2: MTT should be 0 for full speed hub, + * but it may be already set to 1 when setup an xHCI virtual + * device, so clear it anyway. + */ + if (hub->tt.multi) slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); + else if (udev->speed == USB_SPEED_FULL) + slot_ctx->dev_info &= cpu_to_le32(~DEV_MTT); slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(udev->maxchild)); /* * Set TT think time - convert from ns to FS bit times. @@ -1452,6 +1459,7 @@ static int xhci_update_hub_device(struct udevice *dev, struct usb_device *udev) think_time = (think_time / 666) - 1; if (udev->speed == USB_SPEED_HIGH) slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time)); + slot_ctx->dev_state = 0; return xhci_configure_endpoints(udev, false); } |