Loading Documentation/devicetree/bindings/usb/msm-ssusb.txt +0 −2 Original line number Original line Diff line number Diff line Loading @@ -33,8 +33,6 @@ Optional properties : TX fifo allocation in bytes TX fifo allocation in bytes - qcom,utmi-clk-rate: Indicates refclk frequency (in Hz) to the core. If not - qcom,utmi-clk-rate: Indicates refclk frequency (in Hz) to the core. If not specified, default of 19.2MHz is assumed. specified, default of 19.2MHz is assumed. - qcom,no-suspend-resume: If present, the device will not perform any activity during suspend/resume - qcom,usb-dbm : phandle for the DBM device - qcom,usb-dbm : phandle for the DBM device - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform power collapse when cable is disconencted. power collapse when cable is disconencted. Loading drivers/usb/dwc3/dwc3-msm.c +52 −133 Original line number Original line Diff line number Diff line Loading @@ -62,10 +62,6 @@ static int override_phy_init; module_param(override_phy_init, int, S_IRUGO|S_IWUSR); module_param(override_phy_init, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq"); MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq"); static bool usb_lpm_override; module_param(usb_lpm_override, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(usb_lpm_override, "Override no_suspend_resume with USB"); /* Max current to be drawn for HVDCP charger */ /* Max current to be drawn for HVDCP charger */ static int hvdcp_max_current = DWC3_HVDCP_CHG_MAX; static int hvdcp_max_current = DWC3_HVDCP_CHG_MAX; module_param(hvdcp_max_current, int, S_IRUGO|S_IWUSR); module_param(hvdcp_max_current, int, S_IRUGO|S_IWUSR); Loading @@ -85,7 +81,6 @@ MODULE_PARM_DESC(dcp_max_current, "max current drawn for DCP charger"); * * */ */ #define QSCRATCH_REG_OFFSET (0x000F8800) #define QSCRATCH_REG_OFFSET (0x000F8800) #define QSCRATCH_CTRL_REG (QSCRATCH_REG_OFFSET + 0x04) #define QSCRATCH_GENERAL_CFG (QSCRATCH_REG_OFFSET + 0x08) #define QSCRATCH_GENERAL_CFG (QSCRATCH_REG_OFFSET + 0x08) #define CGCTL_REG (QSCRATCH_REG_OFFSET + 0x28) #define CGCTL_REG (QSCRATCH_REG_OFFSET + 0x28) #define PWR_EVNT_IRQ_STAT_REG (QSCRATCH_REG_OFFSET + 0x58) #define PWR_EVNT_IRQ_STAT_REG (QSCRATCH_REG_OFFSET + 0x58) Loading Loading @@ -205,13 +200,8 @@ struct dwc3_msm { enum dwc3_id_state id_state; enum dwc3_id_state id_state; unsigned long lpm_flags; unsigned long lpm_flags; #define MDWC3_SS_PHY_SUSPEND BIT(0) #define MDWC3_SS_PHY_SUSPEND BIT(0) #define MDWC3_TCXO_SHUTDOWN BIT(1) #define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(1) #define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(2) #define MDWC3_POWER_COLLAPSE BIT(2) #define MDWC3_POWER_COLLAPSE BIT(3) #define MDWC3_CORECLK_OFF BIT(4) u32 qscratch_ctl_val; bool suspend_resume_no_support; bool power_collapse; /* power collapse on cable disconnect */ bool power_collapse; /* power collapse on cable disconnect */ bool power_collapse_por; /* perform POR sequence after power collapse */ bool power_collapse_por; /* perform POR sequence after power collapse */ Loading Loading @@ -1062,12 +1052,6 @@ static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc) dwc3_msm_write_reg(mdwc->base, CGCTL_REG, dwc3_msm_write_reg(mdwc->base, CGCTL_REG, dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18); dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18); /* * This is required to restore the POR value after userspace * is done with charger detection. */ mdwc->qscratch_ctl_val = dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG); } } static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) Loading Loading @@ -1216,16 +1200,11 @@ static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) { { struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); unsigned long timeout; unsigned long timeout; u32 reg = 0; u32 reg = 0; bool device_mode; device_mode = dwc->is_drd && mdwc->otg_state == OTG_STATE_B_PERIPHERAL; if ((mdwc->in_host_mode || device_mode) && if ((mdwc->in_host_mode || mdwc->vbus_active) dwc3_msm_is_superspeed(mdwc)) { && dwc3_msm_is_superspeed(mdwc)) { if (!atomic_read(&mdwc->in_p3)) { if (!atomic_read(&mdwc->in_p3)) { dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n"); dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n"); return -EBUSY; return -EBUSY; Loading Loading @@ -1295,29 +1274,16 @@ static void dwc3_msm_bus_vote_w(struct work_struct *w) static int dwc3_msm_suspend(struct dwc3_msm *mdwc) static int dwc3_msm_suspend(struct dwc3_msm *mdwc) { { int ret, i; int ret, i; bool dcp; bool host_ss_active; bool can_suspend_ssphy; bool can_suspend_ssphy; bool device_bus_suspend = false; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(mdwc->dev, "%s: entering lpm. usb_lpm_override:%d\n", __func__, usb_lpm_override); dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm)); dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm)); if (!usb_lpm_override && mdwc->suspend_resume_no_support) { dev_dbg(mdwc->dev, "%s no support for suspend\n", __func__); return -EPERM; } if (atomic_read(&dwc->in_lpm)) { if (atomic_read(&dwc->in_lpm)) { dev_dbg(mdwc->dev, "%s: Already suspended\n", __func__); dev_dbg(mdwc->dev, "%s: Already suspended\n", __func__); return 0; return 0; } } if (dwc->is_drd && mdwc->otg_state == OTG_STATE_B_SUSPEND) device_bus_suspend = true; if (!mdwc->in_host_mode) { if (!mdwc->in_host_mode) { /* pending device events unprocessed */ /* pending device events unprocessed */ for (i = 0; i < dwc->num_event_buffers; i++) { for (i = 0; i < dwc->num_event_buffers; i++) { Loading Loading @@ -1350,33 +1316,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) return -EBUSY; return -EBUSY; } } host_ss_active = dwc3_msm_is_host_superspeed(mdwc); if (mdwc->chg_state != USB_CHG_STATE_DETECTED) { /* charger detection wasn't complete; re-init flags */ mdwc->chg_state = USB_CHG_STATE_UNDEFINED; mdwc->chg_type = DWC3_INVALID_CHARGER; } dcp = ((mdwc->chg_type == DWC3_DCP_CHARGER) || (mdwc->chg_type == DWC3_PROPRIETARY_CHARGER) || (mdwc->chg_type == DWC3_FLOATED_CHARGER)); if (dcp) { mdwc->hs_phy->flags |= PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags |= PHY_CHARGER_CONNECTED; } else { mdwc->hs_phy->flags &= ~PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags &= ~PHY_CHARGER_CONNECTED; } can_suspend_ssphy = !(mdwc->in_host_mode && host_ss_active); /* /* * Check if device is not in CONFIGURED state * Check if device is not in CONFIGURED state * then check cotroller state of L2 and break * then check controller state of L2 and break * LPM sequeunce. * LPM sequence. Check this for device bus suspend case. */ */ if (device_bus_suspend && if ((dwc->is_drd && mdwc->otg_state == OTG_STATE_B_SUSPEND) && (dwc->gadget.state != USB_STATE_CONFIGURED)) { (dwc->gadget.state != USB_STATE_CONFIGURED)) { pr_err("%s(): Trying to go in LPM with state:%d\n", pr_err("%s(): Trying to go in LPM with state:%d\n", __func__, dwc->gadget.state); __func__, dwc->gadget.state); Loading @@ -1388,14 +1333,14 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) if (ret) if (ret) return ret; return ret; /* Initialize variables here */ can_suspend_ssphy = !(mdwc->in_host_mode && dwc3_msm_is_host_superspeed(mdwc)); /* Disable core irq */ /* Disable core irq */ if (dwc->irq) if (dwc->irq) disable_irq(dwc->irq); disable_irq(dwc->irq); if (!dcp && !mdwc->in_host_mode) dwc3_msm_write_reg(mdwc->base, QSCRATCH_CTRL_REG, mdwc->qscratch_ctl_val); /* Enable wakeup from LPM */ /* Enable wakeup from LPM */ if (mdwc->pwr_event_irq) { if (mdwc->pwr_event_irq) { disable_irq(mdwc->pwr_event_irq); disable_irq(mdwc->pwr_event_irq); Loading @@ -1403,40 +1348,38 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) enable_irq_wake(mdwc->pwr_event_irq); enable_irq_wake(mdwc->pwr_event_irq); } } /* Suspend HS PHY */ usb_phy_set_suspend(mdwc->hs_phy, 1); usb_phy_set_suspend(mdwc->hs_phy, 1); /* Suspend SS PHY */ if (can_suspend_ssphy) { if (can_suspend_ssphy) { usb_phy_set_suspend(mdwc->ss_phy, 1); usb_phy_set_suspend(mdwc->ss_phy, 1); usleep_range(1000, 1200); mdwc->lpm_flags |= MDWC3_SS_PHY_SUSPEND; mdwc->lpm_flags |= MDWC3_SS_PHY_SUSPEND; } } /* make sure above writes are completed before turning off clocks */ /* make sure above writes are completed before turning off clocks */ wmb(); wmb(); /* Perform controller power collapse */ /* Disable clocks */ if (!mdwc->in_host_mode && !device_bus_suspend && mdwc->power_collapse) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; dev_dbg(mdwc->dev, "%s: power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 0); clk_disable_unprepare(mdwc->sleep_clk); } clk_disable_unprepare(mdwc->iface_clk); clk_disable_unprepare(mdwc->iface_clk); if (mdwc->bus_aggr_clk) if (mdwc->bus_aggr_clk) clk_disable_unprepare(mdwc->bus_aggr_clk); clk_disable_unprepare(mdwc->bus_aggr_clk); clk_disable_unprepare(mdwc->utmi_clk); clk_disable_unprepare(mdwc->utmi_clk); if (can_suspend_ssphy) { clk_set_rate(mdwc->core_clk, 19200000); clk_set_rate(mdwc->core_clk, 19200000); clk_disable_unprepare(mdwc->core_clk); clk_disable_unprepare(mdwc->core_clk); mdwc->lpm_flags |= MDWC3_CORECLK_OFF; /* USB PHY no more requires TCXO */ /* USB PHY no more requires TCXO */ clk_disable_unprepare(mdwc->xo_clk); clk_disable_unprepare(mdwc->xo_clk); mdwc->lpm_flags |= MDWC3_TCXO_SHUTDOWN; /* Perform controller power collapse */ if (!mdwc->in_host_mode && !mdwc->vbus_active && mdwc->power_collapse) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; dev_dbg(mdwc->dev, "%s: power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 0); clk_disable_unprepare(mdwc->sleep_clk); } } /* Remove bus voting */ if (mdwc->bus_perf_client) { if (mdwc->bus_perf_client) { mdwc->bus_vote = 0; mdwc->bus_vote = 0; schedule_work(&mdwc->bus_vote_w); schedule_work(&mdwc->bus_vote_w); Loading @@ -1455,19 +1398,18 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) pm_relax(mdwc->dev); pm_relax(mdwc->dev); } } if (mdwc->hs_phy_irq) { /* /* * with DCP or during cable disconnect, we dont require wakeup * with DCP or during cable disconnect, we dont require wakeup * using HS_PHY_IRQ. Hence enable wakeup only in case of host * using HS_PHY_IRQ. Hence enable wakeup only in case of host * bus suspend and device bus suspend. * bus suspend and device bus suspend. */ */ if (mdwc->in_host_mode || device_bus_suspend) { if (mdwc->hs_phy_irq && (mdwc->vbus_active || mdwc->in_host_mode)) { enable_irq_wake(mdwc->hs_phy_irq); enable_irq_wake(mdwc->hs_phy_irq); mdwc->lpm_flags |= MDWC3_ASYNC_IRQ_WAKE_CAPABILITY; mdwc->lpm_flags |= MDWC3_ASYNC_IRQ_WAKE_CAPABILITY; } } } atomic_set(&dwc->in_lpm, 1); atomic_set(&dwc->in_lpm, 1); if (mdwc->pwr_event_irq) if (mdwc->pwr_event_irq) enable_irq(mdwc->pwr_event_irq); enable_irq(mdwc->pwr_event_irq); Loading @@ -1478,7 +1420,6 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) static int dwc3_msm_resume(struct dwc3_msm *mdwc) static int dwc3_msm_resume(struct dwc3_msm *mdwc) { { int ret; int ret; bool dcp; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__); dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__); Loading @@ -1490,30 +1431,17 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) pm_stay_awake(mdwc->dev); pm_stay_awake(mdwc->dev); /* Enable bus voting */ if (mdwc->bus_perf_client) { if (mdwc->bus_perf_client) { mdwc->bus_vote = 1; mdwc->bus_vote = 1; schedule_work(&mdwc->bus_vote_w); schedule_work(&mdwc->bus_vote_w); } } dcp = ((mdwc->chg_type == DWC3_DCP_CHARGER) || (mdwc->chg_type == DWC3_PROPRIETARY_CHARGER) || (mdwc->chg_type == DWC3_FLOATED_CHARGER)); if (dcp) { mdwc->hs_phy->flags |= PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags |= PHY_CHARGER_CONNECTED; } else { mdwc->hs_phy->flags &= ~PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags &= ~PHY_CHARGER_CONNECTED; } if (mdwc->lpm_flags & MDWC3_TCXO_SHUTDOWN) { /* Vote for TCXO while waking up USB HSPHY */ /* Vote for TCXO while waking up USB HSPHY */ ret = clk_prepare_enable(mdwc->xo_clk); ret = clk_prepare_enable(mdwc->xo_clk); if (ret) if (ret) dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n", dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n", __func__, ret); __func__, ret); mdwc->lpm_flags &= ~MDWC3_TCXO_SHUTDOWN; } /* Restore controller power collapse */ /* Restore controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { Loading @@ -1524,31 +1452,25 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) /* HW requires a short delay for reset to take place properly */ /* HW requires a short delay for reset to take place properly */ usleep_range(1000, 1200); usleep_range(1000, 1200); clk_reset(mdwc->core_clk, CLK_RESET_DEASSERT); clk_reset(mdwc->core_clk, CLK_RESET_DEASSERT); clk_prepare_enable(mdwc->sleep_clk); } } /* Resume SS PHY */ if (mdwc->lpm_flags & MDWC3_SS_PHY_SUSPEND) { if (mdwc->lpm_flags & MDWC3_SS_PHY_SUSPEND) { usb_phy_set_suspend(mdwc->ss_phy, 0); usb_phy_set_suspend(mdwc->ss_phy, 0); mdwc->lpm_flags &= ~MDWC3_SS_PHY_SUSPEND; mdwc->lpm_flags &= ~MDWC3_SS_PHY_SUSPEND; } } usleep_range(1000, 1200); if (mdwc->bus_aggr_clk) /* Resume HS PHY */ clk_prepare_enable(mdwc->bus_aggr_clk); usb_phy_set_suspend(mdwc->hs_phy, 0); clk_prepare_enable(mdwc->iface_clk); /* Enable clocks */ if (mdwc->lpm_flags & MDWC3_CORECLK_OFF) { clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate); clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate); clk_prepare_enable(mdwc->core_clk); clk_prepare_enable(mdwc->core_clk); mdwc->lpm_flags &= ~MDWC3_CORECLK_OFF; } clk_prepare_enable(mdwc->utmi_clk); clk_prepare_enable(mdwc->utmi_clk); if (mdwc->bus_aggr_clk) if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) clk_prepare_enable(mdwc->bus_aggr_clk); clk_prepare_enable(mdwc->sleep_clk); clk_prepare_enable(mdwc->iface_clk); usb_phy_set_suspend(mdwc->hs_phy, 0); /* Recover from controller power collapse */ /* Recover from controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { Loading Loading @@ -2229,9 +2151,6 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->charging_disabled = of_property_read_bool(node, mdwc->charging_disabled = of_property_read_bool(node, "qcom,charging-disabled"); "qcom,charging-disabled"); mdwc->suspend_resume_no_support = of_property_read_bool(node, "qcom,no-suspend-resume"); mdwc->power_collapse_por = of_property_read_bool(node, mdwc->power_collapse_por = of_property_read_bool(node, "qcom,por-after-power-collapse"); "qcom,por-after-power-collapse"); Loading Loading
Documentation/devicetree/bindings/usb/msm-ssusb.txt +0 −2 Original line number Original line Diff line number Diff line Loading @@ -33,8 +33,6 @@ Optional properties : TX fifo allocation in bytes TX fifo allocation in bytes - qcom,utmi-clk-rate: Indicates refclk frequency (in Hz) to the core. If not - qcom,utmi-clk-rate: Indicates refclk frequency (in Hz) to the core. If not specified, default of 19.2MHz is assumed. specified, default of 19.2MHz is assumed. - qcom,no-suspend-resume: If present, the device will not perform any activity during suspend/resume - qcom,usb-dbm : phandle for the DBM device - qcom,usb-dbm : phandle for the DBM device - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform power collapse when cable is disconencted. power collapse when cable is disconencted. Loading
drivers/usb/dwc3/dwc3-msm.c +52 −133 Original line number Original line Diff line number Diff line Loading @@ -62,10 +62,6 @@ static int override_phy_init; module_param(override_phy_init, int, S_IRUGO|S_IWUSR); module_param(override_phy_init, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq"); MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq"); static bool usb_lpm_override; module_param(usb_lpm_override, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(usb_lpm_override, "Override no_suspend_resume with USB"); /* Max current to be drawn for HVDCP charger */ /* Max current to be drawn for HVDCP charger */ static int hvdcp_max_current = DWC3_HVDCP_CHG_MAX; static int hvdcp_max_current = DWC3_HVDCP_CHG_MAX; module_param(hvdcp_max_current, int, S_IRUGO|S_IWUSR); module_param(hvdcp_max_current, int, S_IRUGO|S_IWUSR); Loading @@ -85,7 +81,6 @@ MODULE_PARM_DESC(dcp_max_current, "max current drawn for DCP charger"); * * */ */ #define QSCRATCH_REG_OFFSET (0x000F8800) #define QSCRATCH_REG_OFFSET (0x000F8800) #define QSCRATCH_CTRL_REG (QSCRATCH_REG_OFFSET + 0x04) #define QSCRATCH_GENERAL_CFG (QSCRATCH_REG_OFFSET + 0x08) #define QSCRATCH_GENERAL_CFG (QSCRATCH_REG_OFFSET + 0x08) #define CGCTL_REG (QSCRATCH_REG_OFFSET + 0x28) #define CGCTL_REG (QSCRATCH_REG_OFFSET + 0x28) #define PWR_EVNT_IRQ_STAT_REG (QSCRATCH_REG_OFFSET + 0x58) #define PWR_EVNT_IRQ_STAT_REG (QSCRATCH_REG_OFFSET + 0x58) Loading Loading @@ -205,13 +200,8 @@ struct dwc3_msm { enum dwc3_id_state id_state; enum dwc3_id_state id_state; unsigned long lpm_flags; unsigned long lpm_flags; #define MDWC3_SS_PHY_SUSPEND BIT(0) #define MDWC3_SS_PHY_SUSPEND BIT(0) #define MDWC3_TCXO_SHUTDOWN BIT(1) #define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(1) #define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(2) #define MDWC3_POWER_COLLAPSE BIT(2) #define MDWC3_POWER_COLLAPSE BIT(3) #define MDWC3_CORECLK_OFF BIT(4) u32 qscratch_ctl_val; bool suspend_resume_no_support; bool power_collapse; /* power collapse on cable disconnect */ bool power_collapse; /* power collapse on cable disconnect */ bool power_collapse_por; /* perform POR sequence after power collapse */ bool power_collapse_por; /* perform POR sequence after power collapse */ Loading Loading @@ -1062,12 +1052,6 @@ static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *mdwc) dwc3_msm_write_reg(mdwc->base, CGCTL_REG, dwc3_msm_write_reg(mdwc->base, CGCTL_REG, dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18); dwc3_msm_read_reg(mdwc->base, CGCTL_REG) | 0x18); /* * This is required to restore the POR value after userspace * is done with charger detection. */ mdwc->qscratch_ctl_val = dwc3_msm_read_reg(mdwc->base, QSCRATCH_CTRL_REG); } } static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned event) Loading Loading @@ -1216,16 +1200,11 @@ static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) static int dwc3_msm_prepare_suspend(struct dwc3_msm *mdwc) { { struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); unsigned long timeout; unsigned long timeout; u32 reg = 0; u32 reg = 0; bool device_mode; device_mode = dwc->is_drd && mdwc->otg_state == OTG_STATE_B_PERIPHERAL; if ((mdwc->in_host_mode || device_mode) && if ((mdwc->in_host_mode || mdwc->vbus_active) dwc3_msm_is_superspeed(mdwc)) { && dwc3_msm_is_superspeed(mdwc)) { if (!atomic_read(&mdwc->in_p3)) { if (!atomic_read(&mdwc->in_p3)) { dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n"); dev_err(mdwc->dev, "Not in P3,aborting LPM sequence\n"); return -EBUSY; return -EBUSY; Loading Loading @@ -1295,29 +1274,16 @@ static void dwc3_msm_bus_vote_w(struct work_struct *w) static int dwc3_msm_suspend(struct dwc3_msm *mdwc) static int dwc3_msm_suspend(struct dwc3_msm *mdwc) { { int ret, i; int ret, i; bool dcp; bool host_ss_active; bool can_suspend_ssphy; bool can_suspend_ssphy; bool device_bus_suspend = false; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(mdwc->dev, "%s: entering lpm. usb_lpm_override:%d\n", __func__, usb_lpm_override); dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm)); dbg_event(0xFF, "Ctl Sus", atomic_read(&dwc->in_lpm)); if (!usb_lpm_override && mdwc->suspend_resume_no_support) { dev_dbg(mdwc->dev, "%s no support for suspend\n", __func__); return -EPERM; } if (atomic_read(&dwc->in_lpm)) { if (atomic_read(&dwc->in_lpm)) { dev_dbg(mdwc->dev, "%s: Already suspended\n", __func__); dev_dbg(mdwc->dev, "%s: Already suspended\n", __func__); return 0; return 0; } } if (dwc->is_drd && mdwc->otg_state == OTG_STATE_B_SUSPEND) device_bus_suspend = true; if (!mdwc->in_host_mode) { if (!mdwc->in_host_mode) { /* pending device events unprocessed */ /* pending device events unprocessed */ for (i = 0; i < dwc->num_event_buffers; i++) { for (i = 0; i < dwc->num_event_buffers; i++) { Loading Loading @@ -1350,33 +1316,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) return -EBUSY; return -EBUSY; } } host_ss_active = dwc3_msm_is_host_superspeed(mdwc); if (mdwc->chg_state != USB_CHG_STATE_DETECTED) { /* charger detection wasn't complete; re-init flags */ mdwc->chg_state = USB_CHG_STATE_UNDEFINED; mdwc->chg_type = DWC3_INVALID_CHARGER; } dcp = ((mdwc->chg_type == DWC3_DCP_CHARGER) || (mdwc->chg_type == DWC3_PROPRIETARY_CHARGER) || (mdwc->chg_type == DWC3_FLOATED_CHARGER)); if (dcp) { mdwc->hs_phy->flags |= PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags |= PHY_CHARGER_CONNECTED; } else { mdwc->hs_phy->flags &= ~PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags &= ~PHY_CHARGER_CONNECTED; } can_suspend_ssphy = !(mdwc->in_host_mode && host_ss_active); /* /* * Check if device is not in CONFIGURED state * Check if device is not in CONFIGURED state * then check cotroller state of L2 and break * then check controller state of L2 and break * LPM sequeunce. * LPM sequence. Check this for device bus suspend case. */ */ if (device_bus_suspend && if ((dwc->is_drd && mdwc->otg_state == OTG_STATE_B_SUSPEND) && (dwc->gadget.state != USB_STATE_CONFIGURED)) { (dwc->gadget.state != USB_STATE_CONFIGURED)) { pr_err("%s(): Trying to go in LPM with state:%d\n", pr_err("%s(): Trying to go in LPM with state:%d\n", __func__, dwc->gadget.state); __func__, dwc->gadget.state); Loading @@ -1388,14 +1333,14 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) if (ret) if (ret) return ret; return ret; /* Initialize variables here */ can_suspend_ssphy = !(mdwc->in_host_mode && dwc3_msm_is_host_superspeed(mdwc)); /* Disable core irq */ /* Disable core irq */ if (dwc->irq) if (dwc->irq) disable_irq(dwc->irq); disable_irq(dwc->irq); if (!dcp && !mdwc->in_host_mode) dwc3_msm_write_reg(mdwc->base, QSCRATCH_CTRL_REG, mdwc->qscratch_ctl_val); /* Enable wakeup from LPM */ /* Enable wakeup from LPM */ if (mdwc->pwr_event_irq) { if (mdwc->pwr_event_irq) { disable_irq(mdwc->pwr_event_irq); disable_irq(mdwc->pwr_event_irq); Loading @@ -1403,40 +1348,38 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) enable_irq_wake(mdwc->pwr_event_irq); enable_irq_wake(mdwc->pwr_event_irq); } } /* Suspend HS PHY */ usb_phy_set_suspend(mdwc->hs_phy, 1); usb_phy_set_suspend(mdwc->hs_phy, 1); /* Suspend SS PHY */ if (can_suspend_ssphy) { if (can_suspend_ssphy) { usb_phy_set_suspend(mdwc->ss_phy, 1); usb_phy_set_suspend(mdwc->ss_phy, 1); usleep_range(1000, 1200); mdwc->lpm_flags |= MDWC3_SS_PHY_SUSPEND; mdwc->lpm_flags |= MDWC3_SS_PHY_SUSPEND; } } /* make sure above writes are completed before turning off clocks */ /* make sure above writes are completed before turning off clocks */ wmb(); wmb(); /* Perform controller power collapse */ /* Disable clocks */ if (!mdwc->in_host_mode && !device_bus_suspend && mdwc->power_collapse) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; dev_dbg(mdwc->dev, "%s: power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 0); clk_disable_unprepare(mdwc->sleep_clk); } clk_disable_unprepare(mdwc->iface_clk); clk_disable_unprepare(mdwc->iface_clk); if (mdwc->bus_aggr_clk) if (mdwc->bus_aggr_clk) clk_disable_unprepare(mdwc->bus_aggr_clk); clk_disable_unprepare(mdwc->bus_aggr_clk); clk_disable_unprepare(mdwc->utmi_clk); clk_disable_unprepare(mdwc->utmi_clk); if (can_suspend_ssphy) { clk_set_rate(mdwc->core_clk, 19200000); clk_set_rate(mdwc->core_clk, 19200000); clk_disable_unprepare(mdwc->core_clk); clk_disable_unprepare(mdwc->core_clk); mdwc->lpm_flags |= MDWC3_CORECLK_OFF; /* USB PHY no more requires TCXO */ /* USB PHY no more requires TCXO */ clk_disable_unprepare(mdwc->xo_clk); clk_disable_unprepare(mdwc->xo_clk); mdwc->lpm_flags |= MDWC3_TCXO_SHUTDOWN; /* Perform controller power collapse */ if (!mdwc->in_host_mode && !mdwc->vbus_active && mdwc->power_collapse) { mdwc->lpm_flags |= MDWC3_POWER_COLLAPSE; dev_dbg(mdwc->dev, "%s: power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 0); clk_disable_unprepare(mdwc->sleep_clk); } } /* Remove bus voting */ if (mdwc->bus_perf_client) { if (mdwc->bus_perf_client) { mdwc->bus_vote = 0; mdwc->bus_vote = 0; schedule_work(&mdwc->bus_vote_w); schedule_work(&mdwc->bus_vote_w); Loading @@ -1455,19 +1398,18 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) pm_relax(mdwc->dev); pm_relax(mdwc->dev); } } if (mdwc->hs_phy_irq) { /* /* * with DCP or during cable disconnect, we dont require wakeup * with DCP or during cable disconnect, we dont require wakeup * using HS_PHY_IRQ. Hence enable wakeup only in case of host * using HS_PHY_IRQ. Hence enable wakeup only in case of host * bus suspend and device bus suspend. * bus suspend and device bus suspend. */ */ if (mdwc->in_host_mode || device_bus_suspend) { if (mdwc->hs_phy_irq && (mdwc->vbus_active || mdwc->in_host_mode)) { enable_irq_wake(mdwc->hs_phy_irq); enable_irq_wake(mdwc->hs_phy_irq); mdwc->lpm_flags |= MDWC3_ASYNC_IRQ_WAKE_CAPABILITY; mdwc->lpm_flags |= MDWC3_ASYNC_IRQ_WAKE_CAPABILITY; } } } atomic_set(&dwc->in_lpm, 1); atomic_set(&dwc->in_lpm, 1); if (mdwc->pwr_event_irq) if (mdwc->pwr_event_irq) enable_irq(mdwc->pwr_event_irq); enable_irq(mdwc->pwr_event_irq); Loading @@ -1478,7 +1420,6 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) static int dwc3_msm_resume(struct dwc3_msm *mdwc) static int dwc3_msm_resume(struct dwc3_msm *mdwc) { { int ret; int ret; bool dcp; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__); dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__); Loading @@ -1490,30 +1431,17 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) pm_stay_awake(mdwc->dev); pm_stay_awake(mdwc->dev); /* Enable bus voting */ if (mdwc->bus_perf_client) { if (mdwc->bus_perf_client) { mdwc->bus_vote = 1; mdwc->bus_vote = 1; schedule_work(&mdwc->bus_vote_w); schedule_work(&mdwc->bus_vote_w); } } dcp = ((mdwc->chg_type == DWC3_DCP_CHARGER) || (mdwc->chg_type == DWC3_PROPRIETARY_CHARGER) || (mdwc->chg_type == DWC3_FLOATED_CHARGER)); if (dcp) { mdwc->hs_phy->flags |= PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags |= PHY_CHARGER_CONNECTED; } else { mdwc->hs_phy->flags &= ~PHY_CHARGER_CONNECTED; mdwc->ss_phy->flags &= ~PHY_CHARGER_CONNECTED; } if (mdwc->lpm_flags & MDWC3_TCXO_SHUTDOWN) { /* Vote for TCXO while waking up USB HSPHY */ /* Vote for TCXO while waking up USB HSPHY */ ret = clk_prepare_enable(mdwc->xo_clk); ret = clk_prepare_enable(mdwc->xo_clk); if (ret) if (ret) dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n", dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n", __func__, ret); __func__, ret); mdwc->lpm_flags &= ~MDWC3_TCXO_SHUTDOWN; } /* Restore controller power collapse */ /* Restore controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { Loading @@ -1524,31 +1452,25 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) /* HW requires a short delay for reset to take place properly */ /* HW requires a short delay for reset to take place properly */ usleep_range(1000, 1200); usleep_range(1000, 1200); clk_reset(mdwc->core_clk, CLK_RESET_DEASSERT); clk_reset(mdwc->core_clk, CLK_RESET_DEASSERT); clk_prepare_enable(mdwc->sleep_clk); } } /* Resume SS PHY */ if (mdwc->lpm_flags & MDWC3_SS_PHY_SUSPEND) { if (mdwc->lpm_flags & MDWC3_SS_PHY_SUSPEND) { usb_phy_set_suspend(mdwc->ss_phy, 0); usb_phy_set_suspend(mdwc->ss_phy, 0); mdwc->lpm_flags &= ~MDWC3_SS_PHY_SUSPEND; mdwc->lpm_flags &= ~MDWC3_SS_PHY_SUSPEND; } } usleep_range(1000, 1200); if (mdwc->bus_aggr_clk) /* Resume HS PHY */ clk_prepare_enable(mdwc->bus_aggr_clk); usb_phy_set_suspend(mdwc->hs_phy, 0); clk_prepare_enable(mdwc->iface_clk); /* Enable clocks */ if (mdwc->lpm_flags & MDWC3_CORECLK_OFF) { clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate); clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate); clk_prepare_enable(mdwc->core_clk); clk_prepare_enable(mdwc->core_clk); mdwc->lpm_flags &= ~MDWC3_CORECLK_OFF; } clk_prepare_enable(mdwc->utmi_clk); clk_prepare_enable(mdwc->utmi_clk); if (mdwc->bus_aggr_clk) if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) clk_prepare_enable(mdwc->bus_aggr_clk); clk_prepare_enable(mdwc->sleep_clk); clk_prepare_enable(mdwc->iface_clk); usb_phy_set_suspend(mdwc->hs_phy, 0); /* Recover from controller power collapse */ /* Recover from controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { Loading Loading @@ -2229,9 +2151,6 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->charging_disabled = of_property_read_bool(node, mdwc->charging_disabled = of_property_read_bool(node, "qcom,charging-disabled"); "qcom,charging-disabled"); mdwc->suspend_resume_no_support = of_property_read_bool(node, "qcom,no-suspend-resume"); mdwc->power_collapse_por = of_property_read_bool(node, mdwc->power_collapse_por = of_property_read_bool(node, "qcom,por-after-power-collapse"); "qcom,por-after-power-collapse"); Loading