aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
authorMichael Grzeschik <mgr@pengutronix.de>2013-06-13 10:59:47 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-17 16:45:46 -0400
commite4ce4ecd962e17a92974b3c7ba063d29fce8c86f (patch)
tree2671f6d09147c13d91eab6aff1717153037dbc18 /drivers/usb/chipidea
parentf6a57507f685bb24b83893a12e65623a2fc69489 (diff)
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>
Diffstat (limited to 'drivers/usb/chipidea')
-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 */