int mv_otg_remove(struct platform_device *pdev) { struct mv_otg *mvotg = platform_get_drvdata(pdev); device_init_wakeup(&pdev->dev, 0); sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group); if (mvotg->qwork) { flush_workqueue(mvotg->qwork); destroy_workqueue(mvotg->qwork); } if (mvotg->pdata->extern_attr & (MV_USB_HAS_VBUS_DETECTION | MV_USB_HAS_IDPIN_DETECTION)) pxa_usb_unregister_notifier(mvotg->pdata->id, &mvotg->notifier); mv_otg_disable(mvotg); clk_unprepare(mvotg->clk); pm_qos_remove_request(&mvotg->qos_idle); usb_remove_phy(&mvotg->phy); return 0; }
static int mv_otg_remove(struct platform_device *pdev) { struct mv_otg *mvotg = platform_get_drvdata(pdev); sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group); if (mvotg->qwork) { flush_workqueue(mvotg->qwork); destroy_workqueue(mvotg->qwork); } mv_otg_disable(mvotg); usb_remove_phy(&mvotg->phy); return 0; }
int mv_otg_remove(struct platform_device *dev) { struct mv_otg *mvotg = platform_get_drvdata(dev); BUG_ON(mvotg != the_transceiver); if (mvotg->pdata->vbus) { free_irq(mvotg->pdata->vbus->irq, mvotg); } if (mvotg->pdata->id) { free_irq(mvotg->pdata->id->irq, mvotg); } if (mvotg->qwork) { flush_workqueue(mvotg->qwork); destroy_workqueue(mvotg->qwork); } sysfs_remove_group(&mvotg->dev->dev.kobj, &inputs_attr_group); if (mvotg->irq) free_irq(mvotg->irq, mvotg); mv_otg_disable(mvotg); if (mvotg->cap_regs) iounmap(mvotg->cap_regs); if (mvotg->phy_regs) iounmap((void *)mvotg->phy_regs); otg_set_transceiver(NULL); platform_set_drvdata(dev, NULL); kfree(mvotg); the_transceiver = NULL; return 0; }
static void mv_otg_work(struct work_struct *work) { struct mv_otg *mvotg; struct usb_phy *phy; struct usb_otg *otg; int old_state; mvotg = container_of(to_delayed_work(work), struct mv_otg, work); run: /* work queue is single thread, or we need spin_lock to protect */ phy = &mvotg->phy; otg = phy->otg; old_state = phy->state; if (!mvotg->active) return; mv_otg_update_inputs(mvotg); mv_otg_update_state(mvotg); if (old_state != phy->state) { dev_info(&mvotg->pdev->dev, "change from state %s to %s\n", state_string[old_state], state_string[phy->state]); switch (phy->state) { case OTG_STATE_B_IDLE: otg->default_a = 0; if (old_state == OTG_STATE_B_PERIPHERAL) mv_otg_start_periphrals(mvotg, 0); mv_otg_reset(mvotg); mv_otg_disable(mvotg); break; case OTG_STATE_B_PERIPHERAL: mv_otg_enable(mvotg); mv_otg_start_periphrals(mvotg, 1); break; case OTG_STATE_A_IDLE: otg->default_a = 1; mv_otg_enable(mvotg); if (old_state == OTG_STATE_A_WAIT_VFALL) mv_otg_start_host(mvotg, 0); mv_otg_reset(mvotg); break; case OTG_STATE_A_WAIT_VRISE: mv_otg_set_vbus(otg, 1); break; case OTG_STATE_A_WAIT_BCON: if (old_state != OTG_STATE_A_HOST) mv_otg_start_host(mvotg, 1); mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER, T_A_WAIT_BCON, mv_otg_timer_await_bcon); /* * Now, we directly enter A_HOST. So set b_conn = 1 * here. In fact, it need host driver to notify us. */ mvotg->otg_ctrl.b_conn = 1; break; case OTG_STATE_A_HOST: break; case OTG_STATE_A_WAIT_VFALL: /* * Now, we has exited A_HOST. So set b_conn = 0 * here. In fact, it need host driver to notify us. */ mvotg->otg_ctrl.b_conn = 0; mv_otg_set_vbus(otg, 0); break; case OTG_STATE_A_VBUS_ERR: break; default: break; } goto run; } }