diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-07-01 12:01:33 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-07-01 12:01:33 +0200 |
commit | f254e65ad694a9189163f5a60707a06225f5db25 (patch) | |
tree | 8dc9bde165438949e67a2684c11719200295ce6a /drivers/usb/dwc2 | |
parent | 426d3ff2f5ab7207aea0c1769d74b25a7b51b4dd (diff) | |
parent | aa23ce847ddac1fd5ffe987ff12e12ff48318e45 (diff) | |
download | linux-f254e65ad694a9189163f5a60707a06225f5db25.tar.gz |
Merge tag 'usb-for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes:
usb: changes for v5.3 merge window
The biggest part here is a set of patches removing unnecesary variables
from several drivers.
Meson-g12a's dwc3 glue implemented IRQ-based OTG/DRD role swap.
Qcom's dwc3 glue added support for ACPI, mainly for the AArch64-based
SoCs.
DWC3 also got support for Intel Elkhart Lake platforms.
* tag 'usb-for-v5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (30 commits)
usb: dwc3: remove unused @lock member of dwc3_ep struct
usb: dwc3: pci: Add Support for Intel Elkhart Lake Devices
usb: Replace snprintf with scnprintf in gether_get_ifname
usb: gadget: ether: Fix race between gether_disconnect and rx_submit
usb: gadget: storage: Remove warning message
usb: dwc3: gadget: Add support for disabling U1 and U2 entries
usb: gadget: send usb_gadget as an argument in get_config_params
doc: dt: bindings: usb: dwc3: Update entries for disabling U1 and U2
usb: dwc3: qcom: Use of_clk_get_parent_count()
usb: dwc3: Fix core validation in probe, move after clocks are enabled
usb: dwc3: qcom: Improve error handling
usb: dwc3: qcom: Start USB in 'host mode' on the SDM845
usb: dwc3: qcom: Add support for booting with ACPI
soc: qcom: geni: Add support for ACPI
Revert "usb: dwc2: host: Setting qtd to NULL after freeing it"
usb: gadget: net2272: remove redundant assignments to pointer 's'
usb: gadget: Zero ffs_io_data
USB: omap_udc: Remove unneeded variable
fotg210-udc: Remove unneeded variable
usb: gadget: at91_udc: Remove unneeded variable
...
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r-- | drivers/usb/dwc2/core.h | 8 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd.c | 20 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd.h | 1 | ||||
-rw-r--r-- | drivers/usb/dwc2/params.c | 1 | ||||
-rw-r--r-- | drivers/usb/dwc2/platform.c | 23 |
5 files changed, 48 insertions, 5 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 152ac41dfb2d..d08d070a0fb6 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -861,6 +861,9 @@ struct dwc2_hregs_backup { * @hibernated: True if core is hibernated * @reset_phy_on_wake: Quirk saying that we should assert PHY reset on a * remote wakeup. + * @phy_off_for_suspend: Status of whether we turned the PHY off at suspend. + * @need_phy_for_wake: Quirk saying that we should keep the PHY on at + * suspend if we need USB to wake us up. * @frame_number: Frame number read from the core. For both device * and host modes. The value ranges are from 0 * to HFNUM_MAX_FRNUM. @@ -1049,6 +1052,8 @@ struct dwc2_hsotg { unsigned int ll_hw_enabled:1; unsigned int hibernated:1; unsigned int reset_phy_on_wake:1; + unsigned int need_phy_for_wake:1; + unsigned int phy_off_for_suspend:1; u16 frame_number; struct phy *phy; @@ -1438,6 +1443,7 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg); int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg); int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, int reset); +bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2); static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg) { schedule_work(&hsotg->phy_reset_work); } #else @@ -1463,6 +1469,8 @@ static inline int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) static inline int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, int reset) { return 0; } +static inline bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2) +{ return false; } static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg) {} #endif diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 2192a2873c7c..ee144ff8af5b 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -4685,7 +4685,6 @@ fail2: spin_unlock_irqrestore(&hsotg->lock, flags); urb->hcpriv = NULL; kfree(qtd); - qtd = NULL; fail1: if (qh_allocated) { struct dwc2_qtd *qtd2, *qtd2_tmp; @@ -5587,3 +5586,22 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup, dev_dbg(hsotg->dev, "Host hibernation restore complete\n"); return ret; } + +bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2) +{ + struct usb_device *root_hub = dwc2_hsotg_to_hcd(dwc2)->self.root_hub; + + /* If the controller isn't allowed to wakeup then we can power off. */ + if (!device_may_wakeup(dwc2->dev)) + return true; + + /* + * We don't want to power off the PHY if something under the + * root hub has wakeup enabled. + */ + if (usb_wakeup_enabled_descendants(root_hub)) + return false; + + /* No reason to keep the PHY powered, so allow poweroff */ + return true; +} diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index ce6445a06588..8ca6d12a6f57 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h @@ -582,7 +582,6 @@ static inline void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg, { list_del(&qtd->qtd_list_entry); kfree(qtd); - qtd = NULL; } /* Descriptor DMA support functions */ diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 5949262ff669..55f841a54015 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -76,6 +76,7 @@ static void dwc2_set_s3c6400_params(struct dwc2_hsotg *hsotg) struct dwc2_core_params *p = &hsotg->params; p->power_down = 0; + p->phy_utmi_width = 8; } static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index e98d7812da2d..80fd3c6dcd1c 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -438,6 +438,10 @@ static int dwc2_driver_probe(struct platform_device *dev) if (retval) goto error; + hsotg->need_phy_for_wake = + of_property_read_bool(dev->dev.of_node, + "snps,need-phy-for-wake"); + /* * Reset before dwc2_get_hwparams() then it could get power-on real * reset value form registers. @@ -469,6 +473,14 @@ static int dwc2_driver_probe(struct platform_device *dev) hsotg->gadget_enabled = 1; } + /* + * If we need PHY for wakeup we must be wakeup capable. + * When we have a device that can wake without the PHY we + * can adjust this condition. + */ + if (hsotg->need_phy_for_wake) + device_set_wakeup_capable(&dev->dev, true); + hsotg->reset_phy_on_wake = of_property_read_bool(dev->dev.of_node, "snps,reset-phy-on-wake"); @@ -507,13 +519,17 @@ error: static int __maybe_unused dwc2_suspend(struct device *dev) { struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); + bool is_device_mode = dwc2_is_device_mode(dwc2); int ret = 0; - if (dwc2_is_device_mode(dwc2)) + if (is_device_mode) dwc2_hsotg_suspend(dwc2); - if (dwc2->ll_hw_enabled) + if (dwc2->ll_hw_enabled && + (is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) { ret = __dwc2_lowlevel_hw_disable(dwc2); + dwc2->phy_off_for_suspend = true; + } return ret; } @@ -523,11 +539,12 @@ static int __maybe_unused dwc2_resume(struct device *dev) struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev); int ret = 0; - if (dwc2->ll_hw_enabled) { + if (dwc2->phy_off_for_suspend && dwc2->ll_hw_enabled) { ret = __dwc2_lowlevel_hw_enable(dwc2); if (ret) return ret; } + dwc2->phy_off_for_suspend = false; if (dwc2_is_device_mode(dwc2)) ret = dwc2_hsotg_resume(dwc2); |