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

📄 sl811-hcd.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	spin_lock_irq(&sl811->lock);	if (sl811->ctrl1 & SL11H_CTL1MASK_SUSPEND)		seq_printf(s, "(suspended)\n\n");	else {		u8	t = sl811_read(sl811, SL11H_CTLREG1);		seq_printf(s, "ctrl1 %02x%s%s%s%s\n", t,			(t & SL11H_CTL1MASK_SOF_ENA) ? " sofgen" : "",			({char *s; switch (t & SL11H_CTL1MASK_FORCE) {			case SL11H_CTL1MASK_NORMAL: s = ""; break;			case SL11H_CTL1MASK_SE0: s = " se0/reset"; break;			case SL11H_CTL1MASK_K: s = " k/resume"; break;			default: s = "j"; break;			}; s; }),			(t & SL11H_CTL1MASK_LSPD) ? " lowspeed" : "",			(t & SL11H_CTL1MASK_SUSPEND) ? " suspend" : "");		dump_irq(s, "irq_enable",				sl811_read(sl811, SL11H_IRQ_ENABLE));		dump_irq(s, "irq_status",				sl811_read(sl811, SL11H_IRQ_STATUS));		seq_printf(s, "frame clocks remaining:  %d\n",				sl811_read(sl811, SL11H_SOFTMRREG) << 6);	}	seq_printf(s, "A: qh%p ctl %02x sts %02x\n", sl811->active_a,		sl811_read(sl811, SL811_EP_A(SL11H_HOSTCTLREG)),		sl811_read(sl811, SL811_EP_A(SL11H_PKTSTATREG)));	seq_printf(s, "B: qh%p ctl %02x sts %02x\n", sl811->active_b,		sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG)),		sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG)));	seq_printf(s, "\n");	list_for_each_entry (ep, &sl811->async, schedule) {		struct urb		*urb;		seq_printf(s, "%s%sqh%p, ep%d%s, maxpacket %d"					" nak %d err %d\n",			(ep == sl811->active_a) ? "(A) " : "",			(ep == sl811->active_b) ? "(B) " : "",			ep, ep->epnum,			({ char *s; switch (ep->nextpid) {			case USB_PID_IN: s = "in"; break;			case USB_PID_OUT: s = "out"; break;			case USB_PID_SETUP: s = "setup"; break;			case USB_PID_ACK: s = "status"; break;			default: s = "?"; break;			}; s;}),			ep->maxpacket,			ep->nak_count, ep->error_count);		list_for_each_entry (urb, &ep->hep->urb_list, urb_list) {			seq_printf(s, "  urb%p, %d/%d\n", urb,				urb->actual_length,				urb->transfer_buffer_length);		}	}	if (!list_empty(&sl811->async))		seq_printf(s, "\n");	seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE);	for (i = 0; i < PERIODIC_SIZE; i++) {		ep = sl811->periodic[i];		if (!ep)			continue;		seq_printf(s, "%2d [%3d]:\n", i, sl811->load[i]);		/* DUMB: prints shared entries multiple times */		do {			seq_printf(s,				"   %s%sqh%d/%p (%sdev%d ep%d%s max %d) "					"err %d\n",				(ep == sl811->active_a) ? "(A) " : "",				(ep == sl811->active_b) ? "(B) " : "",				ep->period, ep,				(ep->udev->speed == USB_SPEED_FULL)					? "" : "ls ",				ep->udev->devnum, ep->epnum,				(ep->epnum == 0) ? ""					: ((ep->nextpid == USB_PID_IN)						? "in"						: "out"),				ep->maxpacket, ep->error_count);			ep = ep->next;		} while (ep);	}	spin_unlock_irq(&sl811->lock);	seq_printf(s, "\n");	return 0;}static int proc_sl811h_open(struct inode *inode, struct file *file){	return single_open(file, proc_sl811h_show, PDE(inode)->data);}static struct file_operations proc_ops = {	.open		= proc_sl811h_open,	.read		= seq_read,	.llseek		= seq_lseek,	.release	= single_release,};/* expect just one sl811 per system */static const char proc_filename[] = "driver/sl811h";static void create_debug_file(struct sl811 *sl811){	struct proc_dir_entry *pde;	pde = create_proc_entry(proc_filename, 0, NULL);	if (pde == NULL)		return;	pde->proc_fops = &proc_ops;	pde->data = sl811;	sl811->pde = pde;}static void remove_debug_file(struct sl811 *sl811){	if (sl811->pde)		remove_proc_entry(proc_filename, NULL);}#endif/*-------------------------------------------------------------------------*/static voidsl811h_stop(struct usb_hcd *hcd){	struct sl811	*sl811 = hcd_to_sl811(hcd);	unsigned long	flags;	del_timer_sync(&hcd->rh_timer);	spin_lock_irqsave(&sl811->lock, flags);	port_power(sl811, 0);	spin_unlock_irqrestore(&sl811->lock, flags);}static intsl811h_start(struct usb_hcd *hcd){	struct sl811		*sl811 = hcd_to_sl811(hcd);	struct usb_device	*udev;	/* chip has been reset, VBUS power is off */	udev = usb_alloc_dev(NULL, &hcd->self, 0);	if (!udev)		return -ENOMEM;	udev->speed = USB_SPEED_FULL;	hcd->state = USB_STATE_RUNNING;	if (sl811->board)		hcd->can_wakeup = sl811->board->can_wakeup;	if (hcd_register_root(udev, hcd) != 0) {		usb_put_dev(udev);		sl811h_stop(hcd);		return -ENODEV;	}	if (sl811->board && sl811->board->power)		hub_set_power_budget(udev, sl811->board->power * 2);	return 0;}/*-------------------------------------------------------------------------*/static struct hc_driver sl811h_hc_driver = {	.description =		hcd_name,	.hcd_priv_size =	sizeof(struct sl811),	/*	 * generic hardware linkage	 */	.flags =		HCD_USB11,	/*	 * managing i/o requests and associated device resources	 */	.urb_enqueue =		sl811h_urb_enqueue,	.urb_dequeue =		sl811h_urb_dequeue,	.endpoint_disable =	sl811h_endpoint_disable,	/*	 * periodic schedule support	 */	.get_frame_number =	sl811h_get_frame,	/*	 * root hub support	 */	.hub_status_data =	sl811h_hub_status_data,	.hub_control =		sl811h_hub_control,	.hub_suspend =		sl811h_hub_suspend,	.hub_resume =		sl811h_hub_resume,};/*-------------------------------------------------------------------------*/static int __init_or_modulesl811h_remove(struct device *dev){	struct sl811		*sl811 = dev_get_drvdata(dev);	struct usb_hcd		*hcd = sl811_to_hcd(sl811);	struct platform_device	*pdev;	struct resource		*res;	pdev = container_of(dev, struct platform_device, dev);	if (HCD_IS_RUNNING(hcd->state))		hcd->state = USB_STATE_QUIESCING;	usb_disconnect(&hcd->self.root_hub);	remove_debug_file(sl811);	sl811h_stop(hcd);	usb_deregister_bus(&hcd->self);	free_irq(hcd->irq, hcd);	iounmap(sl811->data_reg);	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);	release_mem_region(res->start, 1);	iounmap(sl811->addr_reg);	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	release_mem_region(res->start, 1);	usb_put_hcd(hcd);	return 0;}#define resource_len(r) (((r)->end - (r)->start) + 1)static int __initsl811h_probe(struct device *dev){	struct usb_hcd		*hcd;	struct sl811		*sl811;	struct platform_device	*pdev;	struct resource		*addr, *data;	int			irq;	void __iomem		*addr_reg;	void __iomem		*data_reg;	int			retval;	u8			tmp;	/* basic sanity checks first.  board-specific init logic should	 * have initialized these three resources and probably board	 * specific platform_data.  we don't probe for IRQs, and do only	 * minimal sanity checking.	 */	pdev = container_of(dev, struct platform_device, dev);	if (pdev->num_resources < 3)		return -ENODEV;	addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);	data = platform_get_resource(pdev, IORESOURCE_MEM, 1);	irq = platform_get_irq(pdev, 0);	if (!addr || !data || irq < 0)		return -ENODEV;	/* refuse to confuse usbcore */	if (dev->dma_mask) {		DBG("no we won't dma\n");		return -EINVAL;	}	if (!request_mem_region(addr->start, 1, hcd_name)) {		retval = -EBUSY;		goto err1;	}	addr_reg = ioremap(addr->start, resource_len(addr));	if (addr_reg == NULL) {		retval = -ENOMEM;		goto err2;	}	if (!request_mem_region(data->start, 1, hcd_name)) {		retval = -EBUSY;		goto err3;	}	data_reg = ioremap(data->start, resource_len(addr));	if (data_reg == NULL) {		retval = -ENOMEM;		goto err4;	}	/* allocate and initialize hcd */	hcd = usb_create_hcd(&sl811h_hc_driver);	if (!hcd) {		retval = 0;		goto err5;	}	sl811 = hcd_to_sl811(hcd);	dev_set_drvdata(dev, sl811);	hcd->self.controller = dev;	hcd->self.bus_name = dev->bus_id;	hcd->irq = irq;	hcd->regs = addr_reg;	spin_lock_init(&sl811->lock);	INIT_LIST_HEAD(&sl811->async);	sl811->board = dev->platform_data;	init_timer(&sl811->timer);	sl811->timer.function = sl811h_timer;	sl811->timer.data = (unsigned long) sl811;	sl811->addr_reg = addr_reg;	sl811->data_reg = data_reg;	spin_lock_irq(&sl811->lock);	port_power(sl811, 0);	spin_unlock_irq(&sl811->lock);	msleep(200);	tmp = sl811_read(sl811, SL11H_HWREVREG);	switch (tmp >> 4) {	case 1:		hcd->product_desc = "SL811HS v1.2";		break;	case 2:		hcd->product_desc = "SL811HS v1.5";		break;	default:		/* reject case 0, SL11S is less functional */		DBG("chiprev %02x\n", tmp);		retval = -ENXIO;		goto err6;	}	/* sl811s would need a different handler for this irq */#ifdef	CONFIG_ARM	/* Cypress docs say the IRQ is IRQT_HIGH ... */	set_irq_type(irq, IRQT_RISING);#endif	retval = request_irq(irq, sl811h_irq, SA_INTERRUPT,			hcd->driver->description, hcd);	if (retval != 0)		goto err6;	INFO("%s, irq %d\n", hcd->product_desc, irq);	retval = usb_register_bus(&hcd->self);	if (retval < 0)		goto err7;	retval = sl811h_start(hcd);	if (retval < 0)		goto err8;	create_debug_file(sl811);	return 0; err8:	usb_deregister_bus(&hcd->self); err7:	free_irq(hcd->irq, hcd); err6:	usb_put_hcd(hcd); err5:	iounmap(data_reg); err4:	release_mem_region(data->start, 1); err3:	iounmap(addr_reg); err2:	release_mem_region(addr->start, 1); err1:	DBG("init error, %d\n", retval);	return retval;}#ifdef	CONFIG_PM/* for this device there's no useful distinction between the controller * and its root hub, except that the root hub only gets direct PM calls  * when CONFIG_USB_SUSPEND is enabled. */static intsl811h_suspend(struct device *dev, u32 state, u32 phase){	struct sl811	*sl811 = dev_get_drvdata(dev);	int		retval = 0;	if (phase != SUSPEND_POWER_DOWN)		return retval;	if (state <= PM_SUSPEND_MEM)		retval = sl811h_hub_suspend(sl811_to_hcd(sl811));	else		port_power(sl811, 0);	if (retval == 0)		dev->power.power_state = state;	return retval;}static intsl811h_resume(struct device *dev, u32 phase){	struct sl811	*sl811 = dev_get_drvdata(dev);	if (phase != RESUME_POWER_ON)		return 0;	/* with no "check to see if VBUS is still powered" board hook,	 * let's assume it'd only be powered to enable remote wakeup.	 */	if (dev->power.power_state > PM_SUSPEND_MEM			|| !sl811_to_hcd(sl811)->can_wakeup) {		sl811->port1 = 0;		port_power(sl811, 1);		return 0;	}	dev->power.power_state = PM_SUSPEND_ON;	return sl811h_hub_resume(sl811_to_hcd(sl811));}#else#define	sl811h_suspend	NULL#define	sl811h_resume	NULL#endifstatic struct device_driver sl811h_driver = {	.name =		(char *) hcd_name,	.bus =		&platform_bus_type,	.probe =	sl811h_probe,	.remove =	sl811h_remove,	.suspend =	sl811h_suspend,	.resume =	sl811h_resume,};/*-------------------------------------------------------------------------*/ static int __init sl811h_init(void) {	if (usb_disabled())		return -ENODEV;	INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION);	return driver_register(&sl811h_driver);}module_init(sl811h_init);static void __exit sl811h_cleanup(void) {		driver_unregister(&sl811h_driver);}module_exit(sl811h_cleanup);

⌨️ 快捷键说明

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