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

📄 l7205.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Get ready to use the L7205 USB Controller. * * Register an interrupt handler and initialize dma. */int udc_init (void){	// This should never happen!	if (IO_USBF_REVISION != USBF_REVISION_11) {		dbg_udc (0, "incorrect or not found version: %02lx should be %02x",			 IO_USBF_REVISION, USBF_REVISION_11);		return -EINVAL;	}	// disable the udc just in case	udc_disable_interrupts (0);	udc_disconnect ();	udc_disable ();	return 0;}/* * Switch off the L7205 USB Function */void udc_disable (void){	udc_device = NULL;	// disable interrupts	IO_USBF_INTDIS =	    USBF_INTDIS_DNSUS |	    USBF_INTDIS_DNF0ERR |	    USBF_INTDIS_DNF1OR |	    USBF_INTDIS_DNF1ERR |	    USBF_INTDIS_DNF2UR |	    USBF_INTDIS_DNF2ERR |	    USBF_INTDIS_DNF3ERR |	    USBF_INTDIS_DNGRSM |	    USBF_INTDIS_DNF0RQ |	    USBF_INTDIS_DNF1RQ |	    USBF_INTDIS_DNF2RQ | USBF_INTDIS_DNF3RQ | USBF_INTDIS_DNSOF | USBF_INTDIS_DNHRST;	// set USBFUNC_EN	IO_SYS_CLOCK_ENABLE &= ~SYS_CLOCK_USBFUNC_EN;	// reset USB function	// IO_USBF_CONTROL |= USBF_CONTROL_FRST;	IO_USBF_CONTROL = 0;	// turn off clocks#ifdef xCONFIG_IRIS	iris_AUXPLL_OFF_for_usb ();#else	IO_SYS_CLOCK_ENABLE &= ~(SYS_CLOCK_AUXPLL_EN | SYS_CLOCK_AUXCLK_EN);#endif}/* * initialize L7205 USB Function */void l7205_init (struct usb_device_instance *device){	//int i;	int offset;	unsigned char *descriptors;	// XXX disable everything	IO_USBF_CONTROL = 0;	udelay (20);#if defined(CONFIG_L7205SDB)	/*	 * Linkup reports that there may be a problem with video conflicting with	 * USB Function, this will disable it.	 */	dbg_udc (2, "1. CLCDCON: %08lx SYS_CLOCK_ENABLE: %08lx", IO_CLCDCON, IO_SYS_CLOCK_ENABLE);	// disable LCD power (bit 22) and wait 20MS	IO_CLCDCON &= ~0x20000;	udelay (100);	dbg_udc (2, "2. CLCDCON: %08lx SYS_CLOCK_ENABLE: %08lx", IO_CLCDCON, IO_SYS_CLOCK_ENABLE);	// disable LCD (bit 0)	IO_CLCDCON &= ~0x1;	dbg_udc (2, "3. CLCDCON: %08lx SYS_CLOCK_ENABLE: %08lx", IO_CLCDCON, IO_SYS_CLOCK_ENABLE);	// disable Vee and backlight bits 1, 2	IO_SYS_CLOCK_ENABLE &= ~0x3;	dbg_udc (2, "4. CLCDCON: %08lx SYS_CLOCK_ENABLE: %08lx", IO_CLCDCON, IO_SYS_CLOCK_ENABLE);#endif	/*	 * Setup FIRCLK to use internal clock - c.f. 13.1.2 Clocks	 */	dbg_udc (5, "setting clocks (internal PLL)");	// clear AUXOSCMUX, AUXPLLMUX and AUXPLLMUL bits of CLOCK_AUX	IO_SYS_CLOCK_AUX = 0;	// clear AUX0SCMUX and set AUXPLLMUL to 13 for 48Mhz	IO_SYS_CLOCK_AUX |= SYS_CLOCK_AUXPLLMUL_48;	// set FIRAUX_SEL	IO_SYS_CLOCK_SELECT |= SYS_CLOCK_FIRAUX_SEL;	// set AUXPLL_EN and AUXCLK_EN #ifdef xCONFIG_IRIS	iris_AUXPLL_ON_for_usb ();#else	IO_SYS_CLOCK_ENABLE |= SYS_CLOCK_AUXPLL_EN | SYS_CLOCK_AUXCLK_EN;#endif	// wait 8us	udelay (10);	// set USBFUNC_EN to enable clock	IO_SYS_CLOCK_ENABLE |= SYS_CLOCK_USBFUNC_EN;	// wait 8us	udelay (10);	// enable USB Function	IO_USBF_CONTROL |= USBF_CONTROL_ENBL;	udelay (20);	// set program modes	IO_USBF_CONTROL |= USBF_CONTROL_F1MOD_IO | USBF_CONTROL_F2MOD_IO;	// Force USB function core reset	// l7205_toggle(IO_USBF_CONTROL, USBF_CONTROL_FRST);	// Reset and clear all FIFO's	// l7205_toggle(IO_USBF_CONTROL, USBF_CONTROL_F0CLR | USBF_CONTROL_F1CLR | USBF_CONTROL_F2CLR | USBF_CONTROL_F3CLR);	// allocate tmp buffer	if ((descriptors = kmalloc (USBF_DESCRIPTORS_MAX, GFP_ATOMIC))) {		// clear the descriptor space		memset (descriptors, 0, USBF_DESCRIPTORS_MAX);		// XXX memset((void *)(__IOA(USBF_DESCRIPTORS)), 0, USBF_DESCRIPTORS_MAX);		// copy in device, configuration, langid and up to four strings		offset = l7205_copy_request (descriptors, device, 0, 0, USB_DESCRIPTOR_TYPE_DEVICE);		offset =		    l7205_copy_request (descriptors, device, USBF_CONFIGBUF1, offset,					USB_DESCRIPTOR_TYPE_CONFIGURATION);		offset =		    l7205_copy_descriptor (descriptors, USBF_STRINGBUF0, offset,					   (struct usb_descriptor *) usbd_get_string (0), 0);		offset =		    l7205_copy_descriptor (descriptors, USBF_STRINGBUF1, offset,					   (struct usb_descriptor *) usbd_get_string (1), 0);		offset =		    l7205_copy_descriptor (descriptors, USBF_STRINGBUF2, offset,					   (struct usb_descriptor *) usbd_get_string (2), 0);		offset =		    l7205_copy_descriptor (descriptors, USBF_STRINGBUF3, offset,					   (struct usb_descriptor *) usbd_get_string (3), 0);		offset =		    l7205_copy_descriptor (descriptors, USBF_STRINGBUF4, offset,					   (struct usb_descriptor *) usbd_get_string (4), 0);		// copy descriptors to shared RAM		memcpy ((unsigned char *) __IOA (USBF_DESCRIPTORS), descriptors,			USBF_DESCRIPTORS_MAX);		kfree (descriptors);	} else {		// should never happen		dbg_udc (0, "cannot malloc descriptors");	}	/*	 * Configuration and Intialization - c.f. 13.1.4 and c.f. 13.1.1	 */	IO_USBF_ENDPTBUF0 = USBF_ENDPTBUF0_EP0MSIZE_8;	IO_USBF_ENDPTBUF1 = USBF_ENDPTBUF1_EP1TYPE_BULK | 0x20;	IO_USBF_ENDPTBUF2 = USBF_ENDPTBUF2_EP2TYPE_BULK | 0x20;	IO_USBF_ENDPTBUF3 = USBF_ENDPTBUF3_EP3TYPE_INT;	IO_USBF_F1TOUT = 1;	IO_USBF_F1BCNT = 0x20;	IO_USBF_F2BCNT = 0;	// Force USB function core reset	l7205_toggle (IO_USBF_CONTROL, USBF_CONTROL_FRST);	// Reset and clear all FIFO's	l7205_toggle (IO_USBF_CONTROL,		      USBF_CONTROL_F0CLR | USBF_CONTROL_F1CLR | USBF_CONTROL_F2CLR |		      USBF_CONTROL_F3CLR);	// Clear interrupts	IO_USBF_INTCLR = 0x3fff;	// set initialization done bit to indicate descriptors and registers are ready	IO_USBF_CONTROL |= USBF_CONTROL_INTD;	// enable interrupts	IO_USBF_INTENA =	    USBF_INTENA_ENSUS |	    USBF_INTENA_ENF0ERR |	    USBF_INTENA_ENF1OR |	    USBF_INTENA_ENF1ERR |	    USBF_INTENA_ENF2UR |	    USBF_INTENA_ENF2ERR |	    USBF_INTENA_ENF3ERR |	    USBF_INTENA_ENGRSM |	    USBF_INTENA_ENF0RQ |	    USBF_INTENA_ENF1RQ |	    USBF_INTENA_ENF2RQ | USBF_INTENA_ENF3RQ | USBF_INTENA_ENSOF | USBF_INTENA_ENHRST;	// wait 	udelay (60);		// XXX	l7205_regs ("finished");}/* * Switch on the L7205 USB Function */void udc_enable (struct usb_device_instance *device){	udc_device = device;	l7205_init (udc_device);	// XXX do when Vbus is present....	return;}#if defined(TRIGGER)static unsigned int max_triggers = 64;static void send_usb_trigger (unsigned int status, char *id){	/* This code is to insert a "trigger" into the outgoing data stream	   so that the a USB protocol anlyser can capture the data surrounding	   it.  It is only used when debugging strange hardware states.	   The "trigger" is data that looks like "0xdeadbeef". */	if (max_triggers == 0) {		printk (KERN_DEBUG "%s & no more triggers\n", id);		return;	}	if (status & USBF_STATUS_F2BSY) {		printk (KERN_DEBUG "%s & F2BSY\n", id);	} else {		static char flag_bytes[48] = {			0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,			    0xde, 0xad, 0xbe, 0xef,			0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,			    0xde, 0xad, 0xbe, 0xef,			0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,			    0xde, 0xad, 0xbe, 0xef		};		unsigned long *slp;		unsigned long *txf = IO_USBF_FIFO_TX;		int i, j, fifo_good;		slp =		    (unsigned long *) (void *) (0xfffffffc &						(unsigned long) (3 + (void *) flag_bytes));		j = 0;		do {			for (i = 0; i < 8; i++) {				IO_USBF_FIFO2 = slp[i];			}			fifo_good = 1;			for (i = 0; i < 8; i++) {				fifo_good &= (slp[i] == txf[i]);			}		} while (++j < 10 && !fifo_good);		if (fifo_good) {			IO_USBF_F2BCNT = 32;			printk (KERN_DEBUG "deadbeef %u %s\n", max_triggers, id);			max_triggers -= 1;		} else {			// too busy receiving?			printk (KERN_DEBUG "%s & F1BSY\n", id);		}	}}#endif#define STATUS_NO_INTR_MASK   ~(USBF_STATUS_F1NE | USBF_STATUS_F2NF | USBF_STATUS_F2NE | USBF_STATUS_F2BSY | USBF_STATUS_VCCMD);/** * udc_int_hndlr - interrupt handler * */void udc_int_hndlr (int irq, void *dev_id, struct pt_regs *regs){	int loopcount;	unsigned int rawstatus;	int ep2_int_hndlr_called = 0;	udc_interrupts++;	// XXX rawstatus = IO_USBF_RAWSTATUS;	for (loopcount = 0; 0 != (rawstatus = IO_USBF_RAWSTATUS) && (loopcount < 4); loopcount++) {		unsigned int status = IO_USBF_STATUS;		IO_USBF_INTCLR = rawstatus;		/*		 * Handle high priority interrupts first to reduce latency and		 * overhead.		 */		if (rawstatus & USBF_RAWSTATUS_RF1RQ) {			ep1_int_hndlr ();			sof_saw_rx_f1ne = 0;		}		if (rawstatus & USBF_RAWSTATUS_RF2RQ) {			ep2_int_hndlr (status);			ep2_int_hndlr_called++;			sof_saw_tx_active = 0;		}		/*		 * check if we have one of the un-common interrupts, this is faster		 * than testing for each one sequentially. Note that we will do the		 * SOF test first, and then another general test for the really		 * un-common interrupts.		 */		if (rawstatus &		    (USBF_RAWSTATUS_RSUS | USBF_RAWSTATUS_RF0ERR | USBF_RAWSTATUS_RF1OR |		     USBF_RAWSTATUS_RF1ERR | USBF_RAWSTATUS_RF2ERR | USBF_RAWSTATUS_RF3ERR |		     USBF_RAWSTATUS_RGRSM | USBF_RAWSTATUS_RF0RQ | USBF_RAWSTATUS_RF3RQ |		     USBF_RAWSTATUS_RHRST | USBF_RAWSTATUS_RSOF)) {			/*			 * SOF - Start of frame interrupt, use as a safe place to check			 * for missed transmit, receive interrupts, turn back on SUS or			 * RST interrupts etc.			 */			if (rawstatus & USBF_RAWSTATUS_RSOF) {				/*				 * Simulate an rx interrupt, if we have not seen a rcv				 * interrupt recently.				 */				if (IO_USBF_STATUS & USBF_STATUS_F1NE) {					if ((sof_saw_rx_f1ne++ > 2)) {						dbg_tick (1, "[%d]: F1NE %ld", udc_interrupts,							  IO_USBF_F1BCNT);						ep1_clear ();						sof_saw_rx_f1ne = 0;					}				} else {					sof_saw_rx_f1ne = 0;				}				/*				 * This is required in case we miss a tx interrupt or we				 * abandoned a tx attempt due to contention with rx fifo				 */				if ((sof_saw_tx_active++ > 10) && ep2_active) {					ep2_int_hndlr_error (status, 0, ep2_int_hndlr_called++);					sof_saw_tx_active = 0;				}				/*				 * The SUS and HRST interrupts disable themselves, now is				 * the time to re-enable them.				 */				if (host_sus_interrupt_disabled) {					IO_USBF_INTENA = USBF_INTENA_ENSUS;					host_sus_interrupt_disabled = 0;					usbd_device_event (udc_device, DEVICE_BUS_ACTIVITY, 0);				}				if (host_reset_interrupt_disabled) {					IO_USBF_INTENA = USBF_INTENA_ENHRST;					host_reset_interrupt_disabled = 0;					usbd_device_event (udc_device, DEVICE_ADDRESS_ASSIGNED, 0);					udc_device->configuration = 0;					usbd_device_event (udc_device, DEVICE_CONFIGURED, 0);					udc_device->interface = 0;					udc_device->alternate = 0;					usbd_device_event (udc_device, DEVICE_SET_INTERFACE, 0);				}				/*				 * If these three bits are on all is lost, we will				 * disconnect.				 */				if ((status & USBF_STATUS_F2BSY) && (status & USBF_STATUS_F2NE)				    && (status & USBF_STATUS_F2NF)) {					// disconnect and reset udc					// XXX udc_disconnect();					// XXX udc_connect();				}			}			/*			 * check if we have a really uncommon interrupt, this saves			 * sequential testing of all of these during SOF only			 * interrupts.			 */			if (rawstatus &			    (USBF_RAWSTATUS_RSUS | USBF_RAWSTATUS_RF0ERR | USBF_RAWSTATUS_RF1OR |			     USBF_RAWSTATUS_RF1ERR | USBF_RAWSTATUS_RF2ERR | USBF_RAWSTATUS_RF3ERR |			     USBF_RAWSTATUS_RGRSM | USBF_RAWSTATUS_RF0RQ | USBF_RAWSTATUS_RF3RQ |			     USBF_RAWSTATUS_RHRST)) {				/*				 * SUS - suspend interrupt, issued device event and disable SUS interrupt				 * until we see an SOF interrupt				 */				if (rawstatus & USBF_RAWSTATUS_RSUS) {					dbg_intr (0, "[%u]: SUS Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);					// disable host interrupt					IO_USBF_INTDIS = USBF_INTDIS_DNSUS;					host_sus_interrupt_disabled++;					usbd_device_event (udc_device, DEVICE_BUS_INACTIVE, 0);				}				/*				 * HRST - Host Reset interrupt, issued device event and disable SUS interrupt				 * until we see an SOF interrupt				 */				if (rawstatus & USBF_RAWSTATUS_RHRST) {					// L7210 AB version would give multiple HRST when the first is cleared,					// ignore them until SOF interrupt					dbg_intr (0, "[%u]: HRST", udc_interrupts);					// XXX l7205_toggle(IO_USBF_CONTROL, USBF_CONTROL_FRST);					// reset udc					l7205_init (udc_device);	// XXX 					// disable host interrupt					IO_USBF_INTDIS = USBF_INTDIS_DNHRST;					host_reset_interrupt_disabled++;					usbd_device_event (udc_device, DEVICE_RESET, 0);				}				/*				 * F1ERR - FIFO 1 error, a receive error, bad news, usually once				 * this has happened we cannot continue or reset to normal				 * state. In desparation we will drop connection and hope that				 * HRST will restore things.				 */				if (rawstatus & USBF_RAWSTATUS_RF1ERR) {					dbg_intr (0, "[%u]: F1ERR Sts: %08x Raw: %08x F1Bcnt: %ld",						  udc_interrupts, status, rawstatus,						  IO_USBF_F1BCNT);					sof_saw_rx_f1ne = 0;#if defined(FLAG_F1ERR) && defined(TRIGGER)					send_usb_trigger (status, "F1ERR");#endif					udc_disconnect ();					ep1_int_hndlr_error ();					udelay (100);					udc_connect ();					udelay (100);					udc_disconnect ();					// XXX udc_disconnect();					// XXX l7205_init(udc_device); // XXX 				}				/*				 * Misc Error interrupts - have never seen any of these.				 */				if (rawstatus & USBF_RAWSTATUS_RF0ERR) {					dbg_intr (0, "[%u]: F0ERR Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);				}				if (rawstatus & USBF_RAWSTATUS_RF1OR) {					dbg_intr (0, "[%u]: F1OR Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);					ep1_int_hndlr_error ();					sof_saw_rx_f1ne = 0;				}				if (rawstatus & USBF_RAWSTATUS_RF2UR) {					dbg_intr (0, "[%u]: F2UR Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);					sof_saw_tx_active = 0;					ep2_int_hndlr_error (status, 1, ep2_int_hndlr_called++);				}				if (rawstatus & USBF_RAWSTATUS_RF2ERR) {					dbg_intr (0, "[%u]: F2ERR Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);					sof_saw_tx_active = 0;					ep2_int_hndlr_error (status, 1, ep2_int_hndlr_called++);				}				if (rawstatus & USBF_RAWSTATUS_RF3ERR) {					dbg_intr (0, "[%u]: F3ERR Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);				}				if (rawstatus & USBF_RAWSTATUS_RGRSM) {					dbg_intr (0, "[%u]: GRSM Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);				}				if (rawstatus & USBF_RAWSTATUS_RF0RQ) {					dbg_intr (0, "[%u]: F0RQ Sts: %08x Raw: %08x",						  udc_interrupts, status, rawstatus);				}				if (rawstatus & USBF_RAWSTATUS_RF3RQ) {					dbg_intr (0, "[%u]: F3RQ Sts: %08x Raw: %08x",

⌨️ 快捷键说明

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