/** * This function is called when an EP is disabled due to disconnect or * change in configuration. Any pending requests will terminate with a * status of -ESHUTDOWN. * * This function modifies the dwc_otg_ep_t data structure for this EP, * and then calls dwc_otg_ep_deactivate. */ static int dwc_otg_pcd_ep_disable(struct usb_ep *_ep) { dwc_otg_pcd_ep_t *ep; unsigned long flags; DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _ep); ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); if (!_ep || !ep->desc) { DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, _ep ? ep->ep.name : NULL); return -EINVAL; } SPIN_LOCK_IRQSAVE(&ep->pcd->lock, flags); request_nuke( ep ); dwc_otg_ep_deactivate( GET_CORE_IF(ep->pcd), &ep->dwc_ep ); ep->desc = 0; ep->stopped = 1; if(ep->dwc_ep.is_in) { release_perio_tx_fifo(GET_CORE_IF(ep->pcd), ep->dwc_ep.tx_fifo_num); release_tx_fifo(GET_CORE_IF(ep->pcd), ep->dwc_ep.tx_fifo_num); } SPIN_UNLOCK_IRQRESTORE(&ep->pcd->lock, flags); DWC_DEBUGPL(DBG_PCD, "%s disabled\n", _ep->name); return 0; }
int dwc_peripheral_start(void *data, bool enable) { struct gadget_wrapper *d; d = gadget_wrapper; pr_info("usb: %s d->vbus=%d, enable=%d\n", __func__, d->vbus, enable); mutex_lock(&udc_lock); d->vbus = enable; if ( !d->softconnect ) { printk("usb: %s , d->softconnect is %d / udc don't start now \r\n",__func__, d->softconnect ); mutex_unlock(&udc_lock); return 0; } if(enable) { wake_lock(&usb_wake_lock); udc_enable(); dwc_otg_core_init(GET_CORE_IF(d->pcd)); dwc_otg_enable_global_interrupts(GET_CORE_IF(d->pcd)); dwc_otg_core_dev_init(GET_CORE_IF(d->pcd)); d->udc_startup = 1; } else { dwc_otg_disable_global_interrupts(GET_CORE_IF(d->pcd)); dwc_otg_clear_all_int(GET_CORE_IF(d->pcd)); dwc_otg_pcd_stop(d->pcd); udc_disable(); d->udc_startup = 0; wake_unlock(&usb_wake_lock); } mutex_unlock(&udc_lock); return 0; }
static void monitor_setup_transfer(unsigned long para) { dwc_otg_pcd_t *pcd; int in_ep_ctrl=0; int in_ep_tsiz=0; dwc_otg_core_if_t *core_if; dwc_otg_dev_if_t *dev_if; pcd = (dwc_otg_pcd_t *)para; if(pcd==NULL) return; core_if = GET_CORE_IF(pcd); dev_if = core_if->dev_if; if(pcd->ep0state == EP0_DISCONNECT) return; in_ep_ctrl = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); in_ep_tsiz = dwc_read_reg32(&dev_if->in_ep_regs[0]->dieptsiz); if((in_ep_ctrl & 0x80000000) && (in_ep_tsiz & 0x80000)) suspend_count++; else suspend_count=0; if(suspend_count > 5){ void dwc_udc_startup(void); void dwc_udc_shutdown(void); pr_info("Reset USB Controller..."); dwc_udc_shutdown(); mdelay(500); dwc_udc_startup(); } }
static void __udc_startup(void) { struct gadget_wrapper *d; d = gadget_wrapper; pr_info("USB:startup udc\n"); if (!d->udc_startup) { wake_lock(&usb_wake_lock); udc_enable(); dwc_otg_core_init(GET_CORE_IF(d->pcd)); dwc_otg_enable_global_interrupts(GET_CORE_IF(d->pcd)); dwc_otg_core_dev_init(GET_CORE_IF(d->pcd)); d->udc_startup = 1; } }
/** * This function allocates an I/O buffer to be used for a transfer * to/from the specified endpoint. * * @param _ep The endpoint to be used with with the request * @param _bytes The desired number of bytes for the buffer * @param _dma Pointer to the buffer's DMA address; must be valid * @param _gfp_flags the GFP_* flags to use. * @return address of a new buffer or null is buffer could not be allocated. */ static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *_ep, unsigned _bytes, dma_addr_t *_dma, unsigned _gfp_flags) { void *buf; dwc_otg_pcd_ep_t *ep; dwc_otg_pcd_t *pcd = 0; ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); pcd = ep->pcd; DWC_DEBUGPL(DBG_PCDV,"%s(%p,%d,%p,%0x)\n", __func__, _ep, _bytes, _dma, _gfp_flags); /* Check dword alignment */ if ((_bytes & 0x3UL) != 0) { DWC_WARN("%s() Buffer size is not a multiple of" "DWORD size (%d)",__func__, _bytes); } if (GET_CORE_IF(pcd)->dma_enable) { buf = dma_alloc_coherent (NULL, _bytes, _dma, _gfp_flags); } else { buf = kmalloc( _bytes, _gfp_flags); } /* Check dword alignment */ if (((long)buf & 0x3UL) != 0) { DWC_WARN("%s() Buffer is not DWORD aligned (%p)", __func__, buf); } return buf; }
/** * This function is called when an EP is disabled due to disconnect or * change in configuration. Any pending requests will terminate with a * status of -ESHUTDOWN. * * This function modifies the dwc_otg_ep_t data structure for this EP, * and then calls dwc_otg_ep_deactivate. */ static int dwc_otg_pcd_ep_disable(struct usb_ep *_ep) { dwc_otg_pcd_ep_t *ep; unsigned long flags; DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _ep); ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); if (!_ep || !ep->desc) { DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, _ep ? ep->ep.name : NULL); return -EINVAL; } spin_lock_irqsave(&ep->pcd->lock, flags); request_nuke( ep ); dwc_otg_ep_deactivate( GET_CORE_IF(ep->pcd), &ep->dwc_ep ); ep->desc = 0; ep->stopped = 1; spin_unlock_irqrestore(&ep->pcd->lock, flags); DWC_DEBUGPL(DBG_PCD, "%s disabled\n", _ep->name); return 0; }
static void __udc_shutdown(void) { struct gadget_wrapper *d; d = gadget_wrapper; pr_info("USB:shutdown udc\n"); if (d->udc_startup) { dwc_otg_disable_global_interrupts(GET_CORE_IF(d->pcd)); dwc_otg_clear_all_int(GET_CORE_IF(d->pcd)); dwc_otg_pcd_stop(d->pcd); udc_disable(); d->udc_startup = 0; wake_unlock(&usb_wake_lock); } }
static void enumeration_enable(void) { struct gadget_wrapper *d; pr_info("enable usb enumeration\n"); d = gadget_wrapper; dwc_otg_enable_global_interrupts(GET_CORE_IF(d->pcd)); return; }
/** * This function frees an I/O buffer that was allocated by alloc_buffer. * * @param _ep the endpoint associated with the buffer * @param _buf address of the buffer * @param _dma The buffer's DMA address * @param _bytes The number of bytes of the buffer */ static void dwc_otg_pcd_free_buffer(struct usb_ep *_ep, void *_buf, dma_addr_t _dma, unsigned _bytes) { dwc_otg_pcd_ep_t *ep; dwc_otg_pcd_t *pcd = 0; ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); pcd = ep->pcd; DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%0x,%d)\n", __func__, _ep, _buf, _dma, _bytes); if (GET_CORE_IF(pcd)->dma_enable) { dma_free_coherent(NULL, _bytes, _buf, _dma); } else { kfree(_buf); } }
/** * This function completes a request. It call's the request call back. */ void request_done(dwc_otg_pcd_ep_t * _ep, dwc_otg_pcd_request_t * _req, int _status) { unsigned stopped = _ep->stopped; dwc_otg_core_if_t *core_if = GET_CORE_IF(_ep->pcd); DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _ep); if(_ep->dwc_ep.num && _ep->dwc_ep.is_in) list_del_init(&_req->pcd_queue); list_del_init(&_req->queue); if (_req->req.status == -EINPROGRESS) { _req->req.status = _status; } else { _status = _req->req.status; } /* don't modify queue heads during completion callback */ _ep->stopped = 1; SPIN_UNLOCK(&_ep->pcd->lock); _req->req.complete(&_ep->ep, &_req->req); SPIN_LOCK(&_ep->pcd->lock); if (_ep->pcd->request_pending > 0) { --_ep->pcd->request_pending; } _ep->stopped = stopped; if(_ep->dwc_ep.is_in && _ep->dwc_ep.num){ DWC_DEBUGPL(DBG_PCDV, "ep%d,len=%d\n",_ep->dwc_ep.num,_req->req.actual); _ep->pcd->ep_in_sync = 0; } if(core_if->dma_enable) dwc_otg_pcd_dma_unmap(&_ep->dwc_ep); }
static void pcd_setup( pcd_struct_t *_pcd ) { struct usb_ctrlrequest ctrl = _pcd->setup_pkt.req; dwc_ep_t *ep0 = &g_dwc_eps[0]; deptsiz0_data_t doeptsize0 = { 0}; if(_pcd->request_enable == 0) return; // _pcd->setup_pkt.d32[0] = 0; // _pcd->setup_pkt.d32[1] = 0; unsigned short status = 0; _pcd->request_enable = 0; doeptsize0.d32 = dwc_read_reg32( DWC_REG_OUT_EP_TSIZE(0)); if (ctrl.bRequestType & USB_DIR_IN) { ep0->is_in = 1; _pcd->ep0state = EP0_IN_DATA_PHASE; } else { ep0->is_in = 0; _pcd->ep0state = EP0_OUT_DATA_PHASE; } if ((ctrl.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) { /* handle non-standard (class/vendor) requests in the gadget driver */ //do_gadget_setup(_pcd, &ctrl ); DBG("Vendor requset\n"); do_vendor_request(_pcd, &ctrl ); dwc_otg_ep_req_start(_pcd,0); return; } /** @todo NGS: Handle bad setup packet? */ switch (ctrl.bRequest) { case USB_REQ_GET_STATUS: switch (ctrl.bRequestType & USB_RECIP_MASK) { case USB_RECIP_DEVICE: status = 0x1; /* Self powered */ status |= 0;//_pcd->remote_wakeup_enable << 1; break; } _pcd->buf = (char *)&status; _pcd->length = 2; dwc_otg_ep_req_start(_pcd,0); break; #if 0 case USB_RECIP_INTERFACE: *status = 0; break; case USB_RECIP_ENDPOINT: ep = get_ep_by_addr(_pcd, ctrl.wIndex); if ( ep == 0 || ctrl.wLength > 2) { ep0_do_stall(_pcd, -EOPNOTSUPP); return; } /** @todo check for EP stall */ *status = ep->stopped; break; } _pcd->ep0_pending = 1; ep0->dwc_ep.start_xfer_buff = (uint8_t *)status; ep0->dwc_ep.xfer_buff = (uint8_t *)status; ep0->dwc_ep.dma_addr = _pcd->status_buf_dma_handle; ep0->dwc_ep.xfer_len = 2; ep0->dwc_ep.xfer_count = 0; ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; dwc_otg_ep0_start_transfer( GET_CORE_IF(_pcd), &ep0->dwc_ep ); break; case USB_REQ_CLEAR_FEATURE: do_clear_feature( _pcd ); break; case USB_REQ_SET_FEATURE: do_set_feature( _pcd ); break; #endif case USB_REQ_SET_ADDRESS: if (ctrl.bRequestType == USB_RECIP_DEVICE) { dcfg_data_t dcfg = { 0 }; //DBG("Set address: %d\n",ctrl.wValue); dcfg.b.devaddr = ctrl.wValue; dwc_modify_reg32(DWC_REG_DCFG,0, dcfg.d32); do_setup_in_status_phase( _pcd ); return; } break; case USB_REQ_SET_INTERFACE: case USB_REQ_SET_CONFIGURATION: _pcd->request_config = 1; /* Configuration changed */ // do_gadget_setup(_pcd, &ctrl ); // break; default: /* Call the Gadget Driver's setup functions */ do_gadget_setup(_pcd, &ctrl ); dwc_otg_ep_req_start(_pcd,0); break; }
/** * This function is used to submit an I/O Request to an EP. * * - When the request completes the request's completion callback * is called to return the request to the driver. * - An EP, except control EPs, may have multiple requests * pending. * - Once submitted the request cannot be examined or modified. * - Each request is turned into one or more packets. * - A BULK EP can queue any amount of data; the transfer is * packetized. * - Zero length Packets are specified with the request 'zero' * flag. */ static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int _gfp_flags) { int prevented = 0; dwc_otg_pcd_request_t *req; dwc_otg_pcd_ep_t *ep; dwc_otg_pcd_t *pcd; unsigned long flags = 0; DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p,%d)\n", __func__, _ep, _req, _gfp_flags); req = container_of(_req, dwc_otg_pcd_request_t, req); if (!_req || !_req->complete || !_req->buf || !list_empty(&req->queue)) { if( !_req ) printk("bad _req\n"); if( !_req->complete ) printk("bad _req->complete\n"); if( !_req->buf ) printk("bad _req->buf\n"); if( !list_empty(&req->queue) ) printk("bad list_empty\n"); DWC_WARN("%s, bad params\n", __func__); return -EINVAL; } ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); if (!_ep || (!ep->desc && ep->dwc_ep.num != 0)) { DWC_WARN("%s, bad ep\n", __func__); return -EINVAL; } pcd = ep->pcd; //cathy, if suspended, drop request if ( (GET_CORE_IF(pcd)->dev_if->suspended == 1) && (ep->dwc_ep.num != 0) ) { DWC_DEBUGPL(DBG_PCDV,"%s, epnum = %d, drop request\n", __func__, ep->dwc_ep.num); return -ESHUTDOWN; } if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", pcd->gadget.speed); DWC_WARN("%s, bogus device state\n", __func__); return -ESHUTDOWN; } DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length, _req->buf); if (!GET_CORE_IF(pcd)->core_params->opt) { if (ep->dwc_ep.num != 0) { DWC_ERROR("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length, _req->buf); } } SPIN_LOCK_IRQSAVE(&ep->pcd->lock, flags); #if defined(DEBUG) & defined(VERBOSE) dump_msg(_req->buf, _req->length); #endif _req->status = -EINPROGRESS; _req->actual = 0; /* * For EP0 IN without premature status, zlp is required? */ if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { DWC_DEBUGPL(DBG_PCDV, "%s-OUT ZLP\n", _ep->name); //_req->zero = 1; } /* Start the transfer */ if (list_empty(&ep->queue) && !ep->stopped) { /* EP0 Transfer? */ if (ep->dwc_ep.num == 0) { switch (pcd->ep0state) { case EP0_IN_DATA_PHASE: DWC_DEBUGPL(DBG_PCD, "%s ep0: EP0_IN_DATA_PHASE\n", __func__); break; case EP0_OUT_DATA_PHASE: DWC_DEBUGPL(DBG_PCD, "%s ep0: EP0_OUT_DATA_PHASE\n", __func__); if (pcd->request_config) { /* Complete STATUS PHASE */ ep->dwc_ep.is_in = 1; pcd->ep0state = EP0_STATUS; } break; default: DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", pcd->ep0state); SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags); return -EL2HLT; } ep->dwc_ep.dma_addr = (u32)_req->buf & ~Uncache_Mask; //_req->dma; //cathy ep->dwc_ep.start_xfer_buff = _req->buf; ep->dwc_ep.xfer_buff = _req->buf; ep->dwc_ep.xfer_len = _req->length; ep->dwc_ep.xfer_count = 0; ep->dwc_ep.sent_zlp = 0; ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; dwc_otg_ep0_start_transfer( GET_CORE_IF(pcd), &ep->dwc_ep ); } else { /* Setup and start the Transfer */ ep->dwc_ep.dma_addr = (u32)_req->buf & ~Uncache_Mask; //_req->dma; //cathy //ep->dwc_ep.dma_addr = _req->dma; ep->dwc_ep.start_xfer_buff = _req->buf; ep->dwc_ep.xfer_buff = _req->buf; ep->dwc_ep.xfer_len = _req->length; ep->dwc_ep.xfer_count = 0; ep->dwc_ep.sent_zlp = 0; ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; dwc_otg_ep_start_transfer( GET_CORE_IF(pcd), &ep->dwc_ep ); } } if ((req != 0) || prevented) { ++pcd->request_pending; list_add_tail(&req->queue, &ep->queue); //cathy #if 0 if (ep->dwc_ep.is_in && ep->stopped && !(GET_CORE_IF(pcd)->dma_enable)) { /** @todo NGS Create a function for this. */ diepmsk_data_t diepmsk = { .d32 = 0}; diepmsk.b.intktxfemp = 1; dwc_modify_reg32( &GET_CORE_IF(pcd)->dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32 ); } #endif }
/** * This function is called by the Gadget Driver for each EP to be * configured for the current configuration (SET_CONFIGURATION). * * This function initializes the dwc_otg_ep_t data structure, and then * calls dwc_otg_ep_activate. */ static int dwc_otg_pcd_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *_desc) { dwc_otg_pcd_ep_t *ep = 0; dwc_otg_pcd_t *pcd = 0; unsigned long flags; DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, _ep, _desc ); ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); if (!_ep || !_desc || ep->desc || _desc->bDescriptorType != USB_DT_ENDPOINT) { DWC_WARN( "%s, bad ep or descriptor\n", __func__); return -EINVAL; } if (ep == &ep->pcd->ep0) { DWC_WARN("%s, bad ep(0)\n", __func__); return -EINVAL; } /* Check FIFO size? */ if (!_desc->wMaxPacketSize) { DWC_WARN("%s, bad %s maxpacket\n", __func__, _ep->name); return -ERANGE; } pcd = ep->pcd; if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { if (!pcd->driver) { bh_otg_dbg2("[%s:%d] gadget[%s] !pcd->driver\n", __FUNCTION__, __LINE__, pcd->gadget.name); } if (pcd->gadget.speed == USB_SPEED_UNKNOWN) { bh_otg_dbg2("[%s:%d] gadget[%s] USB_SPEED_UNKNOWN\n", __FUNCTION__, __LINE__, pcd->gadget.name); } DWC_WARN("%s, bogus device state\n", __func__); return -ESHUTDOWN; } SPIN_LOCK_IRQSAVE(&pcd->lock, flags); ep->desc = _desc; ep->ep.maxpacket = le16_to_cpu (_desc->wMaxPacketSize); /* * Activate the EP */ ep->stopped = 0; ep->dwc_ep.is_in = (USB_DIR_IN & _desc->bEndpointAddress) != 0; ep->dwc_ep.maxpacket = ep->ep.maxpacket; ep->dwc_ep.type = _desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; if(ep->dwc_ep.is_in) { if(!pcd->otg_dev->core_if->en_multiple_tx_fifo) { ep->dwc_ep.tx_fifo_num = 0; if ((_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == //cathy USB_ENDPOINT_XFER_ISOC ) USB_ENDPOINT_XFER_INT ) //assign interrupt in ep (ep3) to periodic tx fifo { /* * if ISOC EP then assign a Periodic Tx FIFO. */ ep->dwc_ep.tx_fifo_num = assign_perio_tx_fifo(pcd->otg_dev->core_if); } } else { /* * if Dedicated FIFOs mode is on then assign a Tx FIFO. */ ep->dwc_ep.tx_fifo_num = assign_tx_fifo(pcd->otg_dev->core_if); } } /* Set initial data PID. */ if ((_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK ) { ep->dwc_ep.data_pid_start = 0; } DWC_DEBUGPL(DBG_PCD, "Activate %s-%s: type=%d, mps=%d desc=%p\n", ep->ep.name, (ep->dwc_ep.is_in ?"IN":"OUT"), ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc ); dwc_otg_ep_activate( GET_CORE_IF(pcd), &ep->dwc_ep ); SPIN_UNLOCK_IRQRESTORE(&pcd->lock, flags); return 0; }
void udc_phy_up(void) { struct gadget_wrapper *d = gadget_wrapper; dwc_otg_dev_soft_connect(GET_CORE_IF(d->pcd)); }
/** * Read the device status register and set the device speed in the * data structure. * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate. */ int32_t dwc_otg_pcd_handle_enum_done_intr(void) { gintsts_data_t gintsts; gusbcfg_data_t gusbcfg; /*dsts_data_t dsts;*/ depctl_data_t diepctl; depctl_data_t doepctl; dctl_data_t dctl ={0}; DBG("SPEED ENUM\n"); /* Read the Device Status and Endpoint 0 Control registers */ /*dsts.d32 = dwc_read_reg32(DWC_REG_DSTS);*/ diepctl.d32 = dwc_read_reg32(DWC_REG_IN_EP_REG(0) ); doepctl.d32 = dwc_read_reg32(DWC_REG_OUT_EP_REG(0)); /* Set the MPS of the IN EP based on the enumeration speed */ diepctl.b.mps = DWC_DEP0CTL_MPS_64; dwc_write_reg32(DWC_REG_IN_EP_REG(0) , diepctl.d32); /* Enable OUT EP for receive */ doepctl.b.epena = 1; dwc_write_reg32(DWC_REG_OUT_EP_REG(0), doepctl.d32); dctl.b.cgnpinnak = 1; dwc_modify_reg32(DWC_REG_DCTL, dctl.d32, dctl.d32); if (this_pcd[0].ep0state == EP0_DISCONNECT) { this_pcd[0].ep0state = EP0_IDLE; } else if (this_pcd[0].ep0state == EP0_STALL) { this_pcd[0].ep0state = EP0_IDLE; } this_pcd[0].ep0state = EP0_IDLE; /* Set USB turnaround time based on device speed and PHY interface. */ gusbcfg.d32 = dwc_read_reg32(DWC_REG_GUSBCFG); #if 0 if (_pcd->gadget.speed == USB_SPEED_HIGH) { if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_ULPI) { /* ULPI interface */ gusbcfg.b.usbtrdtim = 9; } if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI) { /* UTMI+ interface */ if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 16) { gusbcfg.b.usbtrdtim = 5; } else { gusbcfg.b.usbtrdtim = 9; } } if (GET_CORE_IF(_pcd)->hwcfg2.b.hs_phy_type == DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) { /* UTMI+ OR ULPI interface */ if (gusbcfg.b.ulpi_utmi_sel == 1) { /* ULPI interface */ gusbcfg.b.usbtrdtim = 9; } else { /* UTMI+ interface */ if (GET_CORE_IF(_pcd)->core_params->phy_utmi_width == 16) { gusbcfg.b.usbtrdtim = 5; } else { gusbcfg.b.usbtrdtim = 9; } } } } else { /* Full or low speed */ gusbcfg.b.usbtrdtim = 9; } #else /* Full or low speed */ gusbcfg.b.usbtrdtim = 5; #endif dwc_write_reg32(DWC_REG_GUSBCFG, gusbcfg.d32); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.enumdone = 1; dwc_write_reg32(DWC_REG_GINTSTS,gintsts.d32 ); return 1; }
/** * This function is called by the Gadget Driver for each EP to be * configured for the current configuration (SET_CONFIGURATION). * * This function initializes the dwc_otg_ep_t data structure, and then * calls dwc_otg_ep_activate. */ static int dwc_otg_pcd_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *_desc) { dwc_otg_pcd_ep_t *ep = 0; dwc_otg_pcd_t *pcd = 0; unsigned long flags; DWC_DEBUGPL(DBG_PCDV,"%s(%p,%p)\n", __func__, _ep, _desc ); ep = container_of(_ep, dwc_otg_pcd_ep_t, ep); if (!_ep || !_desc || ep->desc || _desc->bDescriptorType != USB_DT_ENDPOINT) { DWC_WARN( "%s, bad ep or descriptor\n", __func__); return -EINVAL; } if (ep == &ep->pcd->ep[0]){ DWC_WARN("%s, bad ep(0)\n", __func__); return -EINVAL; } /* Check FIFO size? */ if (!_desc->wMaxPacketSize) { DWC_WARN("%s, bad %s maxpacket\n", __func__, _ep->name); return -ERANGE; } pcd = ep->pcd; if (!pcd->driver || pcd->gadget.speed == USB_SPEED_UNKNOWN) { DWC_WARN("%s, bogus device state\n", __func__); return -ESHUTDOWN; } spin_lock_irqsave(&pcd->lock, flags); ep->desc = _desc; ep->ep.maxpacket = le16_to_cpu (_desc->wMaxPacketSize); /* * Activate the EP */ ep->stopped = 0; ep->dwc_ep.is_in = (USB_DIR_IN & _desc->bEndpointAddress) != 0; ep->dwc_ep.maxpacket = ep->ep.maxpacket; ep->dwc_ep.tx_fifo_num = 0; ep->dwc_ep.type = _desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; if ((_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC ) { /* * if ISOC EP then assign a Periodic Tx FIFO. */ /** @todo NGS Determine Tx FIFO for periodic EP. * Currently using 1. */ ep->dwc_ep.tx_fifo_num = 1; } /* Set initial data PID. */ if ((_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK ) { ep->dwc_ep.data_pid_start = 0; } DWC_DEBUGPL(DBG_PCD, "Activate %s-%s: type=%d, mps=%d desc=%p\n", ep->ep.name, (ep->dwc_ep.is_in ?"IN":"OUT"), ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc ); dwc_otg_ep_activate( GET_CORE_IF(pcd), &ep->dwc_ep ); spin_unlock_irqrestore(&pcd->lock, flags); return 0; }