Sync Linux kernel dwc3 changes from v6.15 to v6.16-rc7.

The following files are preserved accross the import:
Makefile Kconfig dwc3-meson-g12a.c dwc3-meson-gxl.c dwc3-omap.c
dwc3-uniphier.c dwc3-generic.h dwc3-generic.c dwc3-generic-sti.c
dwc3-layerscape.c ti_usb_phy.c

Skipping unused files:
debugfs.c drd.c dwc3-exynos.c dwc3-haps.c dwc3-imx8mp.c dwc3-keystone.c
dwc3-octeon.c dwc3-of-simple.c dwc3-pci.c dwc3-qcom.c dwc3-qcom-legacy.c
dwc3-rtk.c dwc3-st.c dwc3-xilinx.c host.c trace.c trace.h ulpi.c

Note that this is a raw import and doesn't build.
A fixup commit at the end of the series fixes that.

List of commits: git log --oneline v6.15..v6.16-rc7
Commits imported:
ef8abc0ba49c usb: dwc3: qcom: Don't leave BCR asserted
80e083943775 usb: dwc3: gadget: Fix TRB reclaim logic for short transfers and 
ZLPs
630a1dec3b0e usb: dwc3: Abort suspend on soft disconnect failure
657bfcbbfa38 usb: dwc3-exynos: add support for ExynosAutov920
e33ebb133a24 usb: dwc3: qcom: Use bulk clock API and devres
ab6dc9a6c721 Merge 6.15-rc6 into usb-next
615dca38c2ea Merge 6.15-rc4 into usb-next
4c0fca65d105 usb: dwc3: qcom: Fix error handling in probe
45ebb7baf235 usb: dwc3: qcom: use modern PM macros
1881a32fe14d usb: dwc3: qcom: Transition to flattened model
2dc9f137e194 usb: dwc3: qcom: Don't rely on drvdata during probe
170940f7e685 usb: dwc3: core: Don't touch resets and clocks
613a2e655d4d usb: dwc3: core: Expose core driver as library
b958b03c82d2 usb: dwc3: qcom: Snapshot driver for backwards compatibilty
00b157f8f64b usb: dwc3: exynos: add support for Exynos2200 variant
850e634006f4 usb: dwc3: core: Avoid redundant system suspend/resume callbacks
8da7644493b4 usb: dwc3: Specify maximum number of XHCI interrupters

Signed-off-by: Jens Wiklander <[email protected]>
---
 drivers/usb/dwc3/core.c   | 206 ++++++++++++++++++++++++++++----------
 drivers/usb/dwc3/core.h   |   2 +
 drivers/usb/dwc3/gadget.c |  24 ++---
 drivers/usb/dwc3/glue.h   |  36 +++++++
 4 files changed, 199 insertions(+), 69 deletions(-)
 create mode 100644 drivers/usb/dwc3/glue.h

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 66a08b527165..8002c23a5a02 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -26,6 +26,7 @@
 #include <linux/of_graph.h>
 #include <linux/acpi.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/devinfo.h>
 #include <linux/reset.h>
 #include <linux/bitfield.h>
 
@@ -36,6 +37,7 @@
 
 #include "core.h"
 #include "gadget.h"
+#include "glue.h"
 #include "io.h"
 
 #include "debug.h"
@@ -1699,6 +1701,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
        u8                      tx_thr_num_pkt_prd = 0;
        u8                      tx_max_burst_prd = 0;
        u8                      tx_fifo_resize_max_num;
+       u16                     num_hc_interrupters;
 
        /* default to highest possible threshold */
        lpm_nyet_threshold = 0xf;
@@ -1719,6 +1722,9 @@ static void dwc3_get_properties(struct dwc3 *dwc)
         */
        tx_fifo_resize_max_num = 6;
 
+       /* default to a single XHCI interrupter */
+       num_hc_interrupters = 1;
+
        dwc->maximum_speed = usb_get_maximum_speed(dev);
        dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev);
        dwc->dr_mode = usb_get_dr_mode(dev);
