]> Pileus Git - ~andy/linux/blobdiff - drivers/usb/dwc3/ep0.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[~andy/linux] / drivers / usb / dwc3 / ep0.c
index c8df1dd967efe3e5160fbe8507a8b2bbff972aa5..25910e251c04b4fb7ce0ef8bb9685573e859b9b9 100644 (file)
@@ -76,8 +76,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
                u32 len, u32 type)
 {
        struct dwc3_gadget_ep_cmd_params params;
-       struct dwc3_trb_hw              *trb_hw;
-       struct dwc3_trb                 trb;
+       struct dwc3_trb                 *trb;
        struct dwc3_ep                  *dep;
 
        int                             ret;
@@ -88,19 +87,17 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
                return 0;
        }
 
-       trb_hw = dwc->ep0_trb;
-       memset(&trb, 0, sizeof(trb));
+       trb = dwc->ep0_trb;
 
-       trb.trbctl = type;
-       trb.bplh = buf_dma;
-       trb.length = len;
+       trb->bpl = lower_32_bits(buf_dma);
+       trb->bph = upper_32_bits(buf_dma);
+       trb->size = len;
+       trb->ctrl = type;
 
-       trb.hwo = 1;
-       trb.lst = 1;
-       trb.ioc = 1;
-       trb.isp_imi = 1;
-
-       dwc3_trb_to_hw(&trb, trb_hw);
+       trb->ctrl |= (DWC3_TRB_CTRL_HWO
+                       | DWC3_TRB_CTRL_LST
+                       | DWC3_TRB_CTRL_IOC
+                       | DWC3_TRB_CTRL_ISP_IMI);
 
        memset(&params, 0, sizeof(params));
        params.param0 = upper_32_bits(dwc->ep0_trb_addr);
@@ -302,7 +299,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
        dep = dwc->eps[0];
        dwc->ep0_usb_req.dep = dep;
        dwc->ep0_usb_req.request.length = sizeof(*response_pkt);
-       dwc->ep0_usb_req.request.dma = dwc->setup_buf_addr;
+       dwc->ep0_usb_req.request.buf = dwc->setup_buf;
        dwc->ep0_usb_req.request.complete = dwc3_ep0_status_cmpl;
 
        return __dwc3_gadget_ep0_queue(dep, &dwc->ep0_usb_req);
@@ -315,9 +312,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
        u32                     recip;
        u32                     wValue;
        u32                     wIndex;
-       u32                     reg;
        int                     ret;
-       u32                     mode;
 
        wValue = le16_to_cpu(ctrl->wValue);
        wIndex = le16_to_cpu(ctrl->wIndex);
@@ -356,25 +351,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                        if (!set)
                                return -EINVAL;
 
-                       mode = wIndex >> 8;
-                       reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-                       reg &= ~DWC3_DCTL_TSTCTRL_MASK;
-
-                       switch (mode) {
-                       case TEST_J:
-                       case TEST_K:
-                       case TEST_SE0_NAK:
-                       case TEST_PACKET:
-                       case TEST_FORCE_EN:
-                               reg |= mode << 1;
-                               break;
-                       default:
-                               return -EINVAL;
-                       }
-                       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-                       break;
-               default:
-                       return -EINVAL;
+                       dwc->test_mode_nr = wIndex >> 8;
+                       dwc->test_mode = true;
                }
                break;
 
@@ -396,7 +374,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
        case USB_RECIP_ENDPOINT:
                switch (wValue) {
                case USB_ENDPOINT_HALT:
-                       dep =  dwc3_wIndex_to_dep(dwc, wIndex);
+                       dep = dwc3_wIndex_to_dep(dwc, wIndex);
                        if (!dep)
                                return -EINVAL;
                        ret = __dwc3_gadget_ep_set_halt(dep, set);
@@ -470,8 +448,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        case DWC3_ADDRESS_STATE:
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
                /* if the cfg matches and the cfg is non zero */
-               if (!ret && cfg)
+               if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
                        dwc->dev_state = DWC3_CONFIGURED_STATE;
+                       dwc->resize_fifos = true;
+                       dev_dbg(dwc->dev, "resize fifos flag SET\n");
+               }
                break;
 
        case DWC3_CONFIGURED_STATE:
