dwc_otg_hcd_linux.c

Go to the documentation of this file.
00001 /* ==========================================================================
00002  * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $
00003  * $Revision: #11 $
00004  * $Date: 2009/04/21 $
00005  * $Change: 1237476 $
00006  *
00007  * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
00008  * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
00009  * otherwise expressly agreed to in writing between Synopsys and you.
00010  *
00011  * The Software IS NOT an item of Licensed Software or Licensed Product under
00012  * any End User Software License Agreement or Agreement for Licensed Product
00013  * with Synopsys or any supplement thereto. You are permitted to use and
00014  * redistribute this Software in source and binary forms, with or without
00015  * modification, provided that redistributions of source code must retain this
00016  * notice. You may not view, use, disclose, copy or distribute this file or
00017  * any information contained herein except pursuant to this license grant from
00018  * Synopsys. If you do not agree with this notice, including the disclaimer
00019  * below, then you are not authorized to use the Software.
00020  *
00021  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
00022  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
00025  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00027  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00031  * DAMAGE.
00032  * ========================================================================== */
00033 #ifndef DWC_DEVICE_ONLY
00034 
00041 #include <linux/kernel.h>
00042 #include <linux/module.h>
00043 #include <linux/moduleparam.h>
00044 #include <linux/init.h>
00045 #include <linux/device.h>
00046 #include <linux/errno.h>
00047 #include <linux/list.h>
00048 #include <linux/interrupt.h>
00049 #include <linux/string.h>
00050 #include <linux/dma-mapping.h>
00051 #include <linux/version.h>
00052 #include <asm/io.h>
00053 
00054 #ifdef LM_INTERFACE
00055 #include <asm/arch/regs-irq.h>
00056 #include <asm/arch/lm.h>
00057 #include <asm/arch/irqs.h>
00058 #endif
00059 
00060 #include <linux/usb.h>
00061 #include <../drivers/usb/core/hcd.h>
00062 
00063 #include "dwc_otg_hcd_if.h"
00064 #include "dwc_otg_dbg.h"
00065 #include "dwc_otg_driver.h"
00066 
00071 #define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
00072                                                      ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
00073 
00074 static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
00075 
00078 static int urb_enqueue(struct usb_hcd *hcd,
00079                        struct usb_host_endpoint *ep,
00080                        struct urb *urb, gfp_t mem_flags);
00081 
00082 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
00083 
00084 static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
00085 
00086 static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
00087 extern int hcd_start(struct usb_hcd *hcd);
00088 extern void hcd_stop(struct usb_hcd *hcd);
00089 static int get_frame_number(struct usb_hcd *hcd);
00090 extern int hub_status_data(struct usb_hcd *hcd, char *buf);
00091 extern int hub_control(struct usb_hcd *hcd,
00092                        u16 typeReq,
00093                        u16 wValue, u16 wIndex, char *buf, u16 wLength);
00094 
00095 struct wrapper_priv_data {
00096         dwc_otg_hcd_t *dwc_otg_hcd;
00097 };
00098 
00101 static struct hc_driver dwc_otg_hc_driver = {
00102 
00103         .description = dwc_otg_hcd_name,
00104         .product_desc = "DWC OTG Controller",
00105         .hcd_priv_size = sizeof(struct wrapper_priv_data),
00106 
00107         .irq = dwc_otg_hcd_irq,
00108 
00109         .flags = HCD_MEMORY | HCD_USB2,
00110 
00111         //.reset =              
00112         .start = hcd_start,
00113         //.suspend =            
00114         //.resume =             
00115         .stop = hcd_stop,
00116 
00117         .urb_enqueue = urb_enqueue,
00118         .urb_dequeue = urb_dequeue,
00119         .endpoint_disable = endpoint_disable,
00120 
00121         .get_frame_number = get_frame_number,
00122 
00123         .hub_status_data = hub_status_data,
00124         .hub_control = hub_control,
00125         //.bus_suspend =                
00126         //.bus_resume =         
00127 };
00128 
00130 static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
00131 {
00132         struct wrapper_priv_data *p;
00133         p = (struct wrapper_priv_data *)(hcd->hcd_priv);
00134         return p->dwc_otg_hcd;
00135 }
00136 
00138 static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
00139 {
00140         return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
00141 }
00142 
00144 inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
00145 {
00146         struct usb_device *dev = urb->dev;
00147         int ep_num = usb_pipeendpoint(urb->pipe);
00148 
00149         if (usb_pipein(urb->pipe))
00150                 return dev->ep_in[ep_num];
00151         else
00152                 return dev->ep_out[ep_num];
00153 }
00154 
00155 static int _disconnect(dwc_otg_hcd_t * hcd)
00156 {
00157         struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
00158 
00159         usb_hcd->self.is_b_host = 0;
00160         return 0;
00161 }
00162 
00163 static int _start(dwc_otg_hcd_t * hcd)
00164 {
00165         struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
00166 
00167         usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
00168         hcd_start(usb_hcd);
00169 
00170         return 0;
00171 }
00172 
00173 static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
00174                      uint32_t * port_addr)
00175 {
00176         struct urb *urb = (struct urb *)urb_handle;
00177         if (urb->dev->tt) {
00178                 *hub_addr = urb->dev->tt->hub->devnum;
00179         } else {
00180                 *hub_addr = 0;
00181         }
00182         *port_addr = urb->dev->ttport;
00183         return 0;
00184 }
00185 
00186 static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
00187 {
00188         struct urb *urb = (struct urb *)urb_handle;
00189         return urb->dev->speed;
00190 }
00191 
00192 static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
00193 {
00194         struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
00195         return usb_hcd->self.b_hnp_enable;
00196 }
00197 
00198 static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
00199                                    struct urb *urb)
00200 {
00201         hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
00202         if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00203                 hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
00204         } else {
00205                 hcd_to_bus(hcd)->bandwidth_int_reqs++;
00206         }
00207 }
00208 
00209 static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
00210                                struct urb *urb)
00211 {
00212         hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
00213         if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00214                 hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
00215         } else {
00216                 hcd_to_bus(hcd)->bandwidth_int_reqs--;
00217         }
00218 }
00219 
00224 static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
00225                      dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
00226 {
00227         struct urb *urb = (struct urb *)urb_handle;
00228 #ifdef DEBUG
00229         if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00230                 DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
00231                            __func__, urb, usb_pipedevice(urb->pipe),
00232                            usb_pipeendpoint(urb->pipe),
00233                            usb_pipein(urb->pipe) ? "IN" : "OUT", status);
00234                 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00235                         int i;
00236                         for (i = 0; i < urb->number_of_packets; i++) {
00237                                 DWC_PRINTF("  ISO Desc %d status: %d\n",
00238                                            i, urb->iso_frame_desc[i].status);
00239                         }
00240                 }
00241         }
00242 #endif
00243 
00244         urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
00245         /* Convert status value. */
00246         switch (status) {
00247         case -DWC_E_PROTOCOL:
00248                 status = -EPROTO;
00249                 break;
00250         case -DWC_E_IN_PROGRESS:
00251                 status = -EINPROGRESS;
00252                 break;
00253         case -DWC_E_PIPE:
00254                 status = -EPIPE;
00255                 break;
00256         case -DWC_E_IO:
00257                 status = -EIO;
00258                 break;
00259         case -DWC_E_TIMEOUT:
00260                 status = -ETIMEDOUT;
00261                 break;
00262         case -DWC_E_OVERFLOW:
00263                 status = -EOVERFLOW;
00264                 break;
00265         default:
00266                 if (status) {
00267                         DWC_PRINTF("Uknown urb status %d\n", status);
00268 
00269                 }
00270         }
00271 
00272         if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00273                 int i;
00274 
00275                 urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
00276                 for (i = 0; i < urb->number_of_packets; ++i) {
00277                         urb->iso_frame_desc[i].actual_length =
00278                             dwc_otg_hcd_urb_get_iso_desc_actual_length
00279                             (dwc_otg_urb, i);
00280                         urb->iso_frame_desc[i].status =
00281                             dwc_otg_hcd_urb_get_iso_desc_status
00282                             (dwc_otg_urb, i);
00283                 }
00284         }
00285 
00286         urb->status = status;
00287         urb->hcpriv = NULL;
00288         if (!status) {
00289                 if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
00290                     (urb->actual_length < urb->transfer_buffer_length)) {
00291                         urb->status = -EREMOTEIO;
00292                 }
00293         }
00294 
00295         if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
00296             (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
00297                 struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
00298                 if (ep) {
00299                         free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
00300                                            dwc_otg_hcd_get_ep_bandwidth(hcd,
00301                                                                         ep->
00302                                                                         hcpriv),
00303                                            urb);
00304                 }
00305         }
00306 
00307         dwc_free(dwc_otg_urb);
00308         usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
00309         return 0;
00310 }
00311 
00312 static struct dwc_otg_hcd_function_ops hcd_fops = {
00313         .start = _start,
00314         .disconnect = _disconnect,
00315         .hub_info = _hub_info,
00316         .speed = _speed,
00317         .complete = _complete,
00318         .get_b_hnp_enable = _get_b_hnp_enable,
00319 };
00320 
00327 int hcd_init(
00328 #ifdef LM_INTERFACE
00329         struct lm_device *_dev
00330 #elif  PCI_INTERFACE
00331         struct pci_dev *_dev
00332 #endif
00333         )
00334 {
00335         struct usb_hcd *hcd = NULL;
00336         dwc_otg_hcd_t *dwc_otg_hcd = NULL;
00337 #ifdef LM_INTERFACE
00338         dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
00339 #elif  PCI_INTERFACE
00340         dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
00341 #endif
00342 
00343         int retval = 0;
00344 
00345         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n");
00346 
00347         /* Set device flags indicating whether the HCD supports DMA. */
00348         if (dwc_otg_is_dma_enable(otg_dev->core_if)) {
00349 #ifdef LM_INTERFACE
00350                 _dev->dev.dma_mask = (void *)~0;
00351                 _dev->dev.coherent_dma_mask = ~0;
00352 #elif  PCI_INTERFACE
00353                 pci_set_dma_mask(_dev,DMA_32BIT_MASK);          
00354                 pci_set_consistent_dma_mask(_dev,DMA_32BIT_MASK);
00355 #endif
00356 
00357         } else {
00358 #ifdef LM_INTERFACE
00359                 _dev->dev.dma_mask = (void *)0;
00360                 _dev->dev.coherent_dma_mask = 0;
00361 #elif  PCI_INTERFACE
00362                 pci_set_dma_mask(_dev,0);               
00363                 pci_set_consistent_dma_mask(_dev,0);
00364 #endif
00365         }
00366 
00367         /*
00368          * Allocate memory for the base HCD plus the DWC OTG HCD.
00369          * Initialize the base HCD.
00370          */
00371         hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
00372         if (!hcd) {
00373                 retval = -ENOMEM;
00374                 goto error1;
00375         }
00376 
00377         hcd->regs = otg_dev->base;
00378 
00379         /* Initialize the DWC OTG HCD. */
00380         dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
00381         if (!dwc_otg_hcd) {
00382                 goto error2;
00383         }
00384         ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
00385             dwc_otg_hcd;
00386         otg_dev->hcd = dwc_otg_hcd;
00387 
00388         if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
00389                 goto error2;
00390         }
00391 
00392         hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
00393 
00394         /*
00395          * Finish generic HCD initialization and start the HCD. This function
00396          * allocates the DMA buffer pool, registers the USB bus, requests the
00397          * IRQ line, and calls hcd_start method.
00398          */
00399         retval = usb_add_hcd(hcd, _dev->irq, SA_SHIRQ);
00400         if (retval < 0) {
00401                 goto error2;
00402         }
00403 
00404         dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
00405         return 0;
00406 
00407       error2:
00408         usb_put_hcd(hcd);
00409       error1:
00410         return retval;
00411 }
00412 
00417 void hcd_remove(
00418 #ifdef LM_INTERFACE
00419         struct lm_device *_dev
00420 #elif  PCI_INTERFACE
00421         struct pci_dev *_dev
00422 #endif
00423         )
00424 {
00425 #ifdef LM_INTERFACE
00426         dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
00427 #elif  PCI_INTERFACE
00428         dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
00429 #endif
00430 
00431         dwc_otg_hcd_t *dwc_otg_hcd;
00432         struct usb_hcd *hcd;
00433 
00434         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE\n");
00435 
00436         if (!otg_dev) {
00437                 DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
00438                 return;
00439         }
00440 
00441         dwc_otg_hcd = otg_dev->hcd;
00442 
00443         if (!dwc_otg_hcd) {
00444                 DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
00445                 return;
00446         }
00447 
00448         hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
00449 
00450         if (!hcd) {
00451                 DWC_DEBUGPL(DBG_ANY,
00452                             "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
00453                             __func__);
00454                 return;
00455         }
00456         usb_remove_hcd(hcd);
00457         dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
00458         dwc_otg_hcd_remove(dwc_otg_hcd);
00459         usb_put_hcd(hcd);
00460 }
00461 
00462 /* =========================================================================
00463  *  Linux HC Driver Functions
00464  * ========================================================================= */
00465 
00469 int hcd_start(struct usb_hcd *hcd)
00470 {
00471         dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00472         struct usb_bus *bus;
00473 
00474         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
00475         bus = hcd_to_bus(hcd);
00476 
00477         hcd->state = HC_STATE_RUNNING;
00478         if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
00479                 return 0;
00480         }
00481 
00482         /* Initialize and connect root hub if one is not already attached */
00483         if (bus->root_hub) {
00484                 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
00485                 /* Inform the HUB driver to resume. */
00486                 usb_hcd_resume_root_hub(hcd);
00487         }
00488 
00489         return 0;
00490 }
00491 
00496 void hcd_stop(struct usb_hcd *hcd)
00497 {
00498         dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00499 
00500         dwc_otg_hcd_stop(dwc_otg_hcd);
00501 }
00502 
00504 static int get_frame_number(struct usb_hcd *hcd)
00505 {
00506         dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00507 
00508         return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
00509 }
00510 
00511 #ifdef DEBUG
00512 static void dump_urb_info(struct urb *urb, char *fn_name)
00513 {
00514         DWC_PRINTF("%s, urb %p\n", fn_name, urb);
00515         DWC_PRINTF("  Device address: %d\n", usb_pipedevice(urb->pipe));
00516         DWC_PRINTF("  Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
00517                    (usb_pipein(urb->pipe) ? "IN" : "OUT"));
00518         DWC_PRINTF("  Endpoint type: %s\n", ( {
00519                                              char *pipetype;
00520                                              switch (usb_pipetype(urb->pipe)) {
00521 case PIPE_CONTROL:
00522 pipetype = "CONTROL"; break; case PIPE_BULK:
00523 pipetype = "BULK"; break; case PIPE_INTERRUPT:
00524 pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
00525 pipetype = "ISOCHRONOUS"; break; default:
00526                                              pipetype = "UNKNOWN"; break;};
00527                                              pipetype;}
00528                    )) ;
00529         DWC_PRINTF("  Speed: %s\n", ( {
00530                                      char *speed; switch (urb->dev->speed) {
00531 case USB_SPEED_HIGH:
00532 speed = "HIGH"; break; case USB_SPEED_FULL:
00533 speed = "FULL"; break; case USB_SPEED_LOW:
00534 speed = "LOW"; break; default:
00535                                      speed = "UNKNOWN"; break;};
00536                                      speed;}
00537                    )) ;
00538         DWC_PRINTF("  Max packet size: %d\n",
00539                    usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
00540         DWC_PRINTF("  Data buffer length: %d\n", urb->transfer_buffer_length);
00541         DWC_PRINTF("  Transfer buffer: %p, Transfer DMA: %p\n",
00542                    urb->transfer_buffer, (void *)urb->transfer_dma);
00543         DWC_PRINTF("  Setup buffer: %p, Setup DMA: %p\n",
00544                    urb->setup_packet, (void *)urb->setup_dma);
00545         DWC_PRINTF("  Interval: %d\n", urb->interval);
00546         if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00547                 int i;
00548                 for (i = 0; i < urb->number_of_packets; i++) {
00549                         DWC_PRINTF("  ISO Desc %d:\n", i);
00550                         DWC_PRINTF("    offset: %d, length %d\n",
00551                                    urb->iso_frame_desc[i].offset,
00552                                    urb->iso_frame_desc[i].length);
00553                 }
00554         }
00555 }
00556 
00557 #endif
00558 
00562 static int urb_enqueue(struct usb_hcd *hcd,
00563                        struct usb_host_endpoint *ep,
00564                        struct urb *urb, gfp_t mem_flags)
00565 {
00566         int retval = 0;
00567         dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00568         dwc_otg_hcd_urb_t *dwc_otg_urb;
00569         int i;
00570         int alloc_bandwidth = 0;
00571         uint8_t ep_type = 0;
00572         uint32_t flags = 0;
00573         void *buf;
00574 
00575 #ifdef DEBUG
00576         if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00577                 dump_urb_info(urb, "urb_enqueue");
00578         }
00579 #endif
00580 
00581         if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
00582             || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
00583                 if (!dwc_otg_hcd_is_bandwidth_allocated
00584                     (dwc_otg_hcd, &ep->hcpriv)) {
00585                         alloc_bandwidth = 1;
00586                 }
00587         }
00588 
00589         switch (usb_pipetype(urb->pipe)) {
00590         case PIPE_CONTROL:
00591                 ep_type = USB_ENDPOINT_XFER_CONTROL;
00592                 break;
00593         case PIPE_ISOCHRONOUS:
00594                 ep_type = USB_ENDPOINT_XFER_ISOC;
00595                 break;
00596         case PIPE_BULK:
00597                 ep_type = USB_ENDPOINT_XFER_BULK;
00598                 break;
00599         case PIPE_INTERRUPT:
00600                 ep_type = USB_ENDPOINT_XFER_INT;
00601                 break;
00602         default:
00603                 DWC_WARN("Wrong ep type\n");
00604         }
00605 
00606         dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
00607                                             urb->number_of_packets,
00608                                             mem_flags == GFP_ATOMIC ? 1 : 0);
00609 
00610         dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
00611                                      usb_pipeendpoint(urb->pipe), ep_type,
00612                                      usb_pipein(urb->pipe),
00613                                      usb_maxpacket(urb->dev, urb->pipe,
00614                                                    !(usb_pipein(urb->pipe))));
00615 
00616         buf = urb->transfer_buffer;
00617         if (hcd->self.uses_dma) {
00618                 /*
00619                  * Calculate virtual address from physical address,
00620                  * because some class driver may not fill transfer_buffer.
00621                  * In Buffer DMA mode virual address is used,
00622                  * when handling non DWORD aligned buffers.
00623                  */
00624                 buf = phys_to_virt(urb->transfer_dma);
00625         }
00626         
00627         if (!(urb->transfer_flags & URB_NO_INTERRUPT))
00628                 flags |= URB_GIVEBACK_ASAP;
00629         if (urb->transfer_flags & URB_ZERO_PACKET)
00630                 flags |= URB_SEND_ZERO_PACKET;
00631 
00632         dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
00633                                    urb->transfer_dma,
00634                                    urb->transfer_buffer_length,
00635                                    urb->setup_packet, 
00636                                    urb->setup_dma,
00637                                    flags,
00638                                    urb->interval);
00639 
00640         for (i = 0; i < urb->number_of_packets; ++i) {
00641                 dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
00642                                                     urb->iso_frame_desc[i].
00643                                                     offset,
00644                                                     urb->iso_frame_desc[i].
00645                                                     length);
00646         }
00647 
00648         urb->hcpriv = dwc_otg_urb;
00649         retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, &ep->hcpriv);
00650         if (!retval) {
00651                 if (alloc_bandwidth) {
00652                         allocate_bus_bandwidth(hcd,
00653                                                dwc_otg_hcd_get_ep_bandwidth
00654                                                (dwc_otg_hcd, ep->hcpriv), urb);
00655                 }
00656         } else {
00657                 if (retval == -DWC_E_NO_DEVICE) {
00658                         retval = -ENODEV;
00659                 }
00660         }
00661 
00662         return retval;
00663 }
00664 
00667 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
00668 {
00669         dwc_otg_hcd_t *dwc_otg_hcd;
00670         DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
00671 
00672         dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00673 
00674 #ifdef DEBUG
00675         if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00676                 dump_urb_info(urb, "urb_dequeue");
00677         }
00678 #endif
00679         dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, urb->hcpriv);
00680 
00681         dwc_free(urb->hcpriv);
00682         urb->hcpriv = NULL;
00683 
00684         /* Higher layer software sets URB status. */
00685         usb_hcd_giveback_urb(hcd, urb);
00686         if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00687                 DWC_PRINTF("Called usb_hcd_giveback_urb()\n");
00688                 DWC_PRINTF("  urb->status = %d\n", urb->status);
00689         }
00690 
00691         return 0;
00692 }
00693 
00694 /* Frees resources in the DWC_otg controller related to a given endpoint. Also
00695  * clears state in the HCD related to the endpoint. Any URBs for the endpoint
00696  * must already be dequeued. */
00697 static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
00698 {
00699         dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00700 
00701         DWC_DEBUGPL(DBG_HCD,
00702                     "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
00703                     "endpoint=%d\n", ep->desc.bEndpointAddress,
00704                     dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
00705         dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
00706         ep->hcpriv = NULL;
00707 }
00708 
00714 static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
00715 {
00716         dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00717         int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
00718         if (retval != 0) {
00719                 S3C2410X_CLEAR_EINTPEND();
00720         }
00721         return IRQ_RETVAL(retval);
00722 }
00723 
00728 int hub_status_data(struct usb_hcd *hcd, char *buf)
00729 {
00730         dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00731 
00732         buf[0] = 0;
00733         buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
00734 
00735         return (buf[0] != 0);
00736 }
00737 
00739 int hub_control(struct usb_hcd *hcd,
00740                 u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
00741 {
00742         int retval;
00743 
00744         retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
00745                                          typeReq, wValue, wIndex, buf, wLength);
00746 
00747         switch (retval) {
00748         case -DWC_E_INVALID:
00749                 retval = -EINVAL;
00750                 break;
00751         }
00752 
00753         return retval;
00754 }
00755 
00756 #endif                          /* DWC_DEVICE_ONLY */

Generated on Tue May 5 02:22:48 2009 for DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver by  doxygen 1.4.7