@@ -1765,6 +1771,12 @@ static void dwc3_get_properties(struct dwc3 *dwc)
                                &tx_thr_num_pkt_prd);
        device_property_read_u8(dev, "snps,tx-max-burst-prd",
                                &tx_max_burst_prd);
+       device_property_read_u16(dev, "num-hc-interrupters",
+                                &num_hc_interrupters);
+       /* DWC3 core allowed to have a max of 8 interrupters */
+       if (num_hc_interrupters > 8)
+               num_hc_interrupters = 8;
+
        dwc->do_fifo_resize = device_property_read_bool(dev,
                                                        "tx-fifo-resize");
        if (dwc->do_fifo_resize)
@@ -1851,6 +1863,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
        dwc->tx_max_burst_prd = tx_max_burst_prd;
 
        dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num;
+
+       dwc->num_hc_interrupters = num_hc_interrupters;
 }
 
 /* check whether the core supports IMOD */
@@ -2148,27 +2162,16 @@ static struct power_supply 
*dwc3_get_usb_power_supply(struct dwc3 *dwc)
        return usb_psy;
 }
 
-static int dwc3_probe(struct platform_device *pdev)
+int dwc3_core_probe(const struct dwc3_probe_data *data)
 {
-       struct device           *dev = &pdev->dev;
-       struct resource         *res, dwc_res;
+       struct dwc3             *dwc = data->dwc;
+       struct device           *dev = dwc->dev;
+       struct resource         dwc_res;
        unsigned int            hw_mode;
        void __iomem            *regs;
-       struct dwc3             *dwc;
+       struct resource         *res = data->res;
        int                     ret;
 
-       dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
-       if (!dwc)
-               return -ENOMEM;
-
-       dwc->dev = dev;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "missing memory resource\n");
-               return -ENODEV;
-       }
-
        dwc->xhci_resources[0].start = res->start;
        dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
                                        DWC3_XHCI_REGS_END;
@@ -2208,15 +2211,17 @@ static int dwc3_probe(struct platform_device *pdev)
        if (IS_ERR(dwc->usb_psy))
                return dev_err_probe(dev, PTR_ERR(dwc->usb_psy), "couldn't get 
usb power supply\n");
 
-       dwc->reset = devm_reset_control_array_get_optional_shared(dev);
-       if (IS_ERR(dwc->reset)) {
-               ret = PTR_ERR(dwc->reset);
-               goto err_put_psy;
-       }
+       if (!data->ignore_clocks_and_resets) {
+               dwc->reset = devm_reset_control_array_get_optional_shared(dev);
+               if (IS_ERR(dwc->reset)) {
+                       ret = PTR_ERR(dwc->reset);
+                       goto err_put_psy;
+               }
 
-       ret = dwc3_get_clocks(dwc);
-       if (ret)
-               goto err_put_psy;
+               ret = dwc3_get_clocks(dwc);
+               if (ret)
+                       goto err_put_psy;
+       }
 
        ret = reset_control_deassert(dwc->reset);
        if (ret)
@@ -2232,7 +2237,7 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err_disable_clks;
        }
 
-       platform_set_drvdata(pdev, dwc);
+       dev_set_drvdata(dev, dwc);
        dwc3_cache_hwparams(dwc);
 
        if (!dwc->sysdev_is_parent &&
@@ -2327,12 +2332,35 @@ err_put_psy:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(dwc3_core_probe);
 
-static void dwc3_remove(struct platform_device *pdev)
+static int dwc3_probe(struct platform_device *pdev)
 {
-       struct dwc3     *dwc = platform_get_drvdata(pdev);
+       struct dwc3_probe_data probe_data = {};
+       struct resource *res;
+       struct dwc3 *dwc;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "missing memory resource\n");
+               return -ENODEV;
+       }
+
+       dwc = devm_kzalloc(&pdev->dev, sizeof(*dwc), GFP_KERNEL);
+       if (!dwc)
+               return -ENOMEM;
 
