aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/chipidea/core.c2
-rw-r--r--drivers/usb/chipidea/udc.c20
-rw-r--r--drivers/usb/chipidea/udc.h1
3 files changed, 21 insertions, 2 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 475c9c114689..ade1b91b5ae7 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -43,7 +43,7 @@
43 * 43 *
44 * TODO List 44 * TODO List
45 * - OTG 45 * - OTG
46 * - Isochronous & Interrupt Traffic 46 * - Interrupt Traffic
47 * - Handle requests which spawns into several TDs 47 * - Handle requests which spawns into several TDs
48 * - GET_STATUS(device) - always reports 0 48 * - GET_STATUS(device) - always reports 0
49 * - Gadget API (majority of optional features) 49 * - Gadget API (majority of optional features)
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index b501346484ae..8aed28855c04 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -466,6 +466,14 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
466 mEp->qh.ptr->td.token &= 466 mEp->qh.ptr->td.token &=
467 cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE)); 467 cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
468 468
469 if (mEp->type == USB_ENDPOINT_XFER_ISOC) {
470 u32 mul = mReq->req.length / mEp->ep.maxpacket;
471
472 if (mReq->req.length % mEp->ep.maxpacket)
473 mul++;
474 mEp->qh.ptr->cap |= mul << __ffs(QH_MULT);
475 }
476
469 wmb(); /* synchronize before ep prime */ 477 wmb(); /* synchronize before ep prime */
470 478
471 ret = hw_ep_prime(ci, mEp->num, mEp->dir, 479 ret = hw_ep_prime(ci, mEp->num, mEp->dir,
@@ -678,6 +686,12 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
678 } 686 }
679 } 687 }
680 688
689 if (usb_endpoint_xfer_isoc(mEp->ep.desc) &&
690 mReq->req.length > (1 + mEp->ep.mult) * mEp->ep.maxpacket) {
691 dev_err(mEp->ci->dev, "request length too big for isochronous\n");
692 return -EMSGSIZE;
693 }
694
681 /* first nuke then test link, e.g. previous status has not sent */ 695 /* first nuke then test link, e.g. previous status has not sent */
682 if (!list_empty(&mReq->queue)) { 696 if (!list_empty(&mReq->queue)) {
683 dev_err(mEp->ci->dev, "request already in queue\n"); 697 dev_err(mEp->ci->dev, "request already in queue\n");
@@ -1060,7 +1074,8 @@ static int ep_enable(struct usb_ep *ep,
1060 mEp->num = usb_endpoint_num(desc); 1074 mEp->num = usb_endpoint_num(desc);
1061 mEp->type = usb_endpoint_type(desc); 1075 mEp->type = usb_endpoint_type(desc);
1062 1076
1063 mEp->ep.maxpacket = usb_endpoint_maxp(desc); 1077 mEp->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff;
1078 mEp->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc));
1064 1079
1065 if (mEp->type == USB_ENDPOINT_XFER_CONTROL) 1080 if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
1066 cap |= QH_IOS; 1081 cap |= QH_IOS;
@@ -1246,6 +1261,9 @@ static int ep_set_halt(struct usb_ep *ep, int value)
1246 if (ep == NULL || mEp->ep.desc == NULL) 1261 if (ep == NULL || mEp->ep.desc == NULL)
1247 return -EINVAL; 1262 return -EINVAL;
1248 1263
1264 if (usb_endpoint_xfer_isoc(mEp->ep.desc))
1265 return -EOPNOTSUPP;
1266
1249 spin_lock_irqsave(mEp->lock, flags); 1267 spin_lock_irqsave(mEp->lock, flags);
1250 1268
1251#ifndef STALL_IN 1269#ifndef STALL_IN
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
index d12e8b59b110..a75724a19e1a 100644
--- a/drivers/usb/chipidea/udc.h
+++ b/drivers/usb/chipidea/udc.h
@@ -50,6 +50,7 @@ struct ci13xxx_qh {
50#define QH_MAX_PKT (0x07FFUL << 16) 50#define QH_MAX_PKT (0x07FFUL << 16)
51#define QH_ZLT BIT(29) 51#define QH_ZLT BIT(29)
52#define QH_MULT (0x0003UL << 30) 52#define QH_MULT (0x0003UL << 30)
53#define QH_ISO_MULT(x) ((x >> 11) & 0x03)
53 /* 1 */ 54 /* 1 */
54 u32 curr; 55 u32 curr;
55 /* 2 - 8 */ 56 /* 2 - 8 */