Loading Documentation/devicetree/bindings/usb/msm-ssusb.txt +4 −2 Original line number Diff line number Diff line Loading @@ -52,8 +52,10 @@ Optional properties : - qcom,usb-dbm : phandle for the DBM device - qcom,usbin-vadc: Corresponding vadc device's phandle to read usbin voltage using VADC. This will be used to get value of usb power supply's VOLTAGE_NOW property, - qcom,no-power-collapse: If present, the USB core will not perform power collapse - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform power collapse when cable is disconencted. - qcom,por-after-power-collapse: If present, a partial POR sequence will be performed when recovering from power collapse. Sub nodes: - Sub node for "DWC3- USB3 controller". This sub node is required property for device node. The properties of this subnode Loading drivers/usb/dwc3/dwc3-msm.c +75 −7 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ struct dwc3_msm { #define MDWC3_PHY_REF_AND_CORECLK_OFF BIT(0) #define MDWC3_TCXO_SHUTDOWN BIT(1) #define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(2) #define MDWC3_POWER_COLLAPSE BIT(7) u32 qscratch_ctl_val; dev_t ext_chg_dev; Loading @@ -195,7 +196,9 @@ struct dwc3_msm { unsigned int scm_dev_id; bool reset_hsphy_sleep_clk; bool suspend_resume_no_support; bool disable_power_collapse; bool power_collapse; /* power collapse on cable disconnect */ bool power_collapse_por; /* perform POR sequence after power collapse */ bool enable_suspend_event; }; Loading Loading @@ -1392,6 +1395,50 @@ reset_hsphy_exit: return ret; } static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) { u32 reg; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); /* Put Core in Reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg); usb_phy_init(dwc->usb2_phy); /* Assert USB3 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB3PIPECTL(0), reg); /* Assert USB2 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), reg); udelay(100); /* Clear USB3 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB3PIPECTL(0), reg); /* Clear USB2 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), reg); udelay(100); /* After PHYs are stable we can take Core out of reset state */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg); udelay(100); } static int dwc3_msm_suspend(struct dwc3_msm *mdwc) { int ret, i; Loading @@ -1400,6 +1447,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) bool host_ss_active; bool can_suspend_ssphy; bool device_bus_suspend; bool cable_connected = mdwc->vbus_active; dev_dbg(mdwc->dev, "%s: entering lpm. usb_lpm_override:%d\n", __func__, usb_lpm_override); Loading Loading @@ -1487,9 +1535,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) /* make sure above writes are completed before turning off clocks */ wmb(); /* remove vote for controller power collapse */ if (!host_bus_suspend && !mdwc->disable_power_collapse) /* Perform controller power collapse */ if (!host_bus_suspend && mdwc->power_collapse && !cable_connected) { 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->iface_clk); clk_disable_unprepare(mdwc->utmi_clk); Loading Loading @@ -1576,9 +1627,11 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) mdwc->lpm_flags &= ~MDWC3_TCXO_SHUTDOWN; } /* add vote for controller power collapse */ if (!host_bus_suspend && !mdwc->disable_power_collapse) /* Restore controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { dev_dbg(mdwc->dev, "%s: exit power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 1); } clk_prepare_enable(mdwc->utmi_clk); Loading Loading @@ -1617,6 +1670,15 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) return ret; } /* Recover from controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { dev_dbg(mdwc->dev, "%s: exit power collapse (POR=%d)\n", __func__, mdwc->power_collapse_por); if (mdwc->power_collapse_por) dwc3_msm_power_collapse_por(mdwc); mdwc->lpm_flags &= ~MDWC3_POWER_COLLAPSE; } if (resume_from_core_clk_off) usb_phy_set_suspend(mdwc->ss_phy, 0); atomic_set(&mdwc->in_lpm, 0); Loading Loading @@ -2538,8 +2600,14 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->suspend_resume_no_support = of_property_read_bool(node, "qcom,no-suspend-resume"); mdwc->disable_power_collapse = of_property_read_bool(node, "qcom,no-power-collapse"); mdwc->power_collapse_por = of_property_read_bool(node, "qcom,por-after-power-collapse"); mdwc->power_collapse = of_property_read_bool(node, "qcom,power-collapse-on-cable-disconnect"); dev_dbg(&pdev->dev, "power collapse=%d, POR=%d\n", mdwc->power_collapse, mdwc->power_collapse_por); mdwc->enable_suspend_event = of_property_read_bool(node, "qcom,suspend_event_enable"); Loading Loading
Documentation/devicetree/bindings/usb/msm-ssusb.txt +4 −2 Original line number Diff line number Diff line Loading @@ -52,8 +52,10 @@ Optional properties : - qcom,usb-dbm : phandle for the DBM device - qcom,usbin-vadc: Corresponding vadc device's phandle to read usbin voltage using VADC. This will be used to get value of usb power supply's VOLTAGE_NOW property, - qcom,no-power-collapse: If present, the USB core will not perform power collapse - qcom,power-collapse-on-cable-disconnect: If present, USB core will perform power collapse when cable is disconencted. - qcom,por-after-power-collapse: If present, a partial POR sequence will be performed when recovering from power collapse. Sub nodes: - Sub node for "DWC3- USB3 controller". This sub node is required property for device node. The properties of this subnode Loading
drivers/usb/dwc3/dwc3-msm.c +75 −7 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ struct dwc3_msm { #define MDWC3_PHY_REF_AND_CORECLK_OFF BIT(0) #define MDWC3_TCXO_SHUTDOWN BIT(1) #define MDWC3_ASYNC_IRQ_WAKE_CAPABILITY BIT(2) #define MDWC3_POWER_COLLAPSE BIT(7) u32 qscratch_ctl_val; dev_t ext_chg_dev; Loading @@ -195,7 +196,9 @@ struct dwc3_msm { unsigned int scm_dev_id; bool reset_hsphy_sleep_clk; bool suspend_resume_no_support; bool disable_power_collapse; bool power_collapse; /* power collapse on cable disconnect */ bool power_collapse_por; /* perform POR sequence after power collapse */ bool enable_suspend_event; }; Loading Loading @@ -1392,6 +1395,50 @@ reset_hsphy_exit: return ret; } static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) { u32 reg; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); /* Put Core in Reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg); usb_phy_init(dwc->usb2_phy); /* Assert USB3 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB3PIPECTL(0)); reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB3PIPECTL(0), reg); /* Assert USB2 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), reg); udelay(100); /* Clear USB3 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB3PIPECTL(0)); reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB3PIPECTL(0), reg); /* Clear USB2 PHY reset */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_msm_write_reg(mdwc->base, DWC3_GUSB2PHYCFG(0), reg); udelay(100); /* After PHYs are stable we can take Core out of reset state */ reg = dwc3_msm_read_reg(mdwc->base, DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; dwc3_msm_write_reg(mdwc->base, DWC3_GCTL, reg); udelay(100); } static int dwc3_msm_suspend(struct dwc3_msm *mdwc) { int ret, i; Loading @@ -1400,6 +1447,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) bool host_ss_active; bool can_suspend_ssphy; bool device_bus_suspend; bool cable_connected = mdwc->vbus_active; dev_dbg(mdwc->dev, "%s: entering lpm. usb_lpm_override:%d\n", __func__, usb_lpm_override); Loading Loading @@ -1487,9 +1535,12 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) /* make sure above writes are completed before turning off clocks */ wmb(); /* remove vote for controller power collapse */ if (!host_bus_suspend && !mdwc->disable_power_collapse) /* Perform controller power collapse */ if (!host_bus_suspend && mdwc->power_collapse && !cable_connected) { 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->iface_clk); clk_disable_unprepare(mdwc->utmi_clk); Loading Loading @@ -1576,9 +1627,11 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) mdwc->lpm_flags &= ~MDWC3_TCXO_SHUTDOWN; } /* add vote for controller power collapse */ if (!host_bus_suspend && !mdwc->disable_power_collapse) /* Restore controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { dev_dbg(mdwc->dev, "%s: exit power collapse\n", __func__); dwc3_msm_config_gdsc(mdwc, 1); } clk_prepare_enable(mdwc->utmi_clk); Loading Loading @@ -1617,6 +1670,15 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) return ret; } /* Recover from controller power collapse */ if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) { dev_dbg(mdwc->dev, "%s: exit power collapse (POR=%d)\n", __func__, mdwc->power_collapse_por); if (mdwc->power_collapse_por) dwc3_msm_power_collapse_por(mdwc); mdwc->lpm_flags &= ~MDWC3_POWER_COLLAPSE; } if (resume_from_core_clk_off) usb_phy_set_suspend(mdwc->ss_phy, 0); atomic_set(&mdwc->in_lpm, 0); Loading Loading @@ -2538,8 +2600,14 @@ static int dwc3_msm_probe(struct platform_device *pdev) mdwc->suspend_resume_no_support = of_property_read_bool(node, "qcom,no-suspend-resume"); mdwc->disable_power_collapse = of_property_read_bool(node, "qcom,no-power-collapse"); mdwc->power_collapse_por = of_property_read_bool(node, "qcom,por-after-power-collapse"); mdwc->power_collapse = of_property_read_bool(node, "qcom,power-collapse-on-cable-disconnect"); dev_dbg(&pdev->dev, "power collapse=%d, POR=%d\n", mdwc->power_collapse, mdwc->power_collapse_por); mdwc->enable_suspend_event = of_property_read_bool(node, "qcom,suspend_event_enable"); Loading