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

📄 omap.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 */static voidomap_udc_epn_rx(int ep){	unsigned short status;	/* Check endpoint status */	status = inw(UDC_STAT_FLG);	if (status & UDC_ACK) {		int nbytes;		struct usb_endpoint_instance *endpoint =		    udc_device->bus->endpoint_array + ep;		nbytes = omap_read_noniso_rx_fifo(endpoint);		usbd_rcv_complete_irq(endpoint, nbytes, 0);		/* enable rx FIFO to prepare for next packet */		outw(UDC_Set_FIFO_En, UDC_CTRL);	} else if (status & UDC_STALL) {		UDCDBG("STALL on RX endpoint %d", ep);	} else if (status & UDC_NAK) {		UDCDBG("NAK on RX ep %d", ep);	} else		printk(KERN_WARNING "omap-bi: RX on ep %d with status %x",		       ep, status);}/* Handle TX transaction on non-ISO endpoint. * This function implements TRM Figure 14-29. * The ep argument is a physical endpoint number for a non-ISO IN endpoint * in the range 16 to 30. */static voidomap_udc_epn_tx(int ep){	unsigned short status;	/* Check endpoint status */	status = inw(UDC_STAT_FLG);	if (status & UDC_ACK) {		struct usb_endpoint_instance *endpoint =		    udc_device->bus->endpoint_array + ep;		/* We need to transmit a terminating zero-length packet now if 		 * we have sent all of the data in this URB and the transfer 		 * size was an exact multiple of the packet size.		 */		if (endpoint->tx_urb		    && (endpoint->last == endpoint->tx_packetSize)		    && (endpoint->tx_urb->actual_length - endpoint->sent			- endpoint->last == 0)) {			/* Prepare to transmit a zero-length packet. */			endpoint->sent += endpoint->last;			/* write 0 bytes of data to FIFO */			omap_write_noniso_tx_fifo(endpoint);			/* enable tx FIFO to start transmission */			outw(UDC_Set_FIFO_En, UDC_CTRL);		} else {			/* retire the data that was just sent */			usbd_tx_complete_irq(endpoint, 0);			/* Check to see if we have more data ready to transmit			 * now.			 */			if (endpoint->tx_urb) {				/* write data to FIFO */				omap_write_noniso_tx_fifo(endpoint);				/* enable tx FIFO to start transmission */				outw(UDC_Set_FIFO_En, UDC_CTRL);			}		}	} else if (status & UDC_STALL) {		UDCDBG("STALL on TX endpoint %d", ep);	} else if (status & UDC_NAK) {		UDCDBG("NAK on TX endpoint %d", ep);	} else		printk(KERN_WARNING "omap-bi: TX on ep %d with status %x",		       ep, status);}#if 0static voidomap_udc_eot(void){	UDCDBG("eot NYI");}static voidomap_udc_rx_dma(void){	UDCDBG("rx dma NYI");}static voidomap_udc_tx_dma(void){	UDCDBG("tx dma NYI");}#endif/* Handle general USB interrupts and dispatch according to type. * This function implements TRM Figure 14-13. */static voidomap_udc_irq(int irq, void *dev_id, struct pt_regs *regs){	u16 irq_src = inw(UDC_IRQ_SRC);	int valid_irq = 0;	UDCDBG("< IRQ #%d start >- %d %x %x",	       udc_interrupts, irq, irq_src, inw(UDC_IRQ_EN));	if (irq_src & UDC_DS_Chg) {		/* Device status changed */		omap_udc_state_changed();		valid_irq++;	}	if (irq_src & UDC_EP0_RX) {		/* Endpoint 0 receive */		outw(UDC_EP0_RX, UDC_IRQ_SRC);	/* ack interrupt */		omap_udc_ep0_rx(udc_device->bus->endpoint_array + 0);		valid_irq++;	}	if (irq_src & UDC_EP0_TX) {		/* Endpoint 0 transmit */		outw(UDC_EP0_TX, UDC_IRQ_SRC);	/* ack interrupt */		omap_udc_ep0_tx(udc_device->bus->endpoint_array + 0);		valid_irq++;	}	if (irq_src & UDC_Setup) {		/* Device setup */		omap_udc_setup(udc_device->bus->endpoint_array + 0);		valid_irq++;	}#if 0	if (irq_src & UDC_RXn_EOT) {		/* End of RX DMA transfer */		omap_udc_eot();		valid_irq++;	}	if (irq_src & UDC_RXn_Cnt) {		/* RX DMA count (FIXME: ???) */		omap_udc_rx_dma();		valid_irq++;	}	if (irq_src & UDC_TXn_Done) {		/* TX DMA finished */		omap_udc_tx_dma();		valid_irq++;	}#endif	if (!valid_irq)		printk(KERN_ERR UDC_NAME ": unknown interrupt, IRQ_SRC %.4x\n",		       irq_src);	UDCDBG("< IRQ #%d end >", udc_interrupts);	udc_interrupts++;}/* This function implements TRM Figure 14-26. */static voidomap_udc_noniso_irq(int irq, void *dev_id, struct pt_regs *regs){	unsigned short epnum;	unsigned short irq_src = inw(UDC_IRQ_SRC);	int ep;	int valid_irq = 0;	UDCDBG("non-ISO IRQ, IRQ_EN %x", inw(UDC_IRQ_EN));	if (irq_src & UDC_EPn_RX) {	/* Endpoint N OUT transaction */		/* Determine the endpoint number for this interrupt */		epnum = (inw(UDC_EPN_STAT) & 0x0f00) >> 8;		UDCDBG("RX on ep %d", epnum);		/* acknowledge interrupt */		outw(UDC_EPn_RX, UDC_IRQ_SRC);		if (epnum) {			/* convert epnum to physical ep */			ep = EP_ADDR_TO_PHYS_EP(USB_DIR_OUT | epnum);			/* select the endpoint FIFO */			outw(UDC_EP_Sel | epnum, UDC_EP_NUM);			omap_udc_epn_rx(ep);			/* deselect the endpoint FIFO */			outw(epnum, UDC_EP_NUM);		}		valid_irq++;	}	if (irq_src & UDC_EPn_TX) {	/* Endpoint N IN transaction */		/* Determine the endpoint number for this interrupt */		epnum = inw(UDC_EPN_STAT) & 0x000f;		UDCDBG("TX on ep %d", epnum);		/* acknowledge interrupt */		outw(UDC_EPn_TX, UDC_IRQ_SRC);		if (epnum) {			/* convert epnum to physical ep */			ep = EP_ADDR_TO_PHYS_EP(USB_DIR_IN | epnum);			/* select the endpoint FIFO */			outw(UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM);			omap_udc_epn_tx(ep);			/* deselect the endpoint FIFO */			outw(UDC_EP_Dir | epnum, UDC_EP_NUM);		}		valid_irq++;	}	if (!valid_irq)		printk(KERN_WARNING UDC_NAME		       ": unknown non-ISO interrupt, IRQ_SRC %.4x\n", irq_src);}/* Handle SOF USB interrupts */static voidomap_udc_sof_irq(int irq, void *dev_id, struct pt_regs *regs){	/* For now, nothing except clear interrupt */	outw(UDC_SOF_Flg, UDC_IRQ_SRC);}/* ************************************************************************** *//* ************************************************************************** *//* * Start of public functions. *//* Called by the bus interface driver to start packet transmission. */voidudc_start_in_irq(struct usb_endpoint_instance *endpoint){	unsigned short epnum =	    endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;	UDCDBG("Starting transmit on ep %d", epnum);	if (endpoint->tx_urb) {		/* select the endpoint FIFO */		outw(UDC_EP_Sel | UDC_EP_Dir | epnum, UDC_EP_NUM);		/* write data to FIFO */		omap_write_noniso_tx_fifo(endpoint);		/* enable tx FIFO to start transmission */		outw(UDC_Set_FIFO_En, UDC_CTRL);		/* deselect the endpoint FIFO */		outw(UDC_EP_Dir | epnum, UDC_EP_NUM);	}}/* Start to initialize h/w stuff */intudc_init(void){	u16 udc_rev;	static int banner_printed = 0;	udc_device = NULL;	UDCDBG("starting");#ifdef CONFIG_ARCH_OMAP1610#ifdef CONFIG_OMAP_H2/*set up pinout*//*USB pin group 1 configuration*/	OMAP1610_SET_FUNC_MUX_CTRL(1, FUNC_MUX_CTRL_9, 24);	/*USB1.TXD W14 */	open_drain(4, PULL_DWN_CTRL_2);	OMAP1610_SET_FUNC_MUX_CTRL(2, FUNC_MUX_CTRL_9, 3);	/*USB1.TXEN W16 */	open_drain(29, PULL_DWN_CTRL_1);	//OMAP1610_SET_FUNC_MUX_CTRL(2, FUNC_MUX_CTRL_A, 3);    /*USB1.VP AA17 */	//open_drain(7, PULL_DWN_CTRL_2);	OMAP1610_SET_FUNC_MUX_CTRL(4, FUNC_MUX_CTRL_9, 0);	/*USB1.SEO W13 */	open_drain(28, PULL_DWN_CTRL_1);	OMAP1610_SET_FUNC_MUX_CTRL(1, FUNC_MUX_CTRL_A, 9);	/*USB1.RCV V15 */	open_drain(9, PULL_DWN_CTRL_2);	//OMAP1610_SET_FUNC_MUX_CTRL(2,FUNC_MUX_CTRL_8,27); /*USB1.SUSP J20*/ /*not used on OMAP1610 INNOVATOR*/	//open_drain(27,PULL_DWN_CTRL_1);	//OMAP1610_SET_FUNC_MUX_CTRL(2, FUNC_MUX_CTRL_A, 6);    /*USB1.VM P14 */	//open_drain(8, PULL_DWN_CTRL_2);	OMAP1610_SET_FUNC_MUX_CTRL(5, FUNC_MUX_CTRL_A, 12);	/*USB1.SPEED R13 *//*used on OMAP1610 H2, not INNOVATOR */	open_drain(10, PULL_DWN_CTRL_2);	OMAP1610_CONFIRM_MUX_SETUP();	//USB_TRANSCEIVER_CTRL.7 = 1 (CONF_USB1_UNI_R) //unidirectional vs bidirectional, set to 1 if trx mode 0	outl((inl(USB_TRANSCEIVER_CTRL) & ~(1 << 7)), USB_TRANSCEIVER_CTRL);#else	//USB_TRANSCEIVER_CTRL.7 = x (CONF_USB1_UNI_R) //unidirectional vs bidirectional, set to 1 if trx mode 0	//USB_TRANSCEIVER_CTRL.8 = x (CONF_USB2_UNI_R) //unidirectional vs bidirectional, set to 1 if trx mode 0	//all other bits = 0 (enable integrated transceiver, DP, DM, pull-downs on both)	outl((inl(USB_TRANSCEIVER_CTRL) & ((1 << 7) | (1 << 8))),	     USB_TRANSCEIVER_CTRL);#endif	/*set up USB Host without OTG function.	   OTG registers still must be configured */	//RESET_CONTROL.0 = 1 (CONF_OCP_RESET_R) //page oct03.448	//RESET_CONTROL.2 = 1 (CONF_ARMIO_RESET_R)	outl(inl(RESET_CONTROL) | 5, RESET_CONTROL);	//ARM_RSTCT2.0 = 1(PER_EN)	outl(inl(ARM_RSTCT2) | 1, ARM_RSTCT2);	//CLOCK_CTRL_REG.5 = 0 (DIS_USB_PVCI_CLK)	//CLOCK_CTRL_REG.4 = 1 (USB_MCLK_EN)	outl((inl(CLOCK_CTRL_REG) & ~(1 << 5)), CLOCK_CTRL_REG);	outl((inl(CLOCK_CTRL_REG) | (1 << 4)), CLOCK_CTRL_REG);	//SOFT_REQ_REG.8 = 1 (SOFT_USB_OTG_DPLL_REQ)	//SOFT_REQ_REG.4 = 1 (USB_REQ_EN) //USB Client HW DPLL req	//SOFT_REQ_REG.3 = 1 (SOFT_USB_REQ)	//SOFT_REQ_REG.0 = 1 (SOFT_DPLL_REQ) //ULPD_PLL clock req	outl((inl(SOFT_REQ_REG) | (1 << 0) | (1 << 3) | (1 << 4) | (1 << 8)),	     SOFT_REQ_REG);	//SOFT_DISABLE_REQ_REG.3 = 0 (DIS_PERIPH_REQ)	outl((inl(SOFT_DISABLE_REQ_REG) & ~(1 << 3)), SOFT_DISABLE_REQ_REG);	//MOD_CONF_CTRL_0.17 = 0 (CONF_MOD_USB_W2FC_VBUS_MODE_R) //VBUS Detection via AA2/via FUNC_MUX_CTRL_0(19-18)	outl((inl(MOD_CONF_CTRL_0) & ~(1 << 17)), MOD_CONF_CTRL_0);	//? OTG_SYSCON_1.1 = 1 (SOFT_RST)	//? OTG_SYSCON_1.2 == 1 ? (RESET_DONE)	//OTG_SYSCON_1.15 = 0 (OTG_IDLE_EN)	//OTG_SYSCON_1.13 = 0 (DEV_IDLE_EN) //user choice	//OTG_SYSCON_1.1 = 0 (SOFT_RST)#ifdef CONFIG_OMAP_H2	//OTG_SYSCON_1.26-24 = 0 (USB2_TRXMODE) //user choice	//OTG_SYSCON_1.22-20 = 2 (USB1_TRXMODE) //user choice	//OTG_SYSCON_1.18-16 = 0 (USB0_TRXMODE) //user choice	outl((2 << 20), OTG_SYSCON_1);#else	//OTG_SYSCON_1.26-24 = x (USB2_TRXMODE) //user choice	//OTG_SYSCON_1.22-20 = x (USB1_TRXMODE) //user choice	//OTG_SYSCON_1.18-16 = 3 (USB0_TRXMODE) //user choice	outl((inl(OTG_SYSCON_1) & ((7 << 20) | (7 << 24))), OTG_SYSCON_1);	outl((inl(OTG_SYSCON_1) | (3 << 16)), OTG_SYSCON_1);#endif	//OTG_CTRL.18 = 0 (BSESSVLD) //1 = host attached (VBUS present)	outl(0, OTG_CTRL);	//OTG_SYSCON_2.31 = 0 (OTG_EN)	//OTG_SYSCON_2.30 = 1 (USBx_SYNCHRO)	//OTG_SYSCON_2.29 = 0 (OTG_MST16)	//OTG_SYSCON_2.28 = 0 (SRP_GPDATA)	//OTG_SYSCON_2.27 = 0 (SRP_GPDVBUS)	//OTG_SYSCON_2.26-24 = 0 (SRP_GPUVBUS)	//OTG_SYSCON_2.22-20 = 0 (A_WAIT_RISE)	//OTG_SYSCON_2.18-16 = 4 (B_ASE0_BRST)	//OTG_SYSCON_2.14 = 0 (SRP_DPW)	//OTG_SYSCON_2.13 = 0 (SRP_DATA)	//OTG_SYSCON_2.12 = 0 (SRP_VBUS)	//OTG_SYSCON_2.10 = 0 (OTG_PADEN)	//OTG_SYSCON_2.9 = 0 (HMC_PADEN)	//OTG_SYSCON_2.7 = 0 (HMC_TTLSPEED) //user choice	//OTG_SYSCON_2.6 = 0 (HMC_TTLATTACH) //user choice#ifdef CONFIG_OMAP_H2	//OTG_SYSCON_2.8 = 0 (UHOST_EN) //user choice	//OTG_SYSCON_2.5-0 = 3 (HMC_MODE) //user choice	outl((1 << 30) | (4 << 16) | 3, OTG_SYSCON_2);#else	//OTG_SYSCON_2.8 = x (UHOST_EN) //user choice	//OTG_SYSCON_2.5-0 = 4 (HMC_MODE) //user choice	outl((inl(OTG_SYSCON_2) & ((1 << 30) | (4 << 16) | (1 << 8) | 4)),	     OTG_SYSCON_2);	outl((inl(OTG_SYSCON_2) | (1 << 30) | (4 << 16) | 4), OTG_SYSCON_2);#endif	//OTG_IRQ_EN = 0	outl(0, OTG_IRQ_EN);	//OTG_SYSCON_1.15 = 1 (OTG_IDLE_EN) //to reduce power consumption	//outl(inl(OTG_SYSCON_1)|(1<<15),OTG_SYSCON_1); //if enabled, usbserial looses some incoming data#else				/*old OMAP1510 configuration */	/* Check peripheral reset. Must be 1 to make sure	   MPU TIPB peripheral reset is inactive */	UDCREG(ARM_RSTCT2);	/* Set and check clock control.	 * We might ought to be using the clock control API to do 	 * this instead of fiddling with the clock registers directly 	 * here.	 */	outw((1 << 4) | (1 << 5), CLOCK_CTRL);	UDCREG(CLOCK_CTRL);	/* Set and check APLL */	outw(0x0008, APLL_CTRL);	UDCREG(APLL_CTRL);	/* Set and check DPLL */	outw(0x2210, DPLL_CTRL);	UDCREG(DPLL_CTRL);	/* Set and check SOFT */	outw((1 << 4) | (1 << 3) | 1, SOFT_REQ);	/* Short delay to wait for DPLL */	mdelay(1);#endif	/* Print banner with device revision */	udc_rev = inw(UDC_REV) & 0xff;	if (!banner_printed) {		banner_printed = 1;		printk(KERN_INFO		       "TI OMAP1510/1610 USB function module rev %d.%d\n",		       udc_rev >> 4, udc_rev);	}	/* The VBUS_MODE bit selects whether VBUS detection is done via	 * software (1) or hardware (0).  When software detection is	 * selected, VBUS_CTRL selects whether USB is not connected (0)	 * or connected (1).	 */	outl(inl(FUNC_MUX_CTRL_0) | UDC_VBUS_MODE, FUNC_MUX_CTRL_0);	outl(inl(FUNC_MUX_CTRL_0) & ~UDC_VBUS_CTRL, FUNC_MUX_CTRL_0);	UDCREGL(FUNC_MUX_CTRL_0);	/* We'll assume that our firmware has properly initialized our 	 * I/O pin multiplexing configuration so we don't need to fuss	 * with it here.  Keeping this sort of thing out of the driver 	 * makes it more likely that the driver will work without 	 * modification on OMAP boards that might have the USB function 	 * module pinned out differently than the Innovator.	 */#if 0	/* FUNC_MUX_CTRL_D bits 5:3 select whether OMAP pin W4 is the 	 * USB.PUEN signal (000) or the USB.CLK0 signal (001).  Pin W4	 * is used for the USB.PUEN signal on the Innovator.	 */	outl(inl(FUNC_MUX_CTRL_D) & ~(7 << 3), FUNC_MUX_CTRL_D);#endif	UDCREGL(FUNC_MUX_CTRL_D);	/*	 * At this point, device is ready for configuration...	 */	UDCDBG("disable USB interrupts");	outw(0, UDC_IRQ_EN);	UDCREG(UDC_IRQ_EN);	UDCDBG("disable USB DMA");	outw(0, UDC_DMA_IRQ_EN);	UDCREG(UDC_DMA_IRQ_EN);	UDCDBG("initialize SYSCON1");	outw(UDC_SYSCON1_INIT, UDC_SYSCON1);	UDCREG(UDC_SYSCON1);	return 0;}/* Stall endpoint */voidudc_stall_ep(unsigned int ep){	int ep_addr = PHYS_EP_TO_EP_ADDR(ep);	int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;	unsigned long flags;	UDCDBG("stall ep %d", ep);	/* REVISIT?	 * The OMAP TRM section 14.2.4.2 says we must check that the FIFO	 * is empty before halting the endpoint.  The current implementation 	 * doesn't check that the FIFO is empty.	 */	local_irq_save(flags);	if (!ep_num) {		outw(UDC_Stall_Cmd, UDC_SYSCON2);	} else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {		if (inw(UDC_EP_RX(ep_num)) & UDC_EPn_RX_Valid) {			/* we have a valid rx endpoint, so halt it */			outw(ep_num, UDC_EP_NUM);			outw(UDC_Set_Halt, UDC_CTRL);		}	} else {		if (inw(UDC_EP_TX(ep_num)) & UDC_EPn_TX_Valid) {			/* we have a valid tx endpoint, so halt it */			outw(ep_num | UDC_EP_Dir, UDC_EP_NUM);			outw(UDC_Set_Halt, UDC_CTRL);		}	}	local_irq_restore(flags);}/* Reset endpoint */voidudc_reset_ep(unsigned int ep){	int ep_addr = PHYS_EP_TO_EP_ADDR(ep);	int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;	unsigned long flags;	UDCDBG("reset ep %d", ep);	local_irq_save(flags);	if (!ep_num) {		/* control endpoint 0 can't be reset */	} else if ((ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {		UDCDBG("UDC_EP_RX(%d) = 0x%04x", ep_num,		       inw(UDC_EP_RX(ep_num)));		if (inw(UDC_EP_RX(ep_num)) & UDC_EPn_RX_Valid) {			/* we have a valid rx endpoint, so reset it */			outw(ep_num | UDC_EP_Sel, UDC_EP_NUM);			outw(UDC_Reset_EP, UDC_CTRL);			outw(ep_num, UDC_EP_NUM);			UDCDBG("OUT endpoint %d reset", ep_num);		}	} else {		UDCDBG("UDC_EP_TX(%d) = 0x%04x", ep_num,		       inw(UDC_EP_TX(ep_num)));		/* Resetting of tx endpoints seems to be causing the USB function 		 * module to fail, which causes problems when the driver is 		 * uninstalled.  We'll skip resetting tx endpoints for now until 		 * we figure out what the problem is.

⌨️ 快捷键说明

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