⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c2410_udc.c

📁 ARM S3C2410 USB SLAVE LINUX驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
						nuke (dev, ep);			len = read_fifo_crq(&crq);			if (len != sizeof(crq)) {			  	dprintk("setup begin: fifo READ ERROR" 				    	" wanted %d bytes got %d. Stalling out...\n", 					sizeof(crq), len); 				set_ep0_ss();				return;			}			/* cope with automagic for some standard requests. */			dev->req_std = (crq.bRequestType & USB_TYPE_MASK)						== USB_TYPE_STANDARD;			dev->req_config = 0;			dev->req_pending = 1;			switch (crq.bRequest) {				/* hardware restricts gadget drivers here! */				case USB_REQ_SET_CONFIGURATION:				    	dprintk("USB_REQ_SET_CONFIGURATION ... \n");					if (crq.bRequestType == USB_RECIP_DEVICE) {config_change:						dev->req_config = 1;						clear_ep_state(dev);						set_ep0_de_out();					}					break;				/* ... and here, even more ... */				case USB_REQ_SET_INTERFACE:				    	dprintk("USB_REQ_SET_INTERFACE ... \n");					if (crq.bRequestType == USB_RECIP_INTERFACE) {						goto config_change;					}					break;				/* hardware was supposed to hide this */				case USB_REQ_SET_ADDRESS:				    	dprintk("USB_REQ_SET_ADDRESS ... \n");					if (crq.bRequestType == USB_RECIP_DEVICE) {						tmp = crq.wValue & 0x7F;						dev->address = tmp; 						__raw_writel((tmp | 0x80), S3C2410_UDC_FUNC_ADDR_REG);						set_ep0_de_out();						return;					}					break;				default:					clear_ep0_opr();					break;			}			if (crq.bRequestType & USB_DIR_IN)				dev->ep0state = EP0_IN_DATA_PHASE;			else				dev->ep0state = EP0_OUT_DATA_PHASE;			ret = dev->driver->setup(&dev->gadget, &crq);			if (ret < 0) {				if (dev->req_config) {					dprintk("config change %02x fail %d?\n",						crq.bRequest, ret);					return;				}				if (ret == -EOPNOTSUPP)					dprintk("Operation not supported\n");				else					dprintk("dev->driver->setup failed. (%d)\n",ret);				dev->ep0state = EP0_STALL;			/* deferred i/o == no response yet */			} else if (dev->req_pending) {			    	dprintk("dev->req_pending... what now?\n");				dev->req_pending=0;			}			dprintk("ep0state %s\n",ep0states[dev->ep0state]);		}		break;	case EP0_IN_DATA_PHASE:			/* GET_DESCRIPTOR etc */	    	dprintk("EP0_IN_DATA_PHASE ... what now?\n");		if (!(ep0csr & 2) && req)		{			write_fifo(ep, req);		}		break;	case EP0_OUT_DATA_PHASE:		/* SET_DESCRIPTOR etc */	    	dprintk("EP0_OUT_DATA_PHASE ... what now?\n");		if ((ep0csr & 1) && req ) {			read_fifo(ep,req);		}		break;	case EP0_END_XFER:	    	dprintk("EP0_END_XFER ... what now?\n");		dev->ep0state=EP0_IDLE;		break;	case EP0_STALL:	    	set_ep0_ss();		break;	}}/* * 	handle_ep - Manage I/O endpoints */static void handle_ep(struct s3c2410_ep *ep){	struct s3c2410_request	*req;	int			is_in = ep->bEndpointAddress & USB_DIR_IN;	u32			ep_csr1;	u32			idx;	if (likely (!list_empty(&ep->queue)))		req = list_entry(ep->queue.next,				struct s3c2410_request, queue);	else		req = 0;			idx = (u32)(ep->bEndpointAddress&0x7F);	if (is_in) {		__raw_writel(idx, S3C2410_UDC_INDEX_REG);		ep_csr1 = __raw_readl(S3C2410_UDC_IN_CSR1_REG);		dprintk("ep%01d write csr:%02x ",idx,ep_csr1);				if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL)		{			dprintk("st\n");			__raw_writel(idx, S3C2410_UDC_INDEX_REG);			__raw_writel(0x00,S3C2410_UDC_IN_CSR1_REG);			return;		}		if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req)		{			write_fifo(ep,req);		}	} 	else {		__raw_writel(idx, S3C2410_UDC_INDEX_REG);		ep_csr1 = __raw_readl(S3C2410_UDC_OUT_CSR1_REG);		dprintk("ep%01d read csr:%02x\n",idx,ep_csr1);				if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL)		{			__raw_writel(idx, S3C2410_UDC_INDEX_REG);			__raw_writel(0x00,S3C2410_UDC_OUT_CSR1_REG);			return;		}		if( (ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req)		{			read_fifo(ep,req);		}	}}/* *      s3c2410_udc_irq - interrupt handler */static irqreturn_ts3c2410_udc_irq(int irq, void *_dev, struct pt_regs *r){	struct s3c2410_udc      *dev = _dev;	int usb_status;	int usbd_status;	int pwr_reg;	int ep0csr;	int     i;	u32	idx = __raw_readl(S3C2410_UDC_INDEX_REG);	usb_status = __raw_readl(S3C2410_UDC_USB_INT_REG);	usbd_status = __raw_readl(S3C2410_UDC_EP_INT_REG);	pwr_reg = __raw_readl(S3C2410_UDC_PWR_REG);	S3C2410_UDC_SETIX(EP0);	ep0csr = __raw_readl(S3C2410_UDC_IN_CSR1_REG);	dprintk("usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n", usb_status, usbd_status, pwr_reg,ep0csr);	/*	 * Now, handle interrupts. There's two types : 	 * - Reset, Resume, Suspend coming -> usb_int_reg	 * - EP -> ep_int_reg	 */	/* RESET */	if (usb_status & S3C2410_UDC_USBINT_RESET)	{		dprintk("USB reset\n");	    	__raw_writel(0x00, S3C2410_UDC_PWR_REG);		S3C2410_UDC_SETIX(EP0);		__raw_writel(S3C2410_UDC_MAXP_8, S3C2410_UDC_MAXP_REG);		__raw_writel(0x80, S3C2410_UDC_FUNC_ADDR_REG);//		clear_ep0_opr();		   		/* clear interrupt */		__raw_writel(S3C2410_UDC_USBINT_RESET,			S3C2410_UDC_USB_INT_REG);		dev->gadget.speed = USB_SPEED_FULL;		dev->ep0state = EP0_IDLE;	}	/* RESUME */	if (usb_status & S3C2410_UDC_USBINT_RESUME)	{		dprintk("USB resume\n");				/* clear interrupt */		__raw_writel(S3C2410_UDC_USBINT_RESUME,			S3C2410_UDC_USB_INT_REG);		if (dev->gadget.speed != USB_SPEED_UNKNOWN			&& dev->driver			&& dev->driver->resume)			dev->driver->resume(&dev->gadget);	}	/* SUSPEND */	if (usb_status & S3C2410_UDC_USBINT_SUSPEND)	{		dprintk("USB suspend\n");					/* clear interrupt */		__raw_writel(S3C2410_UDC_USBINT_SUSPEND,			S3C2410_UDC_USB_INT_REG);						if (dev->gadget.speed != USB_SPEED_UNKNOWN				&& dev->driver				&& dev->driver->suspend)			dev->driver->suspend(&dev->gadget);		dev->ep0state = EP0_IDLE;	}	/* EP */	/* control traffic */	/* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready	 * generate an interrupt 	 */	if (usbd_status & S3C2410_UDC_INT_EP0)	{		dprintk("USB ep0 irq\n");		/* Clear the interrupt bit by setting it to 1 */		__raw_writel(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);		handle_ep0(dev);	}	/* endpoint data transfers */	for (i = 1; i < S3C2410_ENDPOINTS; i++) {		u32 tmp = 1 << i;		if (usbd_status & tmp) {			dprintk("USB ep%d irq\n", i);			/* Clear the interrupt bit by setting it to 1 */			__raw_writel(tmp, S3C2410_UDC_EP_INT_REG);			handle_ep(&dev->ep[i]);		}	}		dprintk("irq: %d done.\n", irq);	__raw_writel(idx,S3C2410_UDC_INDEX_REG);	return IRQ_HANDLED;		}/* * udc_reinit */static void udc_reinit(struct s3c2410_udc *dev){	u32     i;		/* device/ep0 records init */	INIT_LIST_HEAD (&dev->gadget.ep_list);	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);	dev->ep0state = EP0_IDLE;		/* basic endpoint records init */	for (i = 0; i < S3C2410_ENDPOINTS; i++) {		struct s3c2410_ep *ep = &dev->ep[i];		if (i != 0)			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);		ep->desc = 0;		INIT_LIST_HEAD (&ep->queue);	}}/*------------------------- s3c2410_ep_ops ----------------------------------*//* * 	s3c2410_ep_enable */static ints3c2410_ep_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc){	struct s3c2410_udc	*dev;	struct s3c2410_ep	*ep;	u32			max, tmp;	unsigned long		flags;	u32			csr1,csr2;	u32			int_en_reg;	ep = container_of (_ep, struct s3c2410_ep, ep);	if (!_ep || !desc || ep->desc || _ep->name == ep0name			|| desc->bDescriptorType != USB_DT_ENDPOINT)		return -EINVAL;	dev = ep->dev;	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)		return -ESHUTDOWN;	max = le16_to_cpu (desc->wMaxPacketSize) & 0x1fff;	spin_lock_irqsave (&dev->lock, flags);	_ep->maxpacket = max & 0x7ff;	ep->desc = desc;	ep->bEndpointAddress = desc->bEndpointAddress;	/* set max packet */	__raw_writel(ep->num, S3C2410_UDC_INDEX_REG);	__raw_writel(max>>3,S3C2410_UDC_MAXP_REG);	/* set type, direction, address; reset fifo counters */	if (desc->bEndpointAddress & USB_DIR_IN)	{		csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT;		csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN;				__raw_writel(ep->num, S3C2410_UDC_INDEX_REG);		__raw_writel(csr1,S3C2410_UDC_IN_CSR1_REG);		__raw_writel(ep->num, S3C2410_UDC_INDEX_REG);		__raw_writel(csr2,S3C2410_UDC_IN_CSR2_REG);	}	else	{		/* don't flush he in fifo or there will be an interrupt for that		 * endpoint */ 		csr1 = S3C2410_UDC_ICSR1_CLRDT;		csr2 = S3C2410_UDC_ICSR2_DMAIEN;		__raw_writel(ep->num, S3C2410_UDC_INDEX_REG);		__raw_writel(csr1,S3C2410_UDC_IN_CSR1_REG);		__raw_writel(ep->num, S3C2410_UDC_INDEX_REG);		__raw_writel(csr2,S3C2410_UDC_IN_CSR2_REG);				csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT;		csr2 = S3C2410_UDC_OCSR2_DMAIEN;				__raw_writel(ep->num, S3C2410_UDC_INDEX_REG);		__raw_writel(csr1,S3C2410_UDC_OUT_CSR1_REG);		__raw_writel(ep->num, S3C2410_UDC_INDEX_REG);		__raw_writel(csr2,S3C2410_UDC_OUT_CSR2_REG);	}		/* enable irqs */	int_en_reg = __raw_readl(S3C2410_UDC_EP_INT_EN_REG);	__raw_writel(int_en_reg | (1<<ep->num),S3C2410_UDC_EP_INT_EN_REG);	/* print some debug message */	tmp = desc->bEndpointAddress;	dprintk ("enable %s(%d) ep%x%s-blk max %02x\n",		_ep->name,ep->num, tmp, desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max);	spin_unlock_irqrestore (&dev->lock, flags);		return 0;}/* * s3c2410_ep_disable */static int s3c2410_ep_disable (struct usb_ep *_ep){	struct s3c2410_ep	*ep = container_of(_ep, struct s3c2410_ep, ep);	unsigned long	flags;	if (!_ep || !ep->desc) {		dprintk("%s not enabled\n",			_ep ? ep->ep.name : NULL);		return -EINVAL;	}	spin_lock_irqsave(&ep->dev->lock, flags);	ep->desc = 0;		nuke (ep->dev, ep);	ep->ep.maxpacket = EP_FIFO_SIZE; 	spin_unlock_irqrestore(&ep->dev->lock, flags);	dprintk("%s disabled\n", _ep->name);	return 0;}/* * s3c2410_alloc_request */static struct usb_request *s3c2410_alloc_request (struct usb_ep *_ep, int mem_flags){	struct s3c2410_ep	*ep;	struct s3c2410_request	*req;    	printk("s3c2410_alloc_request(ep=%p,flags=%d)\n", _ep, mem_flags);	ep = container_of (_ep, struct s3c2410_ep, ep);	if (!_ep)		return 0;	req = kmalloc (sizeof *req, mem_flags);	if (!req)		return 0;	memset (req, 0, sizeof *req);	INIT_LIST_HEAD (&req->queue);	return &req->req;}/* * s3c2410_free_request */static voids3c2410_free_request (struct usb_ep *_ep, struct usb_request *_req){	struct s3c2410_ep	*ep;	struct s3c2410_request	*req;    	printk("s3c2410_free_request(ep=%p,req=%p)\n", _ep, _req);	ep = container_of (_ep, struct s3c2410_ep, ep);	if (!ep || !_req || (!ep->desc && _ep->name != ep0name))		return;	req = container_of (_req, struct s3c2410_request, req);	WARN_ON (!list_empty (&req->queue));	kfree (req);}/* * 	s3c2410_alloc_buffer */static void *s3c2410_alloc_buffer (	struct usb_ep *_ep,	unsigned bytes,	dma_addr_t *dma,	int mem_flags){	char *retval;    	printk("s3c2410_alloc_buffer()\n");	if (!the_controller->driver)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -