1 /* ==========================================================================
2 * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
7 * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 * otherwise expressly agreed to in writing between Synopsys and you.
11 * The Software IS NOT an item of Licensed Software or Licensed Product under
12 * any End User Software License Agreement or Agreement for Licensed Product
13 * with Synopsys or any supplement thereto. You are permitted to use and
14 * redistribute this Software in source and binary forms, with or without
15 * modification, provided that redistributions of source code must retain this
16 * notice. You may not view, use, disclose, copy or distribute this file or
17 * any information contained herein except pursuant to this license grant from
18 * Synopsys. If you do not agree with this notice, including the disclaimer
19 * below, then you are not authorized to use the Software.
21 * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 * ========================================================================== */
36 * This file implements the Peripheral Controller Driver.
38 * The Peripheral Controller Driver (PCD) is responsible for
39 * translating requests from the Function Driver into the appropriate
40 * actions on the DWC_otg controller. It isolates the Function Driver
41 * from the specifics of the controller by providing an API to the
44 * The Peripheral Controller Driver for Linux will implement the
45 * Gadget API, so that the existing Gadget drivers can be used.
46 * (Gadget Driver is the Linux terminology for a Function Driver.)
48 * The Linux Gadget API is defined in the header file
49 * <code><linux/usb_gadget.h></code>. The USB EP operations API is
50 * defined in the structure <code>usb_ep_ops</code> and the USB
51 * Controller API is defined in the structure
52 * <code>usb_gadget_ops</code>.
56 #include "dwc_otg_os_dep.h"
57 #include "dwc_otg_pcd_if.h"
58 #include "dwc_otg_pcd.h"
59 #include "dwc_otg_driver.h"
60 #include "dwc_otg_dbg.h"
61 #include "dwc_otg_attr.h"
63 #include "usbdev_rk.h"
64 static struct gadget_wrapper {
67 struct usb_gadget gadget;
68 struct usb_gadget_driver *driver;
71 struct usb_ep in_ep[16];
72 struct usb_ep out_ep[16];
76 /* Display the contents of the buffer */
77 extern void dump_msg(const u8 *buf, unsigned int length);
80 * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
81 * if the endpoint is not found
83 static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t *pcd, void *handle)
86 if (pcd->ep0.priv == handle) {
90 for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) {
91 if (pcd->in_ep[i].priv == handle)
92 return &pcd->in_ep[i];
93 if (pcd->out_ep[i].priv == handle)
94 return &pcd->out_ep[i];
100 /* USB Endpoint Operations */
102 * The following sections briefly describe the behavior of the Gadget
103 * API endpoint operations implemented in the DWC_otg driver
104 * software. Detailed descriptions of the generic behavior of each of
105 * these functions can be found in the Linux header file
106 * include/linux/usb_gadget.h.
108 * The Gadget API provides wrapper functions for each of the function
109 * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper
110 * function, which then calls the underlying PCD function. The
111 * following sections are named according to the wrapper
112 * functions. Within each section, the corresponding DWC_otg PCD
113 * function name is specified.
118 * This function is called by the Gadget Driver for each EP to be
119 * configured for the current configuration (SET_CONFIGURATION).
121 * This function initializes the dwc_otg_ep_t data structure, and then
122 * calls dwc_otg_ep_activate.
124 static int ep_enable(struct usb_ep *usb_ep,
125 const struct usb_endpoint_descriptor *ep_desc)
129 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
131 if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
132 DWC_WARN("%s, bad ep or descriptor\n", __func__);
135 if (usb_ep == &gadget_wrapper->ep0) {
136 DWC_WARN("%s, bad ep(0)\n", __func__);
140 /* Check FIFO size? */
141 if (!ep_desc->wMaxPacketSize) {
142 DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
146 if (!gadget_wrapper->driver ||
147 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
148 DWC_WARN("%s, bogus device state\n", __func__);
152 /* Delete after check - MAS */
154 nat = (uint32_t) ep_desc->wMaxPacketSize;
155 printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat);
156 nat = (nat >> 11) & 0x03;
157 printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat);
159 retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
160 (const uint8_t *)ep_desc,
163 DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
167 usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
173 * This function is called when an EP is disabled due to disconnect or
174 * change in configuration. Any pending requests will terminate with a
175 * status of -ESHUTDOWN.
177 * This function modifies the dwc_otg_ep_t data structure for this EP,
178 * and then calls dwc_otg_ep_deactivate.
180 static int ep_disable(struct usb_ep *usb_ep)
184 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
186 DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
187 usb_ep ? usb_ep->name : NULL);
191 retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
200 * This function allocates a request object to use with the specified
203 * @param ep The endpoint to be used with with the request
204 * @param gfp_flags the GFP_* flags to use.
206 static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
209 struct usb_request *usb_req;
211 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
213 DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
216 usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
218 DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
221 memset(usb_req, 0, sizeof(*usb_req));
222 usb_req->dma = DWC_DMA_ADDR_INVALID;
228 * This function frees a request object.
230 * @param ep The endpoint associated with the request
231 * @param req The request being freed
233 static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
235 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
237 if (0 == ep || 0 == req) {
238 DWC_WARN("%s() %s\n", __func__,
239 "Invalid ep or req argument!\n");
246 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
248 * This function allocates an I/O buffer to be used for a transfer
249 * to/from the specified endpoint.
251 * @param usb_ep The endpoint to be used with with the request
252 * @param bytes The desired number of bytes for the buffer
253 * @param dma Pointer to the buffer's DMA address; must be valid
254 * @param gfp_flags the GFP_* flags to use.
255 * @return address of a new buffer or null is buffer could not be allocated.
257 static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
258 dma_addr_t *dma, gfp_t gfp_flags)
261 dwc_otg_pcd_t *pcd = 0;
263 pcd = gadget_wrapper->pcd;
265 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
268 /* Check dword alignment */
269 if ((bytes & 0x3UL) != 0) {
270 DWC_WARN("%s() Buffer size is not a multiple of"
271 "DWORD size (%d)", __func__, bytes);
274 buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
276 /* Check dword alignment */
277 if (((int)buf & 0x3UL) != 0) {
278 DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
286 * This function frees an I/O buffer that was allocated by alloc_buffer.
288 * @param usb_ep the endpoint associated with the buffer
289 * @param buf address of the buffer
290 * @param dma The buffer's DMA address
291 * @param bytes The number of bytes of the buffer
293 static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
294 dma_addr_t dma, unsigned bytes)
296 dwc_otg_pcd_t *pcd = 0;
298 pcd = gadget_wrapper->pcd;
300 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
302 dma_free_coherent(NULL, bytes, buf, dma);
307 * This function is used to submit an I/O Request to an EP.
309 * - When the request completes the request's completion callback
310 * is called to return the request to the driver.
311 * - An EP, except control EPs, may have multiple requests
313 * - Once submitted the request cannot be examined or modified.
314 * - Each request is turned into one or more packets.
315 * - A BULK EP can queue any amount of data; the transfer is
317 * - Zero length Packets are specified with the request 'zero'
320 static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
324 struct dwc_otg_pcd_ep *ep = NULL;
325 int retval = 0, is_isoc_ep = 0;
326 dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID;
328 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
329 __func__, usb_ep, usb_req, gfp_flags);
331 if (!usb_req || !usb_req->complete || !usb_req->buf) {
332 DWC_WARN("bad params\n");
337 DWC_WARN("bad ep\n");
341 pcd = gadget_wrapper->pcd;
342 if (!gadget_wrapper->driver ||
343 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
344 DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
345 gadget_wrapper->gadget.speed);
346 DWC_WARN("bogus device state\n");
350 DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n",
351 usb_ep->name, usb_req, usb_req->length, usb_req->buf);
353 usb_req->status = -EINPROGRESS;
356 ep = ep_from_handle(pcd, usb_ep);
360 is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0;
361 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
362 dma_addr = usb_req->dma;
364 if (GET_CORE_IF(pcd)->dma_enable) {
365 /* if (usb_req->length != 0) {*/
366 /* In device DMA mode when gadget perform ep_queue request
367 * with buffer length 0, Kernel stack dump occurred. For 0
368 * length buffers perform dma_map_single() with length 4.*/
369 if (usb_req->dma == DWC_DMA_ADDR_INVALID) {
371 dma_map_single(gadget_wrapper->gadget.dev.parent,
374 0 ? usb_req->length : 4,
376 is_in ? DMA_TO_DEVICE :
378 usb_req->dma = dma_addr;
380 dma_addr = usb_req->dma;
386 #ifdef DWC_UTE_PER_IO
387 if (is_isoc_ep == 1) {
389 dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf,
390 dma_addr, usb_req->length,
391 usb_req->zero, usb_req,
392 gfp_flags == GFP_ATOMIC ? 1 : 0,
400 retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
401 usb_req->length, usb_req->zero, usb_req,
402 gfp_flags == GFP_ATOMIC ? 1 : 0);
411 * This function cancels an I/O request from an EP.
413 static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
415 DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
417 if (!usb_ep || !usb_req) {
418 DWC_WARN("bad argument\n");
421 if (!gadget_wrapper->driver ||
422 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
423 DWC_WARN("bogus device state\n");
426 if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
434 * usb_ep_set_halt stalls an endpoint.
436 * usb_ep_clear_halt clears an endpoint halt and resets its data
439 * Both of these functions are implemented with the same underlying
440 * function. The behavior depends on the value argument.
442 * @param[in] usb_ep the Endpoint to halt or clear halt.
444 * - 0 means clear_halt.
445 * - 1 means set_halt,
446 * - 2 means clear stall lock flag.
447 * - 3 means set stall lock flag.
449 static int ep_halt(struct usb_ep *usb_ep, int value)
453 DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
456 DWC_WARN("bad ep\n");
460 retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
461 if (retval == -DWC_E_AGAIN) {
470 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
471 static int ep_wedge(struct usb_ep *usb_ep)
473 DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
475 return ep_halt(usb_ep, 3);
481 * This function is used to submit an ISOC Transfer Request to an EP.
483 * - Every time a sync period completes the request's completion callback
484 * is called to provide data to the gadget driver.
485 * - Once submitted the request cannot be modified.
486 * - Each request is turned into periodic data packets untill ISO
487 * Transfer is stopped..
489 static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
494 if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
495 DWC_WARN("bad params\n");
500 DWC_PRINTF("bad params\n");
504 req->status = -EINPROGRESS;
507 dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
508 req->buf1, req->dma0, req->dma1,
509 req->sync_frame, req->data_pattern_frame,
511 req->flags & USB_REQ_ISO_ASAP ? -1 :
512 req->start_frame, req->buf_proc_intrvl,
513 req, gfp_flags == GFP_ATOMIC ? 1 : 0);
523 * This function stops ISO EP Periodic Data Transfer.
525 static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
529 DWC_WARN("bad ep\n");
532 if (!gadget_wrapper->driver ||
533 gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
534 DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
535 gadget_wrapper->gadget.speed);
536 DWC_WARN("bogus device state\n");
539 dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
547 static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
548 int packets, gfp_t gfp_flags)
550 struct usb_iso_request *pReq = NULL;
553 req_size = sizeof(struct usb_iso_request);
555 (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
557 pReq = kmalloc(req_size, gfp_flags);
559 DWC_WARN("Can't allocate Iso Request\n");
562 pReq->iso_packet_desc0 = (void *)(pReq + 1);
564 pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
569 static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
574 static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
577 .disable = ep_disable,
579 .alloc_request = dwc_otg_pcd_alloc_request,
580 .free_request = dwc_otg_pcd_free_request,
582 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
583 .alloc_buffer = dwc_otg_pcd_alloc_buffer,
584 .free_buffer = dwc_otg_pcd_free_buffer,
588 .dequeue = ep_dequeue,
592 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
593 .set_wedge = ep_wedge,
599 .iso_ep_start = iso_ep_start,
600 .iso_ep_stop = iso_ep_stop,
601 .alloc_iso_request = alloc_iso_request,
602 .free_iso_request = free_iso_request,
607 static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
609 .disable = ep_disable,
611 .alloc_request = dwc_otg_pcd_alloc_request,
612 .free_request = dwc_otg_pcd_free_request,
614 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
615 .alloc_buffer = dwc_otg_pcd_alloc_buffer,
616 .free_buffer = dwc_otg_pcd_free_buffer,
620 .dequeue = ep_dequeue,
624 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
625 .set_wedge = ep_wedge,
633 #endif /* _EN_ISOC_ */
634 /* Gadget Operations */
636 * The following gadget operations will be implemented in the DWC_otg
637 * PCD. Functions in the API that are not described below are not
640 * The Gadget API provides wrapper functions for each of the function
641 * pointers defined in usb_gadget_ops. The Gadget Driver calls the
642 * wrapper function, which then calls the underlying PCD function. The
643 * following sections are named according to the wrapper functions
644 * (except for ioctl, which doesn't have a wrapper function). Within
645 * each section, the corresponding DWC_otg PCD function name is
651 *Gets the USB Frame number of the last SOF.
653 static int get_frame_number(struct usb_gadget *gadget)
655 struct gadget_wrapper *d;
657 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
663 d = container_of(gadget, struct gadget_wrapper, gadget);
664 return dwc_otg_pcd_get_frame_number(d->pcd);
667 #ifdef CONFIG_USB_DWC_OTG_LPM
668 static int test_lpm_enabled(struct usb_gadget *gadget)
670 struct gadget_wrapper *d;
672 d = container_of(gadget, struct gadget_wrapper, gadget);
674 return dwc_otg_pcd_is_lpm_enabled(d->pcd);
677 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
678 static int test_besl_enabled(struct usb_gadget *gadget)
680 struct gadget_wrapper *d;
682 d = container_of(gadget, struct gadget_wrapper, gadget);
684 return dwc_otg_pcd_is_besl_enabled(d->pcd);
687 static int get_param_baseline_besl(struct usb_gadget *gadget)
689 struct gadget_wrapper *d;
691 d = container_of(gadget, struct gadget_wrapper, gadget);
693 return dwc_otg_pcd_get_param_baseline_besl(d->pcd);
696 static int get_param_deep_besl(struct usb_gadget *gadget)
698 struct gadget_wrapper *d;
700 d = container_of(gadget, struct gadget_wrapper, gadget);
702 return dwc_otg_pcd_get_param_deep_besl(d->pcd);
708 * Initiates Session Request Protocol (SRP) to wakeup the host if no
709 * session is in progress. If a session is already in progress, but
710 * the device is suspended, remote wakeup signaling is started.
713 static int wakeup(struct usb_gadget *gadget)
715 struct gadget_wrapper *d;
717 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
722 d = container_of(gadget, struct gadget_wrapper, gadget);
724 dwc_otg_pcd_wakeup(d->pcd);
728 static int dwc_otg_pcd_pullup(struct usb_gadget *_gadget, int is_on)
730 struct gadget_wrapper *d;
732 dwc_otg_core_if_t *core_if;
734 printk("pcd_pullup, is_on %d\n", is_on);
738 d = container_of(_gadget, struct gadget_wrapper, gadget);
740 core_if = GET_CORE_IF(d->pcd);
744 /* dwc_otg_pcd_pullup_enable(pcd); */
746 pcd->conn_status = 0;
748 dwc_otg_pcd_pullup_disable(pcd);
756 static int dwc_otg_gadget_start(struct usb_gadget *g,
757 struct usb_gadget_driver *driver)
759 DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
760 driver->driver.name);
761 if (gadget_wrapper == 0) {
762 DWC_ERROR("ENODEV\n");
765 if (gadget_wrapper->driver != 0) {
766 DWC_ERROR("EBUSY (%p)\n", gadget_wrapper->driver);
769 /* hook up the driver */
770 gadget_wrapper->driver = driver;
771 gadget_wrapper->gadget.dev.driver = &driver->driver;
773 DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
778 static int dwc_otg_gadget_stop(struct usb_gadget *g)
780 struct gadget_wrapper *d;
788 d = container_of(g, struct gadget_wrapper, gadget);
790 /* all endpoints should be shutdown */
791 dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
792 for (i = 0; i < dev_endpoints; i++) {
797 dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
798 for (i = 0; i < dev_endpoints; i++) {
803 gadget_wrapper->driver = NULL;
804 gadget_wrapper->gadget.dev.driver = NULL;
809 static const struct usb_gadget_ops dwc_otg_pcd_ops = {
810 .get_frame = get_frame_number,
812 .pullup = dwc_otg_pcd_pullup,
813 #ifdef CONFIG_USB_DWC_OTG_LPM
814 .lpm_support = test_lpm_enabled,
815 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
816 .besl_support = test_besl_enabled,
817 .get_baseline_besl = get_param_baseline_besl,
818 .get_deep_besl = get_param_deep_besl,
821 .udc_start = dwc_otg_gadget_start,
822 .udc_stop = dwc_otg_gadget_stop,
824 /* current versions must always be self-powered */
827 static int _setup(dwc_otg_pcd_t *pcd, uint8_t *bytes)
829 int retval = -DWC_E_NOT_SUPPORTED;
830 if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
831 retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
832 (struct usb_ctrlrequest
836 if (retval == -ENOTSUPP) {
837 retval = -DWC_E_NOT_SUPPORTED;
838 } else if (retval < 0) {
839 retval = -DWC_E_INVALID;
846 static int _isoc_complete(dwc_otg_pcd_t *pcd, void *ep_handle,
847 void *req_handle, int proc_buf_num)
850 struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
851 struct usb_iso_request *iso_req = req_handle;
854 iso_packet = iso_req->iso_packet_desc1;
856 iso_packet = iso_req->iso_packet_desc0;
859 dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
860 for (i = 0; i < packet_count; ++i) {
864 dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
865 i, &status, &actual, &offset);
872 DWC_PRINTF("unknown status in isoc packet\n");
876 iso_packet[i].status = status;
877 iso_packet[i].offset = offset;
878 iso_packet[i].actual_length = actual;
882 iso_req->process_buffer(ep_handle, iso_req);
886 #endif /* DWC_EN_ISOC */
888 #ifdef DWC_UTE_PER_IO
890 * Copy the contents of the extended request to the Linux usb_request's
891 * extended part and call the gadget's completion.
893 * @param pcd Pointer to the pcd structure
894 * @param ep_handle Void pointer to the usb_ep structure
895 * @param req_handle Void pointer to the usb_request structure
896 * @param status Request status returned from the portable logic
897 * @param ereq_port Void pointer to the extended request structure
898 * created in the the portable part that contains the
899 * results of the processed iso packets.
901 static int _xisoc_complete(dwc_otg_pcd_t *pcd, void *ep_handle,
902 void *req_handle, int32_t status, void *ereq_port)
904 struct dwc_ute_iso_req_ext *ereqorg = NULL;
905 struct dwc_iso_xreq_port *ereqport = NULL;
906 struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
908 struct usb_request *req;
909 /* struct dwc_ute_iso_packet_descriptor * */
910 /* int status = 0; */
912 req = (struct usb_request *)req_handle;
913 ereqorg = &req->ext_req;
914 ereqport = (struct dwc_iso_xreq_port *)ereq_port;
915 desc_org = ereqorg->per_io_frame_descs;
917 if (req && req->complete) {
918 /* Copy the request data from the portable logic to our request */
919 for (i = 0; i < ereqport->pio_pkt_count; i++) {
920 desc_org[i].actual_length =
921 ereqport->per_io_frame_descs[i].actual_length;
923 ereqport->per_io_frame_descs[i].status;
927 case -DWC_E_SHUTDOWN:
928 req->status = -ESHUTDOWN;
931 req->status = -ECONNRESET;
934 req->status = -EINVAL;
937 req->status = -ETIMEDOUT;
940 req->status = status;
943 /* And call the gadget's completion */
944 req->complete(ep_handle, req);
949 #endif /* DWC_UTE_PER_IO */
951 static int _complete(dwc_otg_pcd_t *pcd, void *ep_handle,
952 void *req_handle, int32_t status, uint32_t actual)
954 struct usb_request *req = (struct usb_request *)req_handle;
955 struct dwc_otg_pcd_ep *ep = NULL;
957 ep = ep_from_handle(pcd, ep_handle);
959 if (GET_CORE_IF(pcd)->dma_enable) {
960 /* if (req->length != 0) */
961 if (req->dma != DWC_DMA_ADDR_INVALID) {
962 dma_unmap_single(gadget_wrapper->gadget.dev.parent,
967 ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
968 req->dma = DWC_DMA_ADDR_INVALID;
972 if (req && req->complete) {
974 case -DWC_E_SHUTDOWN:
975 req->status = -ESHUTDOWN;
978 req->status = -ECONNRESET;
981 req->status = -EINVAL;
984 req->status = -ETIMEDOUT;
987 req->status = status;
991 req->actual = actual;
992 DWC_SPINUNLOCK(pcd->lock);
993 req->complete(ep_handle, req);
994 DWC_SPINLOCK(pcd->lock);
1001 static int _connect(dwc_otg_pcd_t *pcd, int speed)
1003 gadget_wrapper->gadget.speed = speed;
1007 static int _disconnect(dwc_otg_pcd_t *pcd)
1009 if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
1010 gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
1015 static int _resume(dwc_otg_pcd_t *pcd)
1017 if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
1018 gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
1024 static int _suspend(dwc_otg_pcd_t *pcd)
1026 if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
1027 gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
1033 * This function updates the otg values in the gadget structure.
1035 static int _hnp_changed(dwc_otg_pcd_t *pcd)
1038 if (!gadget_wrapper->gadget.is_otg)
1041 gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
1042 gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
1043 gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
1047 static int _reset(dwc_otg_pcd_t *pcd)
1053 static int _cfi_setup(dwc_otg_pcd_t *pcd, void *cfi_req)
1055 int retval = -DWC_E_INVALID;
1056 if (gadget_wrapper->driver->cfi_feature_setup) {
1058 gadget_wrapper->driver->cfi_feature_setup(&gadget_wrapper->
1069 static const struct dwc_otg_pcd_function_ops fops = {
1070 .complete = _complete,
1072 .isoc_complete = _isoc_complete,
1075 .disconnect = _disconnect,
1076 .connect = _connect,
1078 .suspend = _suspend,
1079 .hnp_changed = _hnp_changed,
1082 .cfi_setup = _cfi_setup,
1084 #ifdef DWC_UTE_PER_IO
1085 .xisoc_complete = _xisoc_complete,
1090 * This function is the top level PCD interrupt handler.
1092 static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
1094 dwc_otg_pcd_t *pcd = dev;
1095 int32_t retval = IRQ_NONE;
1097 retval = dwc_otg_pcd_handle_intr(pcd);
1099 /* S3C2410X_CLEAR_EINTPEND();*/
1101 return IRQ_RETVAL(retval);
1105 * This function initialized the usb_ep structures to there default
1108 * @param d Pointer on gadget_wrapper.
1110 void gadget_add_eps(struct gadget_wrapper *d)
1112 static const char *names[] = {
1149 int8_t dev_endpoints;
1151 DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
1153 INIT_LIST_HEAD(&d->gadget.ep_list);
1154 d->gadget.ep0 = &d->ep0;
1155 d->gadget.speed = USB_SPEED_UNKNOWN;
1156 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
1157 d->gadget.max_speed = USB_SPEED_HIGH;
1160 INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
1163 * Initialize the EP0 structure.
1167 /* Init the usb_ep structure. */
1168 ep->caps.type_control = true;
1169 ep->name = names[0];
1170 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
1173 * @todo NGS: What should the max packet size be set to
1174 * here? Before EP type is set?
1176 usb_ep_set_maxpacket_limit(ep, MAX_EP0_SIZE);
1177 dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
1179 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
1182 * Initialize the EP structures.
1184 dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
1186 for (i = 0; i < dev_endpoints; i++) {
1189 /* Init the usb_ep structure. */
1190 ep->caps.dir_in = true;
1191 ep->caps.type_iso = true;
1192 ep->caps.type_bulk = true;
1193 ep->caps.type_int = true;
1194 ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
1195 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
1198 * @todo NGS: What should the max packet size be set to
1199 * here? Before EP type is set?
1201 usb_ep_set_maxpacket_limit(ep, MAX_PACKET_SIZE);
1202 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
1205 dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
1207 for (i = 0; i < dev_endpoints; i++) {
1210 /* Init the usb_ep structure. */
1211 ep->caps.dir_out = true;
1212 ep->caps.type_iso = true;
1213 ep->caps.type_bulk = true;
1214 ep->caps.type_int = true;
1215 ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
1216 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
1219 * @todo NGS: What should the max packet size be set to
1220 * here? Before EP type is set?
1222 usb_ep_set_maxpacket_limit(ep, MAX_PACKET_SIZE);
1223 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
1226 /* remove ep0 from the list. There is a ep0 pointer. */
1227 list_del_init(&d->ep0.ep_list);
1229 d->ep0.maxpacket = MAX_EP0_SIZE;
1233 * This function releases the Gadget device.
1234 * required by device_unregister().
1236 * @todo Should this do something? Should it free the PCD?
1238 static void dwc_otg_pcd_gadget_release(struct device *dev)
1240 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
1243 static struct gadget_wrapper *alloc_wrapper(struct platform_device *_dev)
1245 static char pcd_name[] = "dwc_otg_pcd";
1247 dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
1248 struct gadget_wrapper *d;
1251 d = DWC_ALLOC(sizeof(*d));
1256 memset(d, 0, sizeof(*d));
1258 d->gadget.name = pcd_name;
1259 d->pcd = otg_dev->pcd;
1261 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1262 strcpy(d->gadget.dev.bus_id, "gadget");
1264 dev_set_name(&d->gadget.dev, "%s", "gadget");
1267 d->gadget.dev.parent = &_dev->dev;
1268 d->gadget.dev.release = dwc_otg_pcd_gadget_release;
1269 d->gadget.ops = &dwc_otg_pcd_ops;
1270 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0)
1271 d->gadget.is_dualspeed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd);
1273 d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
1275 d->gadget.max_speed = USB_SPEED_HIGH;
1277 d->pcd->conn_en = 0;
1278 /* Register the gadget device */
1279 retval = usb_add_gadget_udc(&_dev->dev, &d->gadget);
1281 DWC_ERROR("device_register failed\n");
1289 static void free_wrapper(struct gadget_wrapper *d)
1292 /* should have been done already by driver model core */
1293 DWC_WARN("driver '%s' is still registered\n",
1294 d->driver->driver.name);
1295 usb_gadget_unregister_driver(d->driver);
1298 usb_del_gadget_udc(&d->gadget);
1302 static void dwc_otg_pcd_work_init(dwc_otg_pcd_t *pcd,
1303 struct platform_device *dev);
1306 * This function initialized the PCD portion of the driver.
1309 int pcd_init(struct platform_device *_dev)
1312 dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
1316 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);
1318 otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
1319 printk("pcd_init otg_dev = %p\n", otg_dev);
1321 if (!otg_dev->pcd) {
1322 DWC_ERROR("dwc_otg_pcd_init failed\n");
1326 otg_dev->pcd->otg_dev = otg_dev;
1327 gadget_wrapper = alloc_wrapper(_dev);
1330 * Initialize EP structures
1332 gadget_add_eps(gadget_wrapper);
1334 * Setup interupt handler
1336 irq = platform_get_irq(_dev, 0);
1337 DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", irq);
1338 retval = request_irq(irq, dwc_otg_pcd_irq,
1340 gadget_wrapper->gadget.name, otg_dev->pcd);
1342 DWC_ERROR("request of irq%d failed\n", irq);
1343 free_wrapper(gadget_wrapper);
1347 dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
1349 dwc_otg_pcd_work_init(otg_dev->pcd, _dev);
1357 void pcd_remove(struct platform_device *_dev)
1360 dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
1361 dwc_otg_pcd_t *pcd = otg_dev->pcd;
1364 DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);
1369 irq = platform_get_irq(_dev, 0);
1371 free_wrapper(gadget_wrapper);
1372 dwc_otg_pcd_remove(otg_dev->pcd);
1377 * This function registers a gadget driver with the PCD.
1379 * When a driver is successfully registered, it will receive control
1380 * requests including set_configuration(), which enables non-control
1381 * requests. then usb traffic follows until a disconnect is reported.
1382 * then a host may connect again, or the driver might get unbound.
1384 * @param driver The driver being registered
1385 * @param bind The bind function of gadget driver
1388 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
1389 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
1391 int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
1392 int (*bind) (struct usb_gadget *))
1397 DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
1398 driver->driver.name);
1401 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
1402 driver->speed == USB_SPEED_UNKNOWN ||
1404 driver->max_speed == USB_SPEED_UNKNOWN ||
1406 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
1411 !driver->unbind || !driver->disconnect || !driver->setup) {
1412 DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
1415 if (gadget_wrapper == 0) {
1416 DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
1419 if (gadget_wrapper->driver != 0) {
1420 DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
1424 /* hook up the driver */
1425 gadget_wrapper->driver = driver;
1426 gadget_wrapper->gadget.dev.driver = &driver->driver;
1428 DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
1429 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
1430 retval = driver->bind(&gadget_wrapper->gadget);
1432 retval = bind(&gadget_wrapper->gadget);
1435 DWC_ERROR("bind to driver %s --> error %d\n",
1436 driver->driver.name, retval);
1437 gadget_wrapper->driver = 0;
1438 gadget_wrapper->gadget.dev.driver = 0;
1441 DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
1442 driver->driver.name);
1446 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
1447 EXPORT_SYMBOL(usb_gadget_register_driver);
1449 EXPORT_SYMBOL(usb_gadget_probe_driver);
1453 * This function unregisters a gadget driver
1455 * @param driver The driver being unregistered
1457 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
1459 /* DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver); */
1461 if (gadget_wrapper == 0) {
1462 DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
1466 if (driver == 0 || driver != gadget_wrapper->driver) {
1467 DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
1472 driver->unbind(&gadget_wrapper->gadget);
1473 gadget_wrapper->driver = 0;
1475 DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
1479 EXPORT_SYMBOL(usb_gadget_unregister_driver);
1483 /************************ for RK platform ************************/
1485 void dwc_otg_msc_lock(dwc_otg_pcd_t *pcd)
1487 unsigned long flags;
1488 local_irq_save(flags);
1489 wake_lock(&pcd->wake_lock);
1490 local_irq_restore(flags);
1493 void dwc_otg_msc_unlock(dwc_otg_pcd_t *pcd)
1495 unsigned long flags;
1496 local_irq_save(flags);
1497 wake_unlock(&pcd->wake_lock);
1498 local_irq_restore(flags);
1501 unsigned int dwc_otg_battery_detect(bool det_type)
1503 printk("%s\n", __func__);
1507 static void dwc_phy_reconnect(struct work_struct *work)
1510 dwc_otg_core_if_t *core_if;
1511 gotgctl_data_t gctrl;
1512 dctl_data_t dctl = {.d32 = 0 };
1513 struct dwc_otg_platform_data *pldata;
1515 pcd = container_of(work, dwc_otg_pcd_t, reconnect.work);
1516 pldata = pcd->otg_dev->pldata;
1517 core_if = GET_CORE_IF(pcd);
1518 gctrl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
1520 if (gctrl.b.bsesvld) {
1522 pldata->soft_reset(pldata, RST_RECNT);
1525 * Enable the global interrupt after all the interrupt
1526 * handlers are installed.
1529 DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl);
1530 dctl.b.sftdiscon = 0;
1531 DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl,
1534 ("*******************soft connect!!!*******************\n");
1538 static void id_status_change(dwc_otg_core_if_t *p, bool current_id)
1540 dwc_otg_core_if_t *core_if = p;
1542 gotgctl_data_t gotgctl = {.d32 = 0 };
1543 dwc_otg_pcd_t *pcd = core_if->otg_dev->pcd;
1545 gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
1546 DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32);
1547 DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts);
1549 if (core_if->usb_mode != USB_MODE_NORMAL)
1552 /* B-Device connector (Device Mode) */
1554 gotgctl_data_t gotgctl_local;
1555 /* Wait for switch to device mode. */
1556 while (!dwc_otg_is_device_mode(core_if)) {
1558 DWC_READ_REG32(&core_if->core_global_regs->gotgctl);
1559 DWC_DEBUGPL(DBG_ANY,
1560 "Waiting for Peripheral Mode, Mode=%s count = %d gotgctl=%08x\n",
1561 (dwc_otg_is_host_mode(core_if) ? "Host" :
1562 "Peripheral"), count, gotgctl_local.d32);
1568 DWC_PRINTF("Connection id status change timed out");
1571 dwc_otg_set_force_mode(core_if, USB_MODE_FORCE_DEVICE);
1572 core_if->op_state = B_PERIPHERAL;
1573 cil_hcd_stop(core_if);
1574 /* pcd->phy_suspend = 1; */
1575 pcd->vbus_status = 0;
1576 dwc_otg_core_init(core_if);
1577 cil_pcd_start(core_if);
1578 dwc_otg_pcd_start_check_vbus_work(pcd);
1580 /* A-Device connector (Host Mode) */
1581 while (!dwc_otg_is_host_mode(core_if)) {
1582 DWC_DEBUGPL(DBG_ANY, "Waiting for Host Mode, Mode=%s\n",
1583 (dwc_otg_is_host_mode(core_if) ? "Host" :
1585 dwc_mdelay(1); /* vahrama previously was 100 */
1590 DWC_PRINTF("Connection id status change timed out");
1594 core_if->op_state = A_HOST;
1595 dwc_otg_set_force_mode(core_if, USB_MODE_FORCE_HOST);
1597 cancel_delayed_work_sync(&pcd->check_vbus_work);
1600 * Initialize the Core for Host mode.
1602 dwc_otg_core_init(core_if);
1603 cil_hcd_start(core_if);
1604 dwc_otg_enable_global_interrupts(core_if);
1609 static void check_id(struct work_struct *work)
1611 dwc_otg_pcd_t *_pcd =
1612 container_of(work, dwc_otg_pcd_t, check_id_work.work);
1613 struct dwc_otg_device *otg_dev = _pcd->otg_dev;
1614 struct dwc_otg_platform_data *pldata = otg_dev->pldata;
1615 static int last_id = -1;
1616 int id = pldata->get_status(USB_STATUS_ID);
1618 if (last_id != id) {
1619 pr_info("[otg id chg] last id %d current id %d\n", last_id, id);
1621 if (pldata->phy_status == USB_PHY_SUSPEND) {
1622 pldata->clock_enable(pldata, 1);
1623 pldata->phy_suspend(pldata, USB_PHY_ENABLED);
1626 /* Force Device or Host by id */
1627 id_status_change(otg_dev->core_if, id);
1630 schedule_delayed_work(&_pcd->check_id_work, (HZ));
1633 static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
1635 dwc_otg_pcd_t *_pcd =
1636 container_of(work, dwc_otg_pcd_t, check_vbus_work.work);
1637 struct dwc_otg_device *otg_dev = _pcd->otg_dev;
1638 struct dwc_otg_platform_data *pldata = otg_dev->pldata;
1640 if (pldata->get_status(USB_STATUS_BVABLID) &&
1641 pldata->get_status(USB_STATUS_ID)) {
1642 /* if usb not connect before ,then start connect */
1643 if (_pcd->vbus_status == USB_BC_TYPE_DISCNT) {
1644 printk("***************vbus detect*****************\n");
1645 if( pldata->bc_detect_cb != NULL )
1646 pldata->bc_detect_cb(_pcd->vbus_status =
1647 usb_battery_charger_detect(1));
1649 _pcd->vbus_status = USB_BC_TYPE_SDP;
1650 if (_pcd->conn_en) {
1652 } else if (pldata->phy_status == USB_PHY_ENABLED) {
1653 /* do not allow to connect, suspend phy */
1654 pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
1656 pldata->clock_enable(pldata, 0);
1658 } else if ((_pcd->conn_en) && (_pcd->conn_status >= 0)
1659 && (_pcd->conn_status < 2)) {
1660 printk("**************soft reconnect**************\n");
1662 } else if (_pcd->conn_status == 2) {
1663 /* release pcd->wake_lock if fail to connect,
1664 * allow system to enter second sleep.
1666 dwc_otg_msc_unlock(_pcd);
1667 _pcd->conn_status++;
1668 if (pldata->bc_detect_cb != NULL) {
1669 pldata->bc_detect_cb(_pcd->vbus_status =
1670 usb_battery_charger_detect(1));
1672 _pcd->vbus_status = USB_BC_TYPE_DCP;
1674 /* fail to connect, suspend usb phy and disable clk */
1675 if (pldata->phy_status == USB_PHY_ENABLED) {
1676 pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
1678 pldata->clock_enable(pldata, 0);
1682 if (pldata->bc_detect_cb != NULL)
1683 pldata->bc_detect_cb(_pcd->vbus_status =
1684 usb_battery_charger_detect(0));
1686 _pcd->vbus_status = USB_BC_TYPE_DISCNT;
1688 if (_pcd->conn_status) {
1689 _pcd->conn_status = 0;
1692 if (pldata->phy_status == USB_PHY_ENABLED) {
1693 /* release wake lock */
1694 dwc_otg_msc_unlock(_pcd);
1695 if (pldata->get_status(USB_STATUS_ID)) {
1696 /* no vbus detect here , close usb phy */
1697 pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
1699 pldata->clock_enable(pldata, 0);
1703 /* usb phy bypass to uart mode */
1704 if (pldata->dwc_otg_uart_mode != NULL)
1705 pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
1708 if (pldata->get_status(USB_STATUS_ID))
1709 schedule_delayed_work(&_pcd->check_vbus_work, HZ);
1713 if (pldata->phy_status) {
1714 pldata->clock_enable(pldata, 1);
1715 pldata->phy_suspend(pldata, USB_PHY_ENABLED);
1718 if (_pcd->conn_status == 0)
1719 dwc_otg_msc_lock(_pcd);
1721 schedule_delayed_work(&_pcd->reconnect, 8); /* delay 8 jiffies */
1722 schedule_delayed_work(&_pcd->check_vbus_work, (HZ));
1726 void dwc_otg_pcd_start_check_vbus_work(dwc_otg_pcd_t *pcd)
1729 * when receive reset int,the vbus state may not be update,so
1730 * always start vbus work here.
1732 schedule_delayed_work(&pcd->check_vbus_work, HZ/2);
1737 * 20091228,HSL@RK,to get the current vbus status.
1739 int dwc_vbus_status(void)
1741 #ifdef CONFIG_USB20_OTG
1742 dwc_otg_pcd_t *pcd = 0;
1743 if (gadget_wrapper) {
1744 pcd = gadget_wrapper->pcd;
1750 return pcd->vbus_status;
1756 EXPORT_SYMBOL(dwc_vbus_status);
1758 static void dwc_otg_pcd_work_init(dwc_otg_pcd_t *pcd,
1759 struct platform_device *dev)
1762 struct dwc_otg_device *otg_dev = pcd->otg_dev;
1763 struct dwc_otg_platform_data *pldata = otg_dev->pldata;
1765 pcd->vbus_status = USB_BC_TYPE_DISCNT;
1766 pcd->phy_suspend = USB_PHY_ENABLED;
1768 INIT_DELAYED_WORK(&pcd->reconnect, dwc_phy_reconnect);
1769 INIT_DELAYED_WORK(&pcd->check_vbus_work, dwc_otg_pcd_check_vbus_work);
1770 INIT_DELAYED_WORK(&pcd->check_id_work, check_id);
1772 wake_lock_init(&pcd->wake_lock, WAKE_LOCK_SUSPEND, "usb_pcd");
1774 if (dwc_otg_is_device_mode(pcd->core_if) &&
1775 (otg_dev->core_if->usb_mode != USB_MODE_FORCE_HOST)) {
1776 if (pldata->get_status(USB_STATUS_BVABLID)) {
1777 /* enter usb phy mode */
1778 pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
1780 /* usb phy bypass to uart mode */
1781 pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
1783 } else if (pldata->dwc_otg_uart_mode != NULL) {
1784 /* host mode,enter usb phy mode */
1785 pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
1787 schedule_delayed_work(&pcd->check_id_work, 8 * HZ);
1788 if (otg_dev->core_if->usb_mode == USB_MODE_FORCE_DEVICE) {
1789 pcd->vbus_status = 0;
1790 dwc_otg_core_init(otg_dev->core_if);
1791 cil_pcd_start(otg_dev->core_if);
1792 dwc_otg_pcd_start_check_vbus_work(pcd);
1796 #endif /* DWC_HOST_ONLY */