As RZ/V2M has both HOST and PERI reset module, we need to do reset release before accessing registers in respective IP module. This patch adds role switch support for RZ/V2M. Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx> --- v1->v2: * No change --- drivers/usb/gadget/udc/renesas_usb3.c | 34 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 8d694501bf02..bee6bceafc4f 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -7,6 +7,7 @@ #include <linux/debugfs.h> #include <linux/delay.h> +#include <linux/device.h> #include <linux/dma-mapping.h> #include <linux/err.h> #include <linux/extcon-provider.h> @@ -2366,6 +2367,9 @@ static int renesas_usb3_start(struct usb_gadget *gadget, usb3 = gadget_to_renesas_usb3(gadget); + if (usb3->is_rzv2m && usb3_is_a_device(usb3)) + return -EBUSY; + /* hook up the driver */ usb3->driver = driver; @@ -2374,6 +2378,10 @@ static int renesas_usb3_start(struct usb_gadget *gadget, pm_runtime_get_sync(usb3_to_dev(usb3)); + /* Peripheral Reset */ + if (usb3->is_rzv2m) + rzv2m_usb3drd_reset(usb3_to_dev(usb3)->parent, false); + renesas_usb3_init_controller(usb3); return 0; @@ -2386,8 +2394,10 @@ static int renesas_usb3_stop(struct usb_gadget *gadget) usb3->softconnect = false; usb3->gadget.speed = USB_SPEED_UNKNOWN; usb3->driver = NULL; - renesas_usb3_stop_controller(usb3); + if (usb3->is_rzv2m) + rzv2m_usb3drd_reset(usb3_to_dev(usb3)->parent, false); + renesas_usb3_stop_controller(usb3); if (usb3->phy) phy_exit(usb3->phy); @@ -2447,18 +2457,29 @@ static void handle_ext_role_switch_states(struct device *dev, switch (role) { case USB_ROLE_NONE: usb3->connection_state = USB_ROLE_NONE; - if (cur_role == USB_ROLE_HOST) + if (!usb3->is_rzv2m && cur_role == USB_ROLE_HOST) device_release_driver(host); - if (usb3->driver) + if (usb3->driver) { + if (usb3->is_rzv2m) + rzv2m_usb3drd_reset(dev->parent, false); usb3_disconnect(usb3); + } usb3_vbus_out(usb3, false); + + if (usb3->is_rzv2m) { + rzv2m_usb3drd_reset(dev->parent, true); + device_release_driver(host); + } break; case USB_ROLE_DEVICE: if (usb3->connection_state == USB_ROLE_NONE) { usb3->connection_state = USB_ROLE_DEVICE; usb3_set_mode(usb3, false); - if (usb3->driver) + if (usb3->driver) { + if (usb3->is_rzv2m) + renesas_usb3_init_controller(usb3); usb3_connect(usb3); + } } else if (cur_role == USB_ROLE_HOST) { device_release_driver(host); usb3_set_mode(usb3, false); @@ -2469,8 +2490,11 @@ static void handle_ext_role_switch_states(struct device *dev, break; case USB_ROLE_HOST: if (usb3->connection_state == USB_ROLE_NONE) { - if (usb3->driver) + if (usb3->driver) { + if (usb3->is_rzv2m) + rzv2m_usb3drd_reset(dev->parent, false); usb3_disconnect(usb3); + } usb3->connection_state = USB_ROLE_HOST; usb3_set_mode(usb3, true); -- 2.25.1