From 1eec2157d84dcb872f25da2329abcbe10d6694a7 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Tue, 24 Jan 2017 18:13:07 -0800 Subject: [PATCH 1/2] usb: dwc3: Update core clock rate based on USB port speed. Core clock rate can be reduced or increased based on operating speeds. Controller starts in Super Speed mode (higher core clock rate) and it will operate in super or high or full or low speed upon device connection. Update the core clock rate based on bus speed to allows system to operate in better low power state (such as SVS1/SVS2 based on system configuration). High Speed rate for core clock is programmed from dtsi. Super Speed rate will be used if High speed core clock rate is not provided for backward compatibility. Change-Id: I265149d34de19ab50bd7f106a670a7112bfae384 Signed-off-by: Hemant Kumar --- .../devicetree/bindings/usb/msm-ssusb.txt | 4 +- drivers/usb/dwc3/dwc3-msm.c | 52 ++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt index fa6ee8969946..47fad8aa4a1a 100644 --- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt +++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt @@ -19,6 +19,7 @@ Required properties : and reset lines used by this controller. - reset-names: reset signal name strings sorted in the same order as the resets property. +- qcom,core-clk-rate: clock frequency to be set for USB master clock. Optional properties : - reg: Additional registers @@ -54,7 +55,8 @@ Optional properties : - qcom,disable-dev-mode-pm: If present, it disables PM runtime functionality for device mode. - qcom,disable-host-mode-pm: If present, it disables XHCI PM runtime functionality when USB host mode is used. -- qcom,core-clk-rate: If present, indicates clock frequency to be set for USB master clock. +- qcom,core-clk-rate-hs: If present, indicates min core clock frequency required to support + hs speed. - extcon: phandles to external connector devices. First phandle should point to external connector, which provide "USB" cable events, the second should point to external connector device, which provide "USB-HOST" diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index bc0e0184a917..7f40766dd197 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -156,6 +156,7 @@ struct dwc3_msm { struct clk *xo_clk; struct clk *core_clk; long core_clk_rate; + long core_clk_rate_hs; struct clk *iface_clk; struct clk *sleep_clk; struct clk *utmi_clk; @@ -195,6 +196,7 @@ struct dwc3_msm { struct power_supply *usb_psy; struct work_struct vbus_draw_work; bool in_host_mode; + enum usb_device_speed max_rh_port_speed; unsigned int tx_fifo_size; bool vbus_active; bool suspend; @@ -342,6 +344,23 @@ static inline void dwc3_msm_write_readback(void *base, u32 offset, __func__, val, offset); } +static bool dwc3_msm_is_ss_rhport_connected(struct dwc3_msm *mdwc) +{ + int i, num_ports; + u32 reg; + + reg = dwc3_msm_read_reg(mdwc->base, USB3_HCSPARAMS1); + num_ports = HCS_MAX_PORTS(reg); + + for (i = 0; i < num_ports; i++) { + reg = dwc3_msm_read_reg(mdwc->base, USB3_PORTSC + i*0x10); + if ((reg & PORT_CONNECT) && DEV_SUPERSPEED(reg)) + return true; + } + + return false; +} + static bool dwc3_msm_is_host_superspeed(struct dwc3_msm *mdwc) { int i, num_ports; @@ -2128,6 +2147,7 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc) static int dwc3_msm_resume(struct dwc3_msm *mdwc) { int ret; + long core_clk_rate; struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); dev_dbg(mdwc->dev, "%s: exiting lpm\n", __func__); @@ -2175,7 +2195,15 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc) clk_prepare_enable(mdwc->iface_clk); if (mdwc->noc_aggr_clk) clk_prepare_enable(mdwc->noc_aggr_clk); - clk_set_rate(mdwc->core_clk, mdwc->core_clk_rate); + + core_clk_rate = mdwc->core_clk_rate; + if (mdwc->in_host_mode && mdwc->max_rh_port_speed == USB_SPEED_HIGH) { + core_clk_rate = mdwc->core_clk_rate_hs; + dev_dbg(mdwc->dev, "%s: set hs core clk rate %ld\n", __func__, + core_clk_rate); + } + + clk_set_rate(mdwc->core_clk, core_clk_rate); clk_prepare_enable(mdwc->core_clk); /* set Memory core: ON, Memory periphery: ON */ @@ -2496,6 +2524,11 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) if (ret) dev_err(mdwc->dev, "fail to set core_clk freq:%d\n", ret); + if (of_property_read_u32(mdwc->dev->of_node, "qcom,core-clk-rate-hs", + (u32 *)&mdwc->core_clk_rate_hs)) { + dev_dbg(mdwc->dev, "USB core-clk-rate-hs is not present\n"); + mdwc->core_clk_rate_hs = mdwc->core_clk_rate; + } mdwc->core_reset = devm_reset_control_get(mdwc->dev, "core_reset"); if (IS_ERR(mdwc->core_reset)) { @@ -3166,10 +3199,26 @@ static int dwc3_msm_host_notifier(struct notifier_block *nb, if (udev->parent && !udev->parent->parent && udev->dev.parent->parent == &dwc->xhci->dev) { if (event == USB_DEVICE_ADD && udev->actconfig) { + if (!dwc3_msm_is_ss_rhport_connected(mdwc)) { + /* + * Core clock rate can be reduced only if root + * hub SS port is not enabled/connected. + */ + clk_set_rate(mdwc->core_clk, + mdwc->core_clk_rate_hs); + dev_dbg(mdwc->dev, + "set hs core clk rate %ld\n", + mdwc->core_clk_rate_hs); + mdwc->max_rh_port_speed = USB_SPEED_HIGH; + } else { + mdwc->max_rh_port_speed = USB_SPEED_SUPER; + } + if (udev->speed >= USB_SPEED_SUPER) max_power = udev->actconfig->desc.bMaxPower * 8; else max_power = udev->actconfig->desc.bMaxPower * 2; + dev_dbg(mdwc->dev, "%s configured bMaxPower:%d (mA)\n", dev_name(&udev->dev), max_power); @@ -3181,6 +3230,7 @@ static int dwc3_msm_host_notifier(struct notifier_block *nb, pval.intval = 0; power_supply_set_property(mdwc->usb_psy, POWER_SUPPLY_PROP_BOOST_CURRENT, &pval); + mdwc->max_rh_port_speed = USB_SPEED_UNKNOWN; } } From e310682ca6bcd0b09280db9fbc4bfea666cd53f5 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Wed, 25 Jan 2017 13:31:22 -0800 Subject: [PATCH 2/2] ARM: dts: msm: Add usb master clock rate in high speed mode for msm8998 This allows system to enter SVS2 when high speed or lower speed device is connected. Change-Id: I57e4f3091f5fed7b36df1c03ba9654075a279ce6 Signed-off-by: Hemant Kumar --- arch/arm/boot/dts/qcom/msm8998.dtsi | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index cfdbf98af76e..8f4d3f57b6c8 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -1739,6 +1739,7 @@ "utmi_clk", "sleep_clk", "xo"; qcom,core-clk-rate = <120000000>; + qcom,core-clk-rate-hs = <60000000>; resets = <&clock_gcc USB_30_BCR>; reset-names = "core_reset";