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

📄 s3c2410_udc.c

📁 S3C2410 USBD驱动程序 s3c2410_udc
💻 C
📖 第 1 页 / 共 2 页
字号:
		udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);	return 0;}static const struct usb_gadget_ops s3c2410_ops = {	.get_frame	    = s3c2410_g_get_frame,	.wakeup		    = s3c2410_wakeup,	.set_selfpowered    = s3c2410_set_selfpowered,};/*-------------------------------------------------------------------------*//* "function" sysfs attribute */static ssize_tshow_function (struct device *_dev, char *buf){	struct s3c2410_udc *udc = the_controller;	if (!udc->driver->function		|| strlen (udc->driver->function) > PAGE_SIZE)		return 0;	return snprintf (buf, PAGE_SIZE, "%s\n", udc->driver->function);}DEVICE_ATTR (function, S_IRUGO, show_function, NULL);/*-------------------------------------------------------------------------*//* * Driver registration/unregistration. * * This is basically hardware-specific; there's usually only one real USB * device (not host) controller since that's how USB devices are intended * to work.  So most implementations of these api calls will rely on the * fact that only one driver will ever bind to the hardware.  But curious * hardware can be built with discrete components, so the gadget API doesn't * require that assumption. */#if 0static voids3c2410_udc_release (struct device *dev){	struct s3c2410_udc *udc = gadget_dev_to_udc (dev);	complete (&udc->released);}static ints3c2410_register_udc (struct s3c2410_udc *udc){	int		rc;	strcpy (udc->gadget.dev.bus_id, "udc");	udc->gadget.dev.parent = &udc->pdev.dev;	udc->gadget.dev.release = s3c2410_udc_release;	rc = device_register (&udc->gadget.dev);	if (rc == 0)		device_create_file (&udc->gadget.dev, &dev_attr_function);	return rc;}static voids3c2410_unregister_udc (struct s3c2410_udc *udc){	device_remove_file (&udc->gadget.dev, &dev_attr_function);	init_completion (&udc->released);	device_unregister (&udc->gadget.dev);	wait_for_completion (&udc->released);}#endifintusb_gadget_register_driver (struct usb_gadget_driver *driver){	struct s3c2410_udc *udc = the_controller;	int		retval, i;	if (!udc)		return -EINVAL;	if (udc->driver)		return -EBUSY;	if (!driver->bind || !driver->unbind || !driver->setup			|| driver->speed == USB_SPEED_UNKNOWN)		return -EINVAL;	/*	 * SLAVE side init ... the layer above hardware, which	 * can't enumerate without help from the driver we're binding.	 */	udc->gadget.name = gadget_name;	udc->gadget.ops = &s3c2410_ops;	udc->gadget.is_dualspeed = 1;	udc->devstatus = 0;	INIT_LIST_HEAD (&udc->gadget.ep_list);	for (i = 0; i < S3C2410_ENDPOINTS; i++) {		struct s3c2410_ep *ep = &udc->ep [i];		if (!ep_name [i])			break;		ep->ep.name = ep_name [i];		ep->ep.ops = &s3c2410_ep_ops;		list_add_tail (&ep->ep.ep_list, &udc->gadget.ep_list);		ep->halted = ep->already_seen = ep->setup_stage = 0;		ep->ep.maxpacket = ~0;		ep->last_io = jiffies;		ep->gadget = &udc->gadget;		ep->desc = 0;		INIT_LIST_HEAD (&ep->queue);	}	udc->gadget.ep0 = &udc->ep[0].ep;	udc->ep[0].ep.maxpacket = 64;	list_del_init (&udc->ep[0].ep.ep_list);	INIT_LIST_HEAD(&udc->fifo_req.queue);	udc->driver = driver;	udc->gadget.dev.driver = &driver->driver;	dprintk( "binding gadget driver '%s'\n", driver->driver.name);	if ((retval = driver->bind (&udc->gadget)) != 0) {		udc->driver = 0;		udc->gadget.dev.driver = 0;		return retval;	}	// FIXME: Check these calls for errors and re-order//	driver->driver.bus = udc->pdev.dev.bus;	driver_register (&driver->driver);	device_bind_driver (&udc->gadget.dev);	/* khubd will enumerate this in a while */	udc->port_status |= USB_PORT_STAT_CONNECTION		| (1 << USB_PORT_FEAT_C_CONNECTION);	return 0;}EXPORT_SYMBOL (usb_gadget_register_driver);/* caller must hold lock */static voidstop_activity (struct s3c2410_udc *udc, struct usb_gadget_driver *driver){	struct s3c2410_ep *ep;	/* prevent any more requests */	udc->address = 0;	/* The timer is left running so that outstanding URBs can fail */	/* nuke any pending requests first, so driver i/o is quiesced */	list_for_each_entry (ep, &udc->gadget.ep_list, ep.ep_list)		nuke (udc, ep);	/* driver now does any non-usb quiescing necessary */	if (driver) {		spin_unlock (&udc->lock);		driver->disconnect (&udc->gadget);		spin_lock (&udc->lock);	}}intusb_gadget_unregister_driver (struct usb_gadget_driver *driver){	struct s3c2410_udc *udc = the_controller;	unsigned long	flags;	if (!udc)		return -ENODEV;	if (!driver || driver != udc->driver)		return -EINVAL;	dprintk( "unregister gadget driver '%s'\n",			driver->driver.name);	spin_lock_irqsave (&udc->lock, flags);	stop_activity (udc, driver);	udc->port_status &= ~USB_PORT_STAT_CONNECTION;	udc->port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);	spin_unlock_irqrestore (&udc->lock, flags);	driver->unbind (&udc->gadget);	udc->driver = 0;	device_release_driver (&udc->gadget.dev);	driver_unregister (&driver->driver);	return 0;}EXPORT_SYMBOL (usb_gadget_unregister_driver);#undef is_enabledint s3c2410_set_fifo_mode (struct usb_gadget *gadget, int mode){	return -ENOSYS;}EXPORT_SYMBOL (s3c2410_set_fifo_mode);/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------*/static void nop_release (struct device *dev){	dprintk("%s %s\n", __FUNCTION__, dev->bus_id);}#define EP0_FIFO_SIZE	16#define BULK_FIFO_SIZE	64/* 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 s3c2410_udc memory = {	.gadget = {		.ops		= &s3c2410_ops,		.ep0		= &memory.ep[0].ep,		.name		= gadget_name,		.dev = {			.bus_id		= "gadget",			.release	= nop_release,		},	},	/* control endpoint */	.ep[0] = {		.ep = {			.name		= ep0name,			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP0_FIFO_SIZE,		},		.dev		= &memory,//		.reg_udccs	= &UDCCS0,//		.reg_uddr	= &UDDR0,	},	/* group of endpoints */	.ep[1] = {		.ep = {			.name		= "ep1-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = 1,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,//		.reg_udccs	= &UDCCS1,//		.reg_uddr	= &UDDR1,//		drcmr (25)	},	.ep[2] = {		.ep = {			.name		= "ep2-bulk",			.ops		= &s3c2410_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)	},	.ep[3] = {		.ep = {			.name		= "ep3-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= BULK_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= BULK_FIFO_SIZE,		.bEndpointAddress = 3,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,//		.reg_udccs	= &UDCCS3,//		.reg_uddr	= &UDDR3,//		drcmr (27)	},};/* *	s3c2410_udc_irq - interrupt handler * * avoid delays in ep0 processing. the control handshaking isn't always * under software control, and delays could cause usb protocol errors. */static irqreturn_ts3c2410_udc_irq(int irq, void *_dev, struct pt_regs *r){	struct s3c2410_udc	*dev = _dev;	static int sb_debug_cnt = 1;		int handled;	dprintk("s3c2410_udc_irq\n");	do {		int saveIdx = __raw_readl(S3C2410_UDC_INDEX_REG);		int usb_status = __raw_readl(S3C2410_UDC_USB_INT_REG);		int usbd_status = __raw_readl(S3C2410_UDC_EP_INT_REG);			handled = 0;			dprintk("usb_status = 0x%02x, usbd_status = 0x%02x\n",				usb_status, usbd_status);						/* ReSeT Interrupt Request - USB reset */		if (usb_status & S3C2410_UDC_USBINT_RESET) {			dprintk("USB reset\n");						/* clear interrupt */			__raw_writel(S3C2410_UDC_USBINT_RESET,				S3C2410_UDC_USB_INT_REG);			dev->gadget.speed = USB_SPEED_FULL;			// memset(&dev->stats, 0, sizeof dev->stats);			/* driver and endpoints are still reset */			// enable_disconnect_irq();			handled = 1;		}		/* RESume Interrupt Request */		if (usb_status & S3C2410_UDC_USBINT_RESUME) {			dprintk("USB resume\n");						/* clear interrupt */			__raw_writel(S3C2410_UDC_USBINT_RESUME,				S3C2410_UDC_USB_INT_REG);			if (dev->gadget.speed != USB_SPEED_UNKNOWN				&& dev->driver				&& dev->driver->resume				/* && is_usb_connected() */)				dev->driver->resume(&dev->gadget);			handled = 1;		}		/* SUSpend Interrupt Request */		if (usb_status & S3C2410_UDC_USBINT_SUSPEND) {					dprintk("USB suspend\n");			/* clear interrupt */			__raw_writel(S3C2410_UDC_USBINT_SUSPEND,				S3C2410_UDC_USB_INT_REG);							// if (!is_usb_connected())				stop_activity(dev, dev->driver);			/* else */ if (dev->gadget.speed != USB_SPEED_UNKNOWN					&& dev->driver					&& dev->driver->suspend)				dev->driver->suspend(&dev->gadget);			// ep0_idle (dev);			handled = 1;		}		// UD_INDEX= saveIdx; /* restore idx */	} while (handled);	return IRQ_HANDLED;}/* *	probe - binds to the platform device */static int __init s3c2410_udc_probe(struct device *_dev){	struct s3c2410_udc *udc = &memory;	int retval, out_dma = 0;	dprintk("s3c2410_udc_probe\n");	/* other non-static parts of init *///	udc->dev = _dev;//	udc->mach = _dev->platform_data;/*	init_timer(&dev->timer);	dev->timer.function = udc_watchdog;	dev->timer.data = (unsigned long) dev;*/	device_initialize(&udc->gadget.dev);	udc->gadget.dev.parent = _dev;	udc->gadget.dev.dma_mask = _dev->dma_mask;	the_controller = udc;	dev_set_drvdata(_dev, udc);	// udc_disable(udc);	// udc_reinit(udc);	/* irq setup after old hardware state is cleaned up */	retval = request_irq(IRQ_USBD, s3c2410_udc_irq,		SA_INTERRUPT, gadget_name, udc);	if (retval != 0) {		printk(KERN_ERR "%s: can't get irq %i, err %d\n",			gadget_name, IRQ_USBD, retval);		return -EBUSY;	}	dprintk("%s: got irq %i\n", gadget_name, IRQ_USBD);	udc->got_irq = 1;//	create_proc_files();	return 0;}static int __exit s3c2410_udc_remove(struct device *_dev){	struct s3c2410_udc *udc = _dev->driver_data;	dprintk("s3c2410_udc_remove\n");	udc_disable(udc);//	remove_proc_files();	usb_gadget_unregister_driver(udc->driver);	if (udc->got_irq) {		free_irq(IRQ_USBD, udc);		udc->got_irq = 0;	}	dev_set_drvdata(_dev, 0);	the_controller = 0;	return 0;}/*-------------------------------------------------------------------------*/static struct device_driver udc_driver = {	.name		= "s3c2410-udc",	.bus		= &platform_bus_type,	.probe		= s3c2410_udc_probe,	.remove		= __exit_p(s3c2410_udc_remove),	// FIXME power management support	// .suspend = ... disable UDC	// .resume = ... re-enable UDC};static int __init udc_init(void){	int tmp;		dprintk("%s: version %s\n", gadget_name, DRIVER_VERSION);		tmp = __raw_readl(S3C2410_CLKCON);	tmp &= ~S3C2410_CLKCON_USBD;	__raw_writel(tmp, S3C2410_CLKCON);	tmp = __raw_readl(S3C2410_MISCCR);	tmp &= ~S3C2410_MISCCR_USBHOST;	__raw_writel(tmp, S3C2410_MISCCR);		/* UPLLCON */	tmp = (0x78 << S3C2410_PLLCON_MDIVSHIFT)		| (0x02 << S3C2410_PLLCON_PDIVSHIFT)		| (0x03 << S3C2410_PLLCON_SDIVSHIFT);	__raw_writel(tmp, S3C2410_UPLLCON);		tmp = __raw_readl(S3C2410_CLKCON);	tmp |= S3C2410_CLKCON_USBD;	__raw_writel(tmp, S3C2410_CLKCON);#ifdef MACH_TOMTOMGO	s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_OUTP);	s3c2410_gpio_setpin(S3C2410_GPE13, 1);	dev_info (&dev->dev, "TomTomGo USB device pullup enabled.\n");#endif	mdelay(10);		return driver_register(&udc_driver);}module_init(udc_init);static void __exit udc_exit(void){	driver_unregister(&udc_driver);}module_exit(udc_exit);MODULE_DESCRIPTION (DRIVER_DESC);MODULE_AUTHOR ("Herbert P鰐zl");MODULE_LICENSE ("GPL");

⌨️ 快捷键说明

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