Loading drivers/usb/dwc3/dwc3-msm.c +34 −86 Original line number Diff line number Diff line Loading @@ -167,7 +167,7 @@ struct dwc3_msm { int hs_phy_irq; struct delayed_work resume_work; struct work_struct restart_usb_work; struct work_struct usb_block_reset_work; bool in_restart; struct dwc3_charger charger; struct usb_phy *otg_xceiv; struct delayed_work chg_work; Loading Loading @@ -203,7 +203,6 @@ struct dwc3_msm { #define MDWC3_PHY_REF_AND_CORECLK_OFF \ (MDWC3_PHY_REF_CLK_OFF | MDWC3_CORECLK_OFF) u32 gctl_val; u32 qscratch_ctl_val; dev_t ext_chg_dev; struct cdev ext_chg_cdev; Loading Loading @@ -879,11 +878,15 @@ void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enabled) } EXPORT_SYMBOL(dwc3_tx_fifo_resize_request); static void dwc3_resume_work(struct work_struct *w); static void dwc3_restart_usb_work(struct work_struct *w) { struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, restart_usb_work); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); enum dwc3_chg_type chg_type; unsigned timeout = 50; dev_dbg(mdwc->dev, "%s\n", __func__); Loading @@ -892,21 +895,41 @@ static void dwc3_restart_usb_work(struct work_struct *w) return; } /* guard against concurrent VBUS handling */ mdwc->in_restart = true; if (!mdwc->ext_xceiv.bsv) { dev_dbg(mdwc->dev, "%s bailing out in disconnect\n", __func__); dwc->err_evt_seen = false; mdwc->in_restart = false; return; } dbg_event(0xFF, "RestartUSB", 0); chg_type = mdwc->charger.chg_type; /* Reset active USB connection */ mdwc->ext_xceiv.bsv = false; queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0); dwc3_resume_work(&mdwc->resume_work.work); /* Make sure disconnect is processed before sending connect */ flush_delayed_work(&mdwc->resume_work); while (--timeout && !pm_runtime_suspended(mdwc->dev)) msleep(20); if (!timeout) { dev_warn(mdwc->dev, "Not in LPM after disconnect, forcing suspend...\n"); pm_runtime_suspend(mdwc->dev); } /* Force reconnect only if cable is still connected */ if (mdwc->vbus_active) { mdwc->ext_xceiv.bsv = true; queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0); mdwc->charger.chg_type = chg_type; dwc3_resume_work(&mdwc->resume_work.work); } dwc->err_evt_seen = false; mdwc->in_restart = false; } /** Loading Loading @@ -1140,11 +1163,8 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) reg |= DWC3_GCTL_CORESOFTRESET; dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg); /* * schedule work for doing block reset for recovery from erratic * error event. */ queue_work(system_nrt_wq, &mdwc->usb_block_reset_work); /* restart USB which performs full reset and reconnect */ queue_work(system_nrt_wq, &mdwc->restart_usb_work); break; case DWC3_CONTROLLER_RESET_EVENT: dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESET_EVENT received\n"); Loading Loading @@ -1220,24 +1240,6 @@ static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset) } static void dwc3_block_reset_usb_work(struct work_struct *w) { struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, usb_block_reset_work); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); unsigned long flags; dev_dbg(mdwc->dev, "%s\n", __func__); dwc3_msm_block_reset(&mdwc->ext_xceiv, true); if (mdwc->ext_xceiv.bsv) { dbg_event(0xFF, "BR EnEVT", 0); dwc3_gadget_enable_irq(dwc); } spin_lock_irqsave(&dwc->lock, flags); dwc->err_evt_seen = 0; spin_unlock_irqrestore(&dwc->lock, flags); } static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc) { u32 chg_ctrl; Loading Loading @@ -1472,6 +1474,7 @@ static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) dwc3_core_init(dwc); /* Re-configure event buffers */ dwc3_event_buffers_setup(dwc); dwc3_msm_notify_event(dwc, DWC3_CONTROLLER_POST_INITIALIZATION_EVENT); } static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) Loading Loading @@ -1690,9 +1693,6 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) /* make sure above writes are completed before turning off clocks */ wmb(); /* Save value of GCTL to rewrite upon resume */ mdwc->gctl_val = dwc3_msm_read_reg(mdwc->base, DWC3_GCTL); /* Perform controller power collapse */ if (!host_bus_suspend && !device_bus_suspend && mdwc->power_collapse) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; Loading Loading @@ -1865,8 +1865,6 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) mdwc->lpm_flags &= ~MDWC3_POWER_COLLAPSE; } dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, mdwc->gctl_val); atomic_set(&dwc->in_lpm, 0); msm_bam_notify_lpm_resume(DWC3_CTRL); Loading Loading @@ -1928,43 +1926,6 @@ static void dwc3_wait_for_ext_chg_done(struct dwc3_msm *mdwc) } static void dwc3_flush_event_buffers(struct dwc3_msm *mdwc) { struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); int i; unsigned long flags; /* Only disable/flush all events when cable is disconnected */ if (mdwc->ext_xceiv.bsv) return; /* Disable all events on cable disconnect */ dbg_event(0xFF, "Dis EVT", 0); dwc3_gadget_disable_irq(dwc); /* Skip remaining events on disconnect */ spin_lock_irqsave(&dwc->lock, flags); for (i = 0; i < dwc->num_event_buffers; i++) { struct dwc3_event_buffer *evt; evt = dwc->ev_buffs[i]; evt->lpos = (evt->lpos + evt->count) % DWC3_EVENT_BUFFERS_SIZE; evt->count = 0; evt->flags &= ~DWC3_EVENT_PENDING; } spin_unlock_irqrestore(&dwc->lock, flags); /* * If there is a pending block reset due to erratic event, * wait for it to complete */ if (dwc->err_evt_seen) { dbg_event(0xFF, "Flush BR", 0); flush_work(&mdwc->usb_block_reset_work); dwc->err_evt_seen = 0; } } static void dwc3_resume_work(struct work_struct *w) { struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, Loading @@ -1978,8 +1939,6 @@ static void dwc3_resume_work(struct work_struct *w) dbg_event(0xFF, "RWrk !lpm", 0); if (mdwc->otg_xceiv) { dwc3_wait_for_ext_chg_done(mdwc); /* Handle erratic events during cable disconnect */ dwc3_flush_event_buffers(mdwc); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, DWC3_EVENT_XCEIV_STATE); } Loading @@ -1994,11 +1953,6 @@ static void dwc3_resume_work(struct work_struct *w) dbg_event(0xFF, "RWrk !PMSus", mdwc->otg_xceiv ? 1 : 0); pm_runtime_get_sync(mdwc->dev); if (mdwc->otg_xceiv) { /* * Handle erratic events during bus suspend and cable * disconnect */ dwc3_flush_event_buffers(mdwc); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, DWC3_EVENT_PHY_RESUME); } else if (mdwc->scope == POWER_SUPPLY_SCOPE_SYSTEM) { Loading Loading @@ -2302,7 +2256,8 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, /* Process PMIC notification in PRESENT prop */ case POWER_SUPPLY_PROP_PRESENT: dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__); if (mdwc->otg_xceiv && !mdwc->ext_inuse) { mdwc->vbus_active = val->intval; if (mdwc->otg_xceiv && !mdwc->ext_inuse && !mdwc->in_restart) { if (mdwc->ext_xceiv.bsv == val->intval) break; Loading @@ -2315,7 +2270,6 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 12); } mdwc->vbus_active = val->intval; break; case POWER_SUPPLY_PROP_ONLINE: mdwc->online = val->intval; Loading Loading @@ -2849,7 +2803,6 @@ static int dwc3_msm_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work); INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work); INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work); INIT_WORK(&mdwc->usb_block_reset_work, dwc3_block_reset_usb_work); INIT_WORK(&mdwc->id_work, dwc3_id_work); INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work); init_completion(&mdwc->ext_chg_wait); Loading Loading @@ -3487,11 +3440,6 @@ static int dwc3_msm_pm_resume(struct device *dev) /* Let OTG know about resume event and update pm_count */ if (mdwc->otg_xceiv) { /* * Handle erratic events on bus suspend, PM suspend * and cable disconnect */ dwc3_flush_event_buffers(mdwc); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, DWC3_EVENT_PHY_RESUME); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, Loading Loading
drivers/usb/dwc3/dwc3-msm.c +34 −86 Original line number Diff line number Diff line Loading @@ -167,7 +167,7 @@ struct dwc3_msm { int hs_phy_irq; struct delayed_work resume_work; struct work_struct restart_usb_work; struct work_struct usb_block_reset_work; bool in_restart; struct dwc3_charger charger; struct usb_phy *otg_xceiv; struct delayed_work chg_work; Loading Loading @@ -203,7 +203,6 @@ struct dwc3_msm { #define MDWC3_PHY_REF_AND_CORECLK_OFF \ (MDWC3_PHY_REF_CLK_OFF | MDWC3_CORECLK_OFF) u32 gctl_val; u32 qscratch_ctl_val; dev_t ext_chg_dev; struct cdev ext_chg_cdev; Loading Loading @@ -879,11 +878,15 @@ void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enabled) } EXPORT_SYMBOL(dwc3_tx_fifo_resize_request); static void dwc3_resume_work(struct work_struct *w); static void dwc3_restart_usb_work(struct work_struct *w) { struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, restart_usb_work); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); enum dwc3_chg_type chg_type; unsigned timeout = 50; dev_dbg(mdwc->dev, "%s\n", __func__); Loading @@ -892,21 +895,41 @@ static void dwc3_restart_usb_work(struct work_struct *w) return; } /* guard against concurrent VBUS handling */ mdwc->in_restart = true; if (!mdwc->ext_xceiv.bsv) { dev_dbg(mdwc->dev, "%s bailing out in disconnect\n", __func__); dwc->err_evt_seen = false; mdwc->in_restart = false; return; } dbg_event(0xFF, "RestartUSB", 0); chg_type = mdwc->charger.chg_type; /* Reset active USB connection */ mdwc->ext_xceiv.bsv = false; queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0); dwc3_resume_work(&mdwc->resume_work.work); /* Make sure disconnect is processed before sending connect */ flush_delayed_work(&mdwc->resume_work); while (--timeout && !pm_runtime_suspended(mdwc->dev)) msleep(20); if (!timeout) { dev_warn(mdwc->dev, "Not in LPM after disconnect, forcing suspend...\n"); pm_runtime_suspend(mdwc->dev); } /* Force reconnect only if cable is still connected */ if (mdwc->vbus_active) { mdwc->ext_xceiv.bsv = true; queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 0); mdwc->charger.chg_type = chg_type; dwc3_resume_work(&mdwc->resume_work.work); } dwc->err_evt_seen = false; mdwc->in_restart = false; } /** Loading Loading @@ -1140,11 +1163,8 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) reg |= DWC3_GCTL_CORESOFTRESET; dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg); /* * schedule work for doing block reset for recovery from erratic * error event. */ queue_work(system_nrt_wq, &mdwc->usb_block_reset_work); /* restart USB which performs full reset and reconnect */ queue_work(system_nrt_wq, &mdwc->restart_usb_work); break; case DWC3_CONTROLLER_RESET_EVENT: dev_dbg(mdwc->dev, "DWC3_CONTROLLER_RESET_EVENT received\n"); Loading Loading @@ -1220,24 +1240,6 @@ static void dwc3_msm_block_reset(struct dwc3_ext_xceiv *xceiv, bool core_reset) } static void dwc3_block_reset_usb_work(struct work_struct *w) { struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, usb_block_reset_work); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); unsigned long flags; dev_dbg(mdwc->dev, "%s\n", __func__); dwc3_msm_block_reset(&mdwc->ext_xceiv, true); if (mdwc->ext_xceiv.bsv) { dbg_event(0xFF, "BR EnEVT", 0); dwc3_gadget_enable_irq(dwc); } spin_lock_irqsave(&dwc->lock, flags); dwc->err_evt_seen = 0; spin_unlock_irqrestore(&dwc->lock, flags); } static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc) { u32 chg_ctrl; Loading Loading @@ -1472,6 +1474,7 @@ static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) dwc3_core_init(dwc); /* Re-configure event buffers */ dwc3_event_buffers_setup(dwc); dwc3_msm_notify_event(dwc, DWC3_CONTROLLER_POST_INITIALIZATION_EVENT); } static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) Loading Loading @@ -1690,9 +1693,6 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) /* make sure above writes are completed before turning off clocks */ wmb(); /* Save value of GCTL to rewrite upon resume */ mdwc->gctl_val = dwc3_msm_read_reg(mdwc->base, DWC3_GCTL); /* Perform controller power collapse */ if (!host_bus_suspend && !device_bus_suspend && mdwc->power_collapse) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; Loading Loading @@ -1865,8 +1865,6 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) mdwc->lpm_flags &= ~MDWC3_POWER_COLLAPSE; } dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, mdwc->gctl_val); atomic_set(&dwc->in_lpm, 0); msm_bam_notify_lpm_resume(DWC3_CTRL); Loading Loading @@ -1928,43 +1926,6 @@ static void dwc3_wait_for_ext_chg_done(struct dwc3_msm *mdwc) } static void dwc3_flush_event_buffers(struct dwc3_msm *mdwc) { struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); int i; unsigned long flags; /* Only disable/flush all events when cable is disconnected */ if (mdwc->ext_xceiv.bsv) return; /* Disable all events on cable disconnect */ dbg_event(0xFF, "Dis EVT", 0); dwc3_gadget_disable_irq(dwc); /* Skip remaining events on disconnect */ spin_lock_irqsave(&dwc->lock, flags); for (i = 0; i < dwc->num_event_buffers; i++) { struct dwc3_event_buffer *evt; evt = dwc->ev_buffs[i]; evt->lpos = (evt->lpos + evt->count) % DWC3_EVENT_BUFFERS_SIZE; evt->count = 0; evt->flags &= ~DWC3_EVENT_PENDING; } spin_unlock_irqrestore(&dwc->lock, flags); /* * If there is a pending block reset due to erratic event, * wait for it to complete */ if (dwc->err_evt_seen) { dbg_event(0xFF, "Flush BR", 0); flush_work(&mdwc->usb_block_reset_work); dwc->err_evt_seen = 0; } } static void dwc3_resume_work(struct work_struct *w) { struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, Loading @@ -1978,8 +1939,6 @@ static void dwc3_resume_work(struct work_struct *w) dbg_event(0xFF, "RWrk !lpm", 0); if (mdwc->otg_xceiv) { dwc3_wait_for_ext_chg_done(mdwc); /* Handle erratic events during cable disconnect */ dwc3_flush_event_buffers(mdwc); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, DWC3_EVENT_XCEIV_STATE); } Loading @@ -1994,11 +1953,6 @@ static void dwc3_resume_work(struct work_struct *w) dbg_event(0xFF, "RWrk !PMSus", mdwc->otg_xceiv ? 1 : 0); pm_runtime_get_sync(mdwc->dev); if (mdwc->otg_xceiv) { /* * Handle erratic events during bus suspend and cable * disconnect */ dwc3_flush_event_buffers(mdwc); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, DWC3_EVENT_PHY_RESUME); } else if (mdwc->scope == POWER_SUPPLY_SCOPE_SYSTEM) { Loading Loading @@ -2302,7 +2256,8 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, /* Process PMIC notification in PRESENT prop */ case POWER_SUPPLY_PROP_PRESENT: dev_dbg(mdwc->dev, "%s: notify xceiv event\n", __func__); if (mdwc->otg_xceiv && !mdwc->ext_inuse) { mdwc->vbus_active = val->intval; if (mdwc->otg_xceiv && !mdwc->ext_inuse && !mdwc->in_restart) { if (mdwc->ext_xceiv.bsv == val->intval) break; Loading @@ -2315,7 +2270,6 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy, queue_delayed_work(system_nrt_wq, &mdwc->resume_work, 12); } mdwc->vbus_active = val->intval; break; case POWER_SUPPLY_PROP_ONLINE: mdwc->online = val->intval; Loading Loading @@ -2849,7 +2803,6 @@ static int dwc3_msm_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&mdwc->chg_work, dwc3_chg_detect_work); INIT_DELAYED_WORK(&mdwc->resume_work, dwc3_resume_work); INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work); INIT_WORK(&mdwc->usb_block_reset_work, dwc3_block_reset_usb_work); INIT_WORK(&mdwc->id_work, dwc3_id_work); INIT_DELAYED_WORK(&mdwc->init_adc_work, dwc3_init_adc_work); init_completion(&mdwc->ext_chg_wait); Loading Loading @@ -3487,11 +3440,6 @@ static int dwc3_msm_pm_resume(struct device *dev) /* Let OTG know about resume event and update pm_count */ if (mdwc->otg_xceiv) { /* * Handle erratic events on bus suspend, PM suspend * and cable disconnect */ dwc3_flush_event_buffers(mdwc); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, DWC3_EVENT_PHY_RESUME); mdwc->ext_xceiv.notify_ext_events(mdwc->otg_xceiv->otg, Loading