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

📄 dm320.c.svn-base

📁 TI DM320处理器支持的linux usb device侧驱动程序
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/* * linux/drivers/usb/gadget/dm320/dm320.c * Texas Instruments DM320 on-chip full speed USB device controllers * Author : Vishal Borker, November 2005, Ingenient Technologies * Report Bugs/Patches to vishal.borker@gmail.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include <linux/config.h>#include <linux/delay.h>#include <linux/device.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/timer.h>#include <linux/usb_ch9.h>#include <linux/usb_gadget.h>#include <linux/dma-mapping.h>#include <asm/arch/gio.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/unaligned.h>#include "dm320_reg_def.h"#include "dm320_usb_config.h"#include "dm320_usb.h"#define EP_BULK_IN_NUM  1    // Endpoing on which we send data to the Host controller Tx EP#define EP_BULK_OUT_NUM 2    // Endpoint on which we get data from the Host controller Rx EP#define EP_INTR_IN_NUM  3    // INTR Endpoint on which the hos periodically polls for interrupt data.#define HOST_CONNECT	1#define HOST_DISCONNECT 0/* * We have a set of debug MACROS's each enabling a different level of debug commands. * define all of the below to enable full debug support * */static int paddr_status = 0;#define IO_DEBUG #ifdef IO_DEBUG#define printkio(fmt,args...) \    printk(fmt , ## args)#else#define printkio(fmt,args...) \    do { } while (0)#endif          /* DEBUG */#ifdef CORE_DEBUG#define core_debug(fmt,args...) \    printk(fmt , ## args)#else#define core_debug(fmt,args...) \    do { } while (0)#endif          /* DEBUG */#ifdef PRINT_INFO#define dm320_info(fmt,args...) \    printk(fmt , ## args)#else#define dm320_info(fmt,args...) \    do { } while (0)#endif          /* DEBUG */#define DM320_USB_BASE 0x80000000#define DRIVER_DESC		"DM320 USB Peripheral Controller (test version 1.0) "#define DRIVER_VERSION		"2005 September 01, Ingenient Technologies "#define DMA_ADDR_INVALID	(~(dma_addr_t)0)const char driver_name [] = "dm320";const char driver_desc [] = DRIVER_DESC;const char ep0name [] = "ep0";const char *ep_name [] = {    ep0name,    "ep1in-bulk", "ep2out-bulk",    "ep3in-intr",};#define	DEBUG			/* messages on error and most fault paths */#define	VERBOSE			/* extra debug messages (success too) */#include "dm320.h"#define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")/* * function prototypes */static int use_dma = 0;static struct usb_ep_ops dm320_ep_ops;static void nuke (struct dm320_ep *);static void usb_reset (struct dm320 *dev);static void usb_reinit (struct dm320 *dev);static void ep_reset (struct dm320_ep *ep);static void dm320_reset_ep(unsigned int index);static void dm320_clear_intrs();static void dm320_reconnect_init(struct dm320 *dev);static int kick_dma (struct dm320_ep *ep, struct dm320_request *req);static int dm320_fifo_status (struct usb_ep *_ep);static void    flushEPFIFO( int iEndpoint )  //Vishal: Derived from USB_FlushFifo(i){//	printk("dm320 : %s: %d\n", __FUNCTION__, iEndpoint);    if( ( iEndpoint < USB_EP0_SELECT ) || ( iEndpoint >= RX_EP_MAX ) )        return ;    writeb( iEndpoint, USB_INDEX );    if( iEndpoint == USB_EP0_SELECT )    {        writeb( USB_CSR2_FLFIFO, USB_CSR2 );        writeb( USB_CSR2_FLFIFO, USB_CSR2 );    }    else    {        writeb( USB_TXCSR1_FLFIFO, USB_PER_TXCSR1 );        writeb( USB_RXCSR1_FLFIFO, USB_PER_RXCSR1 );    }}static int ep_name_to_index(char *name){	if(!strcmp(name,ep0name))		return 0; 	if(!strcmp(name,"ep1in-bulk"))		return 1;	if(!strcmp(name,"ep2out-bulk"))		return 2;	if(!strcmp(name,"ep3in-intr"))		return 3;}static intdm320_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc){	unsigned int ep_num;	ep_num = ep_name_to_index(_ep->name);	return 0;}static voiddone (struct dm320_ep *ep, struct dm320_request *req, int status){	struct dm320		*dev;	unsigned		stopped = ep->stopped;	if (ep->num == 0) {		if (ep->dev->protocol_stall) {			ep->stopped = 1;			set_halt (ep);		}		allow_status (ep);	}	dev = the_controller;	if (req->req.status == -EINPROGRESS)        req->req.status = status;	else        	status = req->req.status;    /* don't modify queue heads during completion callback *///    spin_unlock (&dev->lock);    req->req.complete (&ep->ep, &req->req);    list_del_init (&req->queue);  //  spin_lock (&dev->lock);    ep->stopped = stopped;}/* returns: 0: still running, 1: completed, negative: errno */static int write_fifo (struct dm320_ep *ep, struct dm320_request *req){	u8		*buf;	int ret = -1;	int count = 0 , max = 0 , total = 0 ;	int		is_last;	int		status;	int     nBytesWritten   = 0;	while(1)	{		if(req){			buf = req->req.buf + req->req.actual;			prefetch (buf);			total = req->req.length - req->req.actual;		//printkio("%s: <1> request of size: %d, wrote  so far: %d, total left: %d\n", __FUNCTION__,req->req.length,req->req.actual, total);		mdelay(1);		}else {		    //printkio("%s: req NULL. Invalid condition. Cannot occur. \n", __FUNCTION__);			return 0;		}		count = ep->ep.maxpacket;		if (count > total)  /* min() cannot be used on a bitfield */        		count = total;		if(count <= 0)			goto finish;		if( ( count = USB_WriteEP(ep_name_to_index(ep->ep.name),buf , total ) ) <= 0 )        	{            		printkio("USB_WriteEP( ) error! : %d\n", count );	        	return ret;        	}		req->req.actual += count;		//printkio("%s: <1> request of size: %d, wrote  so far: %d, total left: %d\n", __FUNCTION__,req->req.length,req->req.actual, total);		if ((req->req.length == req->req.actual) || count < BULK_TRANS_SIZE) /*Modify to handle control ep's as well */        	{finish:					//printkio("%s: wrote . Calling Done.\n", __FUNCTION__);            		done (ep, req, 0);            		return 0;        	}	}	return 0;//	return -1;}static int read_fifo (struct dm320_ep *ep, struct dm320_request *req){	u8		*buf;	unsigned	count, max, total= 0;	int		is_last;	int		status;	int     nBytesWritten   = 0;		while(1)	{		//udelay(250);		//udelay(5);		if(req){			buf = req->req.buf+ req->req.actual;		}		if( ( count = USB_ReadEP(ep_name_to_index(ep->ep.name),buf , BULK_TRANS_SIZE ) ) <= 0 )			return -1;		else			req->req.actual += count;        if (req->req.length == req->req.actual || count < BULK_TRANS_SIZE ) /*Modify to handle control ep's as well */		{		//	printk("%s: read . Calling Done.\n", __FUNCTION__);					        done (ep, req, 0);			return 0;		}   }	//return -1;	return 0;}/* returns 0 on success, else negative errno */static int kick_dma (struct dm320_ep *ep, struct dm320_request *req){	return -1;}int rx_pending = 0 ;int rx_pending = 0 ;static intdm320_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags){	struct dm320_request	*req;	struct dm320_ep	*ep;	struct dm320		*dev;	unsigned long		flags;//	spin_lock_irqsave (&dev->lock, flags);	int			status = -1;	int ep_num;	u8			s;		ep = container_of (_ep, struct dm320_ep, ep);	dev = ep->dev;	req = container_of (_req, struct dm320_request, req);	if (!_req || !_req->complete || !_req->buf)		return -EINVAL;	if(!_ep)		return -EINVAL;	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)		return -ESHUTDOWN;	_req->status = -EINPROGRESS;	_req->actual = 0;		spin_lock_irqsave (&dev->lock, flags);	local_irq_disable();	//printk("\n\n %s: queued the request of length %d to ep: %s\n", __FUNCTION__,_req->length, ep->ep.name);	/* if list is empty */	if(_req->length==0 && (ep->is_in || ep_num  == 3) ){		printk("NULL PACKET SENDING\n");    		writeb( readb( USB_PER_TXCSR1 ) | USB_TXCSR1_TXPKTRDY, USB_PER_TXCSR1 );		list_add_tail (&req->queue, &ep->queue);		goto done;	}	if (list_empty (&ep->queue) && !ep->stopped) {		/* maybe there's no control data, just status ack */		if (ep->num == 0 && _req->length == 0) { /* No dta to transfer */			done (ep, req, 0);			printk("%s: %s status ack\n",__FUNCTION__, ep->ep.name);			goto done;		}		/* try dma first */		status = kick_dma (ep, req);		if (status < 0) {			/* dma failed (most likely in use by another endpoint) 			 * fallback to pio			 */			status = 0;			ep_num = ep_name_to_index(ep->ep.name);					if((ep->is_in)|| ep_num  == 3)				status = write_fifo (ep, req);			else 			{				if(rx_pending)				{					//printk("%s: rx pending interrupt\n", __FUNCTION__);					status = read_fifo (ep, req);   /*Vishal: read from FIFO into request struct */							rx_pending = 0;				}				else					status = -1;			}			//	status = -1;   /*Vishal: read from FIFO into request struct */		}	}	/*Add to queue of pertinent endpoint */	if (status != 0)		list_add_tail (&req->queue, &ep->queue);done:	local_irq_enable();	spin_unlock_irqrestore (&dev->lock, flags);	return 0;}/* dequeue ALL requests */static void nuke (struct dm320_ep *ep){	struct dm320_request	*req;	/* called with spinlock held *///	ep->stopped = 1;	while (!list_empty (&ep->queue)) {		req = list_entry (ep->queue.next,struct dm320_request,queue);		done (ep, req, -ESHUTDOWN);	}}/* dequeue JUST ONE request */static int dm320_dequeue (struct usb_ep *_ep, struct usb_request *_req){	struct dm320_ep *ep;	struct dm320		*dev;	dev = the_controller;    if (!_ep)        return 0;    ep = container_of (_ep, struct dm320_ep, ep);	printk("%s: dm320  API called\n", __FUNCTION__);    spin_lock (&dev->lock);	nuke(ep);	    spin_unlock (&dev->lock);	return 0;}//#define PIPE_STALL 1static intdm320_set_halt (struct usb_ep *_ep, int value){	struct dm320_ep	*ep;	unsigned long		flags;	int			retval = 0;#ifdef  PIPE_STALL	printk("%s: Non functional dm320  API called\n", __FUNCTION__);	writeb(EP_BULK_IN_NUM, USB_INDEX );	writeb(readb(USB_PER_TXCSR1)|USB_TXCSR1_SENDST,USB_PER_TXCSR1);	printk("Stalled BULK-IN Endpoint\n");	return 0;#endif	return -1;}static intdm320_fifo_status (struct usb_ep *_ep){	printk("%s: Non functional dm320  API called\n", __FUNCTION__);}static voiddm320_fifo_flush (struct usb_ep *_ep){	//printk("dm320: Flushing H/W FIFO's\n");	flushEPFIFO( ep_name_to_index(_ep->name) );}static voidstop_activity (struct dm320 *dev, struct usb_gadget_driver *driver){	printk("%s: Non functional dm320 USB gadget API\n", __FUNCTION__);}static int dm320_disable (struct usb_ep *_ep){	struct dm320_ep	*ep;	unsigned long		flags;	ep = container_of (_ep, struct dm320_ep, ep);	if (!_ep || !ep->desc || _ep->name == ep0name)		return -EINVAL;	spin_lock_irqsave (&ep->dev->lock, flags);	nuke (ep);	ep_reset (ep);	VDEBUG (ep->dev, "disabled %s\n", _ep->name);	spin_unlock_irqrestore (&ep->dev->lock, flags);	return 0;}static struct dm320	*the_controller;static void usb_reinit (struct dm320 *dev){	int	tmp;    for (tmp = 0; tmp < NUM_OF_ENDPOINTS + 1; tmp++) {        struct dm320_ep   *ep = &dev->ep[tmp];        ep->ep.name = ep_name [tmp];        ep->dev = dev;        ep->num = tmp;        if (tmp > 0 && tmp <=  NUM_OF_ENDPOINTS + 1) {            ep->fifo_size = EP0_FIFO_SIZE;        } else   	        ep->fifo_size = EP0_FIFO_SIZE;	     ep_reset (ep);    }    dev->ep [0].ep.maxpacket = EP0_FIFO_SIZE;     /* Vishal: CHANGE /8 handled this statically. Not good*/    //Vishal : dev->ep [1].ep.maxpacket = 8 ; /* Bulk  IN  endpoint */    dev->ep [1].ep.maxpacket = BULK_TRANS_SIZE ; /* Bulk  IN  endpoint */	dev->ep [1].is_in = 1;    //Vishal: dev->ep [2].ep.maxpacket = 8;  /* Bulk  OUT endpoint */    dev->ep [2].ep.maxpacket = BULK_TRANS_SIZE;  /* Bulk  OUT endpoint */	dev->ep [2].is_in = 0;    dev->ep [3].ep.maxpacket = INTR_TRANS_SIZE;  /* INTR IN  endpoint */    dev->gadget.ep0 = &dev->ep [0].ep;    dev->ep [0].stopped = 0;	dev->ep[0].pending = dev->ep[1].pending = dev->ep[2].pending = dev->ep[2].pending= 0;    INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);}static void ep0_start (struct dm320 *dev){	dm320_reset_ep(0);	writeb( USB_EP0, USB_INTRTX1E );		// enable endpoint EP0 RX/TX )	writeb( USB_RESET | USB_RESUME | USB_SUSPEND | USB_SESSREQ | USB_SOF , USB_INTRUSBE );		// Peripheral mode & 'B' type( slave )	}static void ep_reset (struct dm320_ep *ep){	ep->desc = NULL;	INIT_LIST_HEAD (&ep->queue);	ep->ep.maxpacket = ~0;	ep->ep.ops = &dm320_ep_ops;	dm320_reset_ep(ep);}static struct usb_request *dm320_alloc_request (struct usb_ep *_ep, int gfp_flags){    struct dm320_ep *ep;    struct dm320_request    *req;    if (!_ep)        return NULL;    ep = container_of (_ep, struct dm320_ep, ep);    req = kmalloc (sizeof *req, gfp_flags);    if (!req)	      return NULL;    memset (req, 0, sizeof *req);    req->req.dma = DMA_ADDR_INVALID;    INIT_LIST_HEAD (&req->queue);    return &req->req;}static voiddm320_free_request (struct usb_ep *_ep, struct usb_request *_req){    struct dm320_ep *ep;

⌨️ 快捷键说明

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