-       pm_runtime_get_sync(&pdev->dev);
+       dwc->dev = &pdev->dev;
+
+       probe_data.dwc = dwc;
+       probe_data.res = res;
+
+       return dwc3_core_probe(&probe_data);
+}
+
+void dwc3_core_remove(struct dwc3 *dwc)
+{
+       pm_runtime_get_sync(dwc->dev);
 
        dwc3_core_exit_mode(dwc);
        dwc3_debugfs_exit(dwc);
@@ -2340,22 +2368,28 @@ static void dwc3_remove(struct platform_device *pdev)
        dwc3_core_exit(dwc);
        dwc3_ulpi_exit(dwc);
 
-       pm_runtime_allow(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
-       pm_runtime_dont_use_autosuspend(&pdev->dev);
-       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_allow(dwc->dev);
+       pm_runtime_disable(dwc->dev);
+       pm_runtime_dont_use_autosuspend(dwc->dev);
+       pm_runtime_put_noidle(dwc->dev);
        /*
         * HACK: Clear the driver data, which is currently accessed by parent
         * glue drivers, before allowing the parent to suspend.
         */
-       platform_set_drvdata(pdev, NULL);
-       pm_runtime_set_suspended(&pdev->dev);
+       dev_set_drvdata(dwc->dev, NULL);
+       pm_runtime_set_suspended(dwc->dev);
 
        dwc3_free_event_buffers(dwc);
 
        if (dwc->usb_psy)
                power_supply_put(dwc->usb_psy);
 }
+EXPORT_SYMBOL_GPL(dwc3_core_remove);
+
+static void dwc3_remove(struct platform_device *pdev)
+{
+       dwc3_core_remove(platform_get_drvdata(pdev));
+}
 
 #ifdef CONFIG_PM
 static int dwc3_core_init_for_resume(struct dwc3 *dwc)
@@ -2388,6 +2422,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, 
pm_message_t msg)
 {
        u32 reg;
        int i;
+       int ret;
 
        if (!pm_runtime_suspended(dwc->dev) && !PMSG_IS_AUTO(msg)) {
                dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) 
&
@@ -2406,7 +2441,9 @@ static int dwc3_suspend_common(struct dwc3 *dwc, 
pm_message_t msg)
        case DWC3_GCTL_PRTCAP_DEVICE:
                if (pm_runtime_suspended(dwc->dev))
                        break;
-               dwc3_gadget_suspend(dwc);
+               ret = dwc3_gadget_suspend(dwc);
+               if (ret)
+                       return ret;
                synchronize_irq(dwc->irq_gadget);
                dwc3_core_exit(dwc);
                break;
@@ -2441,7 +2478,9 @@ static int dwc3_suspend_common(struct dwc3 *dwc, 
pm_message_t msg)
                        break;
 
                if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
-                       dwc3_gadget_suspend(dwc);
+                       ret = dwc3_gadget_suspend(dwc);
+                       if (ret)
+                               return ret;
                        synchronize_irq(dwc->irq_gadget);
                }
 
@@ -2544,9 +2583,8 @@ static int dwc3_runtime_checks(struct dwc3 *dwc)
        return 0;
 }
 
