]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/usb/chipidea/udc.c
usb: chipidea: udc: configure iso endpoints
[karo-tx-linux.git] / drivers / usb / chipidea / udc.c
index b501346484aeb16ab5e92e91e9aaf2458bf04784..8aed28855c0439777cb9d58a499c9d224f9d78a3 100644 (file)
@@ -466,6 +466,14 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
        mEp->qh.ptr->td.token &=
                cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
 
+       if (mEp->type == USB_ENDPOINT_XFER_ISOC) {
+               u32 mul = mReq->req.length / mEp->ep.maxpacket;
+
+               if (mReq->req.length % mEp->ep.maxpacket)
+                       mul++;
+               mEp->qh.ptr->cap |= mul << __ffs(QH_MULT);
+       }
+
        wmb();   /* synchronize before ep prime */
 
        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,
                }
        }
 
+       if (usb_endpoint_xfer_isoc(mEp->ep.desc) &&
+           mReq->req.length > (1 + mEp->ep.mult) * mEp->ep.maxpacket) {
+               dev_err(mEp->ci->dev, "request length too big for isochronous\n");
+               return -EMSGSIZE;
+       }
+
        /* first nuke then test link, e.g. previous status has not sent */
        if (!list_empty(&mReq->queue)) {
                dev_err(mEp->ci->dev, "request already in queue\n");
@@ -1060,7 +1074,8 @@ static int ep_enable(struct usb_ep *ep,
        mEp->num  = usb_endpoint_num(desc);
        mEp->type = usb_endpoint_type(desc);
 
-       mEp->ep.maxpacket = usb_endpoint_maxp(desc);
+       mEp->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff;
+       mEp->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc));
 
        if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
                cap |= QH_IOS;
@@ -1246,6 +1261,9 @@ static int ep_set_halt(struct usb_ep *ep, int value)
        if (ep == NULL || mEp->ep.desc == NULL)
                return -EINVAL;
 
+       if (usb_endpoint_xfer_isoc(mEp->ep.desc))
+               return -EOPNOTSUPP;
+
        spin_lock_irqsave(mEp->lock, flags);
 
 #ifndef STALL_IN