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

📄 omap_udc.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		ep->irqs++;		if (!list_empty(&ep->queue))			pending = 1;	}	if (!pending)		UDC_IRQ_EN_REG &= ~UDC_SOF_IE;	UDC_IRQ_SRC_REG = UDC_SOF;	spin_unlock_irqrestore(&udc->lock, flags);	return IRQ_HANDLED;}#endif/*-------------------------------------------------------------------------*/static struct omap_udc *udc;int usb_gadget_register_driver (struct usb_gadget_driver *driver){	int		status = -ENODEV;	struct omap_ep	*ep;	unsigned long	flags;	/* basic sanity tests */	if (!udc)		return -ENODEV;	if (!driver			// FIXME if otg, check:  driver->is_otg			|| driver->speed < USB_SPEED_FULL			|| !driver->bind			|| !driver->unbind			|| !driver->setup)		return -EINVAL;	spin_lock_irqsave(&udc->lock, flags);	if (udc->driver) {		spin_unlock_irqrestore(&udc->lock, flags);		return -EBUSY;	}	/* reset state */	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list) {		ep->irqs = 0;		if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)			continue;		use_ep(ep, 0);		UDC_CTRL_REG = UDC_SET_HALT;	}	udc->ep0_pending = 0;	udc->ep[0].irqs = 0;	udc->softconnect = 1;	/* hook up the driver */	driver->driver.bus = NULL;	udc->driver = driver;	udc->gadget.dev.driver = &driver->driver;	spin_unlock_irqrestore(&udc->lock, flags);	status = driver->bind (&udc->gadget);	if (status) {		DBG("bind to %s --> %d\n", driver->driver.name, status);		udc->gadget.dev.driver = NULL;		udc->driver = NULL;		goto done;	}	DBG("bound to driver %s\n", driver->driver.name);	UDC_IRQ_SRC_REG = UDC_IRQ_SRC_MASK;	/* connect to bus through transceiver */	if (udc->transceiver) {		status = otg_set_peripheral(udc->transceiver, &udc->gadget);		if (status < 0) {			ERR("can't bind to transceiver\n");			driver->unbind (&udc->gadget);			udc->gadget.dev.driver = NULL;			udc->driver = NULL;			goto done;		}	} else {		if (can_pullup(udc))			pullup_enable (udc);		else			pullup_disable (udc);	}	/* boards that don't have VBUS sensing can't autogate 48MHz;	 * can't enter deep sleep while a gadget driver is active.	 */	if (machine_is_omap_innovator() || machine_is_omap_osk())		omap_vbus_session(&udc->gadget, 1);done:	return status;}EXPORT_SYMBOL(usb_gadget_register_driver);int usb_gadget_unregister_driver (struct usb_gadget_driver *driver){	unsigned long	flags;	int		status = -ENODEV;	if (!udc)		return -ENODEV;	if (!driver || driver != udc->driver)		return -EINVAL;	if (machine_is_omap_innovator() || machine_is_omap_osk())		omap_vbus_session(&udc->gadget, 0);	if (udc->transceiver)		(void) otg_set_peripheral(udc->transceiver, NULL);	else		pullup_disable(udc);	spin_lock_irqsave(&udc->lock, flags);	udc_quiesce(udc);	spin_unlock_irqrestore(&udc->lock, flags);	driver->unbind(&udc->gadget);	udc->gadget.dev.driver = NULL;	udc->driver = NULL;	DBG("unregistered driver '%s'\n", driver->driver.name);	return status;}EXPORT_SYMBOL(usb_gadget_unregister_driver);/*-------------------------------------------------------------------------*/#ifdef CONFIG_USB_GADGET_DEBUG_FILES#include <linux/seq_file.h>static const char proc_filename[] = "driver/udc";#define FOURBITS "%s%s%s%s"#define EIGHTBITS FOURBITS FOURBITSstatic void proc_ep_show(struct seq_file *s, struct omap_ep *ep){	u16		stat_flg;	struct omap_req	*req;	char		buf[20];	use_ep(ep, 0);	if (use_dma && ep->has_dma)		snprintf(buf, sizeof buf, "(%cxdma%d lch%d) ",			(ep->bEndpointAddress & USB_DIR_IN) ? 't' : 'r',			ep->dma_channel - 1, ep->lch);	else		buf[0] = 0;	stat_flg = UDC_STAT_FLG_REG;	seq_printf(s,		"\n%s %s%s%sirqs %ld stat %04x " EIGHTBITS FOURBITS "%s\n",		ep->name, buf,		ep->double_buf ? "dbuf " : "",		({char *s; switch(ep->ackwait){		case 0: s = ""; break;		case 1: s = "(ackw) "; break;		case 2: s = "(ackw2) "; break;		default: s = "(?) "; break;		} s;}),		ep->irqs, stat_flg,		(stat_flg & UDC_NO_RXPACKET) ? "no_rxpacket " : "",		(stat_flg & UDC_MISS_IN) ? "miss_in " : "",		(stat_flg & UDC_DATA_FLUSH) ? "data_flush " : "",		(stat_flg & UDC_ISO_ERR) ? "iso_err " : "",		(stat_flg & UDC_ISO_FIFO_EMPTY) ? "iso_fifo_empty " : "",		(stat_flg & UDC_ISO_FIFO_FULL) ? "iso_fifo_full " : "",		(stat_flg & UDC_EP_HALTED) ? "HALT " : "",		(stat_flg & UDC_STALL) ? "STALL " : "",		(stat_flg & UDC_NAK) ? "NAK " : "",		(stat_flg & UDC_ACK) ? "ACK " : "",		(stat_flg & UDC_FIFO_EN) ? "fifo_en " : "",		(stat_flg & UDC_NON_ISO_FIFO_EMPTY) ? "fifo_empty " : "",		(stat_flg & UDC_NON_ISO_FIFO_FULL) ? "fifo_full " : "");	if (list_empty (&ep->queue))		seq_printf(s, "\t(queue empty)\n");	else		list_for_each_entry (req, &ep->queue, queue) {			unsigned	length = req->req.actual;			if (use_dma && buf[0]) {				length += ((ep->bEndpointAddress & USB_DIR_IN)						? dma_src_len : dma_dest_len)					(ep, req->req.dma + length);				buf[0] = 0;			}			seq_printf(s, "\treq %p len %d/%d buf %p\n",					&req->req, length,					req->req.length, req->req.buf);		}}static char *trx_mode(unsigned m, int enabled){	switch (m) {	case 0:		return enabled ? "*6wire" : "unused";	case 1:		return "4wire";	case 2:		return "3wire";	case 3: 	return "6wire";	default:	return "unknown";	}}static int proc_otg_show(struct seq_file *s){	u32		tmp;	u32		trans;	tmp = OTG_REV_REG;	trans = USB_TRANSCEIVER_CTRL_REG;	seq_printf(s, "\nOTG rev %d.%d, transceiver_ctrl %05x\n",		tmp >> 4, tmp & 0xf, trans);	tmp = OTG_SYSCON_1_REG;	seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"			FOURBITS "\n", tmp,		trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R),		trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R),		(USB0_TRX_MODE(tmp) == 0 && !cpu_is_omap1710())			? "internal"			: trx_mode(USB0_TRX_MODE(tmp), 1),		(tmp & OTG_IDLE_EN) ? " !otg" : "",		(tmp & HST_IDLE_EN) ? " !host" : "",		(tmp & DEV_IDLE_EN) ? " !dev" : "",		(tmp & OTG_RESET_DONE) ? " reset_done" : " reset_active");	tmp = OTG_SYSCON_2_REG;	seq_printf(s, "otg_syscon2 %08x%s" EIGHTBITS			" b_ase_brst=%d hmc=%d\n", tmp,		(tmp & OTG_EN) ? " otg_en" : "",		(tmp & USBX_SYNCHRO) ? " synchro" : "",		// much more SRP stuff		(tmp & SRP_DATA) ? " srp_data" : "",		(tmp & SRP_VBUS) ? " srp_vbus" : "",		(tmp & OTG_PADEN) ? " otg_paden" : "",		(tmp & HMC_PADEN) ? " hmc_paden" : "",		(tmp & UHOST_EN) ? " uhost_en" : "",		(tmp & HMC_TLLSPEED) ? " tllspeed" : "",		(tmp & HMC_TLLATTACH) ? " tllattach" : "",		B_ASE_BRST(tmp),		OTG_HMC(tmp));	tmp = OTG_CTRL_REG;	seq_printf(s, "otg_ctrl    %06x" EIGHTBITS EIGHTBITS "%s\n", tmp,		(tmp & OTG_ASESSVLD) ? " asess" : "",		(tmp & OTG_BSESSEND) ? " bsess_end" : "",		(tmp & OTG_BSESSVLD) ? " bsess" : "",		(tmp & OTG_VBUSVLD) ? " vbus" : "",		(tmp & OTG_ID) ? " id" : "",		(tmp & OTG_DRIVER_SEL) ? " DEVICE" : " HOST",		(tmp & OTG_A_SETB_HNPEN) ? " a_setb_hnpen" : "",		(tmp & OTG_A_BUSREQ) ? " a_bus" : "",		(tmp & OTG_B_HNPEN) ? " b_hnpen" : "",		(tmp & OTG_B_BUSREQ) ? " b_bus" : "",		(tmp & OTG_BUSDROP) ? " busdrop" : "",		(tmp & OTG_PULLDOWN) ? " down" : "",		(tmp & OTG_PULLUP) ? " up" : "",		(tmp & OTG_DRV_VBUS) ? " drv" : "",		(tmp & OTG_PD_VBUS) ? " pd_vb" : "",		(tmp & OTG_PU_VBUS) ? " pu_vb" : "",		(tmp & OTG_PU_ID) ? " pu_id" : ""		);	tmp = OTG_IRQ_EN_REG;	seq_printf(s, "otg_irq_en  %04x" "\n", tmp);	tmp = OTG_IRQ_SRC_REG;	seq_printf(s, "otg_irq_src %04x" "\n", tmp);	tmp = OTG_OUTCTRL_REG;	seq_printf(s, "otg_outctrl %04x" "\n", tmp);	tmp = OTG_TEST_REG;	seq_printf(s, "otg_test    %04x" "\n", tmp);	return 0;}static int proc_udc_show(struct seq_file *s, void *_){	u32		tmp;	struct omap_ep	*ep;	unsigned long	flags;	spin_lock_irqsave(&udc->lock, flags);	seq_printf(s, "%s, version: " DRIVER_VERSION#ifdef	USE_ISO		" (iso)"#endif		"%s\n",		driver_desc,		use_dma ?  " (dma)" : "");	tmp = UDC_REV_REG & 0xff; 	seq_printf(s,		"UDC rev %d.%d, fifo mode %d, gadget %s\n"		"hmc %d, transceiver %s\n",		tmp >> 4, tmp & 0xf,		fifo_mode,		udc->driver ? udc->driver->driver.name : "(none)",		HMC,		udc->transceiver ? udc->transceiver->label : "(none)");	seq_printf(s, "ULPD control %04x req %04x status %04x\n",		__REG16(ULPD_CLOCK_CTRL),		__REG16(ULPD_SOFT_REQ),		__REG16(ULPD_STATUS_REQ));	/* OTG controller registers */	if (!cpu_is_omap15xx())		proc_otg_show(s);	tmp = UDC_SYSCON1_REG;	seq_printf(s, "\nsyscon1     %04x" EIGHTBITS "\n", tmp,		(tmp & UDC_CFG_LOCK) ? " cfg_lock" : "",		(tmp & UDC_DATA_ENDIAN) ? " data_endian" : "",		(tmp & UDC_DMA_ENDIAN) ? " dma_endian" : "",		(tmp & UDC_NAK_EN) ? " nak" : "",		(tmp & UDC_AUTODECODE_DIS) ? " autodecode_dis" : "",		(tmp & UDC_SELF_PWR) ? " self_pwr" : "",		(tmp & UDC_SOFF_DIS) ? " soff_dis" : "",		(tmp & UDC_PULLUP_EN) ? " PULLUP" : "");	// syscon2 is write-only	/* UDC controller registers */	if (!(tmp & UDC_PULLUP_EN)) {		seq_printf(s, "(suspended)\n");		spin_unlock_irqrestore(&udc->lock, flags);		return 0;	}	tmp = UDC_DEVSTAT_REG;	seq_printf(s, "devstat     %04x" EIGHTBITS "%s%s\n", tmp,		(tmp & UDC_B_HNP_ENABLE) ? " b_hnp" : "",		(tmp & UDC_A_HNP_SUPPORT) ? " a_hnp" : "",		(tmp & UDC_A_ALT_HNP_SUPPORT) ? " a_alt_hnp" : "",		(tmp & UDC_R_WK_OK) ? " r_wk_ok" : "",		(tmp & UDC_USB_RESET) ? " usb_reset" : "",		(tmp & UDC_SUS) ? " SUS" : "",		(tmp & UDC_CFG) ? " CFG" : "",		(tmp & UDC_ADD) ? " ADD" : "",		(tmp & UDC_DEF) ? " DEF" : "",		(tmp & UDC_ATT) ? " ATT" : "");	seq_printf(s, "sof         %04x\n", UDC_SOF_REG);	tmp = UDC_IRQ_EN_REG;	seq_printf(s, "irq_en      %04x" FOURBITS "%s\n", tmp,		(tmp & UDC_SOF_IE) ? " sof" : "",		(tmp & UDC_EPN_RX_IE) ? " epn_rx" : "",		(tmp & UDC_EPN_TX_IE) ? " epn_tx" : "",		(tmp & UDC_DS_CHG_IE) ? " ds_chg" : "",		(tmp & UDC_EP0_IE) ? " ep0" : "");	tmp = UDC_IRQ_SRC_REG;	seq_printf(s, "irq_src     %04x" EIGHTBITS "%s%s\n", tmp,		(tmp & UDC_TXN_DONE) ? " txn_done" : "",		(tmp & UDC_RXN_CNT) ? " rxn_cnt" : "",		(tmp & UDC_RXN_EOT) ? " rxn_eot" : "",		(tmp & UDC_SOF) ? " sof" : "",		(tmp & UDC_EPN_RX) ? " epn_rx" : "",		(tmp & UDC_EPN_TX) ? " epn_tx" : "",		(tmp & UDC_DS_CHG) ? " ds_chg" : "",		(tmp & UDC_SETUP) ? " setup" : "",		(tmp & UDC_EP0_RX) ? " ep0out" : "",		(tmp & UDC_EP0_TX) ? " ep0in" : "");	if (use_dma) {		unsigned i;		tmp = UDC_DMA_IRQ_EN_REG;		seq_printf(s, "dma_irq_en  %04x%s" EIGHTBITS "\n", tmp,			(tmp & UDC_TX_DONE_IE(3)) ? " tx2_done" : "",			(tmp & UDC_RX_CNT_IE(3)) ? " rx2_cnt" : "",			(tmp & UDC_RX_EOT_IE(3)) ? " rx2_eot" : "",			(tmp & UDC_TX_DONE_IE(2)) ? " tx1_done" : "",			(tmp & UDC_RX_CNT_IE(2)) ? " rx1_cnt" : "",			(tmp & UDC_RX_EOT_IE(2)) ? " rx1_eot" : "",			(tmp & UDC_TX_DONE_IE(1)) ? " tx0_done" : "",			(tmp & UDC_RX_CNT_IE(1)) ? " rx0_cnt" : "",			(tmp & UDC_RX_EOT_IE(1)) ? " rx0_eot" : "");		tmp = UDC_RXDMA_CFG_REG;		seq_printf(s, "rxdma_cfg   %04x\n", tmp);		if (tmp) {			for (i = 0; i < 3; i++) {				if ((tmp & (0x0f << (i * 4))) == 0)					continue;				seq_printf(s, "rxdma[%d]    %04x\n", i,						UDC_RXDMA_REG(i + 1));			}		}		tmp = UDC_TXDMA_CFG_REG;		seq_printf(s, "txdma_cfg   %04x\n", tmp);		if (tmp) {			for (i = 0; i < 3; i++) {				if (!(tmp & (0x0f << (i * 4))))					continue;				seq_printf(s, "txdma[%d]    %04x\n", i,						UDC_TXDMA_REG(i + 1));			}		}	}	tmp = UDC_DEVSTAT_REG;	if (tmp & UDC_ATT) {		proc_ep_show(s, &udc->ep[0]);		if (tmp & UDC_ADD) {			list_for_each_entry (ep, &udc->gadget.ep_list,					ep.ep_list) {				if (ep->desc)					proc_ep_show(s, ep);			}		}	}	spin_unlock_irqrestore(&udc->lock, flags);	return 0;}static int proc_udc_open(struct inode *inode, struct file *file){	return single_open(file, proc_udc_show, NULL);}static struct file_operations proc_ops = {	.open		= proc_udc_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= single_release,};static void create_proc_file(void){	struct proc_dir_entry *pde;	pde = create_proc_entry (proc_filename, 0, NULL);	if (pde)		pde->proc_fops = &proc_ops;}static void remove_proc_file(void){	remove_proc_entry(proc_filename, NULL);}#elsestatic inline void create_proc_file(void) {}static inline void remove_proc_file(void) {}#endif/*-------------------------------------------------------------------------*//* Before this controller can enumerate, we need to pick an endpoint * configuration, or "fifo_mode"  That involves allocating 2KB of packet * buffer space among the endpoints we'll be operating. * * NOTE: as of OMAP 1710 ES2.0, writing a new endpoint config when * UDC_SYSCON_1_REG.CFG_LOCK is set can now work.  We won't use that * capability yet though. */static unsigned __initomap_ep_setup(char *name, u8 addr, u8 type,		unsigned buf, unsigned maxp, int dbuf){	struct omap_ep	*ep;	u16		epn_rxtx = 0;	/* OUT endpoints first, then IN */	ep = &udc->ep[addr & 0xf];	if (addr & USB_DIR_IN)		ep += 16;	/* in case of ep init table bugs */	BUG_ON(ep->name[0]);	/* chip setup ... bit values are same for IN, OUT */	if (type == USB_ENDPOINT_XFER_ISOC) {		switch (maxp) {		case 8:		epn_rxtx = 0 << 12; break;		case 16:	epn_rxtx = 1 << 12; break;		case 32:	epn_rxtx = 2 << 12; break;		case 64:	epn_rxtx = 3 << 12; break;		case 128:	epn_rxtx = 4 << 12; break;		case 256:	epn_rxtx = 5 << 12; break;		case 512:	epn_rxtx = 6 << 12; break;		default:	BUG();		}		epn_rxtx |= UDC_EPN_RX_ISO;		dbuf = 1;	} else {		/* double-buffering "not supported" on 15xx,		 * and ignored for PIO-IN on 16xx		 */		if (!use_dma || cpu_is_omap15xx())			dbuf = 0;		switch (maxp) {		case 8:		epn_rxtx = 0 << 12; break;		case 16:	epn_rxtx = 1 << 12; break;		case 32:	epn_rxtx = 2 << 12; break;		case 64:	epn_rxtx = 3 << 12; break;		default:	BUG();		}		if (dbuf && addr)			e

⌨️ 快捷键说明

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