Loading drivers/usb/phy/phy-msm-usb.c +52 −6 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/pm_runtime.h> #include <linux/suspend.h> #include <linux/of.h> #include <linux/dma-mapping.h> #include <linux/clk/msm-clk.h> Loading Loading @@ -3498,11 +3499,13 @@ static void msm_otg_set_vbus_state(int online) return; } if (atomic_read(&motg->pm_suspended)) if (atomic_read(&motg->pm_suspended)) { motg->sm_work_pending = true; else } else if (!motg->sm_work_pending) { /* process event only if previous one is not pending */ queue_work(system_nrt_wq, &motg->sm_work); } } static void msm_id_status_w(struct work_struct *w) { Loading @@ -3511,6 +3514,8 @@ static void msm_id_status_w(struct work_struct *w) int work = 0; int id_state = 0; dev_dbg(motg->phy.dev, "ID status_w\n"); if (motg->pdata->pmic_id_irq) id_state = msm_otg_read_pmic_id_state(motg); else if (motg->ext_id_irq) Loading @@ -3530,11 +3535,13 @@ static void msm_id_status_w(struct work_struct *w) } if (work && (motg->phy.state != OTG_STATE_UNDEFINED)) { if (atomic_read(&motg->pm_suspended)) if (atomic_read(&motg->pm_suspended)) { motg->sm_work_pending = true; else } else if (!motg->sm_work_pending) { /* process event only if previous one is not pending */ queue_work(system_nrt_wq, &motg->sm_work); } } } Loading @@ -3557,6 +3564,34 @@ static irqreturn_t msm_id_irq(int irq, void *data) return IRQ_HANDLED; } int msm_otg_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused) { struct msm_otg *motg = container_of( notify_block, struct msm_otg, pm_notify); dev_dbg(motg->phy.dev, "OTG PM notify:%lx, sm_pending:%u\n", mode, motg->sm_work_pending); switch (mode) { case PM_POST_SUSPEND: /* OTG sm_work can be armed now */ atomic_set(&motg->pm_suspended, 0); /* Handle any deferred wakeup events from USB during suspend */ if (motg->sm_work_pending) { motg->sm_work_pending = false; queue_work(system_nrt_wq, &motg->sm_work); } break; default: break; } return NOTIFY_OK; } static int msm_otg_mode_show(struct seq_file *s, void *unused) { struct msm_otg *motg = s->private; Loading Loading @@ -4918,6 +4953,9 @@ static int msm_otg_probe(struct platform_device *pdev) } } motg->pm_notify.notifier_call = msm_otg_pm_notify; register_pm_notifier(&motg->pm_notify); return 0; remove_cdev: Loading Loading @@ -4993,6 +5031,8 @@ static int msm_otg_remove(struct platform_device *pdev) if (phy->otg->host || phy->otg->gadget) return -EBUSY; unregister_pm_notifier(&motg->pm_notify); if (!motg->ext_chg_device) { device_destroy(motg->ext_chg_class, motg->ext_chg_dev); cdev_del(&motg->ext_chg_cdev); Loading Loading @@ -5161,7 +5201,9 @@ static int msm_otg_pm_resume(struct device *dev) dev_dbg(dev, "OTG PM resume\n"); motg->pm_done = 0; if (!motg->host_bus_suspend) atomic_set(&motg->pm_suspended, 0); if (motg->async_int || motg->sm_work_pending || !pm_runtime_suspended(dev)) { pm_runtime_get_noresume(dev); Loading @@ -5172,7 +5214,11 @@ static int msm_otg_pm_resume(struct device *dev) pm_runtime_set_active(dev); pm_runtime_enable(dev); if (motg->sm_work_pending) { /* * Defer any host mode disconnect events until * all devices are RESUMED */ if (motg->sm_work_pending && !motg->host_bus_suspend) { motg->sm_work_pending = false; queue_work(system_nrt_wq, &motg->sm_work); } Loading include/linux/usb/msm_hsusb.h +5 −0 Original line number Diff line number Diff line Loading @@ -347,6 +347,10 @@ struct msm_otg_platform_data { * @usb_phy_ctrl_reg: relevant PHY_CTRL_REG register base address. * @inputs: OTG state machine inputs(Id, SessValid etc). * @sm_work: OTG state machine work. * @pm_suspended: OTG device is system(PM) suspended. * @pm_notify: Notifier to receive system wide PM transition events. It is used to defer wakeup events processing until system is RESUMED. * @in_lpm: indicates low power mode (LPM) state. * @async_int: IRQ line on which ASYNC interrupt arrived in LPM. * @cur_power: The amount of mA available from downstream port. Loading Loading @@ -413,6 +417,7 @@ struct msm_otg { struct work_struct sm_work; bool sm_work_pending; atomic_t pm_suspended; struct notifier_block pm_notify; atomic_t in_lpm; atomic_t set_fpr_with_lpm_exit; int async_int; Loading Loading
drivers/usb/phy/phy-msm-usb.c +52 −6 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/pm_runtime.h> #include <linux/suspend.h> #include <linux/of.h> #include <linux/dma-mapping.h> #include <linux/clk/msm-clk.h> Loading Loading @@ -3498,11 +3499,13 @@ static void msm_otg_set_vbus_state(int online) return; } if (atomic_read(&motg->pm_suspended)) if (atomic_read(&motg->pm_suspended)) { motg->sm_work_pending = true; else } else if (!motg->sm_work_pending) { /* process event only if previous one is not pending */ queue_work(system_nrt_wq, &motg->sm_work); } } static void msm_id_status_w(struct work_struct *w) { Loading @@ -3511,6 +3514,8 @@ static void msm_id_status_w(struct work_struct *w) int work = 0; int id_state = 0; dev_dbg(motg->phy.dev, "ID status_w\n"); if (motg->pdata->pmic_id_irq) id_state = msm_otg_read_pmic_id_state(motg); else if (motg->ext_id_irq) Loading @@ -3530,11 +3535,13 @@ static void msm_id_status_w(struct work_struct *w) } if (work && (motg->phy.state != OTG_STATE_UNDEFINED)) { if (atomic_read(&motg->pm_suspended)) if (atomic_read(&motg->pm_suspended)) { motg->sm_work_pending = true; else } else if (!motg->sm_work_pending) { /* process event only if previous one is not pending */ queue_work(system_nrt_wq, &motg->sm_work); } } } Loading @@ -3557,6 +3564,34 @@ static irqreturn_t msm_id_irq(int irq, void *data) return IRQ_HANDLED; } int msm_otg_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused) { struct msm_otg *motg = container_of( notify_block, struct msm_otg, pm_notify); dev_dbg(motg->phy.dev, "OTG PM notify:%lx, sm_pending:%u\n", mode, motg->sm_work_pending); switch (mode) { case PM_POST_SUSPEND: /* OTG sm_work can be armed now */ atomic_set(&motg->pm_suspended, 0); /* Handle any deferred wakeup events from USB during suspend */ if (motg->sm_work_pending) { motg->sm_work_pending = false; queue_work(system_nrt_wq, &motg->sm_work); } break; default: break; } return NOTIFY_OK; } static int msm_otg_mode_show(struct seq_file *s, void *unused) { struct msm_otg *motg = s->private; Loading Loading @@ -4918,6 +4953,9 @@ static int msm_otg_probe(struct platform_device *pdev) } } motg->pm_notify.notifier_call = msm_otg_pm_notify; register_pm_notifier(&motg->pm_notify); return 0; remove_cdev: Loading Loading @@ -4993,6 +5031,8 @@ static int msm_otg_remove(struct platform_device *pdev) if (phy->otg->host || phy->otg->gadget) return -EBUSY; unregister_pm_notifier(&motg->pm_notify); if (!motg->ext_chg_device) { device_destroy(motg->ext_chg_class, motg->ext_chg_dev); cdev_del(&motg->ext_chg_cdev); Loading Loading @@ -5161,7 +5201,9 @@ static int msm_otg_pm_resume(struct device *dev) dev_dbg(dev, "OTG PM resume\n"); motg->pm_done = 0; if (!motg->host_bus_suspend) atomic_set(&motg->pm_suspended, 0); if (motg->async_int || motg->sm_work_pending || !pm_runtime_suspended(dev)) { pm_runtime_get_noresume(dev); Loading @@ -5172,7 +5214,11 @@ static int msm_otg_pm_resume(struct device *dev) pm_runtime_set_active(dev); pm_runtime_enable(dev); if (motg->sm_work_pending) { /* * Defer any host mode disconnect events until * all devices are RESUMED */ if (motg->sm_work_pending && !motg->host_bus_suspend) { motg->sm_work_pending = false; queue_work(system_nrt_wq, &motg->sm_work); } Loading
include/linux/usb/msm_hsusb.h +5 −0 Original line number Diff line number Diff line Loading @@ -347,6 +347,10 @@ struct msm_otg_platform_data { * @usb_phy_ctrl_reg: relevant PHY_CTRL_REG register base address. * @inputs: OTG state machine inputs(Id, SessValid etc). * @sm_work: OTG state machine work. * @pm_suspended: OTG device is system(PM) suspended. * @pm_notify: Notifier to receive system wide PM transition events. It is used to defer wakeup events processing until system is RESUMED. * @in_lpm: indicates low power mode (LPM) state. * @async_int: IRQ line on which ASYNC interrupt arrived in LPM. * @cur_power: The amount of mA available from downstream port. Loading Loading @@ -413,6 +417,7 @@ struct msm_otg { struct work_struct sm_work; bool sm_work_pending; atomic_t pm_suspended; struct notifier_block pm_notify; atomic_t in_lpm; atomic_t set_fpr_with_lpm_exit; int async_int; Loading