On Thu, May 16, 2013 at 09:53:57AM +0200, Michael Grzeschik wrote: > 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@xxxxxxxxxxxxxx> > --- > Changes since v1: > - fixed style issues and typo > - changed bitops to human readable operations > > drivers/usb/chipidea/core.c | 2 +- > drivers/usb/chipidea/udc.c | 20 +++++++++++++++++++- > drivers/usb/chipidea/udc.h | 1 + > 3 files changed, 21 insertions(+), 2 deletions(-) > > diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c > index 450107e..3cdb889 100644 > --- a/drivers/usb/chipidea/core.c > +++ b/drivers/usb/chipidea/core.c > @@ -43,7 +43,7 @@ > * > * TODO List > * - OTG > - * - Isochronous & Interrupt Traffic > + * - Interrupt Traffic > * - Handle requests which spawns into several TDs > * - GET_STATUS(device) - always reports 0 > * - Gadget API (majority of optional features) > diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c > index 519ead2..e9a57bb0 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) > 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 > diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h > index d12e8b5..a75724a 100644 > --- a/drivers/usb/chipidea/udc.h > +++ b/drivers/usb/chipidea/udc.h > @@ -50,6 +50,7 @@ struct ci13xxx_qh { > #define QH_MAX_PKT (0x07FFUL << 16) > #define QH_ZLT BIT(29) > #define QH_MULT (0x0003UL << 30) > +#define QH_ISO_MULT(x) ((x >> 11) & 0x03) > /* 1 */ > u32 curr; > /* 2 - 8 */ Reviewed-by: Peter Chen <peter.chen@xxxxxxxxxxxxx> -- Best Regards, Peter Chen -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html