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

📄 s3c2410_udc.c

📁 linux下面gadget设备驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
static const struct usb_gadget_ops s3c2410_ops = {	.get_frame		= s3c2410_udc_get_frame,	.wakeup			= s3c2410_udc_wakeup,	.set_selfpowered	= s3c2410_udc_set_selfpowered,	.pullup			= s3c2410_udc_pullup,	.vbus_session		= s3c2410_udc_vbus_session,	.vbus_draw		= s3c2410_vbus_draw,};/*------------------------- gadget driver handling---------------------------*//* * s3c2410_udc_disable */static void s3c2410_udc_disable(struct s3c2410_udc *dev){	dprintk(DEBUG_NORMAL, "%s()\n", __func__);	/* Disable all interrupts */	udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG);	udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG);	/* Clear the interrupt registers */	udc_write(S3C2410_UDC_USBINT_RESET				| S3C2410_UDC_USBINT_RESUME				| S3C2410_UDC_USBINT_SUSPEND,			S3C2410_UDC_USB_INT_REG);	udc_write(0x1F, S3C2410_UDC_EP_INT_REG);	/* Good bye, cruel world */	if (udc_info && udc_info->udc_command)		udc_info->udc_command(S3C2410_UDC_P_DISABLE);	/* Set speed to unknown */	dev->gadget.speed = USB_SPEED_UNKNOWN;}/* * s3c2410_udc_reinit */static void s3c2410_udc_reinit(struct s3c2410_udc *dev){	u32 i;	/* device/ep0 records init */	INIT_LIST_HEAD (&dev->gadget.ep_list);	INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);	dev->ep0state = EP0_IDLE;	for (i = 0; i < S3C2410_ENDPOINTS; i++) {		struct s3c2410_ep *ep = &dev->ep[i];		if (i != 0)			list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list);		ep->dev = dev;		ep->desc = NULL;		ep->halted = 0;		INIT_LIST_HEAD (&ep->queue);	}}/* * s3c2410_udc_enable */static void s3c2410_udc_enable(struct s3c2410_udc *dev){	int i;	dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n");	/* dev->gadget.speed = USB_SPEED_UNKNOWN; */	dev->gadget.speed = USB_SPEED_FULL;	/* Set MAXP for all endpoints */	for (i = 0; i < S3C2410_ENDPOINTS; i++) {		udc_write(i, S3C2410_UDC_INDEX_REG);		udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3,				S3C2410_UDC_MAXP_REG);	}	/* Set default power state */	udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG);	/* Enable reset and suspend interrupt interrupts */	udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND,			S3C2410_UDC_USB_INT_EN_REG);	/* Enable ep0 interrupt */	udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);	/* time to say "hello, world" */	if (udc_info && udc_info->udc_command)		udc_info->udc_command(S3C2410_UDC_P_ENABLE);}/* *	usb_gadget_register_driver */int usb_gadget_register_driver(struct usb_gadget_driver *driver){	struct s3c2410_udc *udc = the_controller;	int		retval;	dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n",		driver->driver.name);	/* Sanity checks */	if (!udc)		return -ENODEV;	if (udc->driver)		return -EBUSY;	if (!driver->bind || !driver->setup			|| driver->speed != USB_SPEED_FULL) {		printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",			driver->bind, driver->setup, driver->speed);		return -EINVAL;	}#if defined(MODULE)	if (!driver->unbind) {		printk(KERN_ERR "Invalid driver: no unbind method\n");		return -EINVAL;	}#endif	/* Hook the driver */	udc->driver = driver;	udc->gadget.dev.driver = &driver->driver;	/* Bind the driver */	if ((retval = device_add(&udc->gadget.dev)) != 0) {		printk(KERN_ERR "Error in device_add() : %d\n",retval);		goto register_error;	}	dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n",		driver->driver.name);	if ((retval = driver->bind (&udc->gadget)) != 0) {		device_del(&udc->gadget.dev);		goto register_error;	}	/* Enable udc */	s3c2410_udc_enable(udc);	return 0;register_error:	udc->driver = NULL;	udc->gadget.dev.driver = NULL;	return retval;}/* *	usb_gadget_unregister_driver */int usb_gadget_unregister_driver(struct usb_gadget_driver *driver){	struct s3c2410_udc *udc = the_controller;	if (!udc)		return -ENODEV;	if (!driver || driver != udc->driver || !driver->unbind)		return -EINVAL;	dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",		driver->driver.name);	if (driver->disconnect)		driver->disconnect(&udc->gadget);	device_del(&udc->gadget.dev);	udc->driver = NULL;	/* Disable udc */	s3c2410_udc_disable(udc);	return 0;}/*---------------------------------------------------------------------------*/static struct s3c2410_udc memory = {	.gadget = {		.ops		= &s3c2410_ops,		.ep0		= &memory.ep[0].ep,		.name		= gadget_name,		.dev = {			.bus_id		= "gadget",		},	},	/* control endpoint */	.ep[0] = {		.num		= 0,		.ep = {			.name		= ep0name,			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP0_FIFO_SIZE,		},		.dev		= &memory,	},	/* first group of endpoints */	.ep[1] = {		.num		= 1,		.ep = {			.name		= "ep1-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 1,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	},	.ep[2] = {		.num		= 2,		.ep = {			.name		= "ep2-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 2,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	},	.ep[3] = {		.num		= 3,		.ep = {			.name		= "ep3-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 3,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	},	.ep[4] = {		.num		= 4,		.ep = {			.name		= "ep4-bulk",			.ops		= &s3c2410_ep_ops,			.maxpacket	= EP_FIFO_SIZE,		},		.dev		= &memory,		.fifo_size	= EP_FIFO_SIZE,		.bEndpointAddress = 4,		.bmAttributes	= USB_ENDPOINT_XFER_BULK,	}};/* *	probe - binds to the platform device */static int s3c2410_udc_probe(struct platform_device *pdev){	struct s3c2410_udc *udc = &memory;	struct device *dev = &pdev->dev;	int retval;	unsigned int irq;	dev_dbg(dev, "%s()\n", __func__);	usb_bus_clock = clk_get(NULL, "usb-bus-gadget");	if (IS_ERR(usb_bus_clock)) {		dev_err(dev, "failed to get usb bus clock source\n");		return PTR_ERR(usb_bus_clock);	}	clk_enable(usb_bus_clock);	udc_clock = clk_get(NULL, "usb-device");	if (IS_ERR(udc_clock)) {		dev_err(dev, "failed to get udc clock source\n");		return PTR_ERR(udc_clock);	}	clk_enable(udc_clock);	mdelay(10);	dev_dbg(dev, "got and enabled clocks\n");	if (strncmp(pdev->name, "s3c2440", 7) == 0) {		dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n");		memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE;		memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE;		memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE;		memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE;	}	spin_lock_init (&udc->lock);	udc_info = pdev->dev.platform_data;	rsrc_start = S3C2410_PA_USBDEV;	rsrc_len   = S3C24XX_SZ_USBDEV;	if (!request_mem_region(rsrc_start, rsrc_len, gadget_name))		return -EBUSY;	base_addr = ioremap(rsrc_start, rsrc_len);	if (!base_addr) {		retval = -ENOMEM;		goto err_mem;	}	device_initialize(&udc->gadget.dev);	udc->gadget.dev.parent = &pdev->dev;	udc->gadget.dev.dma_mask = pdev->dev.dma_mask;	the_controller = udc;	platform_set_drvdata(pdev, udc);	s3c2410_udc_disable(udc);	s3c2410_udc_reinit(udc);	/* irq setup after old hardware state is cleaned up */	retval = request_irq(IRQ_USBD, s3c2410_udc_irq,			IRQF_DISABLED, gadget_name, udc);	if (retval != 0) {		dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval);		retval = -EBUSY;		goto err_map;	}	dev_dbg(dev, "got irq %i\n", IRQ_USBD);	if (udc_info && udc_info->vbus_pin > 0) {		irq = s3c2410_gpio_getirq(udc_info->vbus_pin);		retval = request_irq(irq, s3c2410_udc_vbus_irq,				     IRQF_DISABLED | IRQF_TRIGGER_RISING				     | IRQF_TRIGGER_FALLING | IRQF_SHARED,				     gadget_name, udc);		if (retval != 0) {			dev_err(dev, "can't get vbus irq %i, err %d\n",				irq, retval);			retval = -EBUSY;			goto err_int;		}		dev_dbg(dev, "got irq %i\n", irq);	} else {		udc->vbus = 1;	}	if (s3c2410_udc_debugfs_root) {		udc->regs_info = debugfs_create_file("registers", S_IRUGO,				s3c2410_udc_debugfs_root,				udc, &s3c2410_udc_debugfs_fops);		if (IS_ERR(udc->regs_info)) {			dev_warn(dev, "debugfs file creation failed %ld\n",				 PTR_ERR(udc->regs_info));			udc->regs_info = NULL;		}	}	dev_dbg(dev, "probe ok\n");	return 0;err_int:	free_irq(IRQ_USBD, udc);err_map:	iounmap(base_addr);err_mem:	release_mem_region(rsrc_start, rsrc_len);	return retval;}/* *	s3c2410_udc_remove */static int s3c2410_udc_remove(struct platform_device *pdev){	struct s3c2410_udc *udc = platform_get_drvdata(pdev);	unsigned int irq;	dev_dbg(&pdev->dev, "%s()\n", __func__);	if (udc->driver)		return -EBUSY;	debugfs_remove(udc->regs_info);	if (udc_info && udc_info->vbus_pin > 0) {		irq = s3c2410_gpio_getirq(udc_info->vbus_pin);		free_irq(irq, udc);	}	free_irq(IRQ_USBD, udc);	iounmap(base_addr);	release_mem_region(rsrc_start, rsrc_len);	platform_set_drvdata(pdev, NULL);	if (!IS_ERR(udc_clock) && udc_clock != NULL) {		clk_disable(udc_clock);		clk_put(udc_clock);		udc_clock = NULL;	}	if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {		clk_disable(usb_bus_clock);		clk_put(usb_bus_clock);		usb_bus_clock = NULL;	}	dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);	return 0;}#ifdef CONFIG_PMstatic int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message){	if (udc_info && udc_info->udc_command)		udc_info->udc_command(S3C2410_UDC_P_DISABLE);	return 0;}static int s3c2410_udc_resume(struct platform_device *pdev){	if (udc_info && udc_info->udc_command)		udc_info->udc_command(S3C2410_UDC_P_ENABLE);	return 0;}#else#define s3c2410_udc_suspend	NULL#define s3c2410_udc_resume	NULL#endifstatic struct platform_driver udc_driver_2410 = {	.driver		= {		.name	= "s3c2410-usbgadget",		.owner	= THIS_MODULE,	},	.probe		= s3c2410_udc_probe,	.remove		= s3c2410_udc_remove,	.suspend	= s3c2410_udc_suspend,	.resume		= s3c2410_udc_resume,};static struct platform_driver udc_driver_2440 = {	.driver		= {		.name	= "s3c2440-usbgadget",		.owner	= THIS_MODULE,	},	.probe		= s3c2410_udc_probe,	.remove		= s3c2410_udc_remove,	.suspend	= s3c2410_udc_suspend,	.resume		= s3c2410_udc_resume,};static int __init udc_init(void){	int retval;	dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);	s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);	if (IS_ERR(s3c2410_udc_debugfs_root)) {		printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",			gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));		s3c2410_udc_debugfs_root = NULL;	}	retval = platform_driver_register(&udc_driver_2410);	if (retval)		goto err;	retval = platform_driver_register(&udc_driver_2440);	if (retval)		goto err;	return 0;err:	debugfs_remove(s3c2410_udc_debugfs_root);	return retval;}static void __exit udc_exit(void){	platform_driver_unregister(&udc_driver_2410);	platform_driver_unregister(&udc_driver_2440);	debugfs_remove(s3c2410_udc_debugfs_root);}EXPORT_SYMBOL(usb_gadget_unregister_driver);EXPORT_SYMBOL(usb_gadget_register_driver);module_init(udc_init);module_exit(udc_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_VERSION(DRIVER_VERSION);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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