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

📄 pxa2xx_udc.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
				dev->driver->resume(&dev->gadget);		}		/* ReSeT Interrupt Request - USB reset */		if (unlikely(udccr & UDCCR_RSTIR)) {			udc_ack_int_UDCCR(UDCCR_RSTIR);			handled = 1;			if ((UDCCR & UDCCR_UDA) == 0) {				DBG(DBG_VERBOSE, "USB reset start\n");				/* reset driver and endpoints,				 * in case that's not yet done				 */				stop_activity (dev, dev->driver);			} else {				DBG(DBG_VERBOSE, "USB reset end\n");				dev->gadget.speed = USB_SPEED_FULL;				LED_CONNECTED_ON;				memset(&dev->stats, 0, sizeof dev->stats);				/* driver and endpoints are still reset */			}		} else {			u32	usir0 = USIR0 & ~UICR0;			u32	usir1 = USIR1 & ~UICR1;			int	i;			if (unlikely (!usir0 && !usir1))				continue;			DBG(DBG_VERY_NOISY, "irq %02x.%02x\n", usir1, usir0);			/* control traffic */			if (usir0 & USIR0_IR0) {				dev->ep[0].pio_irqs++;				handle_ep0(dev);				handled = 1;			}			/* endpoint data transfers */			for (i = 0; i < 8; i++) {				u32	tmp = 1 << i;				if (i && (usir0 & tmp)) {					handle_ep(&dev->ep[i]);					USIR0 |= tmp;					handled = 1;				}				if (usir1 & tmp) {					handle_ep(&dev->ep[i+8]);					USIR1 |= tmp;					handled = 1;				}			}		}		/* we could also ask for 1 msec SOF (SIR) interrupts */	} while (handled);	return IRQ_HANDLED;}/*-------------------------------------------------------------------------*/static void nop_release (struct device *dev){	DMSG("%s %s\n", __FUNCTION__, dev->bus_id);}/* this uses load-time allocation and initialization (instead of * doing it at run-time) to save code, eliminate fault paths, and * be more obviously correct. */static struct pxa2xx_udc memory = {	.gadget = {		.ops		= &pxa2xx_udc_ops,		.ep0		= &memory.ep[0].ep,		.name		= driver_name,		.dev = {			.bus_id		= "gadget",			.release	= nop_release,		},	},	/* control endpoint */	.ep[0] = {		.ep = {			.name		= ep0name,			.ops		= &pxa2xx_ep_ops,			.maxpacket	= EP0_FIFO_SIZE,		},		.dev		= &memory,		.reg_udccs	= &UDCCS0,		.reg_uddr	= &UDDR0,	},	/* first group of endpoints */	.ep[1] = {		.ep = {			.name		= "ep1in-bulk",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 1,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,		.reg_udccs	= &UDCCS1,		.reg_uddr	= &UDDR1,		drcmr (25)	},	.ep[2] = {		.ep = {			.name		= "ep2out-bulk",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = 2,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,		.reg_udccs	= &UDCCS2,		.reg_ubcr	= &UBCR2,		.reg_uddr	= &UDDR2,		drcmr (26)	},#ifndef CONFIG_USB_PXA2XX_SMALL	.ep[3] = {		.ep = {			.name		= "ep3in-iso",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= ISO_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= ISO_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 3,		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,		.reg_udccs	= &UDCCS3,		.reg_uddr	= &UDDR3,		drcmr (27)	},	.ep[4] = {		.ep = {			.name		= "ep4out-iso",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= ISO_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= ISO_FIFO_SIZE,		.bEndpointAddress = 4,		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,		.reg_udccs	= &UDCCS4,		.reg_ubcr	= &UBCR4,		.reg_uddr	= &UDDR4,		drcmr (28)	},	.ep[5] = {		.ep = {			.name		= "ep5in-int",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= INT_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= INT_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 5,		.bmAttributes	= USB_ENDPOINT_XFER_INT,		.reg_udccs	= &UDCCS5,		.reg_uddr	= &UDDR5,	},	/* second group of endpoints */	.ep[6] = {		.ep = {			.name		= "ep6in-bulk",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 6,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,		.reg_udccs	= &UDCCS6,		.reg_uddr	= &UDDR6,		drcmr (30)	},	.ep[7] = {		.ep = {			.name		= "ep7out-bulk",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = 7,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,		.reg_udccs	= &UDCCS7,		.reg_ubcr	= &UBCR7,		.reg_uddr	= &UDDR7,		drcmr (31)	},	.ep[8] = {		.ep = {			.name		= "ep8in-iso",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= ISO_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= ISO_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 8,		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,		.reg_udccs	= &UDCCS8,		.reg_uddr	= &UDDR8,		drcmr (32)	},	.ep[9] = {		.ep = {			.name		= "ep9out-iso",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= ISO_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= ISO_FIFO_SIZE,		.bEndpointAddress = 9,		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,		.reg_udccs	= &UDCCS9,		.reg_ubcr	= &UBCR9,		.reg_uddr	= &UDDR9,		drcmr (33)	},	.ep[10] = {		.ep = {			.name		= "ep10in-int",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= INT_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= INT_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 10,		.bmAttributes	= USB_ENDPOINT_XFER_INT,		.reg_udccs	= &UDCCS10,		.reg_uddr	= &UDDR10,	},	/* third group of endpoints */	.ep[11] = {		.ep = {			.name		= "ep11in-bulk",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 11,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,		.reg_udccs	= &UDCCS11,		.reg_uddr	= &UDDR11,		drcmr (35)	},	.ep[12] = {		.ep = {			.name		= "ep12out-bulk",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = 12,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,		.reg_udccs	= &UDCCS12,		.reg_ubcr	= &UBCR12,		.reg_uddr	= &UDDR12,		drcmr (36)	},	.ep[13] = {		.ep = {			.name		= "ep13in-iso",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= ISO_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= ISO_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 13,		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,		.reg_udccs	= &UDCCS13,		.reg_uddr	= &UDDR13,		drcmr (37)	},	.ep[14] = {		.ep = {			.name		= "ep14out-iso",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= ISO_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= ISO_FIFO_SIZE,		.bEndpointAddress = 14,		.bmAttributes	= USB_ENDPOINT_XFER_ISOC,		.reg_udccs	= &UDCCS14,		.reg_ubcr	= &UBCR14,		.reg_uddr	= &UDDR14,		drcmr (38)	},	.ep[15] = {		.ep = {			.name		= "ep15in-int",			.ops		= &pxa2xx_ep_ops,			.maxpacket	= INT_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= INT_FIFO_SIZE,		.bEndpointAddress = USB_DIR_IN | 15,		.bmAttributes	= USB_ENDPOINT_XFER_INT,		.reg_udccs	= &UDCCS15,		.reg_uddr	= &UDDR15,	},#endif /* !CONFIG_USB_PXA2XX_SMALL */};#define CP15R0_VENDOR_MASK	0xffffe000#if	defined(CONFIG_ARCH_PXA)#define CP15R0_XSCALE_VALUE	0x69052000	/* intel/arm/xscale */#elif	defined(CONFIG_ARCH_IXP4XX)#define CP15R0_XSCALE_VALUE	0x69054000	/* intel/arm/ixp4xx */#endif#define CP15R0_PROD_MASK	0x000003f0#define PXA25x			0x00000100	/* and PXA26x */#define PXA210			0x00000120#define CP15R0_REV_MASK		0x0000000f#define CP15R0_PRODREV_MASK	(CP15R0_PROD_MASK | CP15R0_REV_MASK)#define PXA255_A0		0x00000106	/* or PXA260_B1 */#define PXA250_C0		0x00000105	/* or PXA26x_B0 */#define PXA250_B2		0x00000104#define PXA250_B1		0x00000103	/* or PXA260_A0 */#define PXA250_B0		0x00000102#define PXA250_A1		0x00000101#define PXA250_A0		0x00000100#define PXA210_C0		0x00000125#define PXA210_B2		0x00000124#define PXA210_B1		0x00000123#define PXA210_B0		0x00000122#define IXP425_A0		0x000001c1/* * 	probe - binds to the platform device */static int __init pxa2xx_udc_probe(struct device *_dev){	struct pxa2xx_udc *dev = &memory;	int retval, out_dma = 1;	u32 chiprev;	/* insist on Intel/ARM/XScale */	asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));	if ((chiprev & CP15R0_VENDOR_MASK) != CP15R0_XSCALE_VALUE) {		printk(KERN_ERR "%s: not XScale!\n", driver_name);		return -ENODEV;	}	/* trigger chiprev-specific logic */	switch (chiprev & CP15R0_PRODREV_MASK) {#if	defined(CONFIG_ARCH_PXA)	case PXA255_A0:		dev->has_cfr = 1;		break;	case PXA250_A0:	case PXA250_A1:		/* A0/A1 "not released"; ep 13, 15 unusable */		/* fall through */	case PXA250_B2: case PXA210_B2:	case PXA250_B1: case PXA210_B1:	case PXA250_B0: case PXA210_B0:		out_dma = 0;		/* fall through */	case PXA250_C0: case PXA210_C0:		break;#elif	defined(CONFIG_ARCH_IXP4XX)	case IXP425_A0:		out_dma = 0;		break;#endif	default:		out_dma = 0;		printk(KERN_ERR "%s: unrecognized processor: %08x\n",			driver_name, chiprev);		/* iop3xx, ixp4xx, ... */		return -ENODEV;	}	pr_debug("%s: IRQ %d%s%s%s\n", driver_name, IRQ_USB,		dev->has_cfr ? "" : " (!cfr)",		out_dma ? "" : " (broken dma-out)",		SIZE_STR DMASTR		);#ifdef	USE_DMA#ifndef	USE_OUT_DMA	out_dma = 0;#endif	/* pxa 250 erratum 130 prevents using OUT dma (fixed C0) */	if (!out_dma) {		DMSG("disabled OUT dma\n");		dev->ep[ 2].reg_drcmr = dev->ep[ 4].reg_drcmr = 0;		dev->ep[ 7].reg_drcmr = dev->ep[ 9].reg_drcmr = 0;		dev->ep[12].reg_drcmr = dev->ep[14].reg_drcmr = 0;	}#endif	/* other non-static parts of init */	dev->dev = _dev;	dev->mach = _dev->platform_data;	init_timer(&dev->timer);	dev->timer.function = udc_watchdog;	dev->timer.data = (unsigned long) dev;	device_initialize(&dev->gadget.dev);	dev->gadget.dev.parent = _dev;	dev->gadget.dev.dma_mask = _dev->dma_mask;	the_controller = dev;	dev_set_drvdata(_dev, dev);	udc_disable(dev);	udc_reinit(dev);	dev->vbus = is_vbus_present();	/* irq setup after old hardware state is cleaned up */	retval = request_irq(IRQ_USB, pxa2xx_udc_irq,			SA_INTERRUPT, driver_name, dev);	if (retval != 0) {		printk(KERN_ERR "%s: can't get irq %i, err %d\n",			driver_name, IRQ_USB, retval);		return -EBUSY;	}	dev->got_irq = 1;#ifdef CONFIG_ARCH_LUBBOCK	if (machine_is_lubbock()) {		retval = request_irq(LUBBOCK_USB_DISC_IRQ,				lubbock_vbus_irq,				SA_INTERRUPT | SA_SAMPLE_RANDOM,				driver_name, dev);		if (retval != 0) {			printk(KERN_ERR "%s: can't get irq %i, err %d\n",				driver_name, LUBBOCK_USB_DISC_IRQ, retval);lubbock_fail0:			free_irq(IRQ_USB, dev);			return -EBUSY;		}		retval = request_irq(LUBBOCK_USB_IRQ,				lubbock_vbus_irq,				SA_INTERRUPT | SA_SAMPLE_RANDOM,				driver_name, dev);		if (retval != 0) {			printk(KERN_ERR "%s: can't get irq %i, err %d\n",				driver_name, LUBBOCK_USB_IRQ, retval);			free_irq(LUBBOCK_USB_DISC_IRQ, dev);			goto lubbock_fail0;		}#ifdef DEBUG		/* with U-Boot (but not BLOB), hex is off by default */		HEX_DISPLAY(dev->stats.irqs);		LUB_DISC_BLNK_LED &= 0xff;#endif	}#endif	create_proc_files();	return 0;}static void pxa2xx_udc_shutdown(struct device *_dev){	pullup_off();}static int __exit pxa2xx_udc_remove(struct device *_dev){	struct pxa2xx_udc *dev = dev_get_drvdata(_dev);	udc_disable(dev);	remove_proc_files();	usb_gadget_unregister_driver(dev->driver);	if (dev->got_irq) {		free_irq(IRQ_USB, dev);		dev->got_irq = 0;	}	if (machine_is_lubbock()) {		free_irq(LUBBOCK_USB_DISC_IRQ, dev);		free_irq(LUBBOCK_USB_IRQ, dev);	}	dev_set_drvdata(_dev, NULL);	the_controller = NULL;	return 0;}/*-------------------------------------------------------------------------*/#ifdef	CONFIG_PM/* USB suspend (controlled by the host) and system suspend (controlled * by the PXA) don't necessarily work well together.  If USB is active, * the 48 MHz clock is required; so the system can't enter 33 MHz idle * mode, or any deeper PM saving state. * * For now, we punt and forcibly disconnect from the USB host when PXA * enters any suspend 

⌨️ 快捷键说明

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