Merge git://git.denx.de/u-boot-usb
diff --git a/common/usb.c b/common/usb.c
index 6283f39..7ff8ac5 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -959,8 +959,6 @@
 
 static int usb_setup_descriptor(struct usb_device *dev, bool do_read)
 {
-	__maybe_unused struct usb_device_descriptor *desc;
-
 	/*
 	 * This is a Windows scheme of initialization sequence, with double
 	 * reset of the device (Linux uses the same sequence)
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index 24a1a56..49bfc09 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -31,7 +31,7 @@
 #endif
 
 /* Keyboard sampling rate */
-#define REPEAT_RATE	(40 / 4)	/* 40msec -> 25cps */
+#define REPEAT_RATE	40		/* 40msec -> 25cps */
 #define REPEAT_DELAY	10		/* 10 x REPEAT_RATE = 400msec */
 
 #define NUM_LOCK	0x53
@@ -103,6 +103,7 @@
 	unsigned long	intpipe;
 	int		intpktsize;
 	int		intinterval;
+	unsigned long	last_report;
 	struct int_queue *intq;
 
 	uint32_t	repeat_delay;
@@ -310,7 +311,7 @@
 /* Interrupt polling */
 static inline void usb_kbd_poll_for_event(struct usb_device *dev)
 {
-#if	defined(CONFIG_SYS_USB_EVENT_POLL)
+#if defined(CONFIG_SYS_USB_EVENT_POLL)
 	struct usb_kbd_pdata *data = dev->privptr;
 
 	/* Submit a interrupt transfer request */
@@ -318,15 +319,17 @@
 			   data->intinterval);
 
 	usb_kbd_irq_worker(dev);
-#elif	defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
+#elif defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) || \
+      defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
+#if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
 	struct usb_interface *iface;
 	struct usb_kbd_pdata *data = dev->privptr;
 	iface = &dev->config.if_desc[0];
 	usb_get_report(dev, iface->desc.bInterfaceNumber,
 		       1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE);
-	if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE))
+	if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) {
 		usb_kbd_irq_worker(dev);
-#elif	defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
+#else
 	struct usb_kbd_pdata *data = dev->privptr;
 	if (poll_int_queue(dev, data->intq)) {
 		usb_kbd_irq_worker(dev);
@@ -335,6 +338,13 @@
 		data->intq = create_int_queue(dev, data->intpipe, 1,
 				      USB_KBD_BOOT_REPORT_SIZE, data->new,
 				      data->intinterval);
+#endif
+		data->last_report = get_timer(0);
+	/* Repeat last usb hid report every REPEAT_RATE ms for keyrepeat */
+	} else if (data->last_report != -1 &&
+		   get_timer(data->last_report) > REPEAT_RATE) {
+		usb_kbd_irq_worker(dev);
+		data->last_report = get_timer(0);
 	}
 #endif
 }
@@ -445,12 +455,16 @@
 	data->intpktsize = min(usb_maxpacket(dev, data->intpipe),
 			       USB_KBD_BOOT_REPORT_SIZE);
 	data->intinterval = ep->bInterval;
+	data->last_report = -1;
 
 	/* We found a USB Keyboard, install it. */
 	usb_set_protocol(dev, iface->desc.bInterfaceNumber, 0);
 
+#if !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) && \
+    !defined(CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE)
 	debug("USB KBD: found set idle...\n");
-	usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE, 0);
+	usb_set_idle(dev, iface->desc.bInterfaceNumber, REPEAT_RATE / 4, 0);
+#endif
 
 	debug("USB KBD: enable interrupt pipe...\n");
 #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 22d288c..aadff42 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -50,6 +50,8 @@
 /* For each endpoint, we need 2 QTDs, one for each of IN and OUT */
 #define ILIST_SZ		(NUM_ENDPOINTS * 2 * ILIST_ENT_SZ)
 
+#define EP_MAX_LENGTH_TRANSFER	0x4000
+
 #ifndef DEBUG
 #define DBG(x...) do {} while (0)
 #else
@@ -102,13 +104,28 @@
 };
 
 /* Init values for USB endpoints. */
