mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] usb: musb: dsps: implement vbus_status and set_vbus platform ops
@ 2026-07-16 12:19 Lucas Martins Alves
  2026-07-16 14:00 ` [PATCH v2 1/2] " Lucas Martins Alves
  0 siblings, 1 reply; 3+ messages in thread
From: Lucas Martins Alves @ 2026-07-16 12:19 UTC (permalink / raw)
  To: b-liu, gregkh, linux-usb, linux-kernel, Lucas Martins Alves,
	Bin Liu, Greg Kroah-Hartman, linux-usb, linux-kernel
  Cc: Lucas Martins Alves

From: Lucas Martins Alves <lucas.alves@lumal21.com.br>

The DSPS glue layer (used on TI AM335x SoCs) was missing implementations
for the vbus_status and set_vbus platform ops defined in struct
musb_platform_ops.

Add dsps_musb_vbus_status() to report VBUS presence by reading the VBUS
field of MUSB_DEVCTL, and dsps_musb_set_vbus() to drive the SESSION bit
on MUSB_DEVCTL, enabling or disabling the USB session. When disabling,
musb_root_disconnect() is called to properly tear down any active host
connection before clearing the session bit.

Register both callbacks in dsps_ops to allow the MUSB core to control
VBUS on AM335x-based platforms. This enables the USB core to perform a
VBUS power cycle as a recovery mechanism when a USB error condition is
detected, and also allows userspace to control VBUS state via the
standard USB sysfs interface.

Signed-off-by: Lucas Martins Alves <lucas.alves@lumal21.com.br>
---
 drivers/usb/musb/musb_dsps.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index e3935f18dd56..e78b8c06f75d 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -618,6 +618,31 @@ static int dsps_musb_recover(struct musb *musb)
 	return session_restart ? 0 : -EPIPE;
 }
 
+static int dsps_musb_vbus_status(struct musb *musb)
+{
+	u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+	return (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS;
+}
+
+static void dsps_musb_set_vbus(struct musb *musb, int is_on)
+{
+	u8 devctl;
+
+	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+	if (is_on) {
+		musb->context.devctl |= MUSB_DEVCTL_SESSION;
+		devctl |= MUSB_DEVCTL_SESSION;
+	} else {
+		musb_root_disconnect(musb);
+		musb->context.devctl &= ~MUSB_DEVCTL_SESSION;
+		devctl &= ~MUSB_DEVCTL_SESSION;
+	}
+
+	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+}
+
 /* Similar to am35x, dm81xx support only 32-bit read operation */
 static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 {
@@ -702,6 +727,8 @@ static struct musb_platform_ops dsps_ops = {
 
 	.set_mode	= dsps_musb_set_mode,
 	.recover	= dsps_musb_recover,
+	.vbus_status	= dsps_musb_vbus_status,
+	.set_vbus	= dsps_musb_set_vbus,
 	.clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
 };
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2 1/2] usb: musb: dsps: implement vbus_status and set_vbus platform ops
  2026-07-16 12:19 [PATCH] usb: musb: dsps: implement vbus_status and set_vbus platform ops Lucas Martins Alves
@ 2026-07-16 14:00 ` Lucas Martins Alves
  2026-07-16 14:00   ` [PATCH v2 2/2] usb: musb: gadget: fix MUSB_DEVCTL race condition in set_vbus Lucas Martins Alves
  0 siblings, 1 reply; 3+ messages in thread
From: Lucas Martins Alves @ 2026-07-16 14:00 UTC (permalink / raw)
  To: b-liu, gregkh, linux-usb, linux-kernel, lucas.alves, Bin Liu,
	Greg Kroah-Hartman, linux-usb, linux-kernel
  Cc: Lucas Martins Alves

From: Lucas Martins Alves <lucas.alves@autotrac.com.br>

The DSPS glue layer (used on TI AM335x SoCs) was missing implementations
for the vbus_status and set_vbus platform ops defined in struct
musb_platform_ops.

Add dsps_musb_vbus_status() to report VBUS presence by reading the VBUS
field of MUSB_DEVCTL, and dsps_musb_set_vbus() to drive the SESSION bit
on MUSB_DEVCTL, enabling or disabling the USB session. When disabling,
musb_root_disconnect() is called to properly tear down any active host
connection before clearing the session bit.

Register both callbacks in dsps_ops to allow the MUSB core to control
VBUS on AM335x-based platforms. This enables the USB core to perform a
VBUS power cycle as a recovery mechanism when a USB error condition is
detected, and also allows userspace to control VBUS state via the
standard USB sysfs interface.

Signed-off-by: Lucas Martins Alves <lucas.alves@autotrac.com.br>
---
 drivers/usb/musb/musb_dsps.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index e3935f18dd56..8e3ef32f615e 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -618,6 +618,34 @@ static int dsps_musb_recover(struct musb *musb)
 	return session_restart ? 0 : -EPIPE;
 }
 
+static int dsps_musb_vbus_status(struct musb *musb)
+{
+	u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+	return (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS;
+}
+
+static void dsps_musb_set_vbus(struct musb *musb, int is_on)
+{
+	u8 devctl;
+
+	devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+	if (is_on) {
+		musb->context.devctl |= MUSB_DEVCTL_SESSION;
+	} else {
+		/* Since we drop the session to turn off vbus, the connection cannot survive */
+		if( musb->port1_status & USB_PORT_STAT_CONNECTION )
+			musb->port1_status |= (USB_PORT_STAT_C_CONNECTION << 16);
+		musb->port1_status &= ~( USB_PORT_STAT_CONNECTION |
+			                     USB_PORT_STAT_HIGH_SPEED |
+								 USB_PORT_STAT_LOW_SPEED );
+		devctl &= ~MUSB_DEVCTL_SESSION;
+	}
+
+	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+}
+
 /* Similar to am35x, dm81xx support only 32-bit read operation */
 static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
 {
@@ -702,6 +730,8 @@ static struct musb_platform_ops dsps_ops = {
 
 	.set_mode	= dsps_musb_set_mode,
 	.recover	= dsps_musb_recover,
+	.vbus_status	= dsps_musb_vbus_status,
+	.set_vbus	= dsps_musb_set_vbus,
 	.clear_ep_rxintr = dsps_musb_clear_ep_rxintr,
 };
 
-- 
2.53.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2 2/2] usb: musb: gadget: fix MUSB_DEVCTL race condition in set_vbus
  2026-07-16 14:00 ` [PATCH v2 1/2] " Lucas Martins Alves
