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

📄 usb_ctl.c

📁 MIZI Research, Inc.发布的嵌入式Linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  This program is derived from Extenex Corporation's SA-1100 usb *  controller core driver by MIZI. *  *  usb_ctl.c * *  S3C2410 USB controller core driver. * *  This file provides interrupt routing and overall coordination *  of the five endpoints. *   *  Seungbum Lim <shawn@mizi.com> *//* * ep0 - register * ep2~4 - dual port async. RAM (interrupt or DMA) * * config: *  ep0. *  ep2 : input - DMA_CH0 ? *  ep1 : output - DMA_CH3 ? */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/tqueue.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/pci.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/irq.h>#include <asm/mach-types.h>#include "s3c2410_usb.h"#include "usb_ctl.h"//////////////////////////////////////////////////////////////////////////////// Prototypes//////////////////////////////////////////////////////////////////////////////int usbctl_next_state_on_event( int event );static void udc_int_hndlr(int, void *, struct pt_regs *);static void initialize_descriptors( void );void ChangeUPllValue(int mdiv, int pdiv, int sdiv);void reset_usbd(void);void reconfig_usbd(void);//#define USB_DEBUG 1#ifdef USB_DEBUG#define LOG(arg...) printk(__FILE__":"__FUNCTION__"(): " ##arg)#else#define LOG(arg...) (void)(0)#endif#if CONFIG_PROC_FS#define PROC_NODE_NAME "usb"static int usbctl_read_proc(char *page, char **start, off_t off,							int count, int *eof, void *data);#endif//////////////////////////////////////////////////////////////////////////////// Globals//////////////////////////////////////////////////////////////////////////////static const char pszMe[] = "usbctl: ";struct usb_info_t usbd_info;  /* global to ep0, usb_recv, usb_send *///static int cnt=0;/* device descriptors */static desc_t desc;#define MAX_STRING_DESC 8static string_desc_t * string_desc_array[ MAX_STRING_DESC ];static string_desc_t sd_zero;  /* special sd_zero holds language codes */// called when configuredstatic usb_notify_t configured_callback = NULL;enum {	kStateZombie  = 0,  kStateZombieSuspend  = 1,		kStateDefault = 2,  kStateDefaultSuspend = 3,		kStateAddr    = 4,  kStateAddrSuspend    = 5,		kStateConfig  = 6,  kStateConfigSuspend  = 7};static int device_state_machine[8][6] = {//                suspend               reset          resume     adddr config deconfig/* zombie */  {  kStateZombieSuspend,  kStateDefault, kError,    kError, kError, kError },/* zom sus */ {  kError, kStateDefault, kStateZombie, kError, kError, kError },/* default */ {  kStateDefaultSuspend, kError, kStateDefault, kStateAddr, kError, kError },/* def sus */ {  kError, kStateDefault, kStateDefault, kError, kError, kError },/* addr */    {  kStateAddrSuspend, kStateDefault, kError, kError, kStateConfig, kError },/* addr sus */{  kError, kStateDefault, kStateAddr, kError, kError, kError },/* config */  {  kStateConfigSuspend, kStateDefault, kError, kError, kError, kStateAddr },/* cfg sus */ {  kError, kStateDefault, kStateConfig, kError, kError, kError }};/* "device state" is the usb device framework state, as opposed to the   "state machine state" which is whatever the driver needs and is much   more fine grained*/static int sm_state_to_device_state[8] =//  zombie           zom suspend          default            default sus{ USB_STATE_POWERED, USB_STATE_SUSPENDED, USB_STATE_DEFAULT, USB_STATE_SUSPENDED,// addr              addr sus             config                config sus  USB_STATE_ADDRESS, USB_STATE_SUSPENDED, USB_STATE_CONFIGURED, USB_STATE_SUSPENDED};static char * state_names[8] ={ "zombie", "zombie suspended", "default", "default suspended",  "address", "address suspended", "configured", "config suspended"};static char * event_names[6] ={ "suspend", "reset", "resume",  "address assigned", "configure", "de-configure"};static char * device_state_names[] ={ "not attached", "attached", "powered", "default",  "address", "configured", "suspended" };static int sm_state = kStateZombie;//////////////////////////////////////////////////////////////////////////////// Reset Fucntions//////////////////////////////////////////////////////////////////////////////void reset_usbd(void){    int i;    UD_PWR = UD_PWR_DEFAULT | UD_PWR_RESET; /* UD_PWR default value, MCU_RESET */    UD_PWR;    UD_PWR = UD_PWR_DEFAULT;	LOG("UD_PWR = 0x%08x\n", UD_PWR);    for(i = 0; i< 0x100; i++) ;}void reconfig_usbd(void){	LOG("\n");    /* sec like, shawn */    ep0_state = EP0_STATE_IDLE;    set_configuration = 1;    set_interface = 1;    device_status = 0;    ep0_status = 0;    ep_bulk_in_status = 0;    ep_bulk_out_status = 0;            UD_PWR = UD_PWR_DEFAULT;        /* EP0 */	UD_INDEX = UD_INDEX_EP0;       	UD_MAXP = UD_MAXP_8; // 8 byte	UD_INDEX = UD_INDEX_EP0;	UD_ICSR1 = EP0_CSR_SOPKTRDY | EP0_CSR_SSE;        /* EP2 */	UD_INDEX = UD_INDEX_EP2;           	UD_MAXP = UD_MAXP_64; // 64 byte	UD_INDEX = UD_INDEX_EP2;	UD_ICSR1 = UD_ICSR1_FFLUSH | UD_ICSR1_CLRDT; // fifo flush, data toggle	UD_INDEX = UD_INDEX_EP2;	UD_ICSR2 = UD_ICSR2_MODEIN | UD_ICSR2_DMAIEN; // input mode, IN_PKT_RDY dis #ifdef USE_USBD_DMA	UD_ICSR2 &= ~UD_ICSR2_DMAIEN;#endif	/* EP1 */	UD_INDEX = UD_INDEX_EP1;            	UD_MAXP = UD_MAXP_64; // 64 byte	UD_INDEX = UD_INDEX_EP1;	UD_ICSR1 = UD_ICSR1_FFLUSH | UD_ICSR1_CLRDT; // fifo flush, data toggle	UD_INDEX = UD_INDEX_EP1;	UD_ICSR2 = 0x0; // output mode	UD_INDEX = UD_INDEX_EP1;	UD_OCSR1 = UD_OCSR1_FFLUSH | UD_OCSR1_CLRDT; // fifo flush	UD_INDEX = UD_INDEX_EP1;	UD_OCSR2 = UD_OCSR2_DMAIEN; // OUT_PKT_RDY interrupt disable#ifdef USE_USBD_DMA	UD_OCSR2 &= ~UD_OCSR2_DMAIEN; // OUT_PKT_RDY interrupt disable#endif	UD_INTE = UD_INTE_EP0 | UD_INTE_EP2 | UD_INTE_EP1;	UD_USBINTE = UD_USBINTE_RESET | UD_USBINTE_SUSPND;        initialize_descriptors();  	bINTCTL(oINTMSK) &= ~(INT_USBD);}    static voidudc_int_hndlr(int irq, void *dev_id, struct pt_regs *regs){  	__u8 saveIdx = UD_INDEX;    	__u8 usb_status = UD_USBINT;  	__u8 usbd_status = UD_INT;	static int sb_debug_cnt = 1;		LOG("usb_status = 0x%02x, usbd_status = 0x%02x\n",			usb_status, usbd_status);	if ( usb_status & UD_USBINT_RESET ) {	    LOG("\n[%d]RESET interrupt\n",sb_debug_cnt++);	    if( usbctl_next_state_on_event(kEvReset) != kError ) {		LOG("%s Resetting\n",pszMe);		ep0_reset();		ep1_reset();/* output */		ep2_reset();/* input */	    }	   // reset_usbd();	    reconfig_usbd();	    UD_USBINT = UD_USBINT_RESET; //RESET_INT should be cleared after reconfig_usbd().- by samsung src	    ep0_state = EP0_STATE_IDLE;	}	/* RESume Interrupt Request */	if ( usb_status & UD_USBINT_RESUM ) { 		LOG("[%d]RESUME interrupt\n", sb_debug_cnt++);		UD_USBINT = UD_USBINT_RESUM;/* clear */		usbctl_next_state_on_event( kEvResume );	}	/* SUSpend Interrupt Request */	if ( usb_status & UD_USBINT_SUSPND ) { 		LOG("[%d]SUSPEND interrupt\n", sb_debug_cnt++);		UD_USBINT = UD_USBINT_SUSPND; /* clear */		usbctl_next_state_on_event( kEvSuspend );	}	if ( usbd_status & UD_INT_EP0 ) {		LOG("\n[%d]EP0 interrupt\n",sb_debug_cnt++);		UD_INT = UD_INT_EP0; /* clear */		ep0_int_hndlr();	}         /* output */	if ( usbd_status & UD_INT_EP1 ) { 		LOG("[%d]EP1 interrupt\n", sb_debug_cnt++);		UD_INT = UD_INT_EP1;/* clear */		ep1_int_hndlr(usbd_status);	}        /* input */	if ( usbd_status & UD_INT_EP2 ) {		LOG("[%d]EP2 interrupt\n", sb_debug_cnt++); 		UD_INT = UD_INT_EP2; /* clear */		ep2_int_hndlr(usbd_status);			}	if(usbd_status & UD_INT_EP3) UD_INT = UD_INT_EP3;	if(usbd_status & UD_INT_EP4) UD_INT = UD_INT_EP4;	  	Clear_pending(INT_USBD);	UD_INDEX= saveIdx;	}//////////////////////////////////////////////////////////////////////////////// Public Interface///////////////////////////////////////////////////////////////////////////////* Open S3C2410 usb core on behalf of a client, but don't start running */ints3c2410_usb_open( const char * client ){	LOG("\n");	 if ( usbd_info.client_name != NULL )		  return -EBUSY;	 usbd_info.client_name = (char*) client;	 memset(&usbd_info.stats, 0, sizeof(struct usb_stats_t));	 memset(string_desc_array, 0, sizeof(string_desc_array));	 /* hack to start in zombie suspended state */#if 0	 sm_state = kStateZombieSuspend;	 usbd_info.state = USB_STATE_SUSPENDED;#endif	 /* create descriptors for enumeration */	 initialize_descriptors();	 printk( "%sOpened for %s\n", pszMe, client );	 return 0;}/* Start running. Must have called usb_open (above) first */ints3c2410_usb_start( void ){	unsigned long tmp;	LOG("\n");	 if ( usbd_info.client_name == NULL ) {		  printk( "%s%s - no client registered\n",				  pszMe, __FUNCTION__ );		  return -EPERM;	 }	 /* start UDC internal machinery running */	 udelay( 100 );	 /* clear stall - receiver seems to start stalled? */	UD_INDEX = UD_INDEX_EP2; // EP2 input 	tmp = UD_ICSR1; 	tmp &= ~(UD_ICSR1_SENTSTL | UD_ICSR1_FFLUSH | UD_ICSR1_UNDRUN);        tmp &= ~(UD_ICSR1_PKTRDY | UD_ICSR1_SENDSTL);	UD_ICSR1 = tmp;	UD_INDEX = UD_INDEX_EP1; // EP1 output	tmp = UD_OCSR1;	tmp &= ~(UD_OCSR1_SENTSTL | UD_OCSR1_FFLUSH | UD_OCSR1_OVRRUN);	tmp &= ~(UD_OCSR1_PKTRDY | UD_OCSR1_SENDSTL);	UD_OCSR1 = tmp;	/* flush DMA and fire through some -EAGAINs */	ep2_init( usbd_info.dmach_tx );	ep1_init( usbd_info.dmach_rx );	/* clear all top-level sources */	UD_INT = UD_INT_EP0 | UD_INT_EP1 | UD_INT_EP2;	UD_USBINT = UD_USBINT_RESET | UD_USBINT_RESUM | UD_USBINT_SUSPND;	printk( "%sStarted for %s\n", pszMe, usbd_info.client_name );	return 0;}/* Stop USB core from running */ints3c2410_usb_stop( void ){	LOG("name=%s\n", usbd_info.client_name ? usbd_info.client_name : "NULL");	 if ( usbd_info.client_name == NULL ) {		  printk( "%s%s - no client registered\n",				  pszMe, __FUNCTION__ );		  return -EPERM;	 }#if 0	 /* It may be default value of S3C2410 USBD and makes only RESET be enalble*/	 UD_INTM = 0x13f;#endif	 ep1_reset(); 	 ep2_reset();	 printk( "%sStopped \n", pszMe );	 return 0;}/* Tell S3C2410 core client is through using it */ints3c2410_usb_close( void ){	 if ( usbd_info.client_name == NULL ) {		  printk( "%s%s - no client registered\n",				  pszMe, __FUNCTION__ );		  return -EPERM;	 }	 usbd_info.client_name = NULL;	 return 0;}/* set a proc to be called when device is configured */usb_notify_t s3c2410_set_configured_callback( usb_notify_t func ){	 usb_notify_t retval = configured_callback;	LOG("\n");	 configured_callback = func;	 return retval;}/*==================================================== * Descriptor Manipulation. * Use these between open() and start() above to setup * the descriptors for your device. * *//* get pointer to static default descriptor */desc_t *s3c2410_usb_get_descriptor_ptr( void ) { return &desc; }/* optional: set a string descriptor */ints3c2410_usb_set_string_descriptor( int i, string_desc_t * p )

⌨️ 快捷键说明

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