-static const struct usb_ep ci_ep_init[2] = {
+static const struct usb_ep ci_ep_init[5] = {
 	[0] = {	/* EP 0 */
 		.maxpacket	= 64,
 		.name		= "ep0",
 		.ops		= &ci_ep_ops,
 	},
-	[1] = {	/* EP 1..n */
+	[1] = {
+		.maxpacket	= 512,
+		.name		= "ep1in-bulk",
+		.ops		= &ci_ep_ops,
+	},
+	[2] = {
+		.maxpacket	= 512,
+		.name		= "ep2out-bulk",
+		.ops		= &ci_ep_ops,
+	},
+	[3] = {
+		.maxpacket	= 512,
+		.name		= "ep3in-int",
+		.ops		= &ci_ep_ops,
+	},
+	[4] = {
 		.maxpacket	= 512,
 		.name		= "ep-",
 		.ops		= &ci_ep_ops,
@@ -197,6 +214,19 @@
 }
 
 /**
+ * ci_flush_td - flush cache over queue item
+ * @td:	td pointer
+ *
+ * This function flushes cache for particular transfer descriptor.
+ */
+static void ci_flush_td(struct ept_queue_item *td)
+{
+	const uint32_t  start = (uint32_t)td;
+	const uint32_t end = (uint32_t) td + ILIST_ENT_SZ;
+	flush_dcache_range(start, end);
+}
+
+/**
  * ci_invalidate_qtd - invalidate cache over queue item
  * @ep_num:	Endpoint number
  *
@@ -211,6 +241,19 @@
 	invalidate_dcache_range(start, end);
 }
 
+/**
+ * ci_invalidate_td - invalidate cache over queue item
+ * @td:	td pointer
+ *
+ * This function invalidates cache for particular transfer descriptor.
+ */
+static void ci_invalidate_td(struct ept_queue_item *td)
+{
+	const uint32_t start = (uint32_t)td;
+	const uint32_t end = start + ILIST_ENT_SZ;
+	invalidate_dcache_range(start, end);
+}
+
 static struct usb_request *
 ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
 {
@@ -376,6 +419,9 @@
 	struct ept_queue_head *head;
 	int bit, num, len, in;
 	struct ci_req *ci_req;
+	u8 *buf;
+	uint32_t length, actlen;
+	struct ept_queue_item *dtd, *qtd;
 
 	ci_ep->req_primed = true;
 
@@ -387,16 +433,41 @@
 	ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
 	len = ci_req->req.length;
 
-	item->info = INFO_BYTES(len) | INFO_ACTIVE;
-	item->page0 = (unsigned long)ci_req->hw_buf;
-	item->page1 = ((unsigned long)ci_req->hw_buf & 0xfffff000) + 0x1000;
-	item->page2 = ((unsigned long)ci_req->hw_buf & 0xfffff000) + 0x2000;
-	item->page3 = ((unsigned long)ci_req->hw_buf & 0xfffff000) + 0x3000;
-	item->page4 = ((unsigned long)ci_req->hw_buf & 0xfffff000) + 0x4000;
-
 	head->next = (unsigned long)item;
 	head->info = 0;
 
+	ci_req->dtd_count = 0;
+	buf = ci_req->hw_buf;
+	actlen = 0;
+	dtd = item;
+
+	do {
+		length = min(ci_req->req.length - actlen,
+			     (unsigned)EP_MAX_LENGTH_TRANSFER);
+
+		dtd->info = INFO_BYTES(length) | INFO_ACTIVE;
+		dtd->page0 = (unsigned long)buf;
+		dtd->page1 = ((unsigned long)buf & 0xfffff000) + 0x1000;
+		dtd->page2 = ((unsigned long)buf & 0xfffff000) + 0x2000;
+		dtd->page3 = ((unsigned long)buf & 0xfffff000) + 0x3000;
+		dtd->page4 = ((unsigned long)buf & 0xfffff000) + 0x4000;
+
+		len -= length;
+		actlen += length;
+		buf += length;
+
+		if (len) {
+			qtd = (struct ept_queue_item *)
+			       memalign(ILIST_ALIGN, ILIST_ENT_SZ);
+			dtd->next = (uint32_t)qtd;
+			dtd = qtd;
+			memset(dtd, 0, ILIST_ENT_SZ);
+		}
+
+		ci_req->dtd_count++;
+	} while (len);
+
+	item = dtd;
 	/*
 	 * When sending the data for an IN transaction, the attached host
 	 * knows that all data for the IN is sent when one of the following
@@ -432,6 +503,12 @@
 
 	ci_flush_qtd(num);
 
+	item = (struct ept_queue_item *)head->next;
+	while (item->next != TERMINATE) {
+		ci_flush_td((struct ept_queue_item *)item->next);
+		item = (struct ept_queue_item *)item->next;
+	}
+
 	DBG("ept%d %s queue len %x, req %p, buffer %p\n",
 	    num, in ? "in" : "out", len, ci_req, ci_req->hw_buf);
 	ci_flush_qh(num);
@@ -497,21 +574,31 @@
 
 static void handle_ep_complete(struct ci_ep *ci_ep)
 {
-	struct ept_queue_item *item;
-	int num, in, len;
+	struct ept_queue_item *item, *next_td;
+	int num, in, len, j;
 	struct ci_req *ci_req;
 
 	num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
 	in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
 	item = ci_get_qtd(num, in);
 	ci_invalidate_qtd(num);
-
-	len = (item->info >> 16) & 0x7fff;
-	if (item->info & 0xff)
-		printf("EP%d/%s FAIL info=%x pg0=%x\n",
-		       num, in ? "in" : "out", item->info, item->page0);
-
 	ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
+
+	next_td = item;
+	len = 0;
+	for (j = 0; j < ci_req->dtd_count; j++) {
+		ci_invalidate_td(next_td);
+		item = next_td;
+		len += (item->info >> 16) & 0x7fff;
+		if (item->info & 0xff)
+			printf("EP%d/%s FAIL info=%x pg0=%x\n",
+			       num, in ? "in" : "out", item->info, item->page0);
+		if (j != ci_req->dtd_count - 1)
+			next_td = (struct ept_queue_item *)item->next;
+		if (j != 0)
+			free(item);
+	}
+
 	list_del_init(&ci_req->queue);
 	ci_ep->req_primed = false;
 
@@ -852,9 +939,19 @@
 	controller.gadget.ep0 = &controller.ep[0].ep;
 	INIT_LIST_HEAD(&controller.gadget.ep0->ep_list);
 
-	/* Init EP 1..n */
-	for (i = 1; i < NUM_ENDPOINTS; i++) {
-		memcpy(&controller.ep[i].ep, &ci_ep_init[1],
+	/* Init EP 1..3 */
+	for (i = 1; i < 4; i++) {
+		memcpy(&controller.ep[i].ep, &ci_ep_init[i],
+		       sizeof(*ci_ep_init));
+		INIT_LIST_HEAD(&controller.ep[i].queue);
+		controller.ep[i].req_primed = false;
+		list_add_tail(&controller.ep[i].ep.ep_list,
+			      &controller.gadget.ep_list);
+	}
+
+	/* Init EP 4..n */
+	for (i = 4; i < NUM_ENDPOINTS; i++) {
+		memcpy(&controller.ep[i].ep, &ci_ep_init[4],
 		       sizeof(*ci_ep_init));
 		INIT_LIST_HEAD(&controller.ep[i].queue);
 		controller.ep[i].req_primed = false;
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 346164a..95cc079 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -86,6 +86,7 @@
 	/* Buffer for the current transfer. Either req.buf/len or b_buf/len */
 	uint8_t *hw_buf;
 	uint32_t hw_len;
+	uint32_t dtd_count;
 };
 
 struct ci_ep {
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 2ac0017..eee60a2 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -932,7 +932,8 @@
 	snpsid = readl(&regs->gsnpsid);
 	printf("Core Release: %x.%03x\n", snpsid >> 12 & 0xf, snpsid & 0xfff);
 
-	if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx) {
+	if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx &&
+	    (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_3xx) {
 		printf("SNPSID invalid (not DWC2 OTG device): %08x\n", snpsid);
 		return -ENODEV;
 	}
diff --git a/drivers/usb/host/dwc2.h b/drivers/usb/host/dwc2.h
index 45408c6..f69372e 100644
--- a/drivers/usb/host/dwc2.h
+++ b/drivers/usb/host/dwc2.h
@@ -732,6 +732,7 @@
 #define DWC2_PCGCCTL_DEEP_SLEEP				(1 << 7)
 #define DWC2_PCGCCTL_DEEP_SLEEP_OFFSET			7
 #define DWC2_SNPSID_DEVID_VER_2xx			(0x4f542 << 12)
+#define DWC2_SNPSID_DEVID_VER_3xx			(0x4f543 << 12)
 #define DWC2_SNPSID_DEVID_MASK				(0xfffff << 12)
 #define DWC2_SNPSID_DEVID_OFFSET			12