ohci-omap.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 671 行 · 第 1/2 页

C
671
字号
/*-------------------------------------------------------------------------*/static irqreturn_t usb_hcd_omap_hcim_irq (int irq, void *__hcd, struct pt_regs * r){	struct usb_hcd *hcd = __hcd;	return usb_hcd_irq(irq, hcd, r);}/*-------------------------------------------------------------------------*/void usb_hcd_omap_remove (struct usb_hcd *, struct omap_dev *);/* configure so an HC device and id are always provided *//* always called with process context; sleeping is OK *//** * usb_hcd_omap_probe - initialize OMAP-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. * * Store this function in the HCD's struct pci_driver as probe(). */int usb_hcd_omap_probe (const struct hc_driver *driver,			  struct usb_hcd **hcd_out,			  struct omap_dev *dev){	int retval;	struct usb_hcd *hcd = 0;	if (!request_mem_region(dev->res.start, 				dev->res.end - dev->res.start + 1, hcd_name)) {		dbg("request_mem_region failed");		return -EBUSY;	}	omap_start_hc(dev);	hcd = driver->hcd_alloc ();	if (hcd == NULL){		dbg ("hcd_alloc failed");		retval = -ENOMEM;		goto err1;	}	hcd->driver = (struct hc_driver *) driver;	hcd->description = driver->description;	hcd->irq = dev->irq[0];	hcd->regs = dev->mapbase;	hcd->self.controller = &dev->dev;	retval = hcd_buffer_create (hcd);	if (retval != 0) {		dbg ("pool alloc fail");		goto err1;	}	retval = request_irq (hcd->irq, 			      usb_hcd_omap_hcim_irq, 			      SA_INTERRUPT, hcd->description, hcd);	if (retval != 0) {		dbg("request_irq failed");		retval = -EBUSY;		goto err2;	}	info ("%s (OMAP) at 0x%p, irq %d\n",	      hcd->description, hcd->regs, hcd->irq);	usb_bus_init (&hcd->self);	hcd->self.op = &usb_hcd_operations;	hcd->self.hcpriv = (void *) hcd;	hcd->self.bus_name = "omap";	hcd->product_desc = "OMAP OHCI";	INIT_LIST_HEAD (&hcd->dev_list);	usb_register_bus (&hcd->self);	if ((retval = driver->start (hcd)) < 0) 	{		usb_hcd_omap_remove(hcd, dev);		return retval;	}	*hcd_out = hcd;	return 0; err2:	hcd_buffer_destroy (hcd);	if (hcd)		driver->hcd_free(hcd); err1:	omap_stop_hc(dev);	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);	return retval;}/* may be called without controller electrically present *//* may be called with controller, bus, and devices active *//** * usb_hcd_omap_remove - shutdown processing for OMAP-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_omap_probe(), first invoking * the HCD's stop() method.  It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */void usb_hcd_omap_remove (struct usb_hcd *hcd, struct omap_dev *dev){	void *base;	info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);	if (in_interrupt ())		BUG ();	hcd->state = USB_STATE_QUIESCING;	dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);	usb_disconnect (&hcd->self.root_hub);	hcd->driver->stop (hcd);	hcd_buffer_destroy (hcd);	hcd->state = USB_STATE_HALT;	free_irq (hcd->irq, hcd);	usb_deregister_bus (&hcd->self);	base = hcd->regs;	hcd->driver->hcd_free (hcd);	omap_stop_hc(dev);	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);}/*-------------------------------------------------------------------------*/static int __devinitohci_omap_start (struct usb_hcd *hcd){	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);	int		ret;	ohci->hcca = dma_alloc_consistent (hcd->self.controller,			sizeof *ohci->hcca, &ohci->hcca_dma);	if (!ohci->hcca)		return -ENOMEM;        memset (ohci->hcca, 0, sizeof (struct ohci_hcca));	if ((ret = ohci_mem_init (ohci)) < 0) {		ohci_stop (hcd);		return ret;	}	ohci->regs = hcd->regs;	if (hc_reset (ohci) < 0) {		ohci_stop (hcd);		return -ENODEV;	}	if (hc_start (ohci) < 0) {		err ("can't start %s", ohci->hcd.self.bus_name);		ohci_stop (hcd);		return -EBUSY;	}	create_debug_files (ohci);#ifdef	DEBUG	ohci_dump (ohci, 1);#endif	return 0;}/*-------------------------------------------------------------------------*/static const struct hc_driver ohci_omap_hc_driver = {	.description =		hcd_name,	/*	 * generic hardware linkage	 */	.irq =			ohci_irq,	.flags =		HCD_USB11,	/*	 * basic lifecycle operations	 */	.start =		ohci_omap_start,#ifdef	CONFIG_PM	/* suspend:		ohci_omap_suspend,  -- tbd */	/* resume:		ohci_omap_resume,   -- tbd */#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};/*-------------------------------------------------------------------------*/static int ohci_hcd_omap_drv_probe(struct omap_dev *dev){	struct usb_hcd *hcd = NULL;	int ret;	if (usb_disabled())		return -ENODEV;	ret = usb_hcd_omap_probe(&ohci_omap_hc_driver, &hcd, dev);	if (ret == 0)		omap_set_drvdata(dev, hcd);	return ret;}static int ohci_hcd_omap_drv_remove(struct omap_dev *dev){	struct usb_hcd *hcd = omap_get_drvdata(dev);	usb_hcd_omap_remove(hcd, dev);	omap_set_drvdata(dev, NULL);	return 0;}/* * Driver definition to register with the OMAP bus */static struct omap_driver ohci_hcd_omap_driver = {	.drv = {		.name	= OMAP_OHCI_NAME,	},	.devid		= OMAP_OCP_DEVID_USB,	.busid		= OMAP_BUS_OCP,	.clocks		= 0,	.probe		= ohci_hcd_omap_drv_probe,	.remove		= ohci_hcd_omap_drv_remove,};/* Any dma_mask must be set for OHCI to work */static u64 omap_dmamask = 0xffffffffUL;	/* * Device definition to match the driver above */static struct omap_dev ohci_hcd_omap_device = {	.name		= OMAP_OHCI_NAME,	.devid		= OMAP_OCP_DEVID_USB,	.busid		= OMAP_BUS_OCP,	.mapbase	= (void *)OMAP_OHCI_BASE,	.dma_mask	= &omap_dmamask,	/* Needed only for OHCI */	.res = {		.start	= OMAP_OHCI_BASE,		.end	= OMAP_OHCI_BASE + OMAP_OHCI_SIZE,	},	.irq = {		INT_USB_HHC_1,	},};static int __init ohci_hcd_omap_init (void){	int ret;	dbg (DRIVER_INFO " (OMAP)");	dbg ("block sizes: ed %d td %d\n",		sizeof (struct ed), sizeof (struct td));	if (hmc_mode < 0 || hmc_mode > 25)		hmc_mode = default_hmc_mode;	/* Register the driver with OMAP bus */	ret = omap_driver_register(&ohci_hcd_omap_driver);	if (ret != 0)		return -ENODEV;	/* Register the device with OMAP bus */	ret = omap_device_register(&ohci_hcd_omap_device);	if (ret != 0) {		omap_driver_unregister(&ohci_hcd_omap_driver);		return -ENODEV;	}	return ret;}MODULE_PARM(hmc_mode, "hmc_mode");static void __exit ohci_hcd_omap_cleanup (void){	omap_device_unregister(&ohci_hcd_omap_device);	omap_driver_unregister(&ohci_hcd_omap_driver);}module_init (ohci_hcd_omap_init);module_exit (ohci_hcd_omap_cleanup);

⌨️ 快捷键说明

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