plat_uds.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 2,070 行 · 第 1/4 页

C
2,070
字号
{	struct musb	*musb = dev_to_musb(dev);	unsigned long	flags;	unsigned long	val;	spin_lock_irqsave(&musb->Lock, flags);	val = musb->a_wait_bcon;	spin_unlock_irqrestore(&musb->Lock, flags);	return sprintf(buf, "%lu\n", val);}static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store);static ssize_tmusb_srp_store(struct device *dev, struct device_attribute *attr,		const char *buf, size_t n){	struct musb	*musb=dev_to_musb(dev);	unsigned long	flags;	unsigned short	srp;	if (sscanf(buf, "%hu", &srp) != 1			|| (srp != 1)) {		printk (KERN_ERR "SRP: Value must be 1\n");		return -EINVAL;	}	spin_lock_irqsave(&musb->Lock, flags);	if (srp == 1)		musb_g_wakeup(musb);	spin_unlock_irqrestore(&musb->Lock, flags);	return n;}static DEVICE_ATTR(srp, 0644, NULL, musb_srp_store);/* Only used to provide cable state change events */static void musb_irq_work(struct work_struct *data){	struct musb *musb = container_of(data, struct musb, irq_work);	sysfs_notify(&musb->controller->kobj, NULL, "cable");}/* -------------------------------------------------------------------------- * Init support */static struct musb *__initallocate_instance(struct device *dev, void __iomem *mbase){	struct musb		*musb;	struct musb_hw_ep	*ep;	int			epnum;	struct usb_hcd	*hcd;	hcd = usb_create_hcd(&musb_hc_driver, dev, dev->bus_id);	if (!hcd)		return NULL;	/* usbcore sets dev->driver_data to hcd, and sometimes uses that... */	musb = hcd_to_musb(hcd);	INIT_LIST_HEAD(&musb->control);	INIT_LIST_HEAD(&musb->in_bulk);	INIT_LIST_HEAD(&musb->out_bulk);	hcd->uses_new_polling = 1;	musb->vbuserr_retry = VBUSERR_RETRY_COUNT;	musb->pRegs = mbase;	musb->ctrl_base = mbase;	musb->nIrq = -ENODEV;	for (epnum = 0, ep = musb->aLocalEnd;			epnum < MUSB_C_NUM_EPS;			epnum++, ep++) {		ep->musb = musb;		ep->bLocalEnd = epnum;	}	musb->controller = dev;	return musb;}static void musb_free(struct musb *musb){	/* this has multiple entry modes. it handles fault cleanup after	 * probe(), where things may be partially set up, as well as rmmod	 * cleanup after everything's been de-activated.	 */	device_remove_file(musb->controller, &dev_attr_mode);	device_remove_file(musb->controller, &dev_attr_cable);	device_remove_file(musb->controller, &dev_attr_vbus);	device_remove_file(musb->controller, &dev_attr_srp);	musb_gadget_cleanup(musb);	if (musb->nIrq >= 0) {		disable_irq_wake(musb->nIrq);		free_irq(musb->nIrq, musb);	}	if (is_dma_capable() && musb->pDmaController) {		struct dma_controller	*c = musb->pDmaController;		(void) c->stop(c->pPrivateData);		dma_controller_destroy(c);	}	musb_writeb(musb->pRegs, MGC_O_HDRC_DEVCTL, 0);	musb_platform_exit(musb);	musb_writeb(musb->pRegs, MGC_O_HDRC_DEVCTL, 0);	if (musb->clock) {		clk_disable(musb->clock);		clk_put(musb->clock);	}	usb_put_hcd(musb_to_hcd(musb));}/* * Perform generic per-controller initialization. * * @pDevice: the controller (already clocked, etc) * @nIrq: irq * @pRegs: virtual address of controller registers, *	not yet corrected for platform-specific offsets */static int __initmusb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl){	int			status;	struct musb		*pThis;	struct musb_hdrc_platform_data *plat = dev->platform_data;	/* The driver might handle more features than the board; OK.	 * Fail when the board needs a feature that's not enabled.	 */	if (!plat) {		dev_dbg(dev, "no platform_data?\n");		return -ENODEV;	}	switch (plat->mode) {	case MUSB_HOST:		break;	case MUSB_PERIPHERAL:		break;	case MUSB_OTG:		break;	default:		dev_err(dev, "incompatible Kconfig role setting\n");		return -EINVAL;	}	/* allocate */	pThis = allocate_instance(dev, ctrl);	if (!pThis)		return -ENOMEM;	spin_lock_init(&pThis->Lock);	pThis->board_mode = plat->mode;	pThis->board_set_power = plat->set_power;	pThis->set_clock = plat->set_clock;	pThis->min_power = plat->min_power;	/* Clock usage is chip-specific ... functional clock (DaVinci,	 * OMAP2430), or PHY ref (some TUSB6010 boards).  All this core	 * code does is make sure a clock handle is available; platform	 * code manages it during start/stop and suspend/resume.	 */	if (plat->clock) {		pThis->clock = clk_get(dev, plat->clock);		if (IS_ERR(pThis->clock)) {			status = PTR_ERR(pThis->clock);			pThis->clock = NULL;			goto fail;		}	}	/* assume vbus is off */	/* platform adjusts pThis->pRegs and pThis->isr if needed,	 * and activates clocks	 */	pThis->isr = generic_interrupt;	status = musb_platform_init(pThis);	if (status < 0)		goto fail;	if (!pThis->isr) {		status = -ENODEV;		goto fail2;	}	/* ideally this would be abstracted in platform setup */	if (!is_dma_capable() || !pThis->pDmaController)		dev->dma_mask = NULL;	/* be sure interrupts are disabled before connecting ISR */	musb_platform_disable(pThis);	musb_generic_disable(pThis);	/* setup musb parts of the core (especially endpoints) */	status = musb_core_init(plat->multipoint			? MUSB_CONTROLLER_MHDRC			: MUSB_CONTROLLER_HDRC, pThis);	if (status < 0)		goto fail2;	INIT_WORK(&pThis->irq_work, musb_irq_work);	/* attach to the IRQ */	if (request_irq (nIrq, pThis->isr, IRQF_DISABLED, dev->bus_id, pThis)) {		dev_err(dev, "request_irq %d failed!\n", nIrq);		status = -ENODEV;		goto fail2;	}	pThis->nIrq = nIrq;// FIXME this handles wakeup irqs wrong	if (enable_irq_wake(nIrq) == 0)		device_init_wakeup(dev, 1);	pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n",			musb_driver_name,			({char *s;			switch (pThis->board_mode) {			case MUSB_HOST:		s = "Host"; break;			case MUSB_PERIPHERAL:	s = "Peripheral"; break;			default:		s = "OTG"; break;			}; s; }),			ctrl,			(is_dma_capable() && pThis->pDmaController)				? "DMA" : "PIO",			pThis->nIrq);	/* host side needs more setup, except for no-host modes */	if (pThis->board_mode != MUSB_PERIPHERAL) {		struct usb_hcd	*hcd = musb_to_hcd(pThis);		if (pThis->board_mode == MUSB_OTG)			hcd->self.otg_port = 1;		pThis->xceiv.host = &hcd->self;		hcd->power_budget = 2 * (plat->power ? : 250);	}	/* For the host-only role, we can activate right away.	 * (We expect the ID pin to be forcibly grounded!!)	 * Otherwise, wait till the gadget driver hooks up.	 */	if (!is_otg_enabled(pThis) && is_host_enabled(pThis)) {		MUSB_HST_MODE(pThis);		pThis->xceiv.default_a = 1;		pThis->xceiv.state = OTG_STATE_A_IDLE;		status = usb_add_hcd(musb_to_hcd(pThis), -1, 0);		DBG(1, "%s mode, status %d, devctl %02x %c\n",			"HOST", status,			musb_readb(pThis->pRegs, MGC_O_HDRC_DEVCTL),			(musb_readb(pThis->pRegs, MGC_O_HDRC_DEVCTL)					& MGC_M_DEVCTL_BDEVICE				? 'B' : 'A'));	} else /* peripheral is enabled */ {		MUSB_DEV_MODE(pThis);		pThis->xceiv.default_a = 0;		pThis->xceiv.state = OTG_STATE_B_IDLE;		status = musb_gadget_setup(pThis);		DBG(1, "%s mode, status %d, dev%02x\n",			is_otg_enabled(pThis) ? "OTG" : "PERIPHERAL",			status,			musb_readb(pThis->pRegs, MGC_O_HDRC_DEVCTL));	}	if (status == 0) {		musb_debug_create("driver/musb_hdrc", pThis);		musb_init_hset("driver/musb_HSET", pThis);	}	else {fail:		if (pThis->clock)			clk_put(pThis->clock);		device_init_wakeup(dev, 0);		musb_free(pThis);		return status;	}	status = device_create_file(dev, &dev_attr_mode);	status = device_create_file(dev, &dev_attr_cable);	status = device_create_file(dev, &dev_attr_vbus);	status = device_create_file(dev, &dev_attr_srp);	status = 0;	return status;fail2:	musb_platform_exit(pThis);	goto fail;}/*-------------------------------------------------------------------------*//* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just * bridge to a platform device; this driver then suffices. */static int __init musb_probe(struct platform_device *pdev){	struct device	*dev = &pdev->dev;	int		irq = platform_get_irq(pdev, 0);	struct resource	*iomem;	void __iomem	*base;	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);	if (!iomem || irq == 0)		return -ENODEV;	base = ioremap(iomem->start, iomem->end - iomem->start + 1);	if (!base) {		dev_err(dev, "ioremap failed\n");		return -ENOMEM;	}	return musb_init_controller(dev, irq, base);}static int __devexit musb_remove(struct platform_device *pdev){	struct musb	*musb = dev_to_musb(&pdev->dev);	void __iomem	*ctrl_base = musb->ctrl_base;	/* this gets called on rmmod.	 *  - Host mode: host may still be active	 *  - Peripheral mode: peripheral is deactivated (or never-activated)	 *  - OTG mode: both roles are deactivated (or never-activated)	 */	musb_shutdown(pdev);	musb_debug_delete("driver/musb_hdrc", musb);	musb_exit_hset("driver/musb_HSET", musb);	if (musb->board_mode == MUSB_HOST)		usb_remove_hcd(musb_to_hcd(musb));	musb_free(musb);	iounmap(ctrl_base);	device_init_wakeup(&pdev->dev, 0);	return 0;}static int musb_suspend(struct platform_device *pdev, pm_message_t message){	struct musb	*musb = dev_to_musb(&pdev->dev);	unsigned long	flags;	int		state =	message.event;//#ifdef USB_INTERNAL_TEST	u8	devctl;//#endif /* USB_INTERNAL_TEST */	if (!musb->clock)		return 0;		DBG(1, "suspend from %d -> %d\n", pdev->dev.power.power_state.event, state);	if (state <= pdev->dev.power.power_state.event)		return 0;	//if (platform_off_state(state))	//	state = OFF_STATE;	//if (state != OFF_STATE)		//goto idle_standby;	spin_lock_irqsave(&musb->Lock, flags);	if (is_peripheral_active(musb)) {		/* FIXME force disconnect unless we know USB will wake		 * the system up quickly enough to respond ...		 */		if (musb->pGadgetDriver)			musb_g_stop_activity(musb, musb->pGadgetDriver);	}	if (is_host_active(musb)) {		/* we know all the children are suspended; sometimes		 * they will even be wakeup-enabled.		 */		spin_unlock_irqrestore(&musb->Lock, flags);//#ifdef USB_INTERNAL_TEST		musb->is_active = 0;			//Clear the session		devctl = musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL);		devctl &= ~MGC_M_DEVCTL_SESSION;		musb_writeb(musb->pRegs, MGC_O_HDRC_DEVCTL, devctl);//#endif /* USB_INTERNAL_TEST */		spin_lock_irqsave(&musb->Lock, flags);		//hcd->self.root_hub->state = USB_STATE_SUSPENDED;		//hcd->state = HC_STATE_SUSPENDED	}	//clk_disable(musb->clock);	spin_unlock_irqrestore(&musb->Lock, flags);//idle_standby:	DBG(1, "idle, standby etc.\n");	/* unlock irq before stopping clocks, because abort of DMA channels in 	 * Mentor DMA controller logs an interrupt that needs to be cleared	 */  	musb_platform_suspend(musb); //, state);	/* asleep = 1 if clocks are OFF */	//if (state == OFF_STATE)	musb->asleep = 1;	pdev->dev.power.power_state.event = state;	return 0;}static int musb_resume(struct platform_device *pdev){	unsigned long	flags;	struct musb	*musb = dev_to_musb(&pdev->dev);//#ifdef USB_INTERNAL_TEST//	struct usb_hcd *hcd = musb_to_hcd(musb);	u8	devctl;//#endif /* USB_INTERNAL_TEST */	if (!musb->clock)		return 0;	DBG(1, "resume %d \n", pdev->dev.power.power_state.event);	spin_lock_irqsave(&musb->Lock, flags);	musb_platform_resume(musb); //, dev->power.power_state.event);	/* asleep = 0 if clocks are ON */	musb->asleep = 0;//	if (!platform_off_state(dev->power.power_state.event))	//	goto done;		if (is_peripheral_active(musb) && musb->pGadgetDriver) {		musb->softconnect = 1;		musb_start(musb);	}	if (is_host_active(musb)) {		DBG(1, "usb resume\n");		/* get extra cleanup even if remote wakeup isn't in use */		spin_unlock_irqrestore(&musb->Lock, flags);//#ifdef USB_INTERNAL_TEST		devctl = musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL);		devctl |= MGC_M_DEVCTL_SESSION;		musb_writeb(musb->pRegs, MGC_O_HDRC_DEVCTL, devctl);	}		/* for static cmos like DaVinci, register values were preserved	 * unless for some reason the whole soc powered down and we're	 * not treating that as a whole-system restart (e.g. swsusp)	 *///done:	spin_unlock_irqrestore(&musb->Lock, flags);	pdev->dev.power.power_state.event = 0; //DEV_SUSPEND_ON;	return 0;}static struct platform_driver musb_driver = {	.driver = {		.name		= (char *)musb_driver_name,		.bus		= &platform_bus_type,		.owner		= THIS_MODULE,	},	.remove		= __devexit_p(musb_remove),	.shutdown	= musb_shutdown,	.suspend	= musb_suspend,	.resume		= musb_resume,};/*-------------------------------------------------------------------------*/static int __init musb_init(void){	if (usb_disabled())		return 0;	pr_info("%s: version " MUSB_VERSION ", "		"pio"		", "		"otg (peripheral+host)"		", debug=%d\n",		musb_driver_name, debug);	return platform_driver_probe(&musb_driver, musb_probe);}/* make us init after usbcore and before usb * gadget and host-side drivers start to register */subsys_initcall(musb_init);static void __exit musb_cleanup(void){	platform_driver_unregister(&musb_driver);}module_exit(musb_cleanup);

⌨️ 快捷键说明

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