plat_uds.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 2,070 行 · 第 1/4 页

C
2,070
字号
		musb_writew(mbase, MGC_O_HDRC_RXFIFOADD, c_off);		hw_ep->rx_double_buffered = !!(c_size & MGC_M_FIFOSZ_DPB);		hw_ep->wMaxPacketSizeRx = maxpacket;		break;	case FIFO_RXTX:		musb_writeb(mbase, MGC_O_HDRC_TXFIFOSZ, c_size);		musb_writew(mbase, MGC_O_HDRC_TXFIFOADD, c_off);		hw_ep->rx_double_buffered = !!(c_size & MGC_M_FIFOSZ_DPB);		hw_ep->wMaxPacketSizeRx = maxpacket;		musb_writeb(mbase, MGC_O_HDRC_RXFIFOSZ, c_size);		musb_writew(mbase, MGC_O_HDRC_RXFIFOADD, c_off);		hw_ep->tx_double_buffered = hw_ep->rx_double_buffered;		hw_ep->wMaxPacketSizeTx = maxpacket;		hw_ep->bIsSharedFifo = TRUE;		break;	}	/* NOTE rx and tx endpoint irqs aren't managed separately,	 * which happens to be ok	 */	musb->wEndMask |= (1 << hw_ep->bLocalEnd);	return offset + (maxpacket << ((c_size & MGC_M_FIFOSZ_DPB) ? 1 : 0));}static struct fifo_cfg __initdata ep0_cfg = {	.style = FIFO_RXTX, .maxpacket = 64,};static int __init ep_config_from_table(struct musb *musb){	const struct fifo_cfg	*cfg;	unsigned		i, n;	int			offset;	struct musb_hw_ep	*hw_ep = musb->aLocalEnd;	switch (fifo_mode) {	default:		fifo_mode = 0;		/* FALLTHROUGH */	case 0:		cfg = mode_0_cfg;		n = ARRAY_SIZE(mode_0_cfg);		break;	case 1:		cfg = mode_1_cfg;		n = ARRAY_SIZE(mode_1_cfg);		break;	case 2:		cfg = mode_2_cfg;		n = ARRAY_SIZE(mode_2_cfg);		break;	case 3:		cfg = mode_3_cfg;		n = ARRAY_SIZE(mode_3_cfg);		break;	case 4:		cfg = mode_4_cfg;		n = ARRAY_SIZE(mode_4_cfg);		break;	}	printk(KERN_DEBUG "%s: setup fifo_mode %d\n",			musb_driver_name, fifo_mode);	offset = fifo_setup(musb, hw_ep, &ep0_cfg, 0);	// assert(offset > 0)	/* NOTE:  for RTL versions >= 1.400 EPINFO and RAMINFO would	 * be better than static MUSB_C_NUM_EPS and DYN_FIFO_SIZE...	 */	for (i = 0; i < n; i++) {		u8	epn = cfg->hw_ep_num;		if (epn >= MUSB_C_NUM_EPS) {			pr_debug( "%s: invalid ep %d\n",					musb_driver_name, epn);			continue;		}		offset = fifo_setup(musb, hw_ep + epn, cfg++, offset);		if (offset < 0) {			pr_debug( "%s: mem overrun, ep %d\n",					musb_driver_name, epn);			return -EINVAL;		}		epn++;		musb->bEndCount = max(epn, musb->bEndCount);	}	printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n",			musb_driver_name,			n + 1, MUSB_C_NUM_EPS * 2 - 1,			offset, DYN_FIFO_SIZE);	if (!musb->bulk_ep) {		pr_debug( "%s: missing bulk\n", musb_driver_name);		return -EINVAL;	}	return 0;}/* * ep_config_from_hw - when MUSB_C_DYNFIFO_DEF is false * @param pThis the controller */static int __init ep_config_from_hw(struct musb *musb){	u8 bEnd = 0, reg;	struct musb_hw_ep *pEnd;	void *pBase = musb->pRegs;	DBG(2, "<== static silicon ep config\n");	/* FIXME pick up ep0 maxpacket size */	for (bEnd = 1; bEnd < MUSB_C_NUM_EPS; bEnd++) {		MGC_SelectEnd(pBase, bEnd);		pEnd = musb->aLocalEnd + bEnd;		/* read from core using indexed model */		reg = musb_readb(pEnd->regs, 0x10 + MGC_O_HDRC_FIFOSIZE);		if (!reg) {			/* 0's returned when no more endpoints */			break;		}		musb->bEndCount++;		musb->wEndMask |= (1 << bEnd);		pEnd->wMaxPacketSizeTx = 1 << (reg & 0x0f);		/* shared TX/RX FIFO? */		if ((reg & 0xf0) == 0xf0) {			pEnd->wMaxPacketSizeRx = pEnd->wMaxPacketSizeTx;			pEnd->bIsSharedFifo = TRUE;			continue;		} else {			pEnd->wMaxPacketSizeRx = 1 << ((reg & 0xf0) >> 4);			pEnd->bIsSharedFifo = FALSE;		}		/* FIXME set up pEnd->{rx,tx}_double_buffered */		/* pick an RX/TX endpoint for bulk */		if (pEnd->wMaxPacketSizeTx < 512				|| pEnd->wMaxPacketSizeRx < 512)			continue;		/* REVISIT:  this algorithm is lazy, we should at least		 * try to pick a double buffered endpoint.		 */		if (musb->bulk_ep)			continue;		musb->bulk_ep = pEnd;	}	if (!musb->bulk_ep) {		pr_debug( "%s: missing bulk\n", musb_driver_name);		return -EINVAL;	}	return 0;}enum { MUSB_CONTROLLER_MHDRC, MUSB_CONTROLLER_HDRC, };/* Initialize MUSB (M)HDRC part of the USB hardware subsystem; * configure endpoints, or take their config from silicon */static int __init musb_core_init(u16 wType, struct musb *pThis){	u8 reg;	char *type;	u16 wRelease, wRelMajor, wRelMinor;	char aInfo[100], aRevision[32], aDate[12];	void __iomem	*pBase = pThis->pRegs;	int		status = 0;	int		i;	/* log core options (read using indexed model) */	//MGC_SelectEnd(pBase, 0);	musb_writeb(pBase, MGC_O_HDRC_INDEX, 0);	reg = musb_readb(pBase, 0x10 + MGC_O_HDRC_CONFIGDATA);	strcpy(aInfo, (reg & MGC_M_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8");	if (reg & MGC_M_CONFIGDATA_DYNFIFO) {		strcat(aInfo, ", dyn FIFOs");	}	if (reg & MGC_M_CONFIGDATA_MPRXE) {		strcat(aInfo, ", bulk combine");		strcat(aInfo, " (X)");		/* no driver support */	}	if (reg & MGC_M_CONFIGDATA_MPTXE) {		strcat(aInfo, ", bulk split");		strcat(aInfo, " (X)");		/* no driver support */	}	if (reg & MGC_M_CONFIGDATA_HBRXE) {		strcat(aInfo, ", HB-ISO Rx");		strcat(aInfo, " (X)");		/* no driver support */	}	if (reg & MGC_M_CONFIGDATA_HBTXE) {		strcat(aInfo, ", HB-ISO Tx");		strcat(aInfo, " (X)");		/* no driver support */	}	if (reg & MGC_M_CONFIGDATA_SOFTCONE) {		strcat(aInfo, ", SoftConn");	}	printk(KERN_DEBUG "%s: ConfigData=0x%02x (%s)\n",			musb_driver_name, reg, aInfo);	aDate[0] = 0;	if (MUSB_CONTROLLER_MHDRC == wType) {		pThis->bIsMultipoint = 1;		type = "M";	} else {		pThis->bIsMultipoint = 0;		type = "";		printk(KERN_ERR			"%s: kernel must blacklist external hubs\n",			musb_driver_name);	}	/* log release info */	wRelease = musb_readw(pBase, MGC_O_HDRC_HWVERS);	wRelMajor = (wRelease >> 10) & 0x1f;	wRelMinor = wRelease & 0x3ff;	snprintf(aRevision, 32, "%d.%d%s", wRelMajor,		wRelMinor, (wRelease & 0x8000) ? "RC" : "");	printk(KERN_DEBUG "%s: %sHDRC RTL version %s %s\n",			musb_driver_name, type, aRevision, aDate);	/* configure ep0 */	pThis->aLocalEnd[0].wMaxPacketSizeTx = MGC_END0_FIFOSIZE;	pThis->aLocalEnd[0].wMaxPacketSizeRx = MGC_END0_FIFOSIZE;	/* discover endpoint configuration */	pThis->bEndCount = 1;	pThis->wEndMask = 1;	if (reg & MGC_M_CONFIGDATA_DYNFIFO) {		if (can_dynfifo())			status = ep_config_from_table(pThis);		else {			ERR("reconfigure software for Dynamic FIFOs\n");			status = -ENODEV;		}	} else {		if (!can_dynfifo())			status = ep_config_from_hw(pThis);		else {			ERR("reconfigure software for static FIFOs\n");			return -ENODEV;		}	}	if (status < 0)		return status;	/* finish init, and print endpoint config */	for (i = 0; i < pThis->bEndCount; i++) {		struct musb_hw_ep	*hw_ep = pThis->aLocalEnd + i;		hw_ep->fifo = MUSB_FIFO_OFFSET(i) + pBase;		hw_ep->regs = MGC_END_OFFSET(i, 0) + pBase;		hw_ep->target_regs = MGC_BUSCTL_OFFSET(i, 0) + pBase;		hw_ep->rx_reinit = 1;		hw_ep->tx_reinit = 1;		if (hw_ep->wMaxPacketSizeTx) {			printk(KERN_DEBUG				"%s: hw_ep %d%s, %smax %d\n",				musb_driver_name, i,				hw_ep->bIsSharedFifo ? "shared" : "tx",				hw_ep->tx_double_buffered					? "doublebuffer, " : "",				hw_ep->wMaxPacketSizeTx);		}		if (hw_ep->wMaxPacketSizeRx && !hw_ep->bIsSharedFifo) {			printk(KERN_DEBUG				"%s: hw_ep %d%s, %smax %d\n",				musb_driver_name, i,				"rx",				hw_ep->rx_double_buffered					? "doublebuffer, " : "",				hw_ep->wMaxPacketSizeRx);		}		if (!(hw_ep->wMaxPacketSizeTx || hw_ep->wMaxPacketSizeRx))			DBG(1, "hw_ep %d not configured\n", i);	}	return 0;}/*-------------------------------------------------------------------------*/static irqreturn_t generic_interrupt(int irq, void *__hci){	unsigned long	flags;	irqreturn_t	retval = IRQ_NONE;	struct musb	*musb = __hci;	spin_lock_irqsave(&musb->Lock, flags);	musb->int_usb = musb_readb(musb->pRegs, MGC_O_HDRC_INTRUSB);	musb->int_tx = musb_readw(musb->pRegs, MGC_O_HDRC_INTRTX);	musb->int_rx = musb_readw(musb->pRegs, MGC_O_HDRC_INTRRX);	if (musb->int_usb || musb->int_tx || musb->int_rx)		retval = musb_interrupt(musb);	spin_unlock_irqrestore(&musb->Lock, flags);	/* REVISIT we sometimes get spurious IRQs on g_ep0	 * not clear why...	 */	if (retval != IRQ_HANDLED)		DBG(5, "spurious?\n");	return IRQ_HANDLED;}/* * handle all the irqs defined by the HDRC core. for now we expect:  other * irq sources (phy, dma, etc) will be handled first, musb->int_* values * will be assigned, and the irq will already have been acked. * * called in irq context with spinlock held, irqs blocked */irqreturn_t musb_interrupt(struct musb *musb){	irqreturn_t	retval = IRQ_NONE;	u8		devctl, power;	int		ep_num;	u32		reg;	devctl = musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL);	power = musb_readb(musb->pRegs, MGC_O_HDRC_POWER);	DBG(4, "** IRQ %s usb%04x tx%04x rx%04x\n",		(devctl & MGC_M_DEVCTL_HM) ? "host" : "peripheral",		musb->int_usb, musb->int_tx, musb->int_rx);	/* the core can interrupt us for multiple reasons; docs have	 * a generic interrupt flowchart to follow	 */	if (musb->int_usb & STAGE0_MASK)		retval |= musb_stage0_irq(musb, musb->int_usb,				devctl, power);	/* "stage 1" is handling endpoint irqs */	/* handle endpoint 0 first */	if (musb->int_tx & 1) {		if (devctl & MGC_M_DEVCTL_HM)			retval |= musb_h_ep0_irq(musb);		else			retval |= musb_g_ep0_irq(musb);	}	/* RX on endpoints 1-15 */	reg = musb->int_rx >> 1;	ep_num = 1;	while (reg) {		if (reg & 1) {			// MGC_SelectEnd(musb->pRegs, ep_num);			/* REVISIT just retval = ep->rx_irq(...) */			retval = IRQ_HANDLED;			if (devctl & MGC_M_DEVCTL_HM) {				if (is_host_capable())					musb_host_rx(musb, ep_num);			} else {				if (is_peripheral_capable())					musb_g_rx(musb, ep_num);			}		}		reg >>= 1;		ep_num++;	}	/* TX on endpoints 1-15 */	reg = musb->int_tx >> 1;	ep_num = 1;	while (reg) {		if (reg & 1) {			// MGC_SelectEnd(musb->pRegs, ep_num);			/* REVISIT just retval |= ep->tx_irq(...) */			retval = IRQ_HANDLED;			if (devctl & MGC_M_DEVCTL_HM) {				if (is_host_capable())					musb_host_tx(musb, ep_num);			} else {				if (is_peripheral_capable())					musb_g_tx(musb, ep_num);			}		}		reg >>= 1;		ep_num++;	}	/* finish handling "global" interrupts after handling fifos */	if (musb->int_usb)		retval |= musb_stage2_irq(musb,				musb->int_usb, devctl, power);	return retval;}#define use_dma			0/*-------------------------------------------------------------------------*/static ssize_tmusb_mode_show(struct device *dev, struct device_attribute *attr, char *buf){	struct musb *musb = dev_to_musb(dev);	unsigned long flags;	int ret = -EINVAL;	spin_lock_irqsave(&musb->Lock, flags);	ret = sprintf(buf, "%s\n", otg_state_string(musb));	spin_unlock_irqrestore(&musb->Lock, flags);	return ret;}static ssize_tmusb_mode_store(struct device *dev, struct device_attribute *attr,		const char *buf, size_t n){	struct musb	*musb = dev_to_musb(dev);	unsigned long	flags;	spin_lock_irqsave(&musb->Lock, flags);	if (!strncmp(buf, "host", 4))		musb_platform_set_mode(musb, MUSB_HOST);	if (!strncmp(buf, "peripheral", 10))		musb_platform_set_mode(musb, MUSB_PERIPHERAL);	if (!strncmp(buf, "otg", 3))		musb_platform_set_mode(musb, MUSB_OTG);	spin_unlock_irqrestore(&musb->Lock, flags);	return n;}static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store);static ssize_tmusb_cable_show(struct device *dev, struct device_attribute *attr, char *buf){	struct musb *musb = dev_to_musb(dev);	char *v1= "", *v2 = "?";	unsigned long flags;	int vbus;	spin_lock_irqsave(&musb->Lock, flags);	/* NOTE: board-specific issues, like too-big capacitors keeping	 * VBUS high for a long time after power has been removed, can	 * cause temporary false indications of a connection.	 */	vbus = musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL);	if (vbus & 0x10) {		/* REVISIT retest on real OTG hardware */		switch (musb->board_mode) {		case MUSB_HOST:			v2 = "A";			break;		case MUSB_PERIPHERAL:			v2 = "B";			break;		case MUSB_OTG:			v1 = "Mini-";			v2 = (vbus & MGC_M_DEVCTL_BDEVICE) ? "B" : "A";			break;		}	} else	/* VBUS level below A-Valid */		v2 = "disconnected";	musb_platform_try_idle(musb, 0);	spin_unlock_irqrestore(&musb->Lock, flags);	return sprintf(buf, "%s%s\n", v1, v2);}static DEVICE_ATTR(cable, S_IRUGO, musb_cable_show, NULL);static ssize_tmusb_vbus_store(struct device *dev, struct device_attribute *attr,		const char *buf, size_t n){	struct musb	*musb = dev_to_musb(dev);	unsigned long	flags;	unsigned long	val;	spin_lock_irqsave(&musb->Lock, flags);	if (sscanf(buf, "%lu", &val) < 1) {		printk(KERN_ERR "Invalid VBUS timeout ms value\n");		return -EINVAL;	}	musb->a_wait_bcon = val;	if (musb->xceiv.state == OTG_STATE_A_WAIT_BCON)		musb->is_active = 0;	musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val));	spin_unlock_irqrestore(&musb->Lock, flags);	return n;}static ssize_tmusb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)

⌨️ 快捷键说明

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