USB: add usb soft reset.
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / dwc_otg_pcd_linux.c
1  /* ==========================================================================
2   * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $
3   * $Revision: #26 $
4   * $Date: 2012/12/13 $
5   * $Change: 2125485 $
6   *
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.
10   *
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.
20   *
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
31   * DAMAGE.
32   * ========================================================================== */
33 #ifndef DWC_HOST_ONLY
34
35 /** @file
36  * This file implements the Peripheral Controller Driver.
37  *
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
42  * Function Driver.
43  *
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.)
47  *
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>.
53  *
54  */
55
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"
62
63 #include "usbdev_rk.h"
64 static struct gadget_wrapper {
65         dwc_otg_pcd_t *pcd;
66
67         struct usb_gadget gadget;
68         struct usb_gadget_driver *driver;
69
70         struct usb_ep ep0;
71         struct usb_ep in_ep[16];
72         struct usb_ep out_ep[16];
73
74 } *gadget_wrapper;
75
76 /* Display the contents of the buffer */
77 extern void dump_msg(const u8 * buf, unsigned int length);
78
79 /**
80  * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case
81  * if the endpoint is not found
82  */
83 static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle)
84 {
85         int i;
86         if (pcd->ep0.priv == handle) {
87                 return &pcd->ep0;
88         }
89
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];
95         }
96
97         return NULL;
98 }
99
100 /* USB Endpoint Operations */
101 /*
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.
107  *
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.
114  *
115  */
116
117 /**
118  * This function is called by the Gadget Driver for each EP to be
119  * configured for the current configuration (SET_CONFIGURATION).
120  *
121  * This function initializes the dwc_otg_ep_t data structure, and then
122  * calls dwc_otg_ep_activate.
123  */
124 static int ep_enable(struct usb_ep *usb_ep,
125                      const struct usb_endpoint_descriptor *ep_desc)
126 {
127         int retval;
128
129         DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc);
130
131         if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) {
132                 DWC_WARN("%s, bad ep or descriptor\n", __func__);
133                 return -EINVAL;
134         }
135         if (usb_ep == &gadget_wrapper->ep0) {
136                 DWC_WARN("%s, bad ep(0)\n", __func__);
137                 return -EINVAL;
138         }
139
140         /* Check FIFO size? */
141         if (!ep_desc->wMaxPacketSize) {
142                 DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name);
143                 return -ERANGE;
144         }
145
146         if (!gadget_wrapper->driver ||
147             gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
148                 DWC_WARN("%s, bogus device state\n", __func__);
149                 return -ESHUTDOWN;
150         }
151
152         /* Delete after check - MAS */
153 #if 0
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);
158 #endif
159         retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd,
160                                        (const uint8_t *)ep_desc,
161                                        (void *)usb_ep);
162         if (retval) {
163                 DWC_WARN("dwc_otg_pcd_ep_enable failed\n");
164                 return -EINVAL;
165         }
166
167         usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize);
168
169         return 0;
170 }
171
172 /**
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.
176  *
177  * This function modifies the dwc_otg_ep_t data structure for this EP,
178  * and then calls dwc_otg_ep_deactivate.
179  */
180 static int ep_disable(struct usb_ep *usb_ep)
181 {
182         int retval;
183
184         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep);
185         if (!usb_ep) {
186                 DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__,
187                             usb_ep ? usb_ep->name : NULL);
188                 return -EINVAL;
189         }
190
191         retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep);
192         if (retval) {
193                 retval = -EINVAL;
194         }
195
196         return retval;
197 }
198
199 /**
200  * This function allocates a request object to use with the specified
201  * endpoint.
202  *
203  * @param ep The endpoint to be used with with the request
204  * @param gfp_flags the GFP_* flags to use.
205  */
206 static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep,
207                                                      gfp_t gfp_flags)
208 {
209         struct usb_request *usb_req;
210
211         DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags);
212         if (0 == ep) {
213                 DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n");
214                 return 0;
215         }
216         usb_req = kmalloc(sizeof(*usb_req), gfp_flags);
217         if (0 == usb_req) {
218                 DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n");
219                 return 0;
220         }
221         memset(usb_req, 0, sizeof(*usb_req));
222         usb_req->dma = DWC_DMA_ADDR_INVALID;
223
224         return usb_req;
225 }
226
227 /**
228  * This function frees a request object.
229  *
230  * @param ep The endpoint associated with the request
231  * @param req The request being freed
232  */
233 static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req)
234 {
235         DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req);
236
237         if (0 == ep || 0 == req) {
238                 DWC_WARN("%s() %s\n", __func__,
239                          "Invalid ep or req argument!\n");
240                 return;
241         }
242
243         kfree(req);
244 }
245
246 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
247 /**
248  * This function allocates an I/O buffer to be used for a transfer
249  * to/from the specified endpoint.
250  *
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.
256  */
257 static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes,
258                                       dma_addr_t * dma, gfp_t gfp_flags)
259 {
260         void *buf;
261         dwc_otg_pcd_t *pcd = 0;
262
263         pcd = gadget_wrapper->pcd;
264
265         DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes,
266                     dma, gfp_flags);
267
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);
272         }
273
274         buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags);
275
276         /* Check dword alignment */
277         if (((int)buf & 0x3UL) != 0) {
278                 DWC_WARN("%s() Buffer is not DWORD aligned (%p)",
279                          __func__, buf);
280         }
281
282         return buf;
283 }
284
285 /**
286  * This function frees an I/O buffer that was allocated by alloc_buffer.
287  *
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
292  */
293 static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf,
294                                     dma_addr_t dma, unsigned bytes)
295 {
296         dwc_otg_pcd_t *pcd = 0;
297
298         pcd = gadget_wrapper->pcd;
299
300         DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes);
301
302         dma_free_coherent(NULL, bytes, buf, dma);
303 }
304 #endif
305
306 /**
307  * This function is used to submit an I/O Request to an EP.
308  *
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
312  *        pending.
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
316  *        packetized.
317  *      - Zero length Packets are specified with the request 'zero'
318  *        flag.
319  */
320 static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req,
321                     gfp_t gfp_flags)
322 {
323         dwc_otg_pcd_t *pcd;
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;
327
328         DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n",
329                     __func__, usb_ep, usb_req, gfp_flags);
330
331         if (!usb_req || !usb_req->complete || !usb_req->buf) {
332                 DWC_WARN("bad params\n");
333                 return -EINVAL;
334         }
335
336         if (!usb_ep) {
337                 DWC_WARN("bad ep\n");
338                 return -EINVAL;
339         }
340
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");
347                 return -ESHUTDOWN;
348         }
349
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);
352
353         usb_req->status = -EINPROGRESS;
354         usb_req->actual = 0;
355
356         ep = ep_from_handle(pcd, usb_ep);
357         if (ep == NULL)
358                 is_isoc_ep = 0;
359         else
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;
363 #else
364         if (GET_CORE_IF(pcd)->dma_enable) {
365 //              if (usb_req->length != 0/* && usb_req->dma == DWC_DMA_ADDR_INVALID*/) {
366                 if(usb_req->dma == DWC_DMA_ADDR_INVALID){
367                         dma_addr = dma_map_single(gadget_wrapper->gadget.dev.parent,
368                                                   usb_req->buf, usb_req->length,
369                                                   ep->dwc_ep.is_in 
370                                                   ? DMA_TO_DEVICE 
371                                                   : DMA_FROM_DEVICE);
372                         usb_req->dma = dma_addr;
373                 }
374
375         }
376 #endif
377
378 #ifdef DWC_UTE_PER_IO
379         if (is_isoc_ep == 1) {
380                 retval =
381                     dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf,
382                                               dma_addr, usb_req->length,
383                                               usb_req->zero, usb_req,
384                                               gfp_flags == GFP_ATOMIC ? 1 : 0,
385                                               &usb_req->ext_req);
386                 if (retval)
387                         return -EINVAL;
388
389                 return 0;
390         }
391 #endif
392         retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr,
393                                       usb_req->length, usb_req->zero, usb_req,
394                                       gfp_flags == GFP_ATOMIC ? 1 : 0);
395         if (retval) {
396                 return -EINVAL;
397         }
398
399         return 0;
400 }
401
402 /**
403  * This function cancels an I/O request from an EP.
404  */
405 static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req)
406 {
407         DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req);
408
409         if (!usb_ep || !usb_req) {
410                 DWC_WARN("bad argument\n");
411                 return -EINVAL;
412         }
413         if (!gadget_wrapper->driver ||
414             gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
415                 DWC_WARN("bogus device state\n");
416                 return -ESHUTDOWN;
417         }
418         if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) {
419                 return -EINVAL;
420         }
421
422         return 0;
423 }
424
425 /**
426  * usb_ep_set_halt stalls an endpoint.
427  *
428  * usb_ep_clear_halt clears an endpoint halt and resets its data
429  * toggle.
430  *
431  * Both of these functions are implemented with the same underlying
432  * function. The behavior depends on the value argument.
433  *
434  * @param[in] usb_ep the Endpoint to halt or clear halt.
435  * @param[in] value
436  *      - 0 means clear_halt.
437  *      - 1 means set_halt,
438  *      - 2 means clear stall lock flag.
439  *      - 3 means set  stall lock flag.
440  */
441 static int ep_halt(struct usb_ep *usb_ep, int value)
442 {
443         int retval = 0;
444
445         DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value);
446
447         if (!usb_ep) {
448                 DWC_WARN("bad ep\n");
449                 return -EINVAL;
450         }
451
452         retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value);
453         if (retval == -DWC_E_AGAIN) {
454                 return -EAGAIN;
455         } else if (retval) {
456                 retval = -EINVAL;
457         }
458
459         return retval;
460 }
461
462 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
463 static int ep_wedge(struct usb_ep *usb_ep)
464 {
465         DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name);
466
467         return ep_halt(usb_ep, 3);
468 }
469 #endif
470
471 #ifdef DWC_EN_ISOC
472 /**
473  * This function is used to submit an ISOC Transfer Request to an EP.
474  *
475  *      - Every time a sync period completes the request's completion callback
476  *        is called to provide data to the gadget driver.
477  *      - Once submitted the request cannot be modified.
478  *      - Each request is turned into periodic data packets untill ISO
479  *        Transfer is stopped..
480  */
481 static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req,
482                         gfp_t gfp_flags)
483 {
484         int retval = 0;
485
486         if (!req || !req->process_buffer || !req->buf0 || !req->buf1) {
487                 DWC_WARN("bad params\n");
488                 return -EINVAL;
489         }
490
491         if (!usb_ep) {
492                 DWC_PRINTF("bad params\n");
493                 return -EINVAL;
494         }
495
496         req->status = -EINPROGRESS;
497
498         retval =
499             dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0,
500                                      req->buf1, req->dma0, req->dma1,
501                                      req->sync_frame, req->data_pattern_frame,
502                                      req->data_per_frame,
503                                      req->
504                                      flags & USB_REQ_ISO_ASAP ? -1 :
505                                      req->start_frame, req->buf_proc_intrvl,
506                                      req, gfp_flags == GFP_ATOMIC ? 1 : 0);
507
508         if (retval) {
509                 return -EINVAL;
510         }
511
512         return retval;
513 }
514
515 /**
516  * This function stops ISO EP Periodic Data Transfer.
517  */
518 static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req)
519 {
520         int retval = 0;
521         if (!usb_ep) {
522                 DWC_WARN("bad ep\n");
523         }
524
525         if (!gadget_wrapper->driver ||
526             gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) {
527                 DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n",
528                             gadget_wrapper->gadget.speed);
529                 DWC_WARN("bogus device state\n");
530         }
531
532         dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req);
533         if (retval) {
534                 retval = -EINVAL;
535         }
536
537         return retval;
538 }
539
540 static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep,
541                                                  int packets, gfp_t gfp_flags)
542 {
543         struct usb_iso_request *pReq = NULL;
544         uint32_t req_size;
545
546         req_size = sizeof(struct usb_iso_request);
547         req_size +=
548             (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor)));
549
550         pReq = kmalloc(req_size, gfp_flags);
551         if (!pReq) {
552                 DWC_WARN("Can't allocate Iso Request\n");
553                 return 0;
554         }
555         pReq->iso_packet_desc0 = (void *)(pReq + 1);
556
557         pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets;
558
559         return pReq;
560 }
561
562 static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req)
563 {
564         kfree(req);
565 }
566
567 static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = {
568         .ep_ops = {
569                 .enable = ep_enable,
570                 .disable = ep_disable,
571
572                 .alloc_request = dwc_otg_pcd_alloc_request,
573                 .free_request = dwc_otg_pcd_free_request,
574
575 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
576                 .alloc_buffer = dwc_otg_pcd_alloc_buffer,
577                 .free_buffer = dwc_otg_pcd_free_buffer,
578 #endif
579
580                 .queue = ep_queue,
581                 .dequeue = ep_dequeue,
582
583                 .set_halt = ep_halt,
584                  
585 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
586                 .set_wedge = ep_wedge,
587 #endif
588                 .fifo_status = 0,
589                 .fifo_flush = 0,
590         },
591
592         .iso_ep_start = iso_ep_start,
593         .iso_ep_stop = iso_ep_stop,
594         .alloc_iso_request = alloc_iso_request,
595         .free_iso_request = free_iso_request,
596 };
597
598 #else
599
600 static struct usb_ep_ops dwc_otg_pcd_ep_ops = {
601         .enable = ep_enable,
602         .disable = ep_disable,
603
604         .alloc_request = dwc_otg_pcd_alloc_request,
605         .free_request = dwc_otg_pcd_free_request,
606
607 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
608         .alloc_buffer = dwc_otg_pcd_alloc_buffer,
609         .free_buffer = dwc_otg_pcd_free_buffer,
610 #endif
611
612         .queue = ep_queue,
613         .dequeue = ep_dequeue,
614
615         .set_halt = ep_halt,
616         
617         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
618                 .set_wedge = ep_wedge,
619     #endif
620
621         .fifo_status = 0,
622         .fifo_flush = 0,
623
624 };
625
626 #endif /* _EN_ISOC_ */
627 /*      Gadget Operations */
628 /**
629  * The following gadget operations will be implemented in the DWC_otg
630  * PCD. Functions in the API that are not described below are not
631  * implemented.
632  *
633  * The Gadget API provides wrapper functions for each of the function
634  * pointers defined in usb_gadget_ops. The Gadget Driver calls the
635  * wrapper function, which then calls the underlying PCD function. The
636  * following sections are named according to the wrapper functions
637  * (except for ioctl, which doesn't have a wrapper function). Within
638  * each section, the corresponding DWC_otg PCD function name is
639  * specified.
640  *
641  */
642
643 /**
644  *Gets the USB Frame number of the last SOF.
645  */
646 static int get_frame_number(struct usb_gadget *gadget)
647 {
648         struct gadget_wrapper *d;
649
650         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
651
652         if (gadget == 0) {
653                 return -ENODEV;
654         }
655
656         d = container_of(gadget, struct gadget_wrapper, gadget);
657         return dwc_otg_pcd_get_frame_number(d->pcd);
658 }
659
660 #ifdef CONFIG_USB_DWC_OTG_LPM
661 static int test_lpm_enabled(struct usb_gadget *gadget)
662 {
663         struct gadget_wrapper *d;
664
665         d = container_of(gadget, struct gadget_wrapper, gadget);
666
667         return dwc_otg_pcd_is_lpm_enabled(d->pcd);
668 }
669 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
670 static int test_besl_enabled(struct usb_gadget *gadget)
671 {
672         struct gadget_wrapper *d;
673
674         d = container_of(gadget, struct gadget_wrapper, gadget);
675
676         return dwc_otg_pcd_is_besl_enabled(d->pcd);
677 }
678 static int get_param_baseline_besl(struct usb_gadget *gadget)
679 {
680         struct gadget_wrapper *d;
681
682         d = container_of(gadget, struct gadget_wrapper, gadget);
683
684         return dwc_otg_pcd_get_param_baseline_besl(d->pcd);
685 }
686 static int get_param_deep_besl(struct usb_gadget *gadget)
687 {
688         struct gadget_wrapper *d;
689
690         d = container_of(gadget, struct gadget_wrapper, gadget);
691
692         return dwc_otg_pcd_get_param_deep_besl(d->pcd);
693 }
694 #endif
695 #endif
696
697 /**
698  * Initiates Session Request Protocol (SRP) to wakeup the host if no
699  * session is in progress. If a session is already in progress, but
700  * the device is suspended, remote wakeup signaling is started.
701  *
702  */
703 static int wakeup(struct usb_gadget *gadget)
704 {
705         struct gadget_wrapper *d;
706
707         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget);
708
709         if (gadget == 0) {
710                 return -ENODEV;
711         } else {
712                 d = container_of(gadget, struct gadget_wrapper, gadget);
713         }
714         dwc_otg_pcd_wakeup(d->pcd);
715         return 0;
716 }
717 static int dwc_otg_pcd_pullup(struct usb_gadget *_gadget, int is_on)
718 {
719         struct gadget_wrapper *d;
720         dwc_otg_pcd_t *pcd;
721         dwc_otg_core_if_t *core_if;
722         
723         printk( "pcd_pullup, is_on %d\n",is_on);
724         if (_gadget == NULL)
725                 return -ENODEV;
726         else{
727                 d = container_of(_gadget, struct gadget_wrapper, gadget);
728                 pcd = d->pcd;
729                 core_if = GET_CORE_IF(d->pcd);
730         }
731
732         if(is_on){
733                 //dwc_otg_pcd_pullup_enable(pcd);
734                 pcd->conn_en = 1;
735                 pcd->conn_status = 0;
736         }else{
737                 dwc_otg_pcd_pullup_disable(pcd);
738                 pcd->conn_status = 2;
739         }
740
741         return 0;
742
743 }
744
745 static int dwc_otg_gadget_start(struct usb_gadget *g,
746                                 struct usb_gadget_driver *driver)
747 {
748         DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", driver->driver.name);
749         if (gadget_wrapper == 0){
750                 DWC_ERROR("ENODEV\n");
751                 return -ENODEV;
752         }
753         if (gadget_wrapper->driver != 0){
754                 DWC_ERROR("EBUSY (%p)\n", gadget_wrapper->driver);
755                 return -EBUSY;
756         }
757         /* hook up the driver */
758         gadget_wrapper->driver = driver;
759         gadget_wrapper->gadget.dev.driver = &driver->driver;
760
761         DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
762
763         return 0;
764 }
765
766 static int dwc_otg_gadget_stop(struct usb_gadget *g,
767                                struct usb_gadget_driver *driver)
768 {
769         return 0;
770 }
771
772 static const struct usb_gadget_ops dwc_otg_pcd_ops = {
773         .get_frame = get_frame_number,
774         .wakeup = wakeup,
775         .pullup = dwc_otg_pcd_pullup,
776 #ifdef CONFIG_USB_DWC_OTG_LPM
777         .lpm_support = test_lpm_enabled,
778 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) 
779         .besl_support = test_besl_enabled,
780         .get_baseline_besl = get_param_baseline_besl,
781         .get_deep_besl = get_param_deep_besl,
782 #endif  
783 #endif
784         .udc_start = dwc_otg_gadget_start,
785         .udc_stop = dwc_otg_gadget_stop,
786
787         // current versions must always be self-powered
788 };
789
790
791
792 static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes)
793 {
794         int retval = -DWC_E_NOT_SUPPORTED;
795         if (gadget_wrapper->driver && gadget_wrapper->driver->setup) {
796                 retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget,
797                                                        (struct usb_ctrlrequest
798                                                         *)bytes);
799         }
800
801         if (retval == -ENOTSUPP) {
802                 retval = -DWC_E_NOT_SUPPORTED;
803         } else if (retval < 0) {
804                 retval = -DWC_E_INVALID;
805         }
806
807         return retval;
808 }
809
810 #ifdef DWC_EN_ISOC
811 static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
812                           void *req_handle, int proc_buf_num)
813 {
814         int i, packet_count;
815         struct usb_gadget_iso_packet_descriptor *iso_packet = 0;
816         struct usb_iso_request *iso_req = req_handle;
817
818         if (proc_buf_num) {
819                 iso_packet = iso_req->iso_packet_desc1;
820         } else {
821                 iso_packet = iso_req->iso_packet_desc0;
822         }
823         packet_count =
824             dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle);
825         for (i = 0; i < packet_count; ++i) {
826                 int status;
827                 int actual;
828                 int offset;
829                 dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle,
830                                                   i, &status, &actual, &offset);
831                 switch (status) {
832                 case -DWC_E_NO_DATA:
833                         status = -ENODATA;
834                         break;
835                 default:
836                         if (status) {
837                                 DWC_PRINTF("unknown status in isoc packet\n");
838                         }
839
840                 }
841                 iso_packet[i].status = status;
842                 iso_packet[i].offset = offset;
843                 iso_packet[i].actual_length = actual;
844         }
845
846         iso_req->status = 0;
847         iso_req->process_buffer(ep_handle, iso_req);
848
849         return 0;
850 }
851 #endif /* DWC_EN_ISOC */
852
853 #ifdef DWC_UTE_PER_IO
854 /**
855  * Copy the contents of the extended request to the Linux usb_request's
856  * extended part and call the gadget's completion.
857  *
858  * @param pcd                   Pointer to the pcd structure
859  * @param ep_handle             Void pointer to the usb_ep structure
860  * @param req_handle    Void pointer to the usb_request structure
861  * @param status                Request status returned from the portable logic
862  * @param ereq_port             Void pointer to the extended request structure
863  *                                              created in the the portable part that contains the
864  *                                              results of the processed iso packets.
865  */
866 static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle,
867                            void *req_handle, int32_t status, void *ereq_port)
868 {
869         struct dwc_ute_iso_req_ext *ereqorg = NULL;
870         struct dwc_iso_xreq_port *ereqport = NULL;
871         struct dwc_ute_iso_packet_descriptor *desc_org = NULL;
872         int i;
873         struct usb_request *req;
874         //struct dwc_ute_iso_packet_descriptor *
875         //int status = 0;
876
877         req = (struct usb_request *)req_handle;
878         ereqorg = &req->ext_req;
879         ereqport = (struct dwc_iso_xreq_port *)ereq_port;
880         desc_org = ereqorg->per_io_frame_descs;
881
882         if (req && req->complete) {
883                 /* Copy the request data from the portable logic to our request */
884                 for (i = 0; i < ereqport->pio_pkt_count; i++) {
885                         desc_org[i].actual_length =
886                             ereqport->per_io_frame_descs[i].actual_length;
887                         desc_org[i].status =
888                             ereqport->per_io_frame_descs[i].status;
889                 }
890
891                 switch (status) {
892                 case -DWC_E_SHUTDOWN:
893                         req->status = -ESHUTDOWN;
894                         break;
895                 case -DWC_E_RESTART:
896                         req->status = -ECONNRESET;
897                         break;
898                 case -DWC_E_INVALID:
899                         req->status = -EINVAL;
900                         break;
901                 case -DWC_E_TIMEOUT:
902                         req->status = -ETIMEDOUT;
903                         break;
904                 default:
905                         req->status = status;
906                 }
907
908                 /* And call the gadget's completion */
909                 req->complete(ep_handle, req);
910         }
911
912         return 0;
913 }
914 #endif /* DWC_UTE_PER_IO */
915
916 static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle,
917                      void *req_handle, int32_t status, uint32_t actual)
918 {
919         struct usb_request *req = (struct usb_request *)req_handle;
920         struct device * dev = NULL;
921 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
922         struct dwc_otg_pcd_ep *ep = NULL;
923 #endif
924
925         if (req && req->complete) {
926                 switch (status) {
927                 case -DWC_E_SHUTDOWN:
928                         req->status = -ESHUTDOWN;
929                         break;
930                 case -DWC_E_RESTART:
931                         req->status = -ECONNRESET;
932                         break;
933                 case -DWC_E_INVALID:
934                         req->status = -EINVAL;
935                         break;
936                 case -DWC_E_TIMEOUT:
937                         req->status = -ETIMEDOUT;
938                         break;
939                 default:
940                         req->status = status;
941
942                 }
943
944                 req->actual = actual;
945                 DWC_SPINUNLOCK(pcd->lock);
946                 req->complete(ep_handle, req);
947                 DWC_SPINLOCK(pcd->lock);
948         }
949         
950         dev = &gadget_wrapper->pcd->otg_dev->os_dep.pdev->dev;
951         ep = ep_from_handle(pcd, ep_handle);
952
953         if (GET_CORE_IF(pcd)->dma_enable) {
954 //              if (req->length != 0)
955                 if(req->dma != DWC_DMA_ADDR_INVALID){
956                         dma_unmap_single(gadget_wrapper->gadget.dev.parent,
957                                          req->dma, req->length,
958                                          ep->dwc_ep.is_in
959                                          ? DMA_TO_DEVICE
960                                          : DMA_FROM_DEVICE);
961                         req->dma = DWC_DMA_ADDR_INVALID;
962                 }
963         }
964         return 0;
965 }
966
967 static int _connect(dwc_otg_pcd_t * pcd, int speed)
968 {
969         gadget_wrapper->gadget.speed = speed;
970         return 0;
971 }
972
973 static int _disconnect(dwc_otg_pcd_t * pcd)
974 {
975         if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) {
976                 gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget);
977         }
978         return 0;
979 }
980
981 static int _resume(dwc_otg_pcd_t * pcd)
982 {
983         if (gadget_wrapper->driver && gadget_wrapper->driver->resume) {
984                 gadget_wrapper->driver->resume(&gadget_wrapper->gadget);
985         }
986
987         return 0;
988 }
989
990 static int _suspend(dwc_otg_pcd_t * pcd)
991 {
992         if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) {
993                 gadget_wrapper->driver->suspend(&gadget_wrapper->gadget);
994         }
995         return 0;
996 }
997
998 /**
999  * This function updates the otg values in the gadget structure.
1000  */
1001 static int _hnp_changed(dwc_otg_pcd_t * pcd)
1002 {
1003
1004         if (!gadget_wrapper->gadget.is_otg)
1005                 return 0;
1006
1007         gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd);
1008         gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd);
1009         gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd);
1010         return 0;
1011 }
1012
1013 static int _reset(dwc_otg_pcd_t * pcd)
1014 {
1015         return 0;
1016 }
1017
1018 #ifdef DWC_UTE_CFI
1019 static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req)
1020 {
1021         int retval = -DWC_E_INVALID;
1022         if (gadget_wrapper->driver->cfi_feature_setup) {
1023                 retval =
1024                     gadget_wrapper->driver->
1025                     cfi_feature_setup(&gadget_wrapper->gadget,
1026                                       (struct cfi_usb_ctrlrequest *)cfi_req);
1027         }
1028
1029         return retval;
1030 }
1031 #endif
1032
1033 static const struct dwc_otg_pcd_function_ops fops = {
1034         .complete = _complete,
1035 #ifdef DWC_EN_ISOC
1036         .isoc_complete = _isoc_complete,
1037 #endif
1038         .setup = _setup,
1039         .disconnect = _disconnect,
1040         .connect = _connect,
1041         .resume = _resume,
1042         .suspend = _suspend,
1043         .hnp_changed = _hnp_changed,
1044         .reset = _reset,
1045 #ifdef DWC_UTE_CFI
1046         .cfi_setup = _cfi_setup,
1047 #endif
1048 #ifdef DWC_UTE_PER_IO
1049         .xisoc_complete = _xisoc_complete,
1050 #endif
1051 };
1052
1053 /**
1054  * This function is the top level PCD interrupt handler.
1055  */
1056 static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev)
1057 {
1058         dwc_otg_pcd_t *pcd = dev;
1059         int32_t retval = IRQ_NONE;
1060
1061         retval = dwc_otg_pcd_handle_intr(pcd);
1062         if (retval != 0) {
1063                 //S3C2410X_CLEAR_EINTPEND();
1064         }
1065         return IRQ_RETVAL(retval);
1066 }
1067
1068 /**
1069  * This function initialized the usb_ep structures to there default
1070  * state.
1071  *
1072  * @param d Pointer on gadget_wrapper.
1073  */
1074 void gadget_add_eps(struct gadget_wrapper *d)
1075 {
1076         static const char *names[] = {
1077
1078                 "ep0",
1079                 "ep1in",
1080                 "ep2in",
1081                 "ep3in",
1082                 "ep4in",
1083                 "ep5in",
1084                 "ep6in",
1085                 "ep7in",
1086                 "ep8in",
1087                 "ep9in",
1088                 "ep10in",
1089                 "ep11in",
1090                 "ep12in",
1091                 "ep13in",
1092                 "ep14in",
1093                 "ep15in",
1094                 "ep1out",
1095                 "ep2out",
1096                 "ep3out",
1097                 "ep4out",
1098                 "ep5out",
1099                 "ep6out",
1100                 "ep7out",
1101                 "ep8out",
1102                 "ep9out",
1103                 "ep10out",
1104                 "ep11out",
1105                 "ep12out",
1106                 "ep13out",
1107                 "ep14out",
1108                 "ep15out"
1109         };
1110
1111         int i;
1112         struct usb_ep *ep;
1113         int8_t dev_endpoints;
1114
1115         DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__);
1116
1117         INIT_LIST_HEAD(&d->gadget.ep_list);
1118         d->gadget.ep0 = &d->ep0;
1119         d->gadget.speed = USB_SPEED_UNKNOWN;
1120 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
1121         d->gadget.max_speed = USB_SPEED_HIGH;
1122 #endif
1123
1124         INIT_LIST_HEAD(&d->gadget.ep0->ep_list);
1125
1126         /**
1127          * Initialize the EP0 structure.
1128          */
1129         ep = &d->ep0;
1130
1131         /* Init the usb_ep structure. */
1132         ep->name = names[0];
1133         ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
1134
1135         /**
1136          * @todo NGS: What should the max packet size be set to
1137          * here?  Before EP type is set?
1138          */
1139         ep->maxpacket = MAX_PACKET_SIZE;
1140         dwc_otg_pcd_ep_enable(d->pcd, NULL, ep);
1141
1142         list_add_tail(&ep->ep_list, &d->gadget.ep_list);
1143
1144         /**
1145          * Initialize the EP structures.
1146          */
1147         dev_endpoints = d->pcd->core_if->dev_if->num_in_eps;
1148
1149         for (i = 0; i < dev_endpoints; i++) {
1150                 ep = &d->in_ep[i];
1151
1152                 /* Init the usb_ep structure. */
1153                 ep->name = names[d->pcd->in_ep[i].dwc_ep.num];
1154                 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
1155
1156                 /**
1157                  * @todo NGS: What should the max packet size be set to
1158                  * here?  Before EP type is set?
1159                  */
1160                 ep->maxpacket = MAX_PACKET_SIZE;
1161                 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
1162         }
1163
1164         dev_endpoints = d->pcd->core_if->dev_if->num_out_eps;
1165
1166         for (i = 0; i < dev_endpoints; i++) {
1167                 ep = &d->out_ep[i];
1168
1169                 /* Init the usb_ep structure. */
1170                 ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num];
1171                 ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops;
1172
1173                 /**
1174                  * @todo NGS: What should the max packet size be set to
1175                  * here?  Before EP type is set?
1176                  */
1177                 ep->maxpacket = MAX_PACKET_SIZE;
1178
1179                 list_add_tail(&ep->ep_list, &d->gadget.ep_list);
1180         }
1181
1182         /* remove ep0 from the list.  There is a ep0 pointer. */
1183         list_del_init(&d->ep0.ep_list);
1184
1185         d->ep0.maxpacket = MAX_EP0_SIZE;
1186 }
1187
1188 /**
1189  * This function releases the Gadget device.
1190  * required by device_unregister().
1191  *
1192  * @todo Should this do something?      Should it free the PCD?
1193  */
1194 static void dwc_otg_pcd_gadget_release(struct device *dev)
1195 {
1196         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev);
1197 }
1198
1199 static struct gadget_wrapper *alloc_wrapper(
1200
1201         struct platform_device *_dev
1202     )
1203 {
1204         static char pcd_name[] = "dwc_otg_pcd";
1205
1206         dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
1207         struct gadget_wrapper *d;
1208         int retval;
1209
1210         d = DWC_ALLOC(sizeof(*d));
1211         if (d == NULL) {
1212                 return NULL;
1213         }
1214
1215         memset(d, 0, sizeof(*d));
1216
1217         d->gadget.name = pcd_name;
1218         d->pcd = otg_dev->pcd;
1219
1220 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
1221         strcpy(d->gadget.dev.bus_id, "gadget");
1222 #else
1223         dev_set_name(&d->gadget.dev, "%s", "gadget");
1224 #endif
1225
1226         d->gadget.dev.parent = &_dev->dev;
1227         d->gadget.dev.release = dwc_otg_pcd_gadget_release;
1228         d->gadget.ops = &dwc_otg_pcd_ops;
1229 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
1230         d->gadget.is_dualspeed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd);
1231 #endif
1232         d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd);
1233
1234         d->gadget.max_speed = USB_SPEED_HIGH;
1235         d->driver = 0;
1236         d->pcd->conn_en = 0;
1237         /* Register the gadget device */
1238         retval = usb_add_gadget_udc(&_dev->dev, &d->gadget);
1239         if (retval != 0) {
1240                 DWC_ERROR("device_register failed\n");
1241                 DWC_FREE(d);
1242                 return NULL;
1243         }
1244
1245         return d;
1246 }
1247
1248 static void free_wrapper(struct gadget_wrapper *d)
1249 {
1250         if (d->driver) {
1251                 /* should have been done already by driver model core */
1252                 DWC_WARN("driver '%s' is still registered\n",
1253                          d->driver->driver.name);
1254                 usb_gadget_unregister_driver(d->driver);
1255         }
1256
1257         usb_del_gadget_udc(&d->gadget);
1258         DWC_FREE(d);
1259 }
1260
1261 static void dwc_otg_pcd_work_init(dwc_otg_pcd_t *pcd, struct platform_device *dev);
1262
1263 /**
1264  * This function initialized the PCD portion of the driver.
1265  *
1266  */
1267 int pcd_init(struct platform_device *_dev)
1268 {
1269
1270         dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
1271
1272         int retval = 0;
1273         int irq;
1274         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);
1275
1276         otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if);
1277         printk("pcd_init otg_dev = %p\n",otg_dev);
1278
1279         if (!otg_dev->pcd) {
1280                 DWC_ERROR("dwc_otg_pcd_init failed\n");
1281                 return -ENOMEM;
1282         }
1283
1284         otg_dev->pcd->otg_dev = otg_dev;
1285         gadget_wrapper = alloc_wrapper(_dev);
1286
1287         /*
1288          * Initialize EP structures
1289          */
1290         gadget_add_eps(gadget_wrapper);
1291         /*
1292          * Setup interupt handler
1293          */
1294         irq = platform_get_irq(_dev,0);
1295         DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", irq);
1296         retval = request_irq(irq, dwc_otg_pcd_irq,
1297                              IRQF_SHARED ,
1298                              gadget_wrapper->gadget.name, otg_dev->pcd);
1299         if (retval != 0) {
1300                 DWC_ERROR("request of irq%d failed\n", irq);
1301                 free_wrapper(gadget_wrapper);
1302                 return -EBUSY;
1303         }
1304
1305         dwc_otg_pcd_start(gadget_wrapper->pcd, &fops);
1306
1307         dwc_otg_pcd_work_init(otg_dev->pcd, _dev);
1308
1309         return retval;
1310 }
1311
1312 /**
1313  * Cleanup the PCD.
1314  */
1315 void pcd_remove(
1316
1317         struct platform_device *_dev
1318     )
1319 {
1320
1321         dwc_otg_device_t *otg_dev = dwc_get_device_platform_data(_dev);
1322         dwc_otg_pcd_t *pcd = otg_dev->pcd;
1323         int irq;
1324
1325         DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _dev);
1326
1327         /*
1328          * Free the IRQ
1329          */
1330         irq = platform_get_irq(_dev,0);
1331         free_irq(irq, pcd);
1332         free_wrapper(gadget_wrapper);
1333         dwc_otg_pcd_remove(otg_dev->pcd);       
1334         otg_dev->pcd = 0;
1335 }
1336
1337 /**
1338  * This function registers a gadget driver with the PCD.
1339  *
1340  * When a driver is successfully registered, it will receive control
1341  * requests including set_configuration(), which enables non-control
1342  * requests.  then usb traffic follows until a disconnect is reported.
1343  * then a host may connect again, or the driver might get unbound.
1344  *
1345  * @param driver The driver being registered
1346  * @param bind The bind function of gadget driver
1347  */
1348 #if 0
1349 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
1350 int usb_gadget_register_driver(struct usb_gadget_driver *driver)
1351 #else
1352 int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
1353                 int (*bind)(struct usb_gadget *))
1354 #endif
1355 {
1356         int retval;
1357
1358         DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n",
1359                     driver->driver.name);
1360
1361         if (!driver || 
1362 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
1363                 driver->speed == USB_SPEED_UNKNOWN ||
1364 #else
1365                 driver->max_speed == USB_SPEED_UNKNOWN ||
1366 #endif
1367 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
1368             !driver->bind ||
1369 #else
1370                 !bind ||
1371 #endif
1372             !driver->unbind || !driver->disconnect || !driver->setup) {
1373                 DWC_DEBUGPL(DBG_PCDV, "EINVAL\n");
1374                 return -EINVAL;
1375         }
1376         if (gadget_wrapper == 0) {
1377                 DWC_DEBUGPL(DBG_PCDV, "ENODEV\n");
1378                 return -ENODEV;
1379         }
1380         if (gadget_wrapper->driver != 0) {
1381                 DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver);
1382                 return -EBUSY;
1383         }
1384
1385         /* hook up the driver */
1386         gadget_wrapper->driver = driver;
1387         gadget_wrapper->gadget.dev.driver = &driver->driver;
1388
1389         DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name);
1390 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
1391         retval = driver->bind(&gadget_wrapper->gadget);
1392 #else
1393         retval = bind(&gadget_wrapper->gadget);
1394 #endif
1395         if (retval) {
1396                 DWC_ERROR("bind to driver %s --> error %d\n",
1397                           driver->driver.name, retval);
1398                 gadget_wrapper->driver = 0;
1399                 gadget_wrapper->gadget.dev.driver = 0;
1400                 return retval;
1401         }
1402         DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n",
1403                     driver->driver.name);
1404         return 0;
1405 }
1406 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
1407 EXPORT_SYMBOL(usb_gadget_register_driver);
1408 #else
1409 EXPORT_SYMBOL(usb_gadget_probe_driver);
1410 #endif
1411
1412 /**
1413  * This function unregisters a gadget driver
1414  *
1415  * @param driver The driver being unregistered
1416  */
1417 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
1418 {
1419         //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver);
1420
1421         if (gadget_wrapper == 0) {
1422                 DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__,
1423                             -ENODEV);
1424                 return -ENODEV;
1425         }
1426         if (driver == 0 || driver != gadget_wrapper->driver) {
1427                 DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__,
1428                             -EINVAL);
1429                 return -EINVAL;
1430         }
1431
1432         driver->unbind(&gadget_wrapper->gadget);
1433         gadget_wrapper->driver = 0;
1434
1435         DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name);
1436         return 0;
1437 }
1438
1439 EXPORT_SYMBOL(usb_gadget_unregister_driver);
1440
1441 #endif
1442
1443 /************************ for RK platform ************************/
1444
1445 void dwc_otg_msc_lock(dwc_otg_pcd_t *pcd)
1446 {
1447         unsigned long flags;
1448         local_irq_save(flags);
1449         wake_lock(&pcd->wake_lock);
1450         local_irq_restore(flags);
1451 }
1452
1453 void dwc_otg_msc_unlock(dwc_otg_pcd_t *pcd)
1454 {
1455         unsigned long flags;
1456         local_irq_save(flags);
1457         wake_unlock(&pcd->wake_lock);
1458         local_irq_restore(flags);
1459 }
1460
1461 unsigned int dwc_otg_battery_detect(bool det_type)
1462 {
1463     printk("%s\n",__func__);
1464     return 0;
1465 }
1466
1467 static void dwc_phy_reconnect(struct work_struct *work)
1468 {
1469         dwc_otg_pcd_t *pcd;
1470         dwc_otg_core_if_t *core_if;
1471         gotgctl_data_t    gctrl;
1472         dctl_data_t dctl = {.d32=0};
1473         struct dwc_otg_platform_data *pldata;
1474
1475         pcd = container_of(work, dwc_otg_pcd_t, reconnect.work);
1476         pldata = pcd->otg_dev->pldata;
1477         core_if = GET_CORE_IF(pcd);
1478         gctrl.d32 = DWC_READ_REG32( &core_if->core_global_regs->gotgctl );
1479
1480         if(gctrl.b.bsesvld){
1481                 pcd->conn_status++;
1482                 pldata->soft_reset();
1483                 dwc_pcd_reset(pcd);
1484                 /*
1485                  * Enable the global interrupt after all the interrupt
1486                  * handlers are installed.
1487                  */
1488                 dctl.d32 = DWC_READ_REG32( &core_if->dev_if->dev_global_regs->dctl );
1489                 dctl.b.sftdiscon = 0;
1490                 DWC_WRITE_REG32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
1491                 printk("*******************soft connect!!!*******************\n");
1492         }
1493 }
1494
1495 static void dwc_otg_pcd_check_vbus_work( struct work_struct *work )
1496 {
1497         dwc_otg_pcd_t * _pcd = container_of(work, dwc_otg_pcd_t, check_vbus_work.work);
1498         struct dwc_otg_device* otg_dev = _pcd->otg_dev;
1499         struct dwc_otg_platform_data *pldata = otg_dev->pldata;
1500         unsigned long flags;
1501
1502         local_irq_save(flags);
1503
1504         if(!pldata->get_status(USB_STATUS_ID)){
1505                 // id low, host mode
1506                 if( pldata->dwc_otg_uart_mode != NULL ){
1507                         //exit phy bypass to uart & enable usb phy
1508                         pldata->dwc_otg_uart_mode( pldata, PHY_USB_MODE);
1509                 }
1510                 if( pldata->phy_status){
1511                         pldata->clock_enable( pldata, 1);
1512                         pldata->phy_suspend(pldata, USB_PHY_ENABLED);
1513                 }
1514                 if( pldata->bc_detect_cb != NULL )
1515             pldata->bc_detect_cb( _pcd->vbus_status = USB_BC_TYPE_DISCNT );
1516         else
1517             _pcd->vbus_status = USB_BC_TYPE_DISCNT;
1518             dwc_otg_enable_global_interrupts(otg_dev->core_if);
1519
1520         }else if(pldata->get_status(USB_STATUS_BVABLID)){
1521                 /* if usb not connect before ,then start connect */
1522                 if( _pcd->vbus_status == USB_BC_TYPE_DISCNT ) {
1523                         printk("*******************vbus detect*********************\n");
1524 //            if( pldata->bc_detect_cb != NULL )
1525 //                pldata->bc_detect_cb( _pcd->vbus_status = usb_battery_charger_detect(1) );
1526 //            else
1527                 _pcd->vbus_status = USB_BC_TYPE_SDP;
1528                         if(_pcd->conn_en){
1529                                 goto connect;
1530                         }
1531                         else if( pldata->phy_status == USB_PHY_ENABLED ){
1532                                 // do not allow to connect, suspend phy
1533                                 pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
1534                                 udelay(3);
1535                                 pldata->clock_enable( pldata, 0);
1536                         }
1537                 }else if((_pcd->conn_en)&&(_pcd->conn_status>=0)&&(_pcd->conn_status <2)){
1538                         printk("******************soft reconnect********************\n");
1539                         goto connect;
1540                 }else if(_pcd->conn_status == 2){
1541                         /* release pcd->wake_lock if fail to connect,
1542                          * allow system to enter second sleep.
1543                          */
1544                         dwc_otg_msc_unlock(_pcd);
1545                         _pcd->conn_status++;
1546             if( pldata->bc_detect_cb != NULL ){
1547                 rk_usb_charger_status = USB_BC_TYPE_DCP;
1548                 pldata->bc_detect_cb( _pcd->vbus_status = USB_BC_TYPE_DCP ); 
1549             }else{
1550                 _pcd->vbus_status = USB_BC_TYPE_DCP;
1551                 rk_usb_charger_status = USB_BC_TYPE_DCP;
1552                         }
1553                         /* fail to connect, suspend usb phy and disable clk */
1554                         if( pldata->phy_status == USB_PHY_ENABLED ){
1555                                 pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
1556                                 udelay(3);
1557                                 pldata->clock_enable( pldata, 0);
1558                         }
1559                 }
1560         }else {
1561         if( pldata->bc_detect_cb != NULL )
1562             pldata->bc_detect_cb( _pcd->vbus_status = USB_BC_TYPE_DISCNT );
1563         else
1564                     _pcd->vbus_status = USB_BC_TYPE_DISCNT;
1565
1566                 if(_pcd->conn_status){
1567                         _pcd->conn_status = 0;
1568                 }
1569
1570                 if( pldata->phy_status == USB_PHY_ENABLED ){
1571                         /* release wake lock */
1572                         dwc_otg_msc_unlock(_pcd);
1573                         /* no vbus detect here , close usb phy  */
1574                         pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
1575                         udelay(3);
1576                         pldata->clock_enable( pldata, 0);
1577                 }
1578
1579                 /* usb phy bypass to uart mode  */
1580                 if( pldata->dwc_otg_uart_mode != NULL )
1581                         pldata->dwc_otg_uart_mode( pldata, PHY_UART_MODE);
1582         }
1583
1584         schedule_delayed_work(&_pcd->check_vbus_work, HZ);
1585         local_irq_restore(flags);
1586
1587         return;
1588     
1589 connect:
1590         if( pldata->phy_status)
1591         {
1592                 pldata->clock_enable(pldata, 1);
1593                 pldata->phy_suspend(pldata, USB_PHY_ENABLED);
1594         }
1595
1596         if(_pcd->conn_status==0)
1597                 dwc_otg_msc_lock(_pcd);
1598
1599         schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 8 jiffies */
1600         schedule_delayed_work(&_pcd->check_vbus_work, (HZ<<2));
1601         local_irq_restore(flags);
1602
1603         return;
1604 }
1605
1606 void dwc_otg_pcd_start_check_vbus_work(dwc_otg_pcd_t * pcd)
1607 {
1608         /* 
1609          * when receive reset int,the vbus state may not be update,so 
1610          * always start vbus work here.
1611          */
1612         schedule_delayed_work(&pcd->check_vbus_work, (HZ*2));
1613 }
1614
1615 /*
1616 * 20091228,HSL@RK,to get the current vbus status.
1617 */
1618 int dwc_vbus_status( void )
1619 {
1620 #ifdef CONFIG_USB20_OTG
1621         dwc_otg_pcd_t *pcd = 0;
1622         if(gadget_wrapper){
1623                 pcd = gadget_wrapper->pcd;
1624         }
1625
1626         if(!pcd)
1627                 return 0;
1628         else
1629                 return pcd->vbus_status ;
1630 #else
1631         return 0;
1632 #endif
1633 }
1634 EXPORT_SYMBOL(dwc_vbus_status);
1635
1636 static void dwc_otg_pcd_work_init(dwc_otg_pcd_t *pcd, struct platform_device *dev)
1637 {
1638
1639         struct dwc_otg_device* otg_dev = pcd->otg_dev;
1640         struct dwc_otg_platform_data *pldata = otg_dev->pldata;
1641         pcd->vbus_status  = USB_BC_TYPE_DISCNT;
1642         pcd->phy_suspend  = USB_PHY_ENABLED;
1643
1644         INIT_DELAYED_WORK(&pcd->reconnect , dwc_phy_reconnect);
1645         INIT_DELAYED_WORK(&pcd->check_vbus_work , dwc_otg_pcd_check_vbus_work);
1646
1647         wake_lock_init(&pcd->wake_lock, WAKE_LOCK_SUSPEND, "usb_pcd");
1648     
1649         if(dwc_otg_is_device_mode(pcd->core_if) &&
1650           (otg_dev->core_if->usb_mode != USB_MODE_FORCE_HOST)){
1651 #ifdef CONFIG_RK_USB_UART        
1652                 if(pldata->get_status(USB_STATUS_BVABLID)){
1653                         //enter usb phy mode
1654                         pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
1655                 }else{
1656                         //usb phy bypass to uart mode
1657                         pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
1658                 }
1659 #endif
1660                 schedule_delayed_work(&pcd->check_vbus_work, (HZ<<4));
1661         }
1662 #ifdef CONFIG_RK_USB_UART
1663         else if(pldata->dwc_otg_uart_mode != NULL)
1664                 //host mode,enter usb phy mode
1665                 pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
1666 #endif
1667
1668 }
1669
1670 #endif /* DWC_HOST_ONLY */