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

📄 fsl_usb2_udc.c

📁 linux下面gadget设备驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
			(tmp_reg & USB_FRINDEX_MASKS));	size -= t;	next += t;	tmp_reg = fsl_readl(&dr_regs->deviceaddr);	t = scnprintf(next, size,			"USB Device Address Reg:" "Device Addr is 0x%x\n\n",			(tmp_reg & USB_DEVICE_ADDRESS_MASK));	size -= t;	next += t;	tmp_reg = fsl_readl(&dr_regs->endpointlistaddr);	t = scnprintf(next, size,			"USB Endpoint List Address Reg:"			"Device Addr is 0x%x\n\n",			(tmp_reg & USB_EP_LIST_ADDRESS_MASK));	size -= t;	next += t;	tmp_reg = fsl_readl(&dr_regs->portsc1);	t = scnprintf(next, size,		"USB Port Status&Control Reg:\n"		"Port Transceiver Type : %s" "Port Speed: %s \n"		"PHY Low Power Suspend: %s" "Port Reset: %s"		"Port Suspend Mode: %s \n" "Over-current Change: %s"		"Port Enable/Disable Change: %s\n"		"Port Enabled/Disabled: %s"		"Current Connect Status: %s\n\n", ( {			char *s;			switch (tmp_reg & PORTSCX_PTS_FSLS) {			case PORTSCX_PTS_UTMI:				s = "UTMI"; break;			case PORTSCX_PTS_ULPI:				s = "ULPI "; break;			case PORTSCX_PTS_FSLS:				s = "FS/LS Serial"; break;			default:				s = "None"; break;			}			s;} ), ( {			char *s;			switch (tmp_reg & PORTSCX_PORT_SPEED_UNDEF) {			case PORTSCX_PORT_SPEED_FULL:				s = "Full Speed"; break;			case PORTSCX_PORT_SPEED_LOW:				s = "Low Speed"; break;			case PORTSCX_PORT_SPEED_HIGH:				s = "High Speed"; break;			default:				s = "Undefined"; break;			}			s;		} ),		(tmp_reg & PORTSCX_PHY_LOW_POWER_SPD) ?		"Normal PHY mode" : "Low power mode",		(tmp_reg & PORTSCX_PORT_RESET) ? "In Reset" :		"Not in Reset",		(tmp_reg & PORTSCX_PORT_SUSPEND) ? "In " : "Not in",		(tmp_reg & PORTSCX_OVER_CURRENT_CHG) ? "Dected" :		"No",		(tmp_reg & PORTSCX_PORT_EN_DIS_CHANGE) ? "Disable" :		"Not change",		(tmp_reg & PORTSCX_PORT_ENABLE) ? "Enable" :		"Not correct",		(tmp_reg & PORTSCX_CURRENT_CONNECT_STATUS) ?		"Attached" : "Not-Att");	size -= t;	next += t;	tmp_reg = fsl_readl(&dr_regs->usbmode);	t = scnprintf(next, size,			"USB Mode Reg:" "Controller Mode is : %s\n\n", ( {				char *s;				switch (tmp_reg & USB_MODE_CTRL_MODE_HOST) {				case USB_MODE_CTRL_MODE_IDLE:					s = "Idle"; break;				case USB_MODE_CTRL_MODE_DEVICE:					s = "Device Controller"; break;				case USB_MODE_CTRL_MODE_HOST:					s = "Host Controller"; break;				default:					s = "None"; break;				}				s;			} ));	size -= t;	next += t;	tmp_reg = fsl_readl(&dr_regs->endptsetupstat);	t = scnprintf(next, size,			"Endpoint Setup Status Reg:" "SETUP on ep 0x%x\n\n",			(tmp_reg & EP_SETUP_STATUS_MASK));	size -= t;	next += t;	for (i = 0; i < udc->max_ep / 2; i++) {		tmp_reg = fsl_readl(&dr_regs->endptctrl[i]);		t = scnprintf(next, size, "EP Ctrl Reg [0x%x]: = [0x%x]\n",				i, tmp_reg);		size -= t;		next += t;	}	tmp_reg = fsl_readl(&dr_regs->endpointprime);	t = scnprintf(next, size, "EP Prime Reg = [0x%x]\n", tmp_reg);	size -= t;	next += t;	tmp_reg = usb_sys_regs->snoop1;	t = scnprintf(next, size, "\nSnoop1 Reg : = [0x%x]\n\n", tmp_reg);	size -= t;	next += t;	tmp_reg = usb_sys_regs->control;	t = scnprintf(next, size, "General Control Reg : = [0x%x]\n\n",			tmp_reg);	size -= t;	next += t;	/* ------fsl_udc, fsl_ep, fsl_request structure information ----- */	ep = &udc->eps[0];	t = scnprintf(next, size, "For %s Maxpkt is 0x%x index is 0x%x\n",			ep->ep.name, ep_maxpacket(ep), ep_index(ep));	size -= t;	next += t;	if (list_empty(&ep->queue)) {		t = scnprintf(next, size, "its req queue is empty\n\n");		size -= t;		next += t;	} else {		list_for_each_entry(req, &ep->queue, queue) {			t = scnprintf(next, size,				"req %p actual 0x%x length 0x%x  buf %p\n",				&req->req, req->req.actual,				req->req.length, req->req.buf);			size -= t;			next += t;		}	}	/* other gadget->eplist ep */	list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) {		if (ep->desc) {			t = scnprintf(next, size,					"\nFor %s Maxpkt is 0x%x "					"index is 0x%x\n",					ep->ep.name, ep_maxpacket(ep),					ep_index(ep));			size -= t;			next += t;			if (list_empty(&ep->queue)) {				t = scnprintf(next, size,						"its req queue is empty\n\n");				size -= t;				next += t;			} else {				list_for_each_entry(req, &ep->queue, queue) {					t = scnprintf(next, size,						"req %p actual 0x%x length"						"0x%x  buf %p\n",						&req->req, req->req.actual,						req->req.length, req->req.buf);					size -= t;					next += t;					}	/* end for each_entry of ep req */				}	/* end for else */			}	/* end for if(ep->queue) */		}		/* end (ep->desc) */	spin_unlock_irqrestore(&udc->lock, flags);	*eof = 1;	return count - size;}#define create_proc_file()	create_proc_read_entry(proc_filename, \				0, NULL, fsl_proc_read, NULL)#define remove_proc_file()	remove_proc_entry(proc_filename, NULL)#else				/* !CONFIG_USB_GADGET_DEBUG_FILES */#define create_proc_file()	do {} while (0)#define remove_proc_file()	do {} while (0)#endif				/* CONFIG_USB_GADGET_DEBUG_FILES *//*-------------------------------------------------------------------------*//* Release udc structures */static void fsl_udc_release(struct device *dev){	complete(udc_controller->done);	dma_free_coherent(dev, udc_controller->ep_qh_size,			udc_controller->ep_qh, udc_controller->ep_qh_dma);	kfree(udc_controller);}/******************************************************************	Internal structure setup functions*******************************************************************//*------------------------------------------------------------------ * init resource for globle controller * Return the udc handle on success or NULL on failure ------------------------------------------------------------------*/static int __init struct_udc_setup(struct fsl_udc *udc,		struct platform_device *pdev){	struct fsl_usb2_platform_data *pdata;	size_t size;	pdata = pdev->dev.platform_data;	udc->phy_mode = pdata->phy_mode;	udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);	if (!udc->eps) {		ERR("malloc fsl_ep failed\n");		return -1;	}	/* initialized QHs, take care of alignment */	size = udc->max_ep * sizeof(struct ep_queue_head);	if (size < QH_ALIGNMENT)		size = QH_ALIGNMENT;	else if ((size % QH_ALIGNMENT) != 0) {		size += QH_ALIGNMENT + 1;		size &= ~(QH_ALIGNMENT - 1);	}	udc->ep_qh = dma_alloc_coherent(&pdev->dev, size,					&udc->ep_qh_dma, GFP_KERNEL);	if (!udc->ep_qh) {		ERR("malloc QHs for udc failed\n");		kfree(udc->eps);		return -1;	}	udc->ep_qh_size = size;	/* Initialize ep0 status request structure */	/* FIXME: fsl_alloc_request() ignores ep argument */	udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),			struct fsl_req, req);	/* allocate a small amount of memory to get valid address */	udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);	udc->status_req->req.dma = virt_to_phys(udc->status_req->req.buf);	udc->resume_state = USB_STATE_NOTATTACHED;	udc->usb_state = USB_STATE_POWERED;	udc->ep0_dir = 0;	udc->remote_wakeup = 0;	/* default to 0 on reset */	spin_lock_init(&udc->lock);	return 0;}/*---------------------------------------------------------------- * Setup the fsl_ep struct for eps * Link fsl_ep->ep to gadget->ep_list * ep0out is not used so do nothing here * ep0in should be taken care *--------------------------------------------------------------*/static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,		char *name, int link){	struct fsl_ep *ep = &udc->eps[index];	ep->udc = udc;	strcpy(ep->name, name);	ep->ep.name = ep->name;	ep->ep.ops = &fsl_ep_ops;	ep->stopped = 0;	/* for ep0: maxP defined in desc	 * for other eps, maxP is set by epautoconfig() called by gadget layer	 */	ep->ep.maxpacket = (unsigned short) ~0;	/* the queue lists any req for this ep */	INIT_LIST_HEAD(&ep->queue);	/* gagdet.ep_list used for ep_autoconfig so no ep0 */	if (link)		list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);	ep->gadget = &udc->gadget;	ep->qh = &udc->ep_qh[index];	return 0;}/* Driver probe function * all intialization operations implemented here except enabling usb_intr reg * board setup should have been done in the platform code */static int __init fsl_udc_probe(struct platform_device *pdev){	struct resource *res;	int ret = -ENODEV;	unsigned int i;	u32 dccparams;	if (strcmp(pdev->name, driver_name)) {		VDBG("Wrong device\n");		return -ENODEV;	}	udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);	if (udc_controller == NULL) {		ERR("malloc udc failed\n");		return -ENOMEM;	}	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (!res) {		kfree(udc_controller);		return -ENXIO;	}	if (!request_mem_region(res->start, res->end - res->start + 1,				driver_name)) {		ERR("request mem region for %s failed \n", pdev->name);		kfree(udc_controller);		return -EBUSY;	}	dr_regs = ioremap(res->start, res->end - res->start + 1);	if (!dr_regs) {		ret = -ENOMEM;		goto err1;	}	usb_sys_regs = (struct usb_sys_interface *)			((u32)dr_regs + USB_DR_SYS_OFFSET);	/* Read Device Controller Capability Parameters register */	dccparams = fsl_readl(&dr_regs->dccparams);	if (!(dccparams & DCCPARAMS_DC)) {		ERR("This SOC doesn't support device role\n");		ret = -ENODEV;		goto err2;	}	/* Get max device endpoints */	/* DEN is bidirectional ep number, max_ep doubles the number */	udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2;	udc_controller->irq = platform_get_irq(pdev, 0);	if (!udc_controller->irq) {		ret = -ENODEV;		goto err2;	}	ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,			driver_name, udc_controller);	if (ret != 0) {		ERR("cannot request irq %d err %d \n",				udc_controller->irq, ret);		goto err2;	}	/* Initialize the udc structure including QH member and other member */	if (struct_udc_setup(udc_controller, pdev)) {		ERR("Can't initialize udc data structure\n");		ret = -ENOMEM;		goto err3;	}	/* initialize usb hw reg except for regs for EP,	 * leave usbintr reg untouched */	dr_controller_setup(udc_controller);	/* Setup gadget structure */	udc_controller->gadget.ops = &fsl_gadget_ops;	udc_controller->gadget.is_dualspeed = 1;	udc_controller->gadget.ep0 = &udc_controller->eps[0].ep;	INIT_LIST_HEAD(&udc_controller->gadget.ep_list);	udc_controller->gadget.speed = USB_SPEED_UNKNOWN;	udc_controller->gadget.name = driver_name;	/* Setup gadget.dev and register with kernel */	strcpy(udc_controller->gadget.dev.bus_id, "gadget");	udc_controller->gadget.dev.release = fsl_udc_release;	udc_controller->gadget.dev.parent = &pdev->dev;	ret = device_register(&udc_controller->gadget.dev);	if (ret < 0)		goto err3;	/* setup QH and epctrl for ep0 */	ep0_setup(udc_controller);	/* setup udc->eps[] for ep0 */	struct_ep_setup(udc_controller, 0, "ep0", 0);	/* for ep0: the desc defined here;	 * for other eps, gadget layer called ep_enable with defined desc	 */	udc_controller->eps[0].desc = &fsl_ep0_desc;	udc_controller->eps[0].ep.maxpacket = USB_MAX_CTRL_PAYLOAD;	/* setup the udc->eps[] for non-control endpoints and link	 * to gadget.ep_list */	for (i = 1; i < (int)(udc_controller->max_ep / 2); i++) {		char name[14];		sprintf(name, "ep%dout", i);		struct_ep_setup(udc_controller, i * 2, name, 1);		sprintf(name, "ep%din", i);		struct_ep_setup(udc_controller, i * 2 + 1, name, 1);	}	/* use dma_pool for TD management */	udc_controller->td_pool = dma_pool_create("udc_td", &pdev->dev,			sizeof(struct ep_td_struct),			DTD_ALIGNMENT, UDC_DMA_BOUNDARY);	if (udc_controller->td_pool == NULL) {		ret = -ENOMEM;		goto err4;	}	create_proc_file();	return 0;err4:	device_unregister(&udc_controller->gadget.dev);err3:	free_irq(udc_controller->irq, udc_controller);err2:	iounmap(dr_regs);err1:	release_mem_region(res->start, res->end - res->start + 1);	kfree(udc_controller);	return ret;}/* Driver removal function * Free resources and finish pending transactions */static int __exit fsl_udc_remove(struct platform_device *pdev){	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	DECLARE_COMPLETION(done);	if (!udc_controller)		return -ENODEV;	udc_controller->done = &done;	/* DR has been stopped in usb_gadget_unregister_driver() */	remove_proc_file();	/* Free allocated memory */	kfree(udc_controller->status_req->req.buf);	kfree(udc_controller->status_req);	kfree(udc_controller->eps);	dma_pool_destroy(udc_controller->td_pool);	free_irq(udc_controller->irq, udc_controller);	iounmap(dr_regs);	release_mem_region(res->start, res->end - res->start + 1);	device_unregister(&udc_controller->gadget.dev);	/* free udc --wait for the release() finished */	wait_for_completion(&done);	return 0;}/*----------------------------------------------------------------- * Modify Power management attributes * Used by OTG statemachine to disable gadget temporarily -----------------------------------------------------------------*/static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state){	dr_controller_stop(udc_controller);	return 0;}/*----------------------------------------------------------------- * Invoked on USB resume. May be called in_interrupt. * Here we start the DR controller and enable the irq *-----------------------------------------------------------------*/static int fsl_udc_resume(struct platform_device *pdev){	/* Enable DR irq reg and set controller Run */	if (udc_controller->stopped) {		dr_controller_setup(udc_controller);		dr_controller_run(udc_controller);	}	udc_controller->usb_state = USB_STATE_ATTACHED;	udc_controller->ep0_state = WAIT_FOR_SETUP;	udc_controller->e

⌨️ 快捷键说明

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