usb: chipidea: udc: configure iso endpoints
This patch adds iso endpoint support to the device controller.
It makes use of the multiplication bits in the maxpacket field
of the endpoint and calculates the multiplier bits for each
transfer description on every request.
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Reviewed-by: Peter Chen <peter.chen@freescale.com>
Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index b501346..8aed288 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -466,6 +466,14 @@
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 @@
}
}
+ 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 @@
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 @@
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