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 + -
显示快捷键?