@ 2026-07-16 14:00   ` Lucas Martins Alves
  0 siblings, 0 replies; 3+ messages in thread
From: Lucas Martins Alves @ 2026-07-16 14:00 UTC (permalink / raw)
  To: b-liu, gregkh, linux-usb, linux-kernel, lucas.alves, Bin Liu,
	Greg Kroah-Hartman, linux-usb, linux-kernel
  Cc: Lucas Martins Alves

From: Lucas Martins Alves <lucas.alves@autotrac.com.br>

During gadget initialization, musb_gadget_start() releases musb->lock,
enables interrupts via musb_start(), and then invokes
musb_platform_set_vbus(musb, 1) in a lockless context.

If musb_interrupt() fires concurrently, it will take musb->lock and
modify MUSB_DEVCTL. Those changes could be silently overwritten when
the callback writes back the stale cached devctl value, causing state
corruption due to the unlocked read-modify-write race condition.

Fix this by acquiring musb->lock before calling musb_platform_set_vbus()
in musb_gadget_start(). This ensures the register operation is atomic
with respect to concurrent interrupt handlers, preventing the RMW race
condition while avoiding deadlock scenarios where this function is called
from interrupt context (which already holds the lock).

Signed-off-by: Lucas Martins Alves <lucas.alves@autotrac.com.br>
---
 drivers/usb/musb/musb_gadget.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 016d3f3fc1e0..8eca252423e9 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1857,8 +1857,11 @@ static int musb_gadget_start(struct usb_gadget *g,
 	 * handles power budgeting ... this way also
 	 * ensures HdrcStart is indirectly called.
 	 */
-	if (musb->xceiv && musb->xceiv->last_event == USB_EVENT_ID)
+	if (musb->xceiv && musb->xceiv->last_event == USB_EVENT_ID) {
+		spin_lock_irqsave(&musb->lock, flags);
 		musb_platform_set_vbus(musb, 1);
+		spin_unlock_irqrestore(&musb->lock, flags);
+	}
 
 	pm_runtime_put_autosuspend(musb->controller);
 
-- 
2.53.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-16 14:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-16 12:19 [PATCH] usb: musb: dsps: implement vbus_status and set_vbus platform ops Lucas Martins Alves
2026-07-16 14:00 ` [PATCH v2 1/2] " Lucas Martins Alves
2026-07-16 14:00   ` [PATCH v2 2/2] usb: musb: gadget: fix MUSB_DEVCTL race condition in set_vbus Lucas Martins Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox