00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
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 #include <linux/usb.h>
00054 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35)
00055 #include <../drivers/usb/core/hcd.h>
00056 #else
00057 #include <linux/usb/hcd.h>
00058 #endif
00059
00060 #include "dwc_otg_hcd_if.h"
00061 #include "dwc_otg_dbg.h"
00062 #include "dwc_otg_driver.h"
00063 #include "dwc_otg_hcd.h"
00068 #define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
00069 ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
00070
00071 static const char dwc_otg_hcd_name[] = "dwc_otg_hcd";
00072
00075 static int urb_enqueue(struct usb_hcd *hcd,
00076 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00077 struct usb_host_endpoint *ep,
00078 #endif
00079 struct urb *urb, gfp_t mem_flags);
00080 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00081 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
00082 #else
00083 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
00084 #endif
00085
00086 static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
00087 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
00088 static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
00089 #endif
00090 static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd);
00091 extern int hcd_start(struct usb_hcd *hcd);
00092 extern void hcd_stop(struct usb_hcd *hcd);
00093 static int get_frame_number(struct usb_hcd *hcd);
00094 extern int hub_status_data(struct usb_hcd *hcd, char *buf);
00095 extern int hub_control(struct usb_hcd *hcd,
00096 u16 typeReq,
00097 u16 wValue, u16 wIndex, char *buf, u16 wLength);
00098
00099 struct wrapper_priv_data {
00100 dwc_otg_hcd_t *dwc_otg_hcd;
00101 };
00102
00105 static struct hc_driver dwc_otg_hc_driver = {
00106
00107 .description = dwc_otg_hcd_name,
00108 .product_desc = "DWC OTG Controller",
00109 .hcd_priv_size = sizeof(struct wrapper_priv_data),
00110
00111 .irq = dwc_otg_hcd_irq,
00112
00113 .flags = HCD_MEMORY | HCD_USB2,
00114
00115
00116 .start = hcd_start,
00117
00118
00119 .stop = hcd_stop,
00120
00121 .urb_enqueue = urb_enqueue,
00122 .urb_dequeue = urb_dequeue,
00123 .endpoint_disable = endpoint_disable,
00124 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
00125 .endpoint_reset = endpoint_reset,
00126 #endif
00127 .get_frame_number = get_frame_number,
00128
00129 .hub_status_data = hub_status_data,
00130 .hub_control = hub_control,
00131
00132
00133 };
00134
00136 static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd)
00137 {
00138 struct wrapper_priv_data *p;
00139 p = (struct wrapper_priv_data *)(hcd->hcd_priv);
00140 return p->dwc_otg_hcd;
00141 }
00142
00144 static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd)
00145 {
00146 return dwc_otg_hcd_get_priv_data(dwc_otg_hcd);
00147 }
00148
00150 inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb)
00151 {
00152 struct usb_device *dev = urb->dev;
00153 int ep_num = usb_pipeendpoint(urb->pipe);
00154
00155 if (usb_pipein(urb->pipe))
00156 return dev->ep_in[ep_num];
00157 else
00158 return dev->ep_out[ep_num];
00159 }
00160
00161 static int _disconnect(dwc_otg_hcd_t * hcd)
00162 {
00163 struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
00164
00165 usb_hcd->self.is_b_host = 0;
00166 return 0;
00167 }
00168
00169 static int _start(dwc_otg_hcd_t * hcd)
00170 {
00171 struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
00172
00173 usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd);
00174 hcd_start(usb_hcd);
00175
00176 return 0;
00177 }
00178
00179 static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr,
00180 uint32_t * port_addr)
00181 {
00182 struct urb *urb = (struct urb *)urb_handle;
00183 if (urb->dev->tt) {
00184 *hub_addr = urb->dev->tt->hub->devnum;
00185 } else {
00186 *hub_addr = 0;
00187 }
00188 *port_addr = urb->dev->ttport;
00189 return 0;
00190 }
00191
00192 static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle)
00193 {
00194 struct urb *urb = (struct urb *)urb_handle;
00195 return urb->dev->speed;
00196 }
00197
00198 static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd)
00199 {
00200 struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd);
00201 return usb_hcd->self.b_hnp_enable;
00202 }
00203
00204 static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
00205 struct urb *urb)
00206 {
00207 hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval;
00208 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00209 hcd_to_bus(hcd)->bandwidth_isoc_reqs++;
00210 } else {
00211 hcd_to_bus(hcd)->bandwidth_int_reqs++;
00212 }
00213 }
00214
00215 static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw,
00216 struct urb *urb)
00217 {
00218 hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval;
00219 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00220 hcd_to_bus(hcd)->bandwidth_isoc_reqs--;
00221 } else {
00222 hcd_to_bus(hcd)->bandwidth_int_reqs--;
00223 }
00224 }
00225
00230 static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
00231 dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
00232 {
00233 struct urb *urb = (struct urb *)urb_handle;
00234 #ifdef DEBUG
00235 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00236 DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
00237 __func__, urb, usb_pipedevice(urb->pipe),
00238 usb_pipeendpoint(urb->pipe),
00239 usb_pipein(urb->pipe) ? "IN" : "OUT", status);
00240 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00241 int i;
00242 for (i = 0; i < urb->number_of_packets; i++) {
00243 DWC_PRINTF(" ISO Desc %d status: %d\n",
00244 i, urb->iso_frame_desc[i].status);
00245 }
00246 }
00247 }
00248 #endif
00249
00250 urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
00251
00252 switch (status) {
00253 case -DWC_E_PROTOCOL:
00254 status = -EPROTO;
00255 break;
00256 case -DWC_E_IN_PROGRESS:
00257 status = -EINPROGRESS;
00258 break;
00259 case -DWC_E_PIPE:
00260 status = -EPIPE;
00261 break;
00262 case -DWC_E_IO:
00263 status = -EIO;
00264 break;
00265 case -DWC_E_TIMEOUT:
00266 status = -ETIMEDOUT;
00267 break;
00268 case -DWC_E_OVERFLOW:
00269 status = -EOVERFLOW;
00270 break;
00271 default:
00272 if (status) {
00273 DWC_PRINTF("Uknown urb status %d\n", status);
00274
00275 }
00276 }
00277
00278 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00279 int i;
00280
00281 urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb);
00282 for (i = 0; i < urb->number_of_packets; ++i) {
00283 urb->iso_frame_desc[i].actual_length =
00284 dwc_otg_hcd_urb_get_iso_desc_actual_length
00285 (dwc_otg_urb, i);
00286 urb->iso_frame_desc[i].status =
00287 dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i);
00288 }
00289 }
00290
00291 urb->status = status;
00292 urb->hcpriv = NULL;
00293 if (!status) {
00294 if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
00295 (urb->actual_length < urb->transfer_buffer_length)) {
00296 urb->status = -EREMOTEIO;
00297 }
00298 }
00299
00300 if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ||
00301 (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
00302 struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb);
00303 if (ep) {
00304 free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd),
00305 dwc_otg_hcd_get_ep_bandwidth(hcd,
00306 ep->hcpriv),
00307 urb);
00308 }
00309 }
00310
00311 DWC_FREE(dwc_otg_urb);
00312
00313 DWC_SPINUNLOCK(hcd->lock);
00314 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00315 usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
00316 #else
00317 usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
00318 #endif
00319 DWC_SPINLOCK(hcd->lock);
00320
00321 return 0;
00322 }
00323
00324 static struct dwc_otg_hcd_function_ops hcd_fops = {
00325 .start = _start,
00326 .disconnect = _disconnect,
00327 .hub_info = _hub_info,
00328 .speed = _speed,
00329 .complete = _complete,
00330 .get_b_hnp_enable = _get_b_hnp_enable,
00331 };
00332
00339 int hcd_init(
00340 #ifdef LM_INTERFACE
00341 struct lm_device *_dev
00342 #elif defined(PCI_INTERFACE)
00343 struct pci_dev *_dev
00344 #endif
00345 )
00346 {
00347 struct usb_hcd *hcd = NULL;
00348 dwc_otg_hcd_t *dwc_otg_hcd = NULL;
00349 #ifdef LM_INTERFACE
00350 dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
00351 #elif defined(PCI_INTERFACE)
00352 dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
00353 #endif
00354
00355 int retval = 0;
00356
00357 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT\n");
00358
00359
00360 if (dwc_otg_is_dma_enable(otg_dev->core_if)) {
00361 #ifdef LM_INTERFACE
00362 _dev->dev.dma_mask = (void *)~0;
00363 _dev->dev.coherent_dma_mask = ~0;
00364 #elif defined(PCI_INTERFACE)
00365 pci_set_dma_mask(_dev, DMA_32BIT_MASK);
00366 pci_set_consistent_dma_mask(_dev, DMA_32BIT_MASK);
00367 #endif
00368
00369 } else {
00370 #ifdef LM_INTERFACE
00371 _dev->dev.dma_mask = (void *)0;
00372 _dev->dev.coherent_dma_mask = 0;
00373 #elif defined(PCI_INTERFACE)
00374 pci_set_dma_mask(_dev, 0);
00375 pci_set_consistent_dma_mask(_dev, 0);
00376 #endif
00377 }
00378
00379
00380
00381
00382
00383 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
00384 hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id);
00385 #else
00386 hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev));
00387 hcd->has_tt = 1;
00388
00389
00390 #endif
00391 if (!hcd) {
00392 retval = -ENOMEM;
00393 goto error1;
00394 }
00395
00396 hcd->regs = otg_dev->os_dep.base;
00397
00398
00399 dwc_otg_hcd = dwc_otg_hcd_alloc_hcd();
00400 if (!dwc_otg_hcd) {
00401 goto error2;
00402 }
00403 ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd =
00404 dwc_otg_hcd;
00405 otg_dev->hcd = dwc_otg_hcd;
00406
00407 if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) {
00408 goto error2;
00409 }
00410
00411 otg_dev->hcd->otg_dev = otg_dev;
00412 hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd);
00413 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel)
00414 hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if);
00415
00416 hcd->self.sg_tablesize = 0;
00417 #endif
00418
00419
00420
00421
00422
00423 retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED);
00424 if (retval < 0) {
00425 goto error2;
00426 }
00427
00428 dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd);
00429 return 0;
00430
00431 error2:
00432 usb_put_hcd(hcd);
00433 error1:
00434 return retval;
00435 }
00436
00441 void hcd_remove(
00442 #ifdef LM_INTERFACE
00443 struct lm_device *_dev
00444 #elif defined(PCI_INTERFACE)
00445 struct pci_dev *_dev
00446 #endif
00447 )
00448 {
00449 #ifdef LM_INTERFACE
00450 dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev);
00451 #elif defined(PCI_INTERFACE)
00452 dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev);
00453 #endif
00454
00455 dwc_otg_hcd_t *dwc_otg_hcd;
00456 struct usb_hcd *hcd;
00457
00458 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE\n");
00459
00460 if (!otg_dev) {
00461 DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__);
00462 return;
00463 }
00464
00465 dwc_otg_hcd = otg_dev->hcd;
00466
00467 if (!dwc_otg_hcd) {
00468 DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__);
00469 return;
00470 }
00471
00472 hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd);
00473
00474 if (!hcd) {
00475 DWC_DEBUGPL(DBG_ANY,
00476 "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n",
00477 __func__);
00478 return;
00479 }
00480 usb_remove_hcd(hcd);
00481 dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL);
00482 dwc_otg_hcd_remove(dwc_otg_hcd);
00483 usb_put_hcd(hcd);
00484 }
00485
00486
00487
00488
00489
00493 int hcd_start(struct usb_hcd *hcd)
00494 {
00495 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00496 struct usb_bus *bus;
00497
00498 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n");
00499 bus = hcd_to_bus(hcd);
00500
00501 hcd->state = HC_STATE_RUNNING;
00502 if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) {
00503 return 0;
00504 }
00505
00506
00507 if (bus->root_hub) {
00508 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n");
00509
00510 usb_hcd_resume_root_hub(hcd);
00511 }
00512
00513 return 0;
00514 }
00515
00520 void hcd_stop(struct usb_hcd *hcd)
00521 {
00522 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00523
00524 dwc_otg_hcd_stop(dwc_otg_hcd);
00525 }
00526
00528 static int get_frame_number(struct usb_hcd *hcd)
00529 {
00530 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00531
00532 return dwc_otg_hcd_get_frame_number(dwc_otg_hcd);
00533 }
00534
00535 #ifdef DEBUG
00536 static void dump_urb_info(struct urb *urb, char *fn_name)
00537 {
00538 DWC_PRINTF("%s, urb %p\n", fn_name, urb);
00539 DWC_PRINTF(" Device address: %d\n", usb_pipedevice(urb->pipe));
00540 DWC_PRINTF(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
00541 (usb_pipein(urb->pipe) ? "IN" : "OUT"));
00542 DWC_PRINTF(" Endpoint type: %s\n", ( {
00543 char *pipetype;
00544 switch (usb_pipetype(urb->pipe)) {
00545 case PIPE_CONTROL:
00546 pipetype = "CONTROL"; break; case PIPE_BULK:
00547 pipetype = "BULK"; break; case PIPE_INTERRUPT:
00548 pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS:
00549 pipetype = "ISOCHRONOUS"; break; default:
00550 pipetype = "UNKNOWN"; break;};
00551 pipetype;}
00552 )) ;
00553 DWC_PRINTF(" Speed: %s\n", ( {
00554 char *speed; switch (urb->dev->speed) {
00555 case USB_SPEED_HIGH:
00556 speed = "HIGH"; break; case USB_SPEED_FULL:
00557 speed = "FULL"; break; case USB_SPEED_LOW:
00558 speed = "LOW"; break; default:
00559 speed = "UNKNOWN"; break;};
00560 speed;}
00561 )) ;
00562 DWC_PRINTF(" Max packet size: %d\n",
00563 usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
00564 DWC_PRINTF(" Data buffer length: %d\n", urb->transfer_buffer_length);
00565 DWC_PRINTF(" Transfer buffer: %p, Transfer DMA: %p\n",
00566 urb->transfer_buffer, (void *)urb->transfer_dma);
00567 DWC_PRINTF(" Setup buffer: %p, Setup DMA: %p\n",
00568 urb->setup_packet, (void *)urb->setup_dma);
00569 DWC_PRINTF(" Interval: %d\n", urb->interval);
00570 if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
00571 int i;
00572 for (i = 0; i < urb->number_of_packets; i++) {
00573 DWC_PRINTF(" ISO Desc %d:\n", i);
00574 DWC_PRINTF(" offset: %d, length %d\n",
00575 urb->iso_frame_desc[i].offset,
00576 urb->iso_frame_desc[i].length);
00577 }
00578 }
00579 }
00580
00581 #endif
00582
00586 static int urb_enqueue(struct usb_hcd *hcd,
00587 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00588 struct usb_host_endpoint *ep,
00589 #endif
00590 struct urb *urb, gfp_t mem_flags)
00591 {
00592 int retval = 0;
00593 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
00594 struct usb_host_endpoint *ep = urb->ep;
00595 #endif
00596 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00597 dwc_otg_hcd_urb_t *dwc_otg_urb;
00598 int i;
00599 int alloc_bandwidth = 0;
00600 uint8_t ep_type = 0;
00601 uint32_t flags = 0;
00602 void *buf;
00603
00604 #ifdef DEBUG
00605 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00606 dump_urb_info(urb, "urb_enqueue");
00607 }
00608 #endif
00609
00610 if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
00611 || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) {
00612 if (!dwc_otg_hcd_is_bandwidth_allocated
00613 (dwc_otg_hcd, &ep->hcpriv)) {
00614 alloc_bandwidth = 1;
00615 }
00616 }
00617
00618 switch (usb_pipetype(urb->pipe)) {
00619 case PIPE_CONTROL:
00620 ep_type = USB_ENDPOINT_XFER_CONTROL;
00621 break;
00622 case PIPE_ISOCHRONOUS:
00623 ep_type = USB_ENDPOINT_XFER_ISOC;
00624 break;
00625 case PIPE_BULK:
00626 ep_type = USB_ENDPOINT_XFER_BULK;
00627 break;
00628 case PIPE_INTERRUPT:
00629 ep_type = USB_ENDPOINT_XFER_INT;
00630 break;
00631 default:
00632 DWC_WARN("Wrong ep type\n");
00633 }
00634
00635 dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd,
00636 urb->number_of_packets,
00637 mem_flags == GFP_ATOMIC ? 1 : 0);
00638
00639 dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe),
00640 usb_pipeendpoint(urb->pipe), ep_type,
00641 usb_pipein(urb->pipe),
00642 usb_maxpacket(urb->dev, urb->pipe,
00643 !(usb_pipein(urb->pipe))));
00644
00645 buf = urb->transfer_buffer;
00646 if (hcd->self.uses_dma) {
00647
00648
00649
00650
00651
00652
00653 buf = phys_to_virt(urb->transfer_dma);
00654 }
00655
00656 if (!(urb->transfer_flags & URB_NO_INTERRUPT))
00657 flags |= URB_GIVEBACK_ASAP;
00658 if (urb->transfer_flags & URB_ZERO_PACKET)
00659 flags |= URB_SEND_ZERO_PACKET;
00660
00661 dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf,
00662 urb->transfer_dma,
00663 urb->transfer_buffer_length,
00664 urb->setup_packet,
00665 urb->setup_dma, flags, urb->interval);
00666
00667 for (i = 0; i < urb->number_of_packets; ++i) {
00668 dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i,
00669 urb->
00670 iso_frame_desc[i].offset,
00671 urb->
00672 iso_frame_desc[i].length);
00673 }
00674
00675 urb->hcpriv = dwc_otg_urb;
00676 retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, &ep->hcpriv,
00677 mem_flags == GFP_ATOMIC ? 1 : 0);
00678 if (!retval) {
00679 if (alloc_bandwidth) {
00680 allocate_bus_bandwidth(hcd,
00681 dwc_otg_hcd_get_ep_bandwidth
00682 (dwc_otg_hcd, ep->hcpriv), urb);
00683 }
00684 } else {
00685 if (retval == -DWC_E_NO_DEVICE) {
00686 retval = -ENODEV;
00687 }
00688 }
00689
00690 return retval;
00691 }
00692
00695 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00696 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
00697 #else
00698 static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
00699 #endif
00700 {
00701 dwc_irqflags_t flags;
00702 dwc_otg_hcd_t *dwc_otg_hcd;
00703 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n");
00704
00705 dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00706
00707 #ifdef DEBUG
00708 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00709 dump_urb_info(urb, "urb_dequeue");
00710 }
00711 #endif
00712
00713 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
00714
00715 dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, urb->hcpriv);
00716
00717 DWC_FREE(urb->hcpriv);
00718 urb->hcpriv = NULL;
00719 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
00720
00721
00722 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
00723 usb_hcd_giveback_urb(hcd, urb);
00724 #else
00725 usb_hcd_giveback_urb(hcd, urb, status);
00726 #endif
00727 if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
00728 DWC_PRINTF("Called usb_hcd_giveback_urb()\n");
00729 DWC_PRINTF(" urb->status = %d\n", urb->status);
00730 }
00731
00732 return 0;
00733 }
00734
00735
00736
00737
00738 static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
00739 {
00740 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00741
00742 DWC_DEBUGPL(DBG_HCD,
00743 "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, "
00744 "endpoint=%d\n", ep->desc.bEndpointAddress,
00745 dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress));
00746 dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250);
00747 ep->hcpriv = NULL;
00748 }
00749
00750 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
00751
00752
00753 static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
00754 {
00755 dwc_irqflags_t flags;
00756 struct usb_device *udev = NULL;
00757 int epnum = usb_endpoint_num(&ep->desc);
00758 int is_out = usb_endpoint_dir_out(&ep->desc);
00759 int is_control = usb_endpoint_xfer_control(&ep->desc);
00760 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00761 #ifdef LM_INTERFACE
00762 struct lm_device *_dev = dwc_otg_hcd->otg_dev->os_dep.lmdev;
00763 #elif defined(PCI_INTERFACE)
00764 struct pci_dev *_dev = dwc_otg_hcd->otg_dev->os_dep.pcidev;
00765 #endif
00766
00767 if (_dev)
00768 udev = to_usb_device(&_dev->dev);
00769 else
00770 return;
00771
00772 DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum);
00773
00774 DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags);
00775 usb_settoggle(udev, epnum, is_out, 0);
00776 if (is_control)
00777 usb_settoggle(udev, epnum, !is_out, 0);
00778
00779 if (ep->hcpriv) {
00780 dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv);
00781 }
00782 DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags);
00783 }
00784 #endif
00785
00791 static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd)
00792 {
00793 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00794 int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd);
00795 if (retval != 0) {
00796 S3C2410X_CLEAR_EINTPEND();
00797 }
00798 return IRQ_RETVAL(retval);
00799 }
00800
00805 int hub_status_data(struct usb_hcd *hcd, char *buf)
00806 {
00807 dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
00808
00809 buf[0] = 0;
00810 buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1;
00811
00812 return (buf[0] != 0);
00813 }
00814
00816 int hub_control(struct usb_hcd *hcd,
00817 u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength)
00818 {
00819 int retval;
00820
00821 retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd),
00822 typeReq, wValue, wIndex, buf, wLength);
00823
00824 switch (retval) {
00825 case -DWC_E_INVALID:
00826 retval = -EINVAL;
00827 break;
00828 }
00829
00830 return retval;
00831 }
00832
00833 #endif