예제 #1
0
파일: dwc_otg_pcd.c 프로젝트: spfy/040005
/** 
 * 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;
}
예제 #2
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;
	}
}
예제 #5
0
파일: dwc_otg_pcd.c 프로젝트: odit/rv042
/**
 * 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;
}
예제 #6
0
파일: dwc_otg_pcd.c 프로젝트: odit/rv042
/**
 * 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);
}
예제 #11
0
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;
        }
예제 #12
0
파일: dwc_otg_pcd.c 프로젝트: spfy/040005
/**
 * 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		
	}
예제 #13
0
파일: dwc_otg_pcd.c 프로젝트: spfy/040005
/**
 * 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));
}
예제 #15
0
파일: dwc_pcd_irq.c 프로젝트: khadas/u-boot
/**
 * 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;
}
예제 #16
0
파일: dwc_otg_pcd.c 프로젝트: odit/rv042
/**
 * 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;
}