iio: ABI: add ABI file for the LTC2688 DAC
[linux-2.6-microblaze.git] / drivers / usb / dwc3 / gadget.c
index 7e3db00..520031b 100644 (file)
@@ -331,9 +331,17 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
                }
        }
 
-       dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
-       dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1);
-       dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2);
+       /*
+        * For some commands such as Update Transfer command, DEPCMDPARn
+        * registers are reserved. Since the driver often sends Update Transfer
+        * command, don't write to DEPCMDPARn to avoid register write delays and
+        * improve performance.
+        */
+       if (DWC3_DEPCMD_CMD(cmd) != DWC3_DEPCMD_UPDATETRANSFER) {
+               dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
+               dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1);
+               dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2);
+       }
 
        /*
         * Synopsys Databook 2.60a states in section 6.3.2.5.6 of that if we're
@@ -357,6 +365,12 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
                cmd |= DWC3_DEPCMD_CMDACT;
 
        dwc3_writel(dep->regs, DWC3_DEPCMD, cmd);
+
+       if (!(cmd & DWC3_DEPCMD_CMDACT)) {
+               ret = 0;
+               goto skip_status;
+       }
+
        do {
                reg = dwc3_readl(dep->regs, DWC3_DEPCMD);
                if (!(reg & DWC3_DEPCMD_CMDACT)) {
@@ -398,6 +412,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
                cmd_status = -ETIMEDOUT;
        }
 
+skip_status:
        trace_dwc3_gadget_ep_cmd(dep, cmd, params, cmd_status);
 
        if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
@@ -1260,12 +1275,17 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
                        trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI;
        }
 
+       /* All TRBs setup for MST must set CSP=1 when LST=0 */
+       if (dep->stream_capable && DWC3_MST_CAPABLE(&dwc->hwparams))
+               trb->ctrl |= DWC3_TRB_CTRL_CSP;
+
        if ((!no_interrupt && !chain) || must_interrupt)
                trb->ctrl |= DWC3_TRB_CTRL_IOC;
 
        if (chain)
                trb->ctrl |= DWC3_TRB_CTRL_CHN;
-       else if (dep->stream_capable && is_last)
+       else if (dep->stream_capable && is_last &&
+                !DWC3_MST_CAPABLE(&dwc->hwparams))
                trb->ctrl |= DWC3_TRB_CTRL_LST;
 
        if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable)
@@ -1513,7 +1533,8 @@ static int dwc3_prepare_trbs(struct dwc3_ep *dep)
                 * burst capability may try to read and use TRBs beyond the
                 * active transfer instead of stopping.
                 */
-               if (dep->stream_capable && req->request.is_last)
+               if (dep->stream_capable && req->request.is_last &&
+                   !DWC3_MST_CAPABLE(&dep->dwc->hwparams))
                        return ret;
        }
 
@@ -1546,7 +1567,8 @@ static int dwc3_prepare_trbs(struct dwc3_ep *dep)
                 * burst capability may try to read and use TRBs beyond the
                 * active transfer instead of stopping.
                 */
-               if (dep->stream_capable && req->request.is_last)
+               if (dep->stream_capable && req->request.is_last &&
+                   !DWC3_MST_CAPABLE(&dwc->hwparams))
                        return ret;
        }
 
@@ -1623,7 +1645,8 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
                return ret;
        }
 
-       if (dep->stream_capable && req->request.is_last)
+       if (dep->stream_capable && req->request.is_last &&
+           !DWC3_MST_CAPABLE(&dep->dwc->hwparams))
                dep->flags |= DWC3_EP_WAIT_TRANSFER_COMPLETE;
 
        return 0;
@@ -2638,6 +2661,13 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
        reg |= DWC3_DCFG_IGNSTRMPP;
        dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
+       /* Enable MST by default if the device is capable of MST */
+       if (DWC3_MST_CAPABLE(&dwc->hwparams)) {
+               reg = dwc3_readl(dwc->regs, DWC3_DCFG1);
+               reg &= ~DWC3_DCFG1_DIS_MST_ENH;
+               dwc3_writel(dwc->regs, DWC3_DCFG1, reg);
+       }
+
        /* Start with SuperSpeed Default */
        dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
 
@@ -3437,7 +3467,8 @@ static void dwc3_gadget_endpoint_stream_event(struct dwc3_ep *dep,
        case DEPEVT_STREAM_NOSTREAM:
                if ((dep->flags & DWC3_EP_IGNORE_NEXT_NOSTREAM) ||
                    !(dep->flags & DWC3_EP_FORCE_RESTART_STREAM) ||
-                   !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE))
+                   (!DWC3_MST_CAPABLE(&dwc->hwparams) &&
+                    !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE)))
                        break;
 
                /*
@@ -4067,7 +4098,6 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
        struct dwc3 *dwc = evt->dwc;
        irqreturn_t ret = IRQ_NONE;
        int left;
-       u32 reg;
 
        left = evt->count;
 
@@ -4099,9 +4129,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt)
        ret = IRQ_HANDLED;
 
        /* Unmask interrupt */
-       reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0));
-       reg &= ~DWC3_GEVNTSIZ_INTMASK;
-       dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
+       dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
+                   DWC3_GEVNTSIZ_SIZE(evt->length));
 
        if (dwc->imod_interval) {
                dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
@@ -4130,7 +4159,6 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
        struct dwc3 *dwc = evt->dwc;
        u32 amount;
        u32 count;
-       u32 reg;
 
        if (pm_runtime_suspended(dwc->dev)) {
                pm_runtime_get(dwc->dev);
@@ -4157,9 +4185,8 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt)
        evt->flags |= DWC3_EVENT_PENDING;
 
        /* Mask interrupt */
-       reg = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0));
-       reg |= DWC3_GEVNTSIZ_INTMASK;
-       dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg);
+       dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
+                   DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length));
 
        amount = min(count, evt->length - evt->lpos);
        memcpy(evt->cache + evt->lpos, evt->buf + evt->lpos, amount);