@@ -560,9 +541,10 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
 {
        struct dwc3_request     *r = NULL;
        struct usb_request      *ur;
-       struct dwc3_trb         trb;
+       struct dwc3_trb         *trb;
        struct dwc3_ep          *ep0;
        u32                     transferred;
+       u32                     length;
        u8                      epnum;
 
        epnum = event->endpoint_number;
@@ -573,16 +555,16 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
        r = next_request(&ep0->request_list);
        ur = &r->request;
 
-       dwc3_trb_to_nat(dwc->ep0_trb, &trb);
+       trb = dwc->ep0_trb;
+       length = trb->size & DWC3_TRB_SIZE_MASK;
 
        if (dwc->ep0_bounced) {
-
                transferred = min_t(u32, ur->length,
-                               ep0->endpoint.maxpacket - trb.length);
+                               ep0->endpoint.maxpacket - length);
                memcpy(ur->buf, dwc->ep0_bounce, transferred);
                dwc->ep0_bounced = false;
        } else {
-               transferred = ur->length - trb.length;
+               transferred = ur->length - length;
                ur->actual += transferred;
        }
 
@@ -614,6 +596,17 @@ static void dwc3_ep0_complete_req(struct dwc3 *dwc,
                dwc3_gadget_giveback(dep, r, 0);
        }
 
+       if (dwc->test_mode) {
+               int ret;
+
+               ret = dwc3_gadget_set_test_mode(dwc, dwc->test_mode_nr);
+               if (ret < 0) {
+                       dev_dbg(dwc->dev, "Invalid Test #%d\n",
+                                       dwc->test_mode_nr);
+                       dwc3_ep0_stall_and_restart(dwc);
+               }
+       }
+
        dwc->ep0state = EP0_SETUP_PHASE;
        dwc3_ep0_out_start(dwc);
 }
@@ -624,6 +617,7 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc,
        struct dwc3_ep          *dep = dwc->eps[event->endpoint_number];
 
        dep->flags &= ~DWC3_EP_BUSY;
+       dep->res_trans_idx = 0;
        dwc->setup_packet_pending = false;
 
        switch (dwc->ep0state) {
@@ -679,7 +673,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
                                DWC3_TRBCTL_CONTROL_DATA);
        } else if ((req->request.length % dep->endpoint.maxpacket)
                        && (event->endpoint_number == 0)) {
-               dwc3_map_buffer_to_dma(req);
+               ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+                               event->endpoint_number);
+               if (ret) {
+                       dev_dbg(dwc->dev, "failed to map request\n");
+                       return;
+               }
 
                WARN_ON(req->request.length > dep->endpoint.maxpacket);
 
@@ -694,7 +693,12 @@ static void dwc3_ep0_do_control_data(struct dwc3 *dwc,
                                dwc->ep0_bounce_addr, dep->endpoint.maxpacket,
                                DWC3_TRBCTL_CONTROL_DATA);
        } else {
-               dwc3_map_buffer_to_dma(req);
+               ret = usb_gadget_map_request(&dwc->gadget, &req->request,
+                               event->endpoint_number);
+               if (ret) {
+                       dev_dbg(dwc->dev, "failed to map request\n");
+                       return;
+               }
 
                ret = dwc3_ep0_start_trans(dwc, event->endpoint_number,
                                req->request.dma, req->request.length,
@@ -720,6 +724,12 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, u32 epnum)
 {
        struct dwc3_ep          *dep = dwc->eps[epnum];
 
+       if (dwc->resize_fifos) {
+               dev_dbg(dwc->dev, "starting to resize fifos\n");
+               dwc3_gadget_resize_tx_fifos(dwc);
+               dwc->resize_fifos = 0;
+       }
+
        WARN_ON(dwc3_ep0_start_control_status(dep));
 }