static void ep0_setup_ack_complete(struct usb_ep *ep, struct usb_request *req) { struct msm_endpoint *ept = to_msm_endpoint(ep); struct usb_info *ui = ept->ui; unsigned int temp; if (!ui->test_mode) return; switch (ui->test_mode) { case J_TEST: pr_info("usb electrical test mode: (J)\n"); temp = readl(USB_PORTSC) & (~PORTSC_PTC); writel(temp | PORTSC_PTC_J_STATE, USB_PORTSC); break; case K_TEST: pr_info("usb electrical test mode: (K)\n"); temp = readl(USB_PORTSC) & (~PORTSC_PTC); writel(temp | PORTSC_PTC_K_STATE, USB_PORTSC); break; case SE0_NAK_TEST: pr_info("usb electrical test mode: (SE0-NAK)\n"); temp = readl(USB_PORTSC) & (~PORTSC_PTC); writel(temp | PORTSC_PTC_SE0_NAK, USB_PORTSC); break; case TST_PKT_TEST: pr_info("usb electrical test mode: (TEST_PKT)\n"); temp = readl(USB_PORTSC) & (~PORTSC_PTC); writel(temp | PORTSC_PTC_TST_PKT, USB_PORTSC); break; } }
static int msm72k_disable(struct usb_ep *_ep) { struct msm_endpoint *ept = to_msm_endpoint(_ep); usb_ept_enable(ept, 0, 0); return 0; }
static int msm72k_set_halt(struct usb_ep *_ep, int value) { struct msm_endpoint *ept = to_msm_endpoint(_ep); struct usb_info *ui = ept->ui; unsigned int in = ept->flags & EPT_FLAG_IN; unsigned int n; unsigned long flags; spin_lock_irqsave(&ui->lock, flags); n = readl(USB_ENDPTCTRL(ept->num)); if (in) { if (value) n |= CTRL_TXS; else { n &= ~CTRL_TXS; n |= CTRL_TXR; } } else { if (value) n |= CTRL_RXS; else { n &= ~CTRL_RXS; n |= CTRL_RXR; } } writel(n, USB_ENDPTCTRL(ept->num)); spin_unlock_irqrestore(&ui->lock, flags); return 0; }
static int msm72k_queue(struct usb_ep *_ep, struct usb_request *req, gfp_t gfp_flags) { struct msm_endpoint *ep = to_msm_endpoint(_ep); struct usb_info *ui = ep->ui; if (ep == &ui->ep0in) { struct msm_request *r = to_msm_request(req); if (!req->length) goto ep_queue_done; else { if (ui->ep0_dir == USB_DIR_OUT) { ep = &ui->ep0out; ep->ep.driver_data = ui->ep0in.ep.driver_data; } /* ep0_queue_ack_complete queue a receive for ACK before ** calling req->complete */ r->gadget_complete = req->complete; req->complete = ep0_queue_ack_complete; } } ep_queue_done: return usb_ept_queue_xfer(ep, req); }
static int msm72k_queue(struct usb_ep *_ep, struct usb_request *req, gfp_t gfp_flags) { struct msm_endpoint *ep = to_msm_endpoint(_ep); struct usb_info *ui = ep->ui; int ret; if (ep == &ui->ep0in) { struct msm_request *r = to_msm_request(req); if (!req->length) goto ep_queue_done; r->gadget_complete = req->complete; /* ep0_queue_ack_complete queue a receive for ACK before ** calling req->complete */ req->complete = ep0_queue_ack_complete; if (ui->ep0_dir == USB_DIR_OUT) ep = &ui->ep0out; goto ep_queue_done; } if (ui->usb_state == USB_STATE_SUSPENDED) { ret = msm72k_wakeup(&ui->gadget); if (ret) return ret; } ep_queue_done: return usb_ept_queue_xfer(ep, req); }
static void ep0_complete(struct usb_ep *ep, struct usb_request *req) { struct msm_request *r = to_msm_request(req); struct msm_endpoint *ept = to_msm_endpoint(ep); struct usb_info *ui = ept->ui; req->complete = r->gadget_complete; r->gadget_complete = NULL; if (req->complete) req->complete(&ui->ep0in.ep, req); }
static int msm72k_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { struct msm_endpoint *ept = to_msm_endpoint(_ep); unsigned char ep_type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; _ep->maxpacket = le16_to_cpu(desc->wMaxPacketSize); usb_ept_enable(ept, 1, ep_type); return 0; }
static void msm72k_free_request(struct usb_ep *_ep, struct usb_request *_req) { struct msm_request *req = to_msm_request(_req); struct msm_endpoint *ept = to_msm_endpoint(_ep); struct usb_info *ui = ept->ui; /* request should not be busy */ BUG_ON(req->busy); if (req->alloced) kfree(req->req.buf); dma_pool_free(ui->pool, req->item, req->item_dma); kfree(req); }
int usb_loop_poll_hw(struct usb_ep *_ept, int is_rx) { struct msm_endpoint *act_ept, *ept = to_msm_endpoint(_ept); struct usb_info *ui = ept->ui; int done = 0; u32 n; /* Normally there is a read request in the endpoint, wait for new data */ for (;;) { n = readl(USB_USBSTS); writel(n, USB_USBSTS); if (n & STS_UI) /* finished transaction */ break; } /* USB Transaction is complete */ if (n & STS_UI) { n = readl(USB_ENDPTSETUPSTAT); if (n & EPT_RX(0)) handle_setup(ui); n = readl(USB_ENDPTCOMPLETE); writel(n, USB_ENDPTCOMPLETE); while (n) { unsigned bit = __ffs(n); act_ept = ui->ept + bit; if (ept == act_ept) { pr_debug("%s: recv'd right tx %d\n", __func__, bit); done = 1; } else { pr_debug("%s: recv'd extra tx from ept %d (exp %d)\n", __func__, bit, ept->bit); } /* always call the handler for KGDB and other usb functions. * this is to avoid hardware timeout, but can leave a bit * kernel code running when kgdb is invoked to stopped the * kernel. this works quite well with adb but might not * support usb mass storage devices very well. */ handle_endpoint(ui, bit); n = n & (~(1 << bit)); } } return done ? 0 : -EAGAIN; }
static void ep0_queue_ack_complete(struct usb_ep *ep, struct usb_request *req) { struct msm_endpoint *ept = to_msm_endpoint(ep); /* queue up the receive of the ACK response from the host */ if (req->status == 0) { struct usb_info *ui = ept->ui; req->length = 0; req->complete = ep0_complete; if (ui->ep0_dir == USB_DIR_IN) usb_ept_queue_xfer(&ui->ep0out, req); else usb_ept_queue_xfer(&ui->ep0in, req); } else ep0_complete(ep, req); }
static int msm72k_dequeue(struct usb_ep *_ep, struct usb_request *_req) { struct msm_endpoint *ep = to_msm_endpoint(_ep); struct msm_request *req = to_msm_request(_req); struct usb_info *ui = ep->ui; struct msm_request *cur, *prev; unsigned long flags; if (!_ep || !_req) return -EINVAL; spin_lock_irqsave(&ui->lock, flags); cur = ep->req; prev = NULL; while (cur != 0) { if (cur == req) { req->busy = 0; req->live = 0; req->req.status = -ECONNRESET; req->req.actual = 0; if (req->req.complete) { spin_unlock_irqrestore(&ui->lock, flags); req->req.complete(&ep->ep, &req->req); spin_lock_irqsave(&ui->lock, flags); } /* remove from linked list */ if (prev) prev->next = cur->next; else ep->req = cur->next; if (ep->last == cur) ep->last = prev; /* break from loop */ cur = NULL; } else { prev = cur; cur = cur->next; } } spin_unlock_irqrestore(&ui->lock, flags); return 0; }
static void msm72k_free_request(struct usb_ep *_ep, struct usb_request *_req) { struct msm_request *req = to_msm_request(_req); struct msm_endpoint *ept = to_msm_endpoint(_ep); struct usb_info *ui = ept->ui; unsigned long flags; int dead = 0; spin_lock_irqsave(&ui->lock, flags); /* defer freeing resources if request is still busy */ if (req->busy) dead = req->dead = 1; spin_unlock_irqrestore(&ui->lock, flags); /* if req->dead, then we will clean up when the request finishes */ if (!dead) do_free_req(ui, req); }
static void msm72k_fifo_flush(struct usb_ep *_ep) { flush_endpoint(to_msm_endpoint(_ep)); }
static struct usb_request * msm72k_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags) { return usb_ept_alloc_req(to_msm_endpoint(_ep), 0, gfp_flags); }