Skip to content

Commit

Permalink
usb: chipidea: udc: configure iso endpoints
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Michael Grzeschik authored and Greg Kroah-Hartman committed Jun 17, 2013
1 parent f6a5750 commit e4ce4ec
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 2 deletions.
2 changes: 1 addition & 1 deletion drivers/usb/chipidea/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
20 changes: 19 additions & 1 deletion drivers/usb/chipidea/udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/chipidea/udc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit e4ce4ec

Please sign in to comment.