-static int dwc3_runtime_suspend(struct device *dev)
+int dwc3_runtime_suspend(struct dwc3 *dwc)
 {
-       struct dwc3     *dwc = dev_get_drvdata(dev);
        int             ret;
 
        if (dwc3_runtime_checks(dwc))
@@ -2558,10 +2596,11 @@ static int dwc3_runtime_suspend(struct device *dev)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(dwc3_runtime_suspend);
 
-static int dwc3_runtime_resume(struct device *dev)
+int dwc3_runtime_resume(struct dwc3 *dwc)
 {
-       struct dwc3     *dwc = dev_get_drvdata(dev);
+       struct device *dev = dwc->dev;
        int             ret;
 
        ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME);
@@ -2571,7 +2610,7 @@ static int dwc3_runtime_resume(struct device *dev)
        switch (dwc->current_dr_role) {
        case DWC3_GCTL_PRTCAP_DEVICE:
                if (dwc->pending_events) {
-                       pm_runtime_put(dwc->dev);
+                       pm_runtime_put(dev);
                        dwc->pending_events = false;
                        enable_irq(dwc->irq_gadget);
                }
@@ -2586,10 +2625,11 @@ static int dwc3_runtime_resume(struct device *dev)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(dwc3_runtime_resume);
 
-static int dwc3_runtime_idle(struct device *dev)
+int dwc3_runtime_idle(struct dwc3 *dwc)
 {
-       struct dwc3     *dwc = dev_get_drvdata(dev);
+       struct device *dev = dwc->dev;
 
        switch (dwc->current_dr_role) {
        case DWC3_GCTL_PRTCAP_DEVICE:
@@ -2607,12 +2647,28 @@ static int dwc3_runtime_idle(struct device *dev)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(dwc3_runtime_idle);
+
+static int dwc3_plat_runtime_suspend(struct device *dev)
+{
+       return dwc3_runtime_suspend(dev_get_drvdata(dev));
+}
+
+static int dwc3_plat_runtime_resume(struct device *dev)
+{
+       return dwc3_runtime_resume(dev_get_drvdata(dev));
+}
+
+static int dwc3_plat_runtime_idle(struct device *dev)
+{
+       return dwc3_runtime_idle(dev_get_drvdata(dev));
+}
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_SLEEP
-static int dwc3_suspend(struct device *dev)
+int dwc3_pm_suspend(struct dwc3 *dwc)
 {
-       struct dwc3     *dwc = dev_get_drvdata(dev);
+       struct device *dev = dwc->dev;
        int             ret;
 
        ret = dwc3_suspend_common(dwc, PMSG_SUSPEND);
@@ -2623,10 +2679,11 @@ static int dwc3_suspend(struct device *dev)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(dwc3_pm_suspend);
 
-static int dwc3_resume(struct device *dev)
+int dwc3_pm_resume(struct dwc3 *dwc)
 {
-       struct dwc3     *dwc = dev_get_drvdata(dev);
+       struct device *dev = dwc->dev;
        int             ret = 0;
 
        pinctrl_pm_select_default_state(dev);
@@ -2645,10 +2702,10 @@ out:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(dwc3_pm_resume);
 
-static void dwc3_complete(struct device *dev)
+void dwc3_pm_complete(struct dwc3 *dwc)
 {
-       struct dwc3     *dwc = dev_get_drvdata(dev);
        u32             reg;
 
        if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
@@ -2658,21 +2715,60 @@ static void dwc3_complete(struct device *dev)
                dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
        }
 }
+EXPORT_SYMBOL_GPL(dwc3_pm_complete);
+
+int dwc3_pm_prepare(struct dwc3 *dwc)
+{
+       struct device *dev = dwc->dev;
+
+       /*
+        * Indicate to the PM core that it may safely leave the device in
+        * runtime suspend if runtime-suspended already in device mode.
+        */
+       if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_DEVICE &&
+           pm_runtime_suspended(dev) &&
+           !dev_pinctrl(dev))
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dwc3_pm_prepare);
+
+static int dwc3_plat_suspend(struct device *dev)
+{
+       return dwc3_pm_suspend(dev_get_drvdata(dev));
+}
+
+static int dwc3_plat_resume(struct device *dev)
+{
+       return dwc3_pm_resume(dev_get_drvdata(dev));
+}
+
+static void dwc3_plat_complete(struct device *dev)
+{
+       dwc3_pm_complete(dev_get_drvdata(dev));
+}
+
+static int dwc3_plat_prepare(struct device *dev)
+{
+       return dwc3_pm_prepare(dev_get_drvdata(dev));
+}
 #else
-#define dwc3_complete NULL
+#define dwc3_plat_complete NULL
+#define dwc3_plat_prepare NULL
 #endif /* CONFIG_PM_SLEEP */
 
 static const struct dev_pm_ops dwc3_dev_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
-       .complete = dwc3_complete,
-
+       SET_SYSTEM_SLEEP_PM_OPS(dwc3_plat_suspend, dwc3_plat_resume)
+       .complete = dwc3_plat_complete,
+       .prepare = dwc3_plat_prepare,
        /*
         * Runtime suspend halts the controller on disconnection. It relies on
         * platforms with custom connection notification to start the controller
         * again.
         */
-       SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
-                       dwc3_runtime_idle)
+       SET_RUNTIME_PM_OPS(dwc3_plat_runtime_suspend, dwc3_plat_runtime_resume,
+                          dwc3_plat_runtime_idle)
 };
 
 #ifdef CONFIG_OF
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 27eae4cf223d..d5b985fa12f4 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1083,6 +1083,7 @@ struct dwc3_scratchpad_array {
  * @tx_max_burst_prd: max periodic ESS transmit burst size
  * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
  * @clear_stall_protocol: endpoint number that requires a delayed status phase
+ * @num_hc_interrupters: number of host controller interrupters
  * @hsphy_interface: "utmi" or "ulpi"
  * @connected: true when we're connected to a host, false otherwise
  * @softconnect: true when gadget connect is called, false when disconnect runs
@@ -1333,6 +1334,7 @@ struct dwc3 {
        u8                      tx_max_burst_prd;
        u8                      tx_fifo_resize_max_num;
        u8                      clear_stall_protocol;
+       u16                     num_hc_interrupters;
 
        const char              *hsphy_interface;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 321361288935..74968f93d4a3 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -3516,7 +3516,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct 
dwc3_ep *dep,
         * We're going to do that here to avoid problems of HW trying
         * to use bogus TRBs for transfers.
         */
-       if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO))
+       if (trb->ctrl & DWC3_TRB_CTRL_HWO)
                trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
 
        /*
@@ -4821,26 +4821,22 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
        int ret;
 
        ret = dwc3_gadget_soft_disconnect(dwc);
-       if (ret)
-               goto err;
-
-       spin_lock_irqsave(&dwc->lock, flags);
-       if (dwc->gadget_driver)
-               dwc3_disconnect_gadget(dwc);
-       spin_unlock_irqrestore(&dwc->lock, flags);
-
-       return 0;
-
-err:
        /*
         * Attempt to reset the controller's state. Likely no
         * communication can be established until the host
         * performs a port reset.
         */
-       if (dwc->softconnect)
+       if (ret && dwc->softconnect) {
                dwc3_gadget_soft_connect(dwc);
+               return -EAGAIN;
+       }
 
-       return ret;
+       spin_lock_irqsave(&dwc->lock, flags);
+       if (dwc->gadget_driver)
+               dwc3_disconnect_gadget(dwc);
+       spin_unlock_irqrestore(&dwc->lock, flags);
+
+       return 0;
 }
 
 int dwc3_gadget_resume(struct dwc3 *dwc)
diff --git a/drivers/usb/dwc3/glue.h b/drivers/usb/dwc3/glue.h
new file mode 100644
index 000000000000..2efd00e763be
--- /dev/null
+++ b/drivers/usb/dwc3/glue.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * glue.h - DesignWare USB3 DRD glue header
+ */
+
+#ifndef __DRIVERS_USB_DWC3_GLUE_H
+#define __DRIVERS_USB_DWC3_GLUE_H
+
+#include <linux/types.h>
+#include "core.h"
+
+/**
+ * dwc3_probe_data: Initialization parameters passed to dwc3_core_probe()
+ * @dwc: Reference to dwc3 context structure
+ * @res: resource for the DWC3 core mmio region
+ * @ignore_clocks_and_resets: clocks and resets defined for the device should
+ *             be ignored by the DWC3 core, as they are managed by the glue
+ */
+struct dwc3_probe_data {
+       struct dwc3 *dwc;
+       struct resource *res;
+       bool ignore_clocks_and_resets;
+};
+
+int dwc3_core_probe(const struct dwc3_probe_data *data);
+void dwc3_core_remove(struct dwc3 *dwc);
+
+int dwc3_runtime_suspend(struct dwc3 *dwc);
+int dwc3_runtime_resume(struct dwc3 *dwc);
+int dwc3_runtime_idle(struct dwc3 *dwc);
+int dwc3_pm_suspend(struct dwc3 *dwc);
+int dwc3_pm_resume(struct dwc3 *dwc);
+void dwc3_pm_complete(struct dwc3 *dwc);
+int dwc3_pm_prepare(struct dwc3 *dwc);
+
+#endif
-- 
2.43.0

Reply via email to