* [PATCH v3 0/3] usb: dwc3: Modify role-switching QC drd usb controllers
@ 2025-08-06 9:58 Krishna Kurapati
2025-08-06 9:58 ` [PATCH v3 1/3] usb: dwc3: core: Introduce glue callbacks for flattened implementations Krishna Kurapati
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Krishna Kurapati @ 2025-08-06 9:58 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, Bjorn Andersson,
Dmitry Baryshkov, Konrad Dybcio
Cc: linux-arm-msm, linux-usb, linux-kernel, Krishna Kurapati
Currently on QC targets, the conndone/disconnect events in device mode are
generated by controller when software writes to QSCRATCH registers in qcom
glue layer rather than the vbus line being routed to dwc3 core IP for it
to recognize and generate these events. We need to set UTMI_OTG_VBUS_VALID
bit of QSCRATCH_HS_PHY_CTRL register to generate a connection done event
and clear it to generate a disconnect event during cable removal or mode
switch is done
When the disconnect is not generated upon cable removal, the "connected"
flag of dwc3 is left marked as "true" and it blocks suspend routines and
for that to happen upon cable removal, the cable disconnect notification
from usb_role_switch to DWC3 core driver needs to reach DWC3 Qualcomm glue
driver for it generate the event.
Currently, the way DWC3 core and Qualcomm glue driver is designed, there
is no mechanism through which the DWC3 core can notify the Qualcomm glue
layer of any role changes which it receives from usb_role_switch. To
register these glue callbacks at probe time, for enabling core to notify
glue layer, the legacy Qualcomm driver has no way to find out when the
child driver probe was successful since it does not check for the same
during of_platform_populate.
For flattened implementation of the glue driver, register callbacks for
core to invoke and notify glue layer of role switch notifications.
Set-Role and Run_stop notifier callbacks have been added to inform glue
of changes in role and any modifications UDC might be performing on the
controller. These callbacks allow us to modify qscratch accordingly and
generate disconnect/connect events to facilitate suspend entry and proper
enumeration.
The series only allows autosuspend to be used but still relies on user
enabling it from userspace (echo auto > a600000.usb/power/control).
Tests done:
1. Enumeration in device mode:
After creating symlinks to ffs.adb and writing to UDC node, ADB is up and
working in a stable way.
2. When none is written to UDC, device enters suspend.
3. When cable is removed, cable disconnect notification comes and when
qscratch registers are cleared properly, it is generating disconnect event
4. Device enters suspend upon removing cable (host and device mode).
5. In host mode, when autosuspend is enabled from userspace for controller,
xhci, roothubs and connected peripheral, the controller
enters runtime suspend.
6. Upon removing cable in host mode, setmode brings back usb to device
mode (which is default setting), it enters suspend as cable is still
disconnected.
7. When in host mode, if we enter runtime suspend with wakeup enabled,
clicking on buttons of headset are resuming the controller.
This series has been tested on SM8450 QRD.
This series depends on removal of extcon functionality first [1].
[1]: https://lore.kernel.org/all/20250729092708.3628187-1-krishna.kurapati@oss.qualcomm.com/
Changes in v3:
Removal of extcon functionality has been moved out of this series.
Addressed coding style comments from Thinh.
Instead of adding notifier and enabling autosuspend for xhci, it has been
done in xhci-plat.c
Link to v2:
https://lore.kernel.org/all/20250610091357.2983085-1-krishna.kurapati@oss.qualcomm.com/
Changes in v2:
Rebased on top of usb-next.
Removed glue's extcon handling and made use of in-core handling.
Link to v1:
https://lore.kernel.org/all/20231017131851.8299-1-quic_kriskura@quicinc.com/
Krishna Kurapati (3):
usb: dwc3: core: Introduce glue callbacks for flattened
implementations
usb: dwc3: qcom: Implement glue callbacks to facilitate runtime
suspend
usb: xhci: plat: Facilitate using autosuspend for xhci plat devices
drivers/usb/dwc3/core.c | 1 +
drivers/usb/dwc3/core.h | 26 ++++++++++++
drivers/usb/dwc3/drd.c | 1 +
drivers/usb/dwc3/dwc3-qcom.c | 80 +++++++++++++++++++++++++++++++-----
drivers/usb/dwc3/gadget.c | 1 +
drivers/usb/host/xhci-plat.c | 1 +
6 files changed, 100 insertions(+), 10 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/3] usb: dwc3: core: Introduce glue callbacks for flattened implementations
2025-08-06 9:58 [PATCH v3 0/3] usb: dwc3: Modify role-switching QC drd usb controllers Krishna Kurapati
@ 2025-08-06 9:58 ` Krishna Kurapati
2025-08-07 1:08 ` Thinh Nguyen
2025-08-06 9:58 ` [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend Krishna Kurapati
2025-08-06 9:58 ` [PATCH v3 3/3] usb: xhci: plat: Facilitate using autosuspend for xhci plat devices Krishna Kurapati
2 siblings, 1 reply; 8+ messages in thread
From: Krishna Kurapati @ 2025-08-06 9:58 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, Bjorn Andersson,
Dmitry Baryshkov, Konrad Dybcio
Cc: linux-arm-msm, linux-usb, linux-kernel, Krishna Kurapati
In certain situations like role switching, the glue layers need to be
informed of these events, so that they can take any necessary action.
But in non-flattened implementations, the glue drivers have no data on
when the core driver probe was successful post invoking of_platform_
populate. Now that the core driver supports flattened implementations
as well, introduce vendor callbacks that can be passed on from glue to
core before invoking dwc3_core_probe.
Introduce callbacks to notify glue layer of role_switch and run_stop
changes. These can be used by flattened implementation of Qualcomm
glue layer to generate connect/disconnect events in controller during
cable connect and run stop modifications by udc in device mode.
Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
---
drivers/usb/dwc3/core.c | 1 +
drivers/usb/dwc3/core.h | 26 ++++++++++++++++++++++++++
drivers/usb/dwc3/drd.c | 1 +
drivers/usb/dwc3/gadget.c | 1 +
4 files changed, 29 insertions(+)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 8002c23a5a02..392ba86c69f5 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -2351,6 +2351,7 @@ static int dwc3_probe(struct platform_device *pdev)
return -ENOMEM;
dwc->dev = &pdev->dev;
+ dwc->glue_ops = NULL;
probe_data.dwc = dwc;
probe_data.res = res;
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index d5b985fa12f4..095311e636c5 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -992,6 +992,17 @@ struct dwc3_scratchpad_array {
__le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
};
+/**
+ * struct dwc3_glue_ops - The ops indicate the notifications that
+ * need to be passed on to glue layer
+ * @notify_set_role: Notify glue of role switch notifications
+ * @notify_run_stop: Notify run stop enable/disable information to glue
+ */
+struct dwc3_glue_ops {
+ void (*pre_set_role)(struct dwc3 *dwc, enum usb_role role);
+ void (*pre_run_stop)(struct dwc3 *dwc, bool is_on);
+};
+
/**
* struct dwc3 - representation of our controller
* @drd_work: workqueue used for role swapping
@@ -1168,6 +1179,7 @@ struct dwc3_scratchpad_array {
* @wakeup_pending_funcs: Indicates whether any interface has requested for
* function wakeup in bitmap format where bit position
* represents interface_id.
+ * @glue_ops: Vendor callbacks for flattened device implementations.
*/
struct dwc3 {
struct work_struct drd_work;
@@ -1197,6 +1209,8 @@ struct dwc3 {
struct usb_gadget *gadget;
struct usb_gadget_driver *gadget_driver;
+ const struct dwc3_glue_ops *glue_ops;
+
struct clk *bus_clk;
struct clk *ref_clk;
struct clk *susp_clk;
@@ -1614,6 +1628,18 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
int dwc3_core_soft_reset(struct dwc3 *dwc);
void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
+static inline void dwc3_pre_set_role(struct dwc3 *dwc, enum usb_role role)
+{
+ if (dwc->glue_ops && dwc->glue_ops->pre_set_role)
+ dwc->glue_ops->pre_set_role(dwc, role);
+}
+
+static inline void dwc3_pre_run_stop(struct dwc3 *dwc, bool is_on)
+{
+ if (dwc->glue_ops && dwc->glue_ops->pre_run_stop)
+ dwc->glue_ops->pre_run_stop(dwc, is_on);
+}
+
#if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
int dwc3_host_init(struct dwc3 *dwc);
void dwc3_host_exit(struct dwc3 *dwc);
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
index 7977860932b1..4c91240eb429 100644
--- a/drivers/usb/dwc3/drd.c
+++ b/drivers/usb/dwc3/drd.c
@@ -464,6 +464,7 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
break;
}
+ dwc3_pre_set_role(dwc, role);
dwc3_set_mode(dwc, mode);
return 0;
}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 25db36c63951..999b2e436622 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2658,6 +2658,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
dwc->pullups_connected = false;
}
+ dwc3_pre_run_stop(dwc, is_on);
dwc3_gadget_dctl_write_safe(dwc, reg);
do {
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend
2025-08-06 9:58 [PATCH v3 0/3] usb: dwc3: Modify role-switching QC drd usb controllers Krishna Kurapati
2025-08-06 9:58 ` [PATCH v3 1/3] usb: dwc3: core: Introduce glue callbacks for flattened implementations Krishna Kurapati
@ 2025-08-06 9:58 ` Krishna Kurapati
2025-08-06 10:32 ` Konrad Dybcio
2025-08-06 9:58 ` [PATCH v3 3/3] usb: xhci: plat: Facilitate using autosuspend for xhci plat devices Krishna Kurapati
2 siblings, 1 reply; 8+ messages in thread
From: Krishna Kurapati @ 2025-08-06 9:58 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, Bjorn Andersson,
Dmitry Baryshkov, Konrad Dybcio
Cc: linux-arm-msm, linux-usb, linux-kernel, Krishna Kurapati
On Qualcomm DWC3 dual-role controllers, the conndone/disconnect events in
device mode are generated by controller when software writes to QSCRATCH
registers in Qualcomm Glue layer rather than the vbus line being routed to
dwc3 core IP for it to recognize and generate these events.
UTMI_OTG_VBUS_VALID bit of QSCRATCH_HS_PHY_CTRL register needs to be set
to generate a connection done event and to be cleared for the controller to
generate a disconnect event during cable removal. When the disconnect is
not generated upon cable removal, the "connected" flag of dwc3 is left
marked as "true" and it blocks suspend routines and for that to happen upon
cable removal, the cable disconnect notification coming in via set_role
call need to be provided to the Qualcomm glue layer as well.
Currently, the way DWC3 core and Qualcomm legacy glue driver are designed,
there is no mechanism through which the DWC3 core can notify the Qualcomm
glue layer of any role changes which it receives via role switch. To
register these glue callbacks at probe time, for enabling core to notify
glue layer, the legacy Qualcomm driver has no way to find out when the
child driver probe was successful since it does not check for the same
during of_platform_populate.
Hence implement the following glue callbacks for flattened Qualcomm glue
driver:
1. set_role: To pass role switching information from drd layer to glue.
This information is needed to identify NONE/DEVICE mode switch and modify
QSCRATCH to generate connect-done event on device mode entry and disconnect
event on cable removal in device mode.
2. run_stop: When booting up in device mode, if autouspend is enabled and
userspace doesn't write UDC on boot, controller enters autosuspend. After
this, if the userspace writes to UDC in the future, run_stop notifier is
required to enable UTMI_OTG_VBUS_VALID of QSCRATCH so that connect done
event is generated after run_stop(1) is done to finish enumeration.
Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
---
drivers/usb/dwc3/dwc3-qcom.c | 80 +++++++++++++++++++++++++++++++-----
1 file changed, 70 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index a7eaefaeec4d..5195267cd34d 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -83,6 +83,8 @@ struct dwc3_qcom {
bool pm_suspended;
struct icc_path *icc_path_ddr;
struct icc_path *icc_path_apps;
+
+ enum usb_role current_role;
};
#define to_dwc3_qcom(d) container_of((d), struct dwc3_qcom, dwc)
@@ -111,10 +113,6 @@ static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
readl(base + offset);
}
-/*
- * TODO: Make the in-core role switching code invoke dwc3_qcom_vbus_override_enable(),
- * validate that the in-core extcon support is functional
- */
static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
{
if (enable) {
@@ -560,6 +558,57 @@ static int dwc3_qcom_setup_irq(struct dwc3_qcom *qcom, struct platform_device *p
return 0;
}
+static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_role)
+{
+ struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
+
+ if (qcom->current_role == next_role)
+ return;
+
+ if (pm_runtime_resume_and_get(qcom->dev) < 0) {
+ dev_dbg(qcom->dev, "Failed to resume device\n");
+ return;
+ }
+
+ if (qcom->current_role == USB_ROLE_DEVICE &&
+ next_role != USB_ROLE_DEVICE)
+ dwc3_qcom_vbus_override_enable(qcom, false);
+ else if ((qcom->current_role != USB_ROLE_DEVICE) &&
+ (next_role == USB_ROLE_DEVICE))
+ dwc3_qcom_vbus_override_enable(qcom, true);
+
+ pm_runtime_mark_last_busy(qcom->dev);
+ pm_runtime_put_sync(qcom->dev);
+
+ /*
+ * Current role changes via usb_role_switch_set_role callback protected
+ * internally by mutex lock.
+ */
+ qcom->current_role = next_role;
+}
+
+static void dwc3_qcom_run_stop_notifier(struct dwc3 *dwc, bool is_on)
+{
+ struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
+
+ /*
+ * When autosuspend is enabled and controller goes to suspend
+ * after removing UDC from userspace, the next UDC write needs
+ * setting of QSCRATCH VBUS_VALID to "1" to generate a connect
+ * done event.
+ */
+ if (!is_on)
+ return;
+
+ dwc3_qcom_vbus_override_enable(qcom, is_on);
+ pm_runtime_mark_last_busy(qcom->dev);
+}
+
+struct dwc3_glue_ops dwc3_qcom_glue_ops = {
+ .pre_set_role = dwc3_qcom_set_role_notifier,
+ .pre_run_stop = dwc3_qcom_run_stop_notifier,
+};
+
static int dwc3_qcom_probe(struct platform_device *pdev)
{
struct dwc3_probe_data probe_data = {};
@@ -636,6 +685,23 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (ignore_pipe_clk)
dwc3_qcom_select_utmi_clk(qcom);
+ qcom->mode = usb_get_dr_mode(dev);
+
+ if (qcom->mode == USB_DR_MODE_HOST) {
+ qcom->current_role = USB_ROLE_HOST;
+ } else if (qcom->mode == USB_DR_MODE_PERIPHERAL) {
+ qcom->current_role = USB_ROLE_DEVICE;
+ dwc3_qcom_vbus_override_enable(qcom, true);
+ } else {
+ if ((device_property_read_bool(dev, "usb-role-switch")) &&
+ (usb_get_role_switch_default_mode(dev) == USB_DR_MODE_HOST))
+ qcom->current_role = USB_ROLE_HOST;
+ else
+ qcom->current_role = USB_ROLE_DEVICE;
+ }
+
+ qcom->dwc.glue_ops = &dwc3_qcom_glue_ops;
+
qcom->dwc.dev = dev;
probe_data.dwc = &qcom->dwc;
probe_data.res = &res;
@@ -650,12 +716,6 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
if (ret)
goto remove_core;
- qcom->mode = usb_get_dr_mode(dev);
-
- /* enable vbus override for device mode */
- if (qcom->mode != USB_DR_MODE_HOST)
- dwc3_qcom_vbus_override_enable(qcom, true);
-
wakeup_source = of_property_read_bool(dev->of_node, "wakeup-source");
device_init_wakeup(&pdev->dev, wakeup_source);
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v3 3/3] usb: xhci: plat: Facilitate using autosuspend for xhci plat devices
2025-08-06 9:58 [PATCH v3 0/3] usb: dwc3: Modify role-switching QC drd usb controllers Krishna Kurapati
2025-08-06 9:58 ` [PATCH v3 1/3] usb: dwc3: core: Introduce glue callbacks for flattened implementations Krishna Kurapati
2025-08-06 9:58 ` [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend Krishna Kurapati
@ 2025-08-06 9:58 ` Krishna Kurapati
2 siblings, 0 replies; 8+ messages in thread
From: Krishna Kurapati @ 2025-08-06 9:58 UTC (permalink / raw)
To: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, Bjorn Andersson,
Dmitry Baryshkov, Konrad Dybcio
Cc: linux-arm-msm, linux-usb, linux-kernel, Krishna Kurapati
Allow autosuspend to be used by xhci plat device. For Qualcomm SoCs,
when in host mode, it is intended that the controller goes to suspend
state to save power and wait for interrupts from connected peripheral
to wake it up. This is particularly used in cases where a HID or Audio
device is connected. In such scenarios, the usb controller can enter
auto suspend and resume action after getting interrupts from the
connected device.
Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
---
drivers/usb/host/xhci-plat.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 5eb51797de32..dd57ffedcaa2 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -171,6 +171,7 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
return ret;
pm_runtime_set_active(&pdev->dev);
+ pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_noresume(&pdev->dev);
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend
2025-08-06 9:58 ` [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend Krishna Kurapati
@ 2025-08-06 10:32 ` Konrad Dybcio
2025-08-07 5:17 ` Krishna Kurapati
0 siblings, 1 reply; 8+ messages in thread
From: Konrad Dybcio @ 2025-08-06 10:32 UTC (permalink / raw)
To: Krishna Kurapati, Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman,
Bjorn Andersson, Dmitry Baryshkov
Cc: linux-arm-msm, linux-usb, linux-kernel
On 8/6/25 11:58 AM, Krishna Kurapati wrote:
> On Qualcomm DWC3 dual-role controllers, the conndone/disconnect events in
> device mode are generated by controller when software writes to QSCRATCH
> registers in Qualcomm Glue layer rather than the vbus line being routed to
> dwc3 core IP for it to recognize and generate these events.
>
> UTMI_OTG_VBUS_VALID bit of QSCRATCH_HS_PHY_CTRL register needs to be set
> to generate a connection done event and to be cleared for the controller to
> generate a disconnect event during cable removal. When the disconnect is
> not generated upon cable removal, the "connected" flag of dwc3 is left
> marked as "true" and it blocks suspend routines and for that to happen upon
> cable removal, the cable disconnect notification coming in via set_role
> call need to be provided to the Qualcomm glue layer as well.
>
> Currently, the way DWC3 core and Qualcomm legacy glue driver are designed,
> there is no mechanism through which the DWC3 core can notify the Qualcomm
> glue layer of any role changes which it receives via role switch. To
> register these glue callbacks at probe time, for enabling core to notify
> glue layer, the legacy Qualcomm driver has no way to find out when the
> child driver probe was successful since it does not check for the same
> during of_platform_populate.
>
> Hence implement the following glue callbacks for flattened Qualcomm glue
> driver:
>
> 1. set_role: To pass role switching information from drd layer to glue.
> This information is needed to identify NONE/DEVICE mode switch and modify
> QSCRATCH to generate connect-done event on device mode entry and disconnect
> event on cable removal in device mode.
>
> 2. run_stop: When booting up in device mode, if autouspend is enabled and
> userspace doesn't write UDC on boot, controller enters autosuspend. After
> this, if the userspace writes to UDC in the future, run_stop notifier is
> required to enable UTMI_OTG_VBUS_VALID of QSCRATCH so that connect done
> event is generated after run_stop(1) is done to finish enumeration.
>
> Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
> ---
> drivers/usb/dwc3/dwc3-qcom.c | 80 +++++++++++++++++++++++++++++++-----
> 1 file changed, 70 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
> index a7eaefaeec4d..5195267cd34d 100644
> --- a/drivers/usb/dwc3/dwc3-qcom.c
> +++ b/drivers/usb/dwc3/dwc3-qcom.c
> @@ -83,6 +83,8 @@ struct dwc3_qcom {
> bool pm_suspended;
> struct icc_path *icc_path_ddr;
> struct icc_path *icc_path_apps;
> +
> + enum usb_role current_role;
> };
>
> #define to_dwc3_qcom(d) container_of((d), struct dwc3_qcom, dwc)
> @@ -111,10 +113,6 @@ static inline void dwc3_qcom_clrbits(void __iomem *base, u32 offset, u32 val)
> readl(base + offset);
> }
>
> -/*
> - * TODO: Make the in-core role switching code invoke dwc3_qcom_vbus_override_enable(),
> - * validate that the in-core extcon support is functional
> - */
> static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
> {
> if (enable) {
> @@ -560,6 +558,57 @@ static int dwc3_qcom_setup_irq(struct dwc3_qcom *qcom, struct platform_device *p
> return 0;
> }
>
> +static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_role)
> +{
> + struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
> +
> + if (qcom->current_role == next_role)
> + return;
> +
> + if (pm_runtime_resume_and_get(qcom->dev) < 0) {
no need for the "< 0":
"""
Return 0 if the runtime PM usage counter of @dev has been
incremented or a negative error code otherwise.
"""
> + dev_dbg(qcom->dev, "Failed to resume device\n");
This probably belongs in the suspend/resume calls themselves
> + return;
> + }
> +
> + if (qcom->current_role == USB_ROLE_DEVICE &&
> + next_role != USB_ROLE_DEVICE)
The second part is unnecessary because the first if-condition in this
function ensures it
> + dwc3_qcom_vbus_override_enable(qcom, false);
> + else if ((qcom->current_role != USB_ROLE_DEVICE) &&
> + (next_role == USB_ROLE_DEVICE))
similarly here
meaning this can become
dwc3_qcom_vbus_override_enable(qcom, next_role == USB_ROLE_DEVICE)
(I'm not sure if it's easier to read, up to you)
> + dwc3_qcom_vbus_override_enable(qcom, true);
> +
> + pm_runtime_mark_last_busy(qcom->dev);
> + pm_runtime_put_sync(qcom->dev);
> +
> + /*
> + * Current role changes via usb_role_switch_set_role callback protected
> + * internally by mutex lock.
> + */
> + qcom->current_role = next_role;
> +}
> +
> +static void dwc3_qcom_run_stop_notifier(struct dwc3 *dwc, bool is_on)
> +{
> + struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
> +
> + /*
> + * When autosuspend is enabled and controller goes to suspend
> + * after removing UDC from userspace, the next UDC write needs
> + * setting of QSCRATCH VBUS_VALID to "1" to generate a connect
> + * done event.
> + */
> + if (!is_on)
> + return;
> +
> + dwc3_qcom_vbus_override_enable(qcom, is_on);
this argument logically becomes true, always
> + pm_runtime_mark_last_busy(qcom->dev);
> +}
> +
> +struct dwc3_glue_ops dwc3_qcom_glue_ops = {
> + .pre_set_role = dwc3_qcom_set_role_notifier,
> + .pre_run_stop = dwc3_qcom_run_stop_notifier,
> +};
> +
> static int dwc3_qcom_probe(struct platform_device *pdev)
> {
> struct dwc3_probe_data probe_data = {};
> @@ -636,6 +685,23 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
> if (ignore_pipe_clk)
> dwc3_qcom_select_utmi_clk(qcom);
>
> + qcom->mode = usb_get_dr_mode(dev);
> +
> + if (qcom->mode == USB_DR_MODE_HOST) {
> + qcom->current_role = USB_ROLE_HOST;
> + } else if (qcom->mode == USB_DR_MODE_PERIPHERAL) {
> + qcom->current_role = USB_ROLE_DEVICE;
> + dwc3_qcom_vbus_override_enable(qcom, true);
> + } else {
> + if ((device_property_read_bool(dev, "usb-role-switch")) &&
> + (usb_get_role_switch_default_mode(dev) == USB_DR_MODE_HOST))
currently this will never be true on any qcom dt ("role-switch-default-mode" is
not present anywhere)
> + qcom->current_role = USB_ROLE_HOST;
> + else
> + qcom->current_role = USB_ROLE_DEVICE;
> + }
> +
> + qcom->dwc.glue_ops = &dwc3_qcom_glue_ops;
> +
Konrad
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 1/3] usb: dwc3: core: Introduce glue callbacks for flattened implementations
2025-08-06 9:58 ` [PATCH v3 1/3] usb: dwc3: core: Introduce glue callbacks for flattened implementations Krishna Kurapati
@ 2025-08-07 1:08 ` Thinh Nguyen
0 siblings, 0 replies; 8+ messages in thread
From: Thinh Nguyen @ 2025-08-07 1:08 UTC (permalink / raw)
To: Krishna Kurapati
Cc: Thinh Nguyen, Greg Kroah-Hartman, Mathias Nyman, Bjorn Andersson,
Dmitry Baryshkov, Konrad Dybcio, linux-arm-msm@vger.kernel.org,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
On Wed, Aug 06, 2025, Krishna Kurapati wrote:
> In certain situations like role switching, the glue layers need to be
> informed of these events, so that they can take any necessary action.
> But in non-flattened implementations, the glue drivers have no data on
> when the core driver probe was successful post invoking of_platform_
> populate. Now that the core driver supports flattened implementations
> as well, introduce vendor callbacks that can be passed on from glue to
> core before invoking dwc3_core_probe.
>
> Introduce callbacks to notify glue layer of role_switch and run_stop
> changes. These can be used by flattened implementation of Qualcomm
> glue layer to generate connect/disconnect events in controller during
> cable connect and run stop modifications by udc in device mode.
>
> Signed-off-by: Krishna Kurapati <krishna.kurapati@oss.qualcomm.com>
> ---
> drivers/usb/dwc3/core.c | 1 +
> drivers/usb/dwc3/core.h | 26 ++++++++++++++++++++++++++
> drivers/usb/dwc3/drd.c | 1 +
> drivers/usb/dwc3/gadget.c | 1 +
> 4 files changed, 29 insertions(+)
>
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 8002c23a5a02..392ba86c69f5 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -2351,6 +2351,7 @@ static int dwc3_probe(struct platform_device *pdev)
> return -ENOMEM;
>
> dwc->dev = &pdev->dev;
> + dwc->glue_ops = NULL;
>
> probe_data.dwc = dwc;
> probe_data.res = res;
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index d5b985fa12f4..095311e636c5 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -992,6 +992,17 @@ struct dwc3_scratchpad_array {
> __le64 dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
> };
>
> +/**
> + * struct dwc3_glue_ops - The ops indicate the notifications that
> + * need to be passed on to glue layer
> + * @notify_set_role: Notify glue of role switch notifications
> + * @notify_run_stop: Notify run stop enable/disable information to glue
Update the names.
> + */
> +struct dwc3_glue_ops {
> + void (*pre_set_role)(struct dwc3 *dwc, enum usb_role role);
> + void (*pre_run_stop)(struct dwc3 *dwc, bool is_on);
> +};
> +
> /**
> * struct dwc3 - representation of our controller
> * @drd_work: workqueue used for role swapping
> @@ -1168,6 +1179,7 @@ struct dwc3_scratchpad_array {
> * @wakeup_pending_funcs: Indicates whether any interface has requested for
> * function wakeup in bitmap format where bit position
> * represents interface_id.
> + * @glue_ops: Vendor callbacks for flattened device implementations.
Update the placement.
> */
> struct dwc3 {
> struct work_struct drd_work;
> @@ -1197,6 +1209,8 @@ struct dwc3 {
> struct usb_gadget *gadget;
> struct usb_gadget_driver *gadget_driver;
>
> + const struct dwc3_glue_ops *glue_ops;
> +
> struct clk *bus_clk;
> struct clk *ref_clk;
> struct clk *susp_clk;
> @@ -1614,6 +1628,18 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
> int dwc3_core_soft_reset(struct dwc3 *dwc);
> void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
>
> +static inline void dwc3_pre_set_role(struct dwc3 *dwc, enum usb_role role)
> +{
> + if (dwc->glue_ops && dwc->glue_ops->pre_set_role)
> + dwc->glue_ops->pre_set_role(dwc, role);
> +}
> +
> +static inline void dwc3_pre_run_stop(struct dwc3 *dwc, bool is_on)
> +{
> + if (dwc->glue_ops && dwc->glue_ops->pre_run_stop)
> + dwc->glue_ops->pre_run_stop(dwc, is_on);
> +}
> +
> #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
> int dwc3_host_init(struct dwc3 *dwc);
> void dwc3_host_exit(struct dwc3 *dwc);
> diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c
> index 7977860932b1..4c91240eb429 100644
> --- a/drivers/usb/dwc3/drd.c
> +++ b/drivers/usb/dwc3/drd.c
> @@ -464,6 +464,7 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw,
> break;
> }
>
> + dwc3_pre_set_role(dwc, role);
> dwc3_set_mode(dwc, mode);
> return 0;
> }
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 25db36c63951..999b2e436622 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -2658,6 +2658,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
> dwc->pullups_connected = false;
> }
>
> + dwc3_pre_run_stop(dwc, is_on);
> dwc3_gadget_dctl_write_safe(dwc, reg);
>
> do {
> --
> 2.34.1
>
The rest looks fine here.
BR,
Thinh
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend
2025-08-06 10:32 ` Konrad Dybcio
@ 2025-08-07 5:17 ` Krishna Kurapati
2025-08-07 12:56 ` Konrad Dybcio
0 siblings, 1 reply; 8+ messages in thread
From: Krishna Kurapati @ 2025-08-07 5:17 UTC (permalink / raw)
To: Konrad Dybcio, Thinh Nguyen
Cc: linux-arm-msm, linux-usb, linux-kernel, Dmitry Baryshkov,
Bjorn Andersson, Mathias Nyman, Greg Kroah-Hartman
On 8/6/2025 4:02 PM, Konrad Dybcio wrote:
> On 8/6/25 11:58 AM, Krishna Kurapati wrote:
[...]
>> +static void dwc3_qcom_set_role_notifier(struct dwc3 *dwc, enum usb_role next_role)
>> +{
>> + struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
>> +
>> + if (qcom->current_role == next_role)
>> + return;
>> +
>> + if (pm_runtime_resume_and_get(qcom->dev) < 0) {
>
> no need for the "< 0":
>
> """
> Return 0 if the runtime PM usage counter of @dev has been
> incremented or a negative error code otherwise.
> """
>
ACK. Will remove the "<" condition here.
>> + dev_dbg(qcom->dev, "Failed to resume device\n");
>
> This probably belongs in the suspend/resume calls themselves
>
I think today, resume fails only if "clk_bulk_prepare_enable" fails.
Would like to keep this log here for now.
>> + return;
>> + }
>> +
>> + if (qcom->current_role == USB_ROLE_DEVICE &&
>> + next_role != USB_ROLE_DEVICE)
>
> The second part is unnecessary because the first if-condition in this
> function ensures it
ACK.
>> + dwc3_qcom_vbus_override_enable(qcom, false);
>> + else if ((qcom->current_role != USB_ROLE_DEVICE) &&
>> + (next_role == USB_ROLE_DEVICE))
>
> similarly here
>
> meaning this can become
>
> dwc3_qcom_vbus_override_enable(qcom, next_role == USB_ROLE_DEVICE)
>
> (I'm not sure if it's easier to read, up to you)
>
Will keep the if-else check as is for now.
>> + dwc3_qcom_vbus_override_enable(qcom, true);
>> +
>> + pm_runtime_mark_last_busy(qcom->dev);
>> + pm_runtime_put_sync(qcom->dev);
>> +
>> + /*
>> + * Current role changes via usb_role_switch_set_role callback protected
>> + * internally by mutex lock.
>> + */
>> + qcom->current_role = next_role;
>> +}
>> +
>> +static void dwc3_qcom_run_stop_notifier(struct dwc3 *dwc, bool is_on)
>> +{
>> + struct dwc3_qcom *qcom = to_dwc3_qcom(dwc);
>> +
>> + /*
>> + * When autosuspend is enabled and controller goes to suspend
>> + * after removing UDC from userspace, the next UDC write needs
>> + * setting of QSCRATCH VBUS_VALID to "1" to generate a connect
>> + * done event.
>> + */
>> + if (!is_on)
>> + return;
>> +
>> + dwc3_qcom_vbus_override_enable(qcom, is_on);
>
> this argument logically becomes true, always
ACK. Will just pass true here in v4.
>
>> + pm_runtime_mark_last_busy(qcom->dev);
>> +}
>> +
>> +struct dwc3_glue_ops dwc3_qcom_glue_ops = {
>> + .pre_set_role = dwc3_qcom_set_role_notifier,
>> + .pre_run_stop = dwc3_qcom_run_stop_notifier,
>> +};
>> +
>> static int dwc3_qcom_probe(struct platform_device *pdev)
>> {
>> struct dwc3_probe_data probe_data = {};
>> @@ -636,6 +685,23 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
>> if (ignore_pipe_clk)
>> dwc3_qcom_select_utmi_clk(qcom);
>>
>> + qcom->mode = usb_get_dr_mode(dev);
>> +
>> + if (qcom->mode == USB_DR_MODE_HOST) {
>> + qcom->current_role = USB_ROLE_HOST;
>> + } else if (qcom->mode == USB_DR_MODE_PERIPHERAL) {
>> + qcom->current_role = USB_ROLE_DEVICE;
>> + dwc3_qcom_vbus_override_enable(qcom, true);
>> + } else {
>> + if ((device_property_read_bool(dev, "usb-role-switch")) &&
>> + (usb_get_role_switch_default_mode(dev) == USB_DR_MODE_HOST))
>
> currently this will never be true on any qcom dt ("role-switch-default-mode" is
> not present anywhere)
Agree. But I wrote for the sake of covering all cases and just in case
anyone uses this property tomorrow.
Regards,
Krishna,
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend
2025-08-07 5:17 ` Krishna Kurapati
@ 2025-08-07 12:56 ` Konrad Dybcio
0 siblings, 0 replies; 8+ messages in thread
From: Konrad Dybcio @ 2025-08-07 12:56 UTC (permalink / raw)
To: Krishna Kurapati, Thinh Nguyen
Cc: linux-arm-msm, linux-usb, linux-kernel, Dmitry Baryshkov,
Bjorn Andersson, Mathias Nyman, Greg Kroah-Hartman
On 8/7/25 7:17 AM, Krishna Kurapati wrote:
>
>
> On 8/6/2025 4:02 PM, Konrad Dybcio wrote:
>> On 8/6/25 11:58 AM, Krishna Kurapati wrote:
>
[...]
>>> + if (qcom->mode == USB_DR_MODE_HOST) {
>>> + qcom->current_role = USB_ROLE_HOST;
>>> + } else if (qcom->mode == USB_DR_MODE_PERIPHERAL) {
>>> + qcom->current_role = USB_ROLE_DEVICE;
>>> + dwc3_qcom_vbus_override_enable(qcom, true);
>>> + } else {
>>> + if ((device_property_read_bool(dev, "usb-role-switch")) &&
>>> + (usb_get_role_switch_default_mode(dev) == USB_DR_MODE_HOST))
>>
>> currently this will never be true on any qcom dt ("role-switch-default-mode" is
>> not present anywhere)
>
> Agree. But I wrote for the sake of covering all cases and just in case anyone uses this property tomorrow.
This is fine, just wanted to make sure this is intended
Konrad
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-08-07 12:57 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-06 9:58 [PATCH v3 0/3] usb: dwc3: Modify role-switching QC drd usb controllers Krishna Kurapati
2025-08-06 9:58 ` [PATCH v3 1/3] usb: dwc3: core: Introduce glue callbacks for flattened implementations Krishna Kurapati
2025-08-07 1:08 ` Thinh Nguyen
2025-08-06 9:58 ` [PATCH v3 2/3] usb: dwc3: qcom: Implement glue callbacks to facilitate runtime suspend Krishna Kurapati
2025-08-06 10:32 ` Konrad Dybcio
2025-08-07 5:17 ` Krishna Kurapati
2025-08-07 12:56 ` Konrad Dybcio
2025-08-06 9:58 ` [PATCH v3 3/3] usb: xhci: plat: Facilitate using autosuspend for xhci plat devices Krishna Kurapati
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).