diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-10-07 16:48:26 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-10-07 16:48:26 -0700 |
commit | d3dcbe24a0fc6373ce7e4a65acd5c785aa8e2396 (patch) | |
tree | 2072b4977f2e22f0b51bd7e48f131c48c14e896d /drivers/usb/dwc3/core.c | |
parent | 6181073dd6a7e5deafc60e7981bd765b6c93da8c (diff) | |
parent | 00988f70a0763f14c97c4c0df76fb9aa4959e953 (diff) | |
download | linux-d3dcbe24a0fc6373ce7e4a65acd5c785aa8e2396.tar.gz linux-d3dcbe24a0fc6373ce7e4a65acd5c785aa8e2396.tar.bz2 linux-d3dcbe24a0fc6373ce7e4a65acd5c785aa8e2396.zip |
Merge tag 'usb-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / Thunderbolt updates from Greg KH:
"Here is the big set of USB and Thunderbolt driver changes for 6.1-rc1.
Nothing major in here, lots of little things with new devices
supported and updates for a few drivers. Highlights include:
- thunderbolt/USB4 devices supported a bit better than before, and
some new ids to enable new hardware devices
- USB gadget uvc updates for newer video formats and better v4l
integration (the v4l portions were acked by those maintainers)
- typec updates for tiny issues and more typec drivers for new chips.
- xhci tiny updates for minor issues
- big usb-serial ftdi_sio driver update to handle new devices better
- lots of tiny dwc3 fixes and updates for the IP block that is
showing up everywhere these days
- dts updates for new devices being supported
- other tiny janitorial and cleanups fixes for lots of different USB
drivers. Full details are in the shortlog.
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (169 commits)
usb: gadget: uvc: don't put item still in use
usb: gadget: uvc: Fix argument to sizeof() in uvc_register_video()
usb: host: ehci-exynos: switch to using gpiod API
Revert "usb: dwc3: Don't switch OTG -> peripheral if extcon is present"
Revert "USB: fixup for merge issue with "usb: dwc3: Don't switch OTG -> peripheral if extcon is present""
dt-bindings: usb: Convert FOTG210 to dt schema
usb: mtu3: fix failed runtime suspend in host only mode
USB: omap_udc: Fix spelling mistake: "tranceiver_ctrl" -> "transceiver_ctrl"
usb: typec: ucsi_ccg: Disable UCSI ALT support on Tegra
usb: typec: Replace custom implementation of device_match_fwnode()
usb: typec: ucsi: Don't warn on probe deferral
usb: add quirks for Lenovo OneLink+ Dock
MAINTAINERS: switch dwc3 to Thinh
usb: idmouse: fix an uninit-value in idmouse_open
USB: PHY: JZ4770: Switch to use dev_err_probe() helper
usb: phy: generic: Switch to use dev_err_probe() helper
usb: ulpi: use DEFINE_SHOW_ATTRIBUTE to simplify ulpi_regs
usb: cdns3: remove dead code
usb: cdc-wdm: Use skb_put_data() instead of skb_put/memcpy pair
usb: musb: sunxi: Switch to use dev_err_probe() helper
...
Diffstat (limited to 'drivers/usb/dwc3/core.c')
-rw-r--r-- | drivers/usb/dwc3/core.c | 137 |
1 files changed, 61 insertions, 76 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index d0237b30c9be..ea51624461b5 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -23,7 +23,6 @@ #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/of.h> -#include <linux/of_graph.h> #include <linux/acpi.h> #include <linux/pinctrl/consumer.h> #include <linux/reset.h> @@ -86,7 +85,7 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) * mode. If the controller supports DRD but the dr_mode is not * specified or set to OTG, then set the mode to peripheral. */ - if (mode == USB_DR_MODE_OTG && !dwc->edev && + if (mode == USB_DR_MODE_OTG && (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) || !device_property_read_bool(dwc->dev, "usb-role-switch")) && !DWC3_VER_IS_PRIOR(DWC3, 330A)) @@ -408,6 +407,10 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc) reg |= FIELD_PREP(DWC3_GFLADJ_REFCLK_FLADJ_MASK, fladj) | FIELD_PREP(DWC3_GFLADJ_240MHZDECR, decr >> 1) | FIELD_PREP(DWC3_GFLADJ_240MHZDECR_PLS1, decr & 1); + + if (dwc->gfladj_refclk_lpm_sel) + reg |= DWC3_GFLADJ_REFCLK_LPM_SEL; + dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); } @@ -789,7 +792,7 @@ static int dwc3_phy_setup(struct dwc3 *dwc) else reg |= DWC3_GUSB2PHYCFG_ENBLSLPM; - if (dwc->dis_u2_freeclk_exists_quirk) + if (dwc->dis_u2_freeclk_exists_quirk || dwc->gfladj_refclk_lpm_sel) reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); @@ -1180,6 +1183,21 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); } + /* + * When configured in HOST mode, after issuing U3/L2 exit controller + * fails to send proper CRC checksum in CRC5 feild. Because of this + * behaviour Transaction Error is generated, resulting in reset and + * re-enumeration of usb device attached. All the termsel, xcvrsel, + * opmode becomes 0 during end of resume. Enabling bit 10 of GUCTL1 + * will correct this problem. This option is to support certain + * legacy ULPI PHYs. + */ + if (dwc->resume_hs_terminations) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); + reg |= DWC3_GUCTL1_RESUME_OPMODE_HS_HOST; + dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); + } + if (!DWC3_VER_IS_PRIOR(DWC3, 250A)) { reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); @@ -1523,8 +1541,12 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,dis-del-phy-power-chg-quirk"); dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, "snps,dis-tx-ipgap-linecheck-quirk"); + dwc->resume_hs_terminations = device_property_read_bool(dev, + "snps,resume-hs-terminations"); dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, "snps,parkmode-disable-ss-quirk"); + dwc->gfladj_refclk_lpm_sel = device_property_read_bool(dev, + "snps,gfladj-refclk-lpm-sel-quirk"); dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, "snps,tx_de_emphasis_quirk"); @@ -1668,46 +1690,6 @@ static void dwc3_check_params(struct dwc3 *dwc) } } -static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) -{ - struct device *dev = dwc->dev; - struct device_node *np_phy; - struct extcon_dev *edev = NULL; - const char *name; - - if (device_property_read_bool(dev, "extcon")) - return extcon_get_edev_by_phandle(dev, 0); - - /* - * Device tree platforms should get extcon via phandle. - * On ACPI platforms, we get the name from a device property. - * This device property is for kernel internal use only and - * is expected to be set by the glue code. - */ - if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) - return extcon_get_extcon_dev(name); - - /* - * Try to get an extcon device from the USB PHY controller's "port" - * node. Check if it has the "port" node first, to avoid printing the - * error message from underlying code, as it's a valid case: extcon - * device (and "port" node) may be missing in case of "usb-role-switch" - * or OTG mode. - */ - np_phy = of_parse_phandle(dev->of_node, "phys", 0); - if (of_graph_is_present(np_phy)) { - struct device_node *np_conn; - - np_conn = of_graph_get_remote_node(np_phy, -1, -1); - if (np_conn) - edev = extcon_find_edev_by_node(np_conn); - of_node_put(np_conn); - } - of_node_put(np_phy); - - return edev; -} - static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1753,8 +1735,10 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_get_properties(dwc); dwc->reset = devm_reset_control_array_get_optional_shared(dev); - if (IS_ERR(dwc->reset)) - return PTR_ERR(dwc->reset); + if (IS_ERR(dwc->reset)) { + ret = PTR_ERR(dwc->reset); + goto put_usb_psy; + } if (dev->of_node) { /* @@ -1764,45 +1748,57 @@ static int dwc3_probe(struct platform_device *pdev) * check for them to retain backwards compatibility. */ dwc->bus_clk = devm_clk_get_optional(dev, "bus_early"); - if (IS_ERR(dwc->bus_clk)) - return dev_err_probe(dev, PTR_ERR(dwc->bus_clk), - "could not get bus clock\n"); + if (IS_ERR(dwc->bus_clk)) { + ret = dev_err_probe(dev, PTR_ERR(dwc->bus_clk), + "could not get bus clock\n"); + goto put_usb_psy; + } if (dwc->bus_clk == NULL) { dwc->bus_clk = devm_clk_get_optional(dev, "bus_clk"); - if (IS_ERR(dwc->bus_clk)) - return dev_err_probe(dev, PTR_ERR(dwc->bus_clk), - "could not get bus clock\n"); + if (IS_ERR(dwc->bus_clk)) { + ret = dev_err_probe(dev, PTR_ERR(dwc->bus_clk), + "could not get bus clock\n"); + goto put_usb_psy; + } } dwc->ref_clk = devm_clk_get_optional(dev, "ref"); - if (IS_ERR(dwc->ref_clk)) - return dev_err_probe(dev, PTR_ERR(dwc->ref_clk), - "could not get ref clock\n"); + if (IS_ERR(dwc->ref_clk)) { + ret = dev_err_probe(dev, PTR_ERR(dwc->ref_clk), + "could not get ref clock\n"); + goto put_usb_psy; + } if (dwc->ref_clk == NULL) { dwc->ref_clk = devm_clk_get_optional(dev, "ref_clk"); - if (IS_ERR(dwc->ref_clk)) - return dev_err_probe(dev, PTR_ERR(dwc->ref_clk), - "could not get ref clock\n"); + if (IS_ERR(dwc->ref_clk)) { + ret = dev_err_probe(dev, PTR_ERR(dwc->ref_clk), + "could not get ref clock\n"); + goto put_usb_psy; + } } dwc->susp_clk = devm_clk_get_optional(dev, "suspend"); - if (IS_ERR(dwc->susp_clk)) - return dev_err_probe(dev, PTR_ERR(dwc->susp_clk), - "could not get suspend clock\n"); + if (IS_ERR(dwc->susp_clk)) { + ret = dev_err_probe(dev, PTR_ERR(dwc->susp_clk), + "could not get suspend clock\n"); + goto put_usb_psy; + } if (dwc->susp_clk == NULL) { dwc->susp_clk = devm_clk_get_optional(dev, "suspend_clk"); - if (IS_ERR(dwc->susp_clk)) - return dev_err_probe(dev, PTR_ERR(dwc->susp_clk), - "could not get suspend clock\n"); + if (IS_ERR(dwc->susp_clk)) { + ret = dev_err_probe(dev, PTR_ERR(dwc->susp_clk), + "could not get suspend clock\n"); + goto put_usb_psy; + } } } ret = reset_control_deassert(dwc->reset); if (ret) - return ret; + goto put_usb_psy; ret = dwc3_clk_enable(dwc); if (ret) @@ -1844,13 +1840,6 @@ static int dwc3_probe(struct platform_device *pdev) goto err2; } - dwc->edev = dwc3_get_extcon(dwc); - if (IS_ERR(dwc->edev)) { - ret = PTR_ERR(dwc->edev); - dev_err_probe(dwc->dev, ret, "failed to get extcon\n"); - goto err3; - } - ret = dwc3_get_dr_mode(dwc); if (ret) goto err3; @@ -1909,7 +1898,7 @@ disable_clks: dwc3_clk_disable(dwc); assert_reset: reset_control_assert(dwc->reset); - +put_usb_psy: if (dwc->usb_psy) power_supply_put(dwc->usb_psy); @@ -1977,9 +1966,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) case DWC3_GCTL_PRTCAP_DEVICE: if (pm_runtime_suspended(dwc->dev)) break; - spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_suspend(dwc); - spin_unlock_irqrestore(&dwc->lock, flags); synchronize_irq(dwc->irq_gadget); dwc3_core_exit(dwc); break; @@ -2040,9 +2027,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) return ret; dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); - spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_resume(dwc); - spin_unlock_irqrestore(&dwc->lock, flags); break; case DWC3_GCTL_PRTCAP_HOST: if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) { |