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

📄 ohci-sl811.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 err1:	driver->hcd_free(hcd); out:	return retval;}/* may be called without controller electrically present *//* may be called with controller, bus, and devices active *//** * usb_hcd_sl811_remove - shutdown processing for HC-SL811-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_sl811_probe(), first invoking * the HCD's stop() method.  It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */static int usb_hcd_sl811_remove(struct usb_hcd *hcd, struct hc_sl811_dev *dev){	struct usb_device	*hub;	BUG_ON(in_interrupt());	if (HCD_IS_RUNNING(hcd->state)) {		hcd->state = USB_STATE_QUIESCING;	}	hub = hcd->self.root_hub;	dev_dbg(hcd->self.controller, "%s: roothub graceful disconnect\n", hcd->self.bus_name);	usb_disconnect(&hub);	sl811_stop_hc(dev);	hcd->driver->stop(hcd);	hcd->state = USB_STATE_HALT;	free_irq(hcd->irq, hcd);	tasklet_kill(&dev->usb_reset_bh);	hcd_buffer_destroy(hcd);	hc_sl811_set_drvdata(dev, NULL);	usb_deregister_bus(&hcd->self);	hcd->driver->hcd_free(hcd);	return 0;}/* * perform OHCI (PCI) bus reset */static int ohci_sl811_reset(struct usb_hcd *hcd){	int ret;	struct ohci_hcd *ohci = hcd_to_ohci(hcd);	ohci->regs = hcd->regs;	sl811_reset_hc(hcd, 1); // initialize controller registers	ret = hc_reset(ohci);	return ret;}static int __devinit ohci_sl811_start(struct usb_hcd *hcd){	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);	int ret;	ohci->hcca = dma_alloc_coherent(hcd->self.controller, sizeof(*ohci->hcca),					&ohci->hcca_dma, 0);	if (!ohci->hcca) {		return -ENOMEM;	}	memset(ohci->hcca, 0, sizeof(struct ohci_hcca));	ret = ohci_mem_init(ohci);	if (ret < 0) {		ohci_stop(hcd);		return ret;	}	if (hc_start(ohci) < 0) {		err("can't start %s", ohci->hcd.self.bus_name);		ohci_stop(hcd);		return -EBUSY;	}	create_debug_files(ohci);	sl811_start_hc(hcd);#ifdef DEBUG	ohci_dump(ohci, 1);#endif	return 0;}/*-------------------------------------------------------------------------*/#ifdef CONFIG_PMstatic int ohci_sl811_suspend(struct usb_hcd *hcd, u32 state){	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);	/* suspend root hub, hoping it keeps power during suspend */	while (time_before(jiffies, ohci->next_statechange)) {		msleep(100);	}#ifdef	CONFIG_USB_SUSPEND	(void)usb_suspend_device(hcd->self.root_hub);#else	down(&hcd->self.root_hub->serialize);	(void)ohci_hub_suspend(hcd);	up(&hcd->self.root_hub->serialize);#endif	/* let things settle down a bit */	msleep(100);	return 0;}static int ohci_sl811_resume(struct usb_hcd *hcd){	int retval;	struct ohci_hcd		*ohci = hcd_to_ohci (hcd);	/* resume root hub */	while (time_before(jiffies, ohci->next_statechange)) {		msleep(100);	}#ifdef	CONFIG_USB_SUSPEND	/* get extra cleanup even if remote wakeup isn't in use */	retval = usb_resume_device(hcd->self.root_hub);#else	down(&hcd->self.root_hub->serialize);	retval = ohci_hub_resume(hcd);	up(&hcd->self.root_hub->serialize);#endif 	retval = hc_restart(hcd_to_ohci(hcd));	if (retval == 0) {		hcd->self.controller->power.power_state = 0;	}	sl811_start_hc(hcd);	return retval;}#endifstatic struct hc_driver ohci_sl811_hc_driver = {	.description		= hcd_name,	/*	 * generic hardware linkage	 */	.irq			= ohci_irq,	.flags			= HCD_MEMORY | HCD_USB11,	/*	 * basic lifecycle operations	 */	.reset			= ohci_sl811_reset,	.start			= ohci_sl811_start,#ifdef	CONFIG_PM	.suspend		= ohci_sl811_suspend,	.resume			= ohci_sl811_resume,#endif	.stop			= ohci_stop,	/*	 * memory lifecycle (except per-request)	 */	.hcd_alloc		= ohci_hcd_alloc,	.hcd_free		= ohci_hcd_free,	/*	 * managing i/o requests and associated device resources	 */	.urb_enqueue		= ohci_urb_enqueue,	.urb_dequeue		= ohci_urb_dequeue,	.endpoint_disable	= ohci_endpoint_disable,	/*	 * scheduling support	 */	.get_frame_number	= ohci_get_frame,	/*	 * root hub support	 */	.hub_status_data	= ohci_hub_status_data,	.hub_control		= ohci_hub_control,#ifdef	CONFIG_USB_SUSPEND	.hub_suspend		= ohci_hub_suspend,	.hub_resume		= ohci_hub_resume,#endif};/*-------------------------------------------------------------------------*/#define res_len(p) ((p)->end - (p)->start + 1)static int ohci_hcd_sl811_drv_probe(struct hc_sl811_dev *dev){	struct usb_hcd *hcd = NULL;	struct platform_device *pdev = to_platform_device(dev->dev.parent);	struct resource *res;	//int req = -1;	int io_len = 0;	int ret;	if (usb_disabled()) {		return -ENODEV;	}	if (pdev->num_resources < 2) {		return -ENODEV;	}	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (!res) {		return -ENODEV;	}	if (!request_mem_region(res->start, res_len(res), hcd_name)) {		ret = -EBUSY;		goto out;	}	io_len = res_len(res);	//dev->addr_reg = ioremap(res->start, res_len(res));	dev->addr_reg = ioremap(0x04700000, 0x00100000);	if (dev->addr_reg == NULL) {		ret = -ENOMEM;		goto out;	}#ifdef	CONFIG_ARCH_FS_PXA255	dev->data_reg = dev->addr_reg+0x10;#else	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);	if (res) {		if (!request_mem_region(res->start, res_len(res), hcd_name)) {			ret = -EBUSY;			goto out;		}		dev->data_reg = ioremap(res->start, res_len(res));		if (dev->data_reg == NULL) {			ret = -ENOMEM;			goto out;		}	} else {		dev->data_reg = dev->addr_reg + io_len - 1;	}#endif	dev->irq = platform_get_irq(pdev, 0);	ret = hc_sl811_chip_probe(dev);	printk("sl811hs probe %s\n", ret?"fail":"success");	if (ret != 0) {		goto out;	}	ret = usb_hcd_sl811_probe(&ohci_sl811_hc_driver, &hcd, dev);	if (ret == 0) {		return ret;	} out:	if (dev->addr_reg) {		iounmap(dev->addr_reg);		dev->addr_reg = NULL;	}	if (res) {		if (dev->data_reg) {			iounmap(dev->data_reg);			dev->data_reg = NULL;		}		release_mem_region(res->start, res_len(res));	}	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (res) {		release_mem_region(res->start, io_len);	}	return ret;}static int ohci_hcd_sl811_drv_remove(struct hc_sl811_dev *dev){	struct usb_hcd *hcd = hc_sl811_get_drvdata(dev);	struct platform_device *pdev = to_platform_device(dev->dev.parent);	struct resource *res;	usb_hcd_sl811_remove(hcd, dev);	iounmap(dev->addr_reg);	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);	release_mem_region(res->start, res_len(res));#ifndef	CONFIG_ARCH_FS_PXA255	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);	if (res) {		iounmap(dev->data_reg);		release_mem_region(res->start, res_len(res));	}#endif	return 0;}static void __sl811_release(struct device *dev){	struct hc_sl811_dev *sl811_dev = dev_get_drvdata(dev);	printk("%s: dev=%08x\n", __FUNCTION__, (u32)dev);	if (sl811_dev != NULL) {		kfree(sl811_dev);	}}#define MALLOC_SIZE sizeof(struct hc_sl811_dev)static int __sl811_probe(struct device *dev, struct resource *mem, struct resource *irq){	int ret;	struct hc_sl811_dev *sl811_dev;	sl811_dev = kmalloc(MALLOC_SIZE, GFP_KERNEL);	if (sl811_dev == NULL) {		return -ENOMEM;	}	memset(sl811_dev, 0, MALLOC_SIZE);	sl811_dev->irq = NO_IRQ;	sl811_dev->dev.parent = dev;	sl811_dev->dev.bus = &platform_bus_type;	sl811_dev->dev.release = __sl811_release;	//spin_lock_init(&sl811_dev->irq_lock);	dev_set_drvdata(dev, sl811_dev);	ret = ohci_hcd_sl811_drv_probe(sl811_dev);	if (ret != 0) {		dev_set_drvdata(dev, NULL);	}	return ret;}#ifdef	CONFIG_PMstatic int usb_hcd_sl811_suspend(struct hc_sl811_dev *dev, u32 state){	struct usb_hcd		*hcd;	int			retval = 0;	hcd = hc_sl811_get_drvdata(dev);	dev_dbg(hcd->self.controller, "suspend D%d --> D%d\n", dev->pm_state, state);	switch (hcd->state) {	case USB_STATE_HALT:		dev_dbg (hcd->self.controller, "halted; hcd not suspended\n");		break;	case HCD_STATE_SUSPENDED:		dev_dbg (hcd->self.controller, "hcd already suspended\n");		break;	default:		retval = hcd->driver->suspend(hcd, state);		if (retval) {			dev_dbg(hcd->self.controller, "suspend fail, retval %d\n", retval);		} else {			hcd->state = HCD_STATE_SUSPENDED;			//pci_save_state (dev, hcd->pci_state);#ifdef	CONFIG_USB_SUSPEND			//pci_enable_wake (dev, state, hcd->remote_wakeup);			//pci_enable_wake (dev, 4, hcd->remote_wakeup);#endif			/* no DMA or IRQs except in D0 */			//pci_disable_device (dev);			sl811_stop_hc(dev);			free_irq(hcd->irq, hcd);						//if (has_pci_pm)				//retval = pci_set_power_state (dev, state);			dev->dev.power.power_state = state;		}	}	return retval;}/* * usb_hcd_sl811_resume - power management resume of an SL811HS based HCD * @dev: USB Host Controller being resumed * * Store this function in the HCD's struct hc_sl811_driver as resume(). */static int usb_hcd_sl811_resume(struct hc_sl811_dev *dev){	struct usb_hcd		*hcd;	int			retval;	hcd = hc_sl811_get_drvdata(dev);	dev_dbg(hcd->self.controller, "resume from state D%d\n", dev->pm_state);	if (hcd->state != HCD_STATE_SUSPENDED) {		dev_dbg(hcd->self.controller, "can't resume, not suspended!\n");		return -EL3HLT;	}	hcd->state = USB_STATE_RESUMING;	dev->dev.power.power_state = 0;	retval = request_irq(dev->irq, ohci_sl811_interrupt, SA_INTERRUPT, hcd->description, hcd);	if (retval < 0) {		dev_err(hcd->self.controller, "can't restore IRQ after resume!\n");		return retval;	}	//pci_set_master (dev);	//pci_restore_state (dev, hcd->pci_state);#ifdef	CONFIG_USB_SUSPEND	//pci_enable_wake (dev, dev->pm_state, 0);	//pci_enable_wake (dev, 4, 0);#endif	dev->pm_state = 0;	retval = hcd->driver->resume(hcd);	if (!HCD_IS_RUNNING(hcd->state)) {		dev_dbg(hcd->self.controller, "resume fail, retval %d\n", retval);		usb_hc_died (hcd);	}	return retval;}#endif	/* CONFIG_PM */static struct hc_sl811_driver ohci_hcd_sl811_driver = {	.drv = {		.name	= "sl811hs-ohci",		.bus	= &platform_bus_type,	},	.devid	= 0,	.probe	= ohci_hcd_sl811_drv_probe,	.remove	= ohci_hcd_sl811_drv_remove,#ifdef CONFIG_PM	.suspend = usb_hcd_sl811_suspend,	.resume = usb_hcd_sl811_resume,#endif};static int sl811_bus_probe(struct device *dev){	struct platform_device *pdev = to_platform_device(dev);	struct resource *mem, *irq = NULL;	int ret = -ENODEV;	mem = &pdev->resource[0];	if (pdev->num_resources == 2) {		irq = &pdev->resource[1];	}	ret = __sl811_probe(dev, mem, irq);	return ret;}static int sl811_bus_remove(struct device *dev){	int ret = 0;	struct hc_sl811_dev *sl811_dev = dev_get_drvdata(dev);	struct hc_sl811_driver *drv = SL811_DRV(dev->driver);	if (drv->remove) {		ret = drv->remove(sl811_dev);	}	return ret;}static int sl811_bus_suspend(struct device *dev, u32 state, u32 level){	int ret = 0;	struct hc_sl811_dev *sl811_dev = dev_get_drvdata(dev);	struct hc_sl811_driver *drv = SL811_DRV(dev->driver);	if (drv->suspend) {		ret = drv->suspend(sl811_dev, state);	}	return ret;}static int sl811_bus_resume(struct device *dev, u32 level){	int ret = 0;	struct hc_sl811_dev *sl811_dev = dev_get_drvdata(dev);	struct hc_sl811_driver *drv = SL811_DRV(dev->driver);	if (drv->resume) {		ret = drv->resume(sl811_dev);	}	return ret;}static int hc_sl811_driver_register(struct hc_sl811_driver *driver){	int ret;	WARN_ON(driver->drv.suspend || driver->drv.resume || driver->drv.probe || driver->drv.remove);	driver->drv.probe = sl811_bus_probe;	driver->drv.remove = sl811_bus_remove;	driver->drv.suspend = sl811_bus_suspend;	driver->drv.resume = sl811_bus_resume;	ret = driver_register(&driver->drv);	return ret;}static void hc_sl811_driver_unregister(struct hc_sl811_driver *driver){	driver_unregister(&driver->drv);}static int __init ohci_hcd_sl811_init(void){	int ret = 0;	printk(DRIVER_INFO " (HC-SL811HS)\n");	ret = hc_sl811_driver_register(&ohci_hcd_sl811_driver);	return ret;}static void __exit ohci_hcd_sl811_cleanup(void){	hc_sl811_driver_unregister(&ohci_hcd_sl811_driver);}module_init(ohci_hcd_sl811_init);module_exit(ohci_hcd_sl811_cleanup);

⌨️ 快捷键说明

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