summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/ci_udc.c5
-rw-r--r--drivers/usb/gadget/f_dfu.c11
-rw-r--r--drivers/usb/gadget/f_fastboot.c28
-rw-r--r--drivers/usb/gadget/f_mass_storage.c1
-rw-r--r--drivers/usb/gadget/f_thor.c10
-rw-r--r--drivers/usb/host/ehci-hcd.c65
-rw-r--r--drivers/usb/host/ehci-tegra.c4
-rw-r--r--drivers/usb/host/ehci.h1
-rw-r--r--drivers/usb/musb-new/musb_core.c2
9 files changed, 76 insertions, 51 deletions
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 2572b34..b0ef35e 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -777,6 +777,11 @@ static int ci_pullup(struct usb_gadget *gadget, int is_on)
/* select DEVICE mode */
writel(USBMODE_DEVICE, &udc->usbmode);
+#if !defined(CONFIG_USB_GADGET_DUALSPEED)
+ /* Port force Full-Speed Connect */
+ setbits_le32(&udc->portsc, PFSC);
+#endif
+
writel(0xffffffff, &udc->epflush);
/* Turn on the USB connection by enabling the pullup resistor */
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index 3e4f029..16fc9dd 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -81,14 +81,6 @@ static struct usb_descriptor_header *dfu_runtime_descs[] = {
NULL,
};
-static const struct usb_qualifier_descriptor dev_qualifier = {
- .bLength = sizeof dev_qualifier,
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_VENDOR_SPEC,
- .bNumConfigurations = 1,
-};
-
static const char dfu_name[] = "Device Firmware Upgrade";
/*
@@ -237,6 +229,7 @@ static inline void to_dfu_mode(struct f_dfu *f_dfu)
{
f_dfu->usb_function.strings = dfu_strings;
f_dfu->usb_function.hs_descriptors = f_dfu->function;
+ f_dfu->usb_function.descriptors = f_dfu->function;
f_dfu->dfu_state = DFU_STATE_dfuIDLE;
}
@@ -244,6 +237,7 @@ static inline void to_runtime_mode(struct f_dfu *f_dfu)
{
f_dfu->usb_function.strings = NULL;
f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+ f_dfu->usb_function.descriptors = dfu_runtime_descs;
}
static int handle_upload(struct usb_request *req, u16 len)
@@ -808,6 +802,7 @@ static int dfu_bind_config(struct usb_configuration *c)
return -ENOMEM;
f_dfu->usb_function.name = "dfu";
f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+ f_dfu->usb_function.descriptors = dfu_runtime_descs;
f_dfu->usb_function.bind = dfu_bind;
f_dfu->usb_function.unbind = dfu_unbind;
f_dfu->usb_function.set_alt = dfu_set_alt;
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 38c0965..71b62e5 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -351,10 +351,11 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
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)) {
+ } else if (!strcmp_l1("downloadsize", cmd) ||
+ !strcmp_l1("max-download-size", cmd)) {
char str_num[12];
- sprintf(str_num, "%08x", CONFIG_USB_FASTBOOT_BUF_SIZE);
+ sprintf(str_num, "0x%08x", CONFIG_USB_FASTBOOT_BUF_SIZE);
strncat(response, str_num, chars_left);
} else if (!strcmp_l1("serialno", cmd)) {
s = getenv("serial#");
@@ -386,6 +387,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
unsigned int transfer_size = download_size - download_bytes;
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);
@@ -398,7 +400,15 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
memcpy((void *)CONFIG_USB_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');
+ }
/* Check if transfer is done */
if (download_bytes >= download_size) {
@@ -420,11 +430,6 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
req->length = ep->maxpacket;
}
- if (download_bytes && !(download_bytes % BYTES_PER_DOT)) {
- putc('.');
- if (!(download_bytes % (74 * BYTES_PER_DOT)))
- putc('\n');
- }
req->actual = 0;
usb_ep_queue(ep, req, 0);
}
@@ -541,7 +546,14 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
error("unknown command: %s\n", cmdbuf);
fastboot_tx_write_str("FAILunknown command");
} else {
- func_cb(ep, req);
+ if (req->actual < req->length) {
+ u8 *buf = (u8 *)req->buf;
+ buf[req->actual] = 0;
+ func_cb(ep, req);
+ } else {
+ error("buffer overflow\n");
+ fastboot_tx_write_str("FAILbuffer overflow");
+ }
}
if (req->status == 0) {
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index f274d96..e045957 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -1110,6 +1110,7 @@ static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh)
memset(buf, 0, 8);
buf[0] = TYPE_DISK;
+ buf[1] = curlun->removable ? 0x80 : 0;
buf[2] = 2; /* ANSI SCSI level 2 */
buf[3] = 2; /* SCSI-2 INQUIRY data format */
buf[4] = 31; /* Additional length */
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index c85b0fb..78519fa 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -458,16 +458,6 @@ static struct usb_endpoint_descriptor hs_int_desc = {
.bInterval = 0x9,
};
-static struct usb_qualifier_descriptor dev_qualifier = {
- .bLength = sizeof(dev_qualifier),
- .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
-
- .bcdUSB = __constant_cpu_to_le16(0x0200),
- .bDeviceClass = USB_CLASS_VENDOR_SPEC,
-
- .bNumConfigurations = 2,
-};
-
/*
* This attribute vendor descriptor is necessary for correct operation with
* Windows version of THOR download program
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index eaf5913..6323c50 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -273,6 +273,29 @@ static inline u8 ehci_encode_speed(enum usb_device_speed speed)
return QH_FULL_SPEED;
}
+static void ehci_update_endpt2_dev_n_port(struct usb_device *dev,
+ struct QH *qh)
+{
+ struct usb_device *ttdev;
+
+ if (dev->speed != USB_SPEED_LOW && dev->speed != USB_SPEED_FULL)
+ return;
+
+ /*
+ * For full / low speed devices we need to get the devnum and portnr of
+ * the tt, so of the first upstream usb-2 hub, there may be usb-1 hubs
+ * in the tree before that one!
+ */
+ ttdev = dev;
+ while (ttdev->parent && ttdev->parent->speed != USB_SPEED_HIGH)
+ ttdev = ttdev->parent;
+ if (!ttdev->parent)
+ return;
+
+ qh->qh_endpt2 |= cpu_to_hc32(QH_ENDPT2_PORTNUM(ttdev->portnr) |
+ QH_ENDPT2_HUBADDR(ttdev->parent->devnum));
+}
+
static int
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
int length, struct devrequest *req)
@@ -390,10 +413,9 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) |
QH_ENDPT1_DEVADDR(usb_pipedevice(pipe));
qh->qh_endpt1 = cpu_to_hc32(endpt);
- endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_PORTNUM(dev->portnr) |
- QH_ENDPT2_HUBADDR(dev->parent->devnum) |
- QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0);
+ endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0);
qh->qh_endpt2 = cpu_to_hc32(endpt);
+ ehci_update_endpt2_dev_n_port(dev, qh);
qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -974,6 +996,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
* Set up periodic list
* Step 1: Parent QH for all periodic transfers.
*/
+ ehcic[index].periodic_schedules = 0;
periodic = &ehcic[index].periodic_queue;
memset(periodic, 0, sizeof(*periodic));
periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE);
@@ -1132,8 +1155,6 @@ disable_periodic(struct ehci_ctrl *ctrl)
return 0;
}
-static int periodic_schedules;
-
struct int_queue *
create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
int elementsize, void *buffer)
@@ -1201,12 +1222,10 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
(1 << 0)); /* S-mask: microframe 0 */
if (dev->speed == USB_SPEED_LOW ||
dev->speed == USB_SPEED_FULL) {
- debug("TT: port: %d, hub address: %d\n",
- dev->portnr, dev->parent->devnum);
- qh->qh_endpt2 |= cpu_to_hc32((dev->portnr << 23) |
- (dev->parent->devnum << 16) |
- (0x1c << 8)); /* C-mask: microframes 2-4 */
+ /* C-mask: microframes 2-4 */
+ qh->qh_endpt2 |= cpu_to_hc32((0x1c << 8));
}
+ ehci_update_endpt2_dev_n_port(dev, qh);
td->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE);
td->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -1258,7 +1277,7 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
debug("FATAL: periodic should never fail, but did");
goto fail3;
}
- periodic_schedules++;
+ ctrl->periodic_schedules++;
debug("Exit create_int_queue\n");
return result;
@@ -1277,6 +1296,7 @@ fail1:
void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
{
struct QH *cur = queue->current;
+ struct qTD *cur_td;
/* depleted queue */
if (cur == NULL) {
@@ -1284,20 +1304,21 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
return NULL;
}
/* still active */
- invalidate_dcache_range((uint32_t)cur,
- ALIGN_END_ADDR(struct QH, cur, 1));
- if (cur->qh_overlay.qt_token & cpu_to_hc32(0x80)) {
- debug("Exit poll_int_queue with no completed intr transfer. "
- "token is %x\n", cur->qh_overlay.qt_token);
+ cur_td = &queue->tds[queue->current - queue->first];
+ invalidate_dcache_range((uint32_t)cur_td,
+ ALIGN_END_ADDR(struct qTD, cur_td, 1));
+ if (QT_TOKEN_GET_STATUS(hc32_to_cpu(cur_td->qt_token)) &
+ QT_TOKEN_STATUS_ACTIVE) {
+ debug("Exit poll_int_queue with no completed intr transfer. token is %x\n",
+ hc32_to_cpu(cur_td->qt_token));
return NULL;
}
if (!(cur->qh_link & QH_LINK_TERMINATE))
queue->current++;
else
queue->current = NULL;
- debug("Exit poll_int_queue with completed intr transfer. "
- "token is %x at %p (first at %p)\n", cur->qh_overlay.qt_token,
- &cur->qh_overlay.qt_token, queue->first);
+ debug("Exit poll_int_queue with completed intr transfer. token is %x at %p (first at %p)\n",
+ hc32_to_cpu(cur_td->qt_token), cur, queue->first);
return cur->buffer;
}
@@ -1313,7 +1334,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
debug("FATAL: periodic should never fail, but did");
goto out;
}
- periodic_schedules--;
+ ctrl->periodic_schedules--;
struct QH *cur = &ctrl->periodic_queue;
timeout = get_timer(0) + 500; /* abort after 500ms */
@@ -1322,6 +1343,8 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
if (NEXT_QH(cur) == queue->first) {
debug("found candidate. removing from chain\n");
cur->qh_link = queue->last->qh_link;
+ flush_dcache_range((uint32_t)cur,
+ ALIGN_END_ADDR(struct QH, cur, 1));
result = 0;
break;
}
@@ -1333,7 +1356,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
}
}
- if (periodic_schedules > 0) {
+ if (ctrl->periodic_schedules > 0) {
result = enable_periodic(ctrl);
if (result < 0)
debug("FATAL: periodic should never fail, but did");
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 33e5ea9..5f0a98e 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -305,11 +305,11 @@ static void init_phy_mux(struct fdt_usb *config, uint pts,
#if defined(CONFIG_TEGRA20)
if (config->periph_id == PERIPH_ID_USBD) {
clrsetbits_le32(&usbctlr->port_sc1, PTS1_MASK,
- PTS_UTMI << PTS1_SHIFT);
+ pts << PTS1_SHIFT);
clrbits_le32(&usbctlr->port_sc1, STS1);
} else {
clrsetbits_le32(&usbctlr->port_sc1, PTS_MASK,
- PTS_UTMI << PTS_SHIFT);
+ pts << PTS_SHIFT);
clrbits_le32(&usbctlr->port_sc1, STS);
}
#else
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 093eb4b..433e703 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -246,6 +246,7 @@ struct ehci_ctrl {
struct QH qh_list __aligned(USB_DMA_MINALIGN);
struct QH periodic_queue __aligned(USB_DMA_MINALIGN);
uint32_t *periodic_list;
+ int periodic_schedules;
int ntds;
};
diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c
index 4edd6d7..242cc30 100644
--- a/drivers/usb/musb-new/musb_core.c
+++ b/drivers/usb/musb-new/musb_core.c
@@ -942,9 +942,7 @@ void musb_start(struct musb *musb)
/* put into basic highspeed mode and start session */
musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
-#ifdef CONFIG_USB_GADGET_DUALSPEED
| MUSB_POWER_HSENAB
-#endif
/* ENSUSPEND wedges tusb */
/* | MUSB_POWER_ENSUSPEND */
);