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

📄 s3c2410_udc.c

📁 2.4核linux的s3c2410-udc驱动代码!经过调试了!
💻 C
📖 第 1 页 / 共 3 页
字号:
		return -EMSGSIZE;	_req->status = -EINPROGRESS;	_req->actual = 0;	if (ep->bEndpointAddress)	{		__raw_writel(ep->bEndpointAddress&0x7F,S3C2410_UDC_INDEX_REG);		ep_csr = __raw_readl(ep->bEndpointAddress&USB_DIR_IN ? S3C2410_UDC_IN_CSR1_REG : S3C2410_UDC_OUT_CSR1_REG);		fifo_count=fifo_count_out();	}	/* kickstart this i/o queue? */	if (list_empty(&ep->queue)) {		if (ep->bEndpointAddress == 0 /* ep0 */) {			switch (dev->ep0state) {			case EP0_IN_DATA_PHASE:				if (write_fifo(ep, req))				{					req = 0;				}				break;			case EP0_OUT_DATA_PHASE:				/* nothing to do here */				dev->ep0state = EP0_IDLE;				break;			default:				return -EL2HLT;			}		}		else if ((ep->bEndpointAddress & USB_DIR_IN) != 0				&& (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY)) && write_fifo(ep, req)) {			req = 0;		} else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY) && fifo_count && read_fifo(ep, req)) {			req = 0;		}	}	/* pio or dma irq handler advances the queue. */	if (likely (req != 0))		list_add_tail(&req->queue, &ep->queue);	dprintk(DEBUG_VERBOSE, "s3c2410_queue normal end\n");	return 0;}/*  * 	s3c2410_dequeue */static int s3c2410_dequeue (struct usb_ep *_ep, struct usb_request *_req){	struct s3c2410_ep	*ep;	struct s3c2410_udc	*udc;	int			retval = -EINVAL;	unsigned long		flags;	struct s3c2410_request	*req = 0;    	dprintk(DEBUG_NORMAL,"s3c2410_dequeue(ep=%p,req=%p)\n", _ep, _req);	if (!the_controller->driver)		return -ESHUTDOWN;	if (!_ep || !_req)		return retval;	ep = container_of (_ep, struct s3c2410_ep, ep);	udc = container_of (ep->gadget, struct s3c2410_udc, gadget);	spin_lock_irqsave (&udc->lock, flags);	list_for_each_entry (req, &ep->queue, queue) {		if (&req->req == _req) {			list_del_init (&req->queue);			_req->status = -ECONNRESET;			retval = 0;			break;		}	}	spin_unlock_irqrestore (&udc->lock, flags);	if (retval == 0) {		dprintk(DEBUG_VERBOSE, "dequeued req %p from %s, len %d buf %p\n",				req, _ep->name, _req->length, _req->buf);		_req->complete (_ep, _req);		done(ep, req, -ECONNRESET);	}	return retval;	return 0;}/*  * s3c2410_set_halt */static ints3c2410_set_halt (struct usb_ep *_ep, int value){	return 0;}static const struct usb_ep_ops s3c2410_ep_ops = {	.enable         = s3c2410_ep_enable,	.disable        = s3c2410_ep_disable,		.alloc_request  = s3c2410_alloc_request,	.free_request   = s3c2410_free_request,		.alloc_buffer   = s3c2410_alloc_buffer,	.free_buffer    = s3c2410_free_buffer,		.queue          = s3c2410_queue,	.dequeue        = s3c2410_dequeue,		.set_halt       = s3c2410_set_halt,};/*------------------------- usb_gadget_ops ----------------------------------*//* * 	s3c2410_g_get_frame */static int s3c2410_g_get_frame (struct usb_gadget *_gadget){	int tmp;		dprintk(DEBUG_VERBOSE,"s3c2410_g_get_frame()\n");	tmp = __raw_readl(S3C2410_UDC_FRAME_NUM2_REG) << 8;	tmp |= __raw_readl(S3C2410_UDC_FRAME_NUM1_REG);		return tmp & 0xffff;}/* * 	s3c2410_wakeup */static int s3c2410_wakeup (struct usb_gadget *_gadget){		dprintk(DEBUG_NORMAL,"s3c2410_wakeup()\n");		return 0;}/* * 	s3c2410_set_selfpowered */static int s3c2410_set_selfpowered (struct usb_gadget *_gadget, int value){	struct s3c2410_udc  *udc;		dprintk(DEBUG_NORMAL, "s3c2410_set_selfpowered()\n");		udc = container_of (_gadget, struct s3c2410_udc, gadget);		if (value)		udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED);	else		udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);		return 0;}                                                                                   static const struct usb_gadget_ops s3c2410_ops = {	.get_frame          = s3c2410_g_get_frame,	.wakeup             = s3c2410_wakeup,	.set_selfpowered    = s3c2410_set_selfpowered,};/*------------------------- gadget driver handling---------------------------*//* * udc_disable */static void udc_disable(struct s3c2410_udc *dev){	dprintk(DEBUG_NORMAL, "udc_disable called");	/* Good bye, cruel world */	if (udc_info && udc_info->udc_command)		udc_info->udc_command(S3C2410_UDC_P_DISABLE);		/* Set address to 0 */	__raw_writel( 0x80, S3C2410_UDC_FUNC_ADDR_REG);	/* Disable all interrupts */	__raw_writel(0x00, S3C2410_UDC_USB_INT_EN_REG);	__raw_writel(0x00, S3C2410_UDC_EP_INT_EN_REG);	/* Set speed to unknown */	dev->gadget.speed = USB_SPEED_UNKNOWN;}/* * 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;		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->dev = dev;		ep->desc = 0;		INIT_LIST_HEAD (&ep->queue);	}}/* * udc_enable */static void udc_enable(struct s3c2410_udc *dev){	int i;		dprintk(DEBUG_NORMAL, "udc_enable called");		dev->gadget.speed = USB_SPEED_UNKNOWN;		/* Set MAXP for all endpoints */	for (i = 0; i < S3C2410_ENDPOINTS; i++) {		__raw_writel(i, S3C2410_UDC_INDEX_REG);		__raw_writel(0x0001,S3C2410_UDC_MAXP_REG);	}	/* Set default power state */	__raw_writel(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);	/* Enable reset and suspend interrupt interrupts */	__raw_writel(1<<2 | 1<<0 ,S3C2410_UDC_USB_INT_EN_REG);		/* Enable ep0 interrupt */	__raw_writel(0x01,S3C2410_UDC_EP_INT_EN_REG);	/* time to say "hello, world" */	if (udc_info && udc_info->udc_command)		udc_info->udc_command(S3C2410_UDC_P_ENABLE);}/* * 	nop_release */static void nop_release (struct device *dev){	        dprintk(DEBUG_NORMAL, "%s %s\n", __FUNCTION__, dev->bus_id);}/* *	usb_gadget_register_driver */intusb_gadget_register_driver (struct usb_gadget_driver *driver){	struct s3c2410_udc *udc = the_controller;	int		retval;    	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",		driver->driver.name);	/* Sanity checks */	if (!udc)		return -ENODEV;	if (udc->driver)		return -EBUSY;	if (!driver->bind || !driver->unbind || !driver->setup			|| driver->speed == USB_SPEED_UNKNOWN)		return -EINVAL;	/* Hook the driver */	udc->driver = driver;	udc->gadget.dev.driver = &driver->driver;	/*Bind the driver */	device_add(&udc->gadget.dev);	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n", driver->driver.name);	if ((retval = driver->bind (&udc->gadget)) != 0) {		device_del(&udc->gadget.dev);		udc->driver = 0;		udc->gadget.dev.driver = 0;		return retval;	}        /* driver->driver.bus = 0; */	/* Enable udc */	udc_enable(udc);		return 0;}/* * 	usb_gadget_unregister_driver */intusb_gadget_unregister_driver (struct usb_gadget_driver *driver){	struct s3c2410_udc *udc = the_controller;	if (!udc)		return -ENODEV;	if (!driver || driver != udc->driver)		return -EINVAL;    	dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",		driver->driver.name);	driver->unbind (&udc->gadget);	device_del(&udc->gadget.dev);	udc->driver = 0;	device_release_driver (&udc->gadget.dev);	driver_unregister (&driver->driver);	/* Disable udc */	udc_disable(udc);		return 0;}/*---------------------------------------------------------------------------*/static struct s3c2410_udc memory = {	.gadget = {		.ops		= &s3c2410_ops,		.ep0		= &memory.ep[0].ep,		.name		= gadget_name,		.dev = {			.bus_id		= "gadget",			.release	= nop_release,		},	},	/* control endpoint */	.ep[0] = {		.num		= 0,		.ep = {			.name		= ep0name,			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP0_FIFO_SIZE,		},		.dev		= &memory,	},	/* first group of endpoints */	.ep[1] = {		.num		= 1,		.ep = {			.name		= "ep1-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 1,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	},	.ep[2] = {		.num		= 2,		.ep = {			.name		= "ep2-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 2,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	},	.ep[3] = {		.num		= 3,		.ep = {			.name		= "ep3-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 3,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	},	.ep[4] = {		.num		= 4,		.ep = {			.name		= "ep4-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 4,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	}};/* *	probe - binds to the platform device */static int s3c2410_udc_probe(struct device *_dev){	struct s3c2410_udc *udc = &memory;	int retval;	dprintk(DEBUG_NORMAL,"s3c2410_udc_probe\n");	spin_lock_init (&udc->lock);	udc_info = _dev->platform_data;	device_initialize(&udc->gadget.dev);	udc->gadget.dev.parent = _dev;	udc->gadget.dev.dma_mask = _dev->dma_mask;	the_controller = udc;	dev_set_drvdata(_dev, udc);	udc_disable(udc);	udc_reinit(udc);		/* irq setup after old hardware state is cleaned up */	retval = request_irq(IRQ_USBD, s3c2410_udc_irq,		SA_INTERRUPT, gadget_name, udc);	if (retval != 0) {		printk(KERN_ERR "%s: can't get irq %i, err %d\n",			gadget_name, IRQ_USBD, retval);		return -EBUSY;	}	dprintk(DEBUG_VERBOSE, "%s: got irq %i\n", gadget_name, IRQ_USBD);#ifdef ENABLE_SYSFS	/* create device files */	device_create_file(_dev, &dev_attr_regs);#endif	return 0;}/* * 	s3c2410_udc_remove */static int s3c2410_udc_remove(struct device *_dev){	struct s3c2410_udc *udc = _dev->driver_data;		dprintk(DEBUG_NORMAL, "s3c2410_udc_remove\n");	usb_gadget_unregister_driver(udc->driver);		if (udc->got_irq) {		free_irq(IRQ_USBD, udc);		udc->got_irq = 0;	}		dev_set_drvdata(_dev, 0);	kfree(udc);		return 0;}                                                                               static struct device_driver udc_driver = {	.name		= "s3c2410-usbgadget",	.bus            = &platform_bus_type,	.probe          = s3c2410_udc_probe,	.remove         = s3c2410_udc_remove,			};static int __init udc_init(void){	u32 tmp;	dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);			udc_clock = clk_get(NULL, "usb-device");	if (!udc_clock) {		printk(KERN_INFO "failed to get udc clock source\n");		return -ENOENT;	}	clk_use(udc_clock);	clk_disable(udc_clock);		tmp = (		 0x78 << S3C2410_PLLCON_MDIVSHIFT)	      | (0x02 << S3C2410_PLLCON_PDIVSHIFT)	      | (0x03 << S3C2410_PLLCON_SDIVSHIFT);	__raw_writel(tmp, S3C2410_UPLLCON);		clk_enable(udc_clock);	mdelay(10);	dprintk(DEBUG_VERBOSE, "got and enabled clock\n");								return driver_register(&udc_driver);}static void __exit udc_exit(void){	if (udc_clock) {		clk_disable(udc_clock);		clk_unuse(udc_clock);		clk_put(udc_clock);		udc_clock = NULL;	}			driver_unregister(&udc_driver);}EXPORT_SYMBOL (usb_gadget_unregister_driver);EXPORT_SYMBOL (usb_gadget_register_driver);module_init(udc_init);module_exit(udc_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_VERSION(DRIVER_VERSION);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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