X-Git-Url: http://git.monstr.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fdwc2%2Fgadget.c;h=837237e4bc962e11a89ce3336ca7223f37c1f154;hb=07281a257a6868b900da5de1eda808c9e20253f1;hp=3146df6e6510d2d3f7cf5128285f38b0cc475427;hpb=ba31f97d43be41ca99ab72a6131d7c226306865f;p=linux-2.6-microblaze.git diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 3146df6e6510..837237e4bc96 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1806,7 +1806,8 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg, case USB_ENDPOINT_HALT: halted = ep->halted; - dwc2_hsotg_ep_sethalt(&ep->ep, set, true); + if (!ep->wedged) + dwc2_hsotg_ep_sethalt(&ep->ep, set, true); ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0); if (ret) { @@ -4066,6 +4067,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, hs_ep->isochronous = 0; hs_ep->periodic = 0; hs_ep->halted = 0; + hs_ep->wedged = 0; hs_ep->interval = desc->bInterval; switch (ep_type) { @@ -4306,6 +4308,27 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) return 0; } +/** + * dwc2_gadget_ep_set_wedge - set wedge on a given endpoint + * @ep: The endpoint to be wedged. + * + */ +static int dwc2_gadget_ep_set_wedge(struct usb_ep *ep) +{ + struct dwc2_hsotg_ep *hs_ep = our_ep(ep); + struct dwc2_hsotg *hs = hs_ep->parent; + + unsigned long flags; + int ret; + + spin_lock_irqsave(&hs->lock, flags); + hs_ep->wedged = 1; + ret = dwc2_hsotg_ep_sethalt(ep, 1, false); + spin_unlock_irqrestore(&hs->lock, flags); + + return ret; +} + /** * dwc2_hsotg_ep_sethalt - set halt on a given endpoint * @ep: The endpoint to set halt. @@ -4357,6 +4380,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now) epctl |= DXEPCTL_EPDIS; } else { epctl &= ~DXEPCTL_STALL; + hs_ep->wedged = 0; xfertype = epctl & DXEPCTL_EPTYPE_MASK; if (xfertype == DXEPCTL_EPTYPE_BULK || xfertype == DXEPCTL_EPTYPE_INTERRUPT) @@ -4376,6 +4400,7 @@ static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value, bool now) // STALL bit will be set in GOUTNAKEFF interrupt handler } else { epctl &= ~DXEPCTL_STALL; + hs_ep->wedged = 0; xfertype = epctl & DXEPCTL_EPTYPE_MASK; if (xfertype == DXEPCTL_EPTYPE_BULK || xfertype == DXEPCTL_EPTYPE_INTERRUPT) @@ -4415,6 +4440,7 @@ static const struct usb_ep_ops dwc2_hsotg_ep_ops = { .queue = dwc2_hsotg_ep_queue_lock, .dequeue = dwc2_hsotg_ep_dequeue, .set_halt = dwc2_hsotg_ep_sethalt_lock, + .set_wedge = dwc2_gadget_ep_set_wedge, /* note, don't believe we have any call for the fifo routines */ }; @@ -4683,12 +4709,35 @@ static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned int mA) return usb_phy_set_power(hsotg->uphy, mA); } +static void dwc2_gadget_set_speed(struct usb_gadget *g, enum usb_device_speed speed) +{ + struct dwc2_hsotg *hsotg = to_hsotg(g); + unsigned long flags; + + spin_lock_irqsave(&hsotg->lock, flags); + switch (speed) { + case USB_SPEED_HIGH: + hsotg->params.speed = DWC2_SPEED_PARAM_HIGH; + break; + case USB_SPEED_FULL: + hsotg->params.speed = DWC2_SPEED_PARAM_FULL; + break; + case USB_SPEED_LOW: + hsotg->params.speed = DWC2_SPEED_PARAM_LOW; + break; + default: + dev_err(hsotg->dev, "invalid speed (%d)\n", speed); + } + spin_unlock_irqrestore(&hsotg->lock, flags); +} + static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = { .get_frame = dwc2_hsotg_gadget_getframe, .set_selfpowered = dwc2_hsotg_set_selfpowered, .udc_start = dwc2_hsotg_udc_start, .udc_stop = dwc2_hsotg_udc_stop, .pullup = dwc2_hsotg_pullup, + .udc_set_speed = dwc2_gadget_set_speed, .vbus_session = dwc2_hsotg_vbus_session, .vbus_draw = dwc2_hsotg_vbus_draw, };