Loading Documentation/devicetree/bindings/usb/msm-ssusb.txt +2 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,8 @@ Optional properties : - 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" Loading drivers/usb/dwc3/dwc3-msm.c +52 −2 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -157,6 +157,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; Loading Loading @@ -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; Loading Loading @@ -340,6 +342,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; Loading Loading @@ -2103,6 +2122,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__); Loading Loading @@ -2150,7 +2170,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 */ Loading Loading @@ -2476,6 +2504,12 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) 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->sleep_clk = devm_clk_get(mdwc->dev, "sleep_clk"); if (IS_ERR(mdwc->sleep_clk)) { dev_err(mdwc->dev, "failed to get sleep_clk\n"); Loading Loading @@ -3123,6 +3157,21 @@ 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 Loading @@ -3138,6 +3187,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; } } Loading Loading
Documentation/devicetree/bindings/usb/msm-ssusb.txt +2 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,8 @@ Optional properties : - 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" Loading
drivers/usb/dwc3/dwc3-msm.c +52 −2 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -157,6 +157,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; Loading Loading @@ -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; Loading Loading @@ -340,6 +342,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; Loading Loading @@ -2103,6 +2122,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__); Loading Loading @@ -2150,7 +2170,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 */ Loading Loading @@ -2476,6 +2504,12 @@ static int dwc3_msm_get_clk_gdsc(struct dwc3_msm *mdwc) 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->sleep_clk = devm_clk_get(mdwc->dev, "sleep_clk"); if (IS_ERR(mdwc->sleep_clk)) { dev_err(mdwc->dev, "failed to get sleep_clk\n"); Loading Loading @@ -3123,6 +3157,21 @@ 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 Loading @@ -3138,6 +3187,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; } } Loading