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

📄 s3c2410_udc.c

📁 ARM S3C2410 USB SLAVE LINUX驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		return 0;	retval = kmalloc (bytes, mem_flags);	*dma = (dma_addr_t) retval;	return retval;}/* * s3c2410_free_buffer */static voids3c2410_free_buffer (	struct usb_ep *_ep,	void *buf,	dma_addr_t dma,	unsigned bytes){    	printk("s3c2410_free_buffer()\n");	if (bytes)		kfree (buf);}/* * 	s3c2410_queue */static ints3c2410_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags){	struct s3c2410_request	*req;	struct s3c2410_ep	*ep;	struct s3c2410_udc	*dev;	u32			ep_csr=0;	int 			fifo_count=0;	req = container_of(_req, struct s3c2410_request, req);	if (unlikely (!_req || !_req->complete || !_req->buf	|| !list_empty(&req->queue))) {		if (!_req)			dprintk("s3c2410_queue: 1 X X X\n");		else		{			dprintk("s3c2410_queue: 0 %01d %01d %01d\n",!_req->complete,!_req->buf, !list_empty(&req->queue));		}		return -EINVAL;	}	ep = container_of(_ep, struct s3c2410_ep, ep);	if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {		dprintk("s3c2410_queue: inval 2\n");		return -EINVAL;	}	dev = ep->dev;	if (unlikely (!dev->driver			|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {		return -ESHUTDOWN;	}	/* iso is always one packet per request, that's the only way	 * we can report per-packet status.  that also helps with dma.	 */	if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC			&& req->req.length > le16_to_cpu						(ep->desc->wMaxPacketSize)))		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("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;    	printk("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( "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;		printk("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){		printk("s3c2410_wakeup()\n");		return 0;}/* * 	s3c2410_set_selfpowered */static int s3c2410_set_selfpowered (struct usb_gadget *_gadget, int value){	struct s3c2410_udc  *udc;		printk("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---------------------------*//* * 	nop_release */static void nop_release (struct device *dev){	        dprintk("%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, i;    	printk("usb_gadget_register_driver() '%s'\n",		driver->driver.name);	if (!udc)		return -ENODEV;	if (udc->driver)		return -EBUSY;	if (!driver->bind || !driver->unbind || !driver->setup			|| driver->speed == USB_SPEED_UNKNOWN)		return -EINVAL;	udc->gadget.name = gadget_name;	udc->gadget.ops = &s3c2410_ops;	udc->gadget.is_dualspeed = 1;	udc->gadget.dev.release = nop_release;	udc->devstatus = 0;	INIT_LIST_HEAD (&udc->gadget.ep_list);	for (i = 0; i < S3C2410_ENDPOINTS; i++) {		struct s3c2410_ep *ep = &udc->ep[i];		if (!ep_name[i])			break;		ep->num = i;		ep->ep.name = ep_name[i];		ep->ep.ops = &s3c2410_ep_ops;		list_add_tail (&ep->ep.ep_list, &udc->gadget.ep_list);		ep->halted = ep->already_seen = ep->setup_stage = 0;		/* maxpacket differs between ep0 and others ep */		if (!i) 			ep->ep.maxpacket = EP0_FIFO_SIZE;		else			ep->ep.maxpacket = EP_FIFO_SIZE;		ep->last_io = jiffies;		ep->gadget = &udc->gadget;		ep->dev = udc;		ep->desc = 0;		INIT_LIST_HEAD (&ep->queue);	}	udc->gadget.ep0 = &udc->ep[0].ep;	udc->ep[0].ep.maxpacket = 8;	list_del_init (&udc->ep[0].ep.ep_list);	INIT_LIST_HEAD(&udc->fifo_req.queue);	udc->driver = driver;	udc->gadget.dev.driver = &driver->driver;	dprintk( "binding gadget driver '%s'\n", driver->driver.name);	if ((retval = driver->bind (&udc->gadget)) != 0) {		udc->driver = 0;		udc->gadget.dev.driver = 0;		return retval;	}        driver->driver.bus = 0;	udc_reinit(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;    	printk("usb_gadget_register_driver() '%s'\n",		driver->driver.name);	driver->unbind (&udc->gadget);	udc->driver = 0;	device_release_driver (&udc->gadget.dev);	driver_unregister (&driver->driver);	return 0;}/*---------------------------------------------------------------------------*//* *	probe - binds to the platform device */static int __init s3c2410_udc_probe(struct device *_dev){	struct s3c2410_udc *udc = &memory;	u32 int_en_reg;	int retval;	dprintk("s3c2410_udc_probe\n");	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);	spin_lock_init (&udc->lock);	/* 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("%s: got irq %i\n", gadget_name, IRQ_USBD);	udc->got_irq = 1;	/* Enable ep0 interrupts */	int_en_reg = __raw_readl(S3C2410_UDC_EP_INT_EN_REG);	__raw_writel(int_en_reg | 1,S3C2410_UDC_EP_INT_EN_REG);	return 0;}/* * 	s3c2410_udc_remove */static int __exit s3c2410_udc_remove(struct device *_dev){	struct s3c2410_udc *udc = _dev->driver_data;		dprintk("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         = __exit_p(s3c2410_udc_remove),			};static int __init udc_init(void){	dprintk("%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_enable(udc_clock);	dprintk("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_LICENSE("GPL");

⌨️ 快捷键说明

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