Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: renesas_usbhs: add suspend event support in gadget mode

When R-Car Gen3 USB 2.0 is in Gadget mode, if host is detached an interrupt
will be generated and Suspended state bit is set in interrupt status
register. Interrupt handler will call driver->suspend(composite_suspend)
if suspended state bit is set. composite_suspend will call
ffs_func_suspend which will post FUNCTIONFS_SUSPEND and will be consumed
by user space application via /dev/ep0.

To be able to detect host detach, extend the DVSQ_MASK to cover the
Suspended bit of the DVSQ[2:0] bitfield from the Interrupt Status
Register 0 (INTSTS0) register and perform appropriate action in the
DVST interrupt handler (usbhsg_irq_dev_state).

Without this commit, disconnection of the phone from R-Car-H3 ES2.0
Salvator-X CN9 port is not recognized and reverse role switch does
not happen. If phone is connected again it does not enumerate.

With this commit, disconnection will be recognized and reverse role
switch will happen by a user space application. If phone is connected
again it will enumerate properly and will become visible in the output
of 'lsusb'.

Signed-off-by: Veeraiyan Chidambaram <veeraiyan.chidambaram@in.bosch.com>
Signed-off-by: Eugeniu Rosca <erosca@de.adit-jv.com>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Tested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://lore.kernel.org/r/1568207756-22325-3-git-send-email-external.veeraiyan.c@de.adit-jv.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Veeraiyan Chidambaram and committed by
Greg Kroah-Hartman
39abcc84 fef22636

+11 -4
+2 -1
drivers/usb/renesas_usbhs/common.h
··· 161 161 #define VBSTS (1 << 7) /* VBUS_0 and VBUSIN_0 Input Status */ 162 162 #define VALID (1 << 3) /* USB Request Receive */ 163 163 164 - #define DVSQ_MASK (0x3 << 4) /* Device State */ 164 + #define DVSQ_MASK (0x7 << 4) /* Device State */ 165 165 #define POWER_STATE (0 << 4) 166 166 #define DEFAULT_STATE (1 << 4) 167 167 #define ADDRESS_STATE (2 << 4) 168 168 #define CONFIGURATION_STATE (3 << 4) 169 + #define SUSPENDED_STATE (4 << 4) 169 170 170 171 #define CTSQ_MASK (0x7) /* Control Transfer Stage */ 171 172 #define IDLE_SETUP_STAGE 0 /* Idle stage or setup stage */
+9 -3
drivers/usb/renesas_usbhs/mod_gadget.c
··· 457 457 { 458 458 struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 459 459 struct device *dev = usbhsg_gpriv_to_dev(gpriv); 460 + int state = usbhs_status_get_device_state(irq_state); 460 461 461 462 gpriv->gadget.speed = usbhs_bus_get_speed(priv); 462 463 463 - dev_dbg(dev, "state = %x : speed : %d\n", 464 - usbhs_status_get_device_state(irq_state), 465 - gpriv->gadget.speed); 464 + dev_dbg(dev, "state = %x : speed : %d\n", state, gpriv->gadget.speed); 465 + 466 + if (gpriv->gadget.speed != USB_SPEED_UNKNOWN && 467 + (state & SUSPENDED_STATE)) { 468 + if (gpriv->driver && gpriv->driver->suspend) 469 + gpriv->driver->suspend(&gpriv->gadget); 470 + usb_gadget_set_state(&gpriv->gadget, USB_STATE_SUSPENDED); 471 + } 466 472 467 473 return 0; 468 474 }