From: Biju Das <biju.das@bp.renesas.com> To: Felipe Balbi <balbi@kernel.org>, Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Cc: Biju Das <biju.das@bp.renesas.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Heikki Krogerus <heikki.krogerus@linux.intel.com>, Simon Horman <horms+renesas@verge.net.au>, Fabrizio Castro <fabrizio.castro@bp.renesas.com>, Kees Cook <keescook@chromium.org>, linux-usb@vger.kernel.org, Simon Horman <horms@verge.net.au>, Geert Uytterhoeven <geert+renesas@glider.be>, Chris Paterson <Chris.Paterson2@renesas.com>, linux-renesas-soc@vger.kernel.org Subject: [PATCH V5 6/9] usb: gadget: udc: renesas_usb3: Use usb_role_switch framework Date: Wed, 24 Apr 2019 10:22:20 +0100 [thread overview] Message-ID: <1556097743-12717-7-git-send-email-biju.das@bp.renesas.com> (raw) In-Reply-To: <1556097743-12717-1-git-send-email-biju.das@bp.renesas.com> RZ/G2E cat874 board is capable of detecting cable connect and disconnect events. Add support for renesas_usb3 to receive connect and disconnect events and support dual-role switch using usb-role-switch framework. Signed-off-by: Biju Das <biju.das@bp.renesas.com> --- V4-->V5 * Incorporated Shimoda-san's review comment (https://patchwork.kernel.org/patch/10902537/) V3-->V4 * No Change V2-->V3 * Incorporated Shimoda-san's review comment (https://patchwork.kernel.org/patch/10852507/) * Used renesas,usb-role-switch property for differentiating USB role switch associated with Type-C port controller driver. V1-->V2 * Driver uses usb role clas for handling dual role switch and handling connect/disconnect events instead of extcon. --- drivers/usb/gadget/udc/renesas_usb3.c | 92 ++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 7dc2485..230f5a5 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -351,6 +351,8 @@ struct renesas_usb3 { int disabled_count; struct usb_request *ep0_req; + + enum usb_role connection_state; u16 test_mode; u8 ep0_buf[USB3_EP0_BUF_SIZE]; bool softconnect; @@ -359,6 +361,7 @@ struct renesas_usb3 { bool extcon_usb; /* check vbus and set EXTCON_USB */ bool forced_b_device; bool start_to_connect; + bool usb_role_switch_property; }; #define gadget_to_renesas_usb3(_gadget) \ @@ -699,8 +702,11 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev) unsigned long flags; spin_lock_irqsave(&usb3->lock, flags); - usb3_set_mode_by_role_sw(usb3, host); - usb3_vbus_out(usb3, a_dev); + if (!usb3->usb_role_switch_property || + usb3->connection_state != USB_ROLE_NONE) { + usb3_set_mode_by_role_sw(usb3, host); + usb3_vbus_out(usb3, a_dev); + } /* for A-Peripheral or forced B-device mode */ if ((!host && a_dev) || usb3->start_to_connect) usb3_connect(usb3); @@ -716,7 +722,9 @@ static void usb3_check_id(struct renesas_usb3 *usb3) { usb3->extcon_host = usb3_is_a_device(usb3); - if (usb3->extcon_host && !usb3->forced_b_device) + if ((!usb3->usb_role_switch_property && + usb3->extcon_host && !usb3->forced_b_device) || + usb3->connection_state == USB_ROLE_HOST) usb3_mode_config(usb3, true, true); else usb3_mode_config(usb3, false, false); @@ -2343,14 +2351,65 @@ static enum usb_role renesas_usb3_role_switch_get(struct device *dev) return cur_role; } -static int renesas_usb3_role_switch_set(struct device *dev, - enum usb_role role) +static void handle_ext_role_switch_states(struct device *dev, + enum usb_role role) +{ + struct renesas_usb3 *usb3 = dev_get_drvdata(dev); + struct device *host = usb3->host_dev; + enum usb_role cur_role = renesas_usb3_role_switch_get(dev); + + switch (role) { + case USB_ROLE_NONE: + usb3->connection_state = USB_ROLE_NONE; + if (usb3->driver) + usb3_disconnect(usb3); + usb3_vbus_out(usb3, false); + 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) + usb3_connect(usb3); + } else if (cur_role == USB_ROLE_HOST) { + device_release_driver(host); + usb3_set_mode(usb3, false); + if (usb3->driver) + usb3_connect(usb3); + } + usb3_vbus_out(usb3, false); + break; + case USB_ROLE_HOST: + if (usb3->connection_state == USB_ROLE_NONE) { + if (usb3->driver) + usb3_disconnect(usb3); + + usb3->connection_state = USB_ROLE_HOST; + usb3_set_mode(usb3, true); + usb3_vbus_out(usb3, true); + if (device_attach(host) < 0) + dev_err(dev, "device_attach(host) failed\n"); + } else if (cur_role == USB_ROLE_DEVICE) { + usb3_disconnect(usb3); + /* Must set the mode before device_attach of the host */ + usb3_set_mode(usb3, true); + /* This device_attach() might sleep */ + if (device_attach(host) < 0) + dev_err(dev, "device_attach(host) failed\n"); + } + break; + default: + break; + } +} + +static void handle_role_switch_states(struct device *dev, + enum usb_role role) { struct renesas_usb3 *usb3 = dev_get_drvdata(dev); struct device *host = usb3->host_dev; enum usb_role cur_role = renesas_usb3_role_switch_get(dev); - pm_runtime_get_sync(dev); if (cur_role == USB_ROLE_HOST && role == USB_ROLE_DEVICE) { device_release_driver(host); usb3_set_mode(usb3, false); @@ -2361,6 +2420,20 @@ static int renesas_usb3_role_switch_set(struct device *dev, if (device_attach(host) < 0) dev_err(dev, "device_attach(host) failed\n"); } +} + +static int renesas_usb3_role_switch_set(struct device *dev, + enum usb_role role) +{ + struct renesas_usb3 *usb3 = dev_get_drvdata(dev); + + pm_runtime_get_sync(dev); + + if (usb3->usb_role_switch_property) + handle_ext_role_switch_states(dev, role); + else + handle_role_switch_states(dev, role); + pm_runtime_put(dev); return 0; @@ -2650,7 +2723,7 @@ static const unsigned int renesas_usb3_cable[] = { EXTCON_NONE, }; -static const struct usb_role_switch_desc renesas_usb3_role_switch_desc = { +static struct usb_role_switch_desc renesas_usb3_role_switch_desc = { .set = renesas_usb3_role_switch_set, .get = renesas_usb3_role_switch_get, .allow_userspace_control = true, @@ -2741,6 +2814,11 @@ static int renesas_usb3_probe(struct platform_device *pdev) if (ret < 0) goto err_dev_create; + if (device_property_read_bool(&pdev->dev, "renesas,usb-role-switch")) { + usb3->usb_role_switch_property = true; + renesas_usb3_role_switch_desc.fwnode = dev_fwnode(&pdev->dev); + } + INIT_WORK(&usb3->role_work, renesas_usb3_role_work); usb3->role_sw = usb_role_switch_register(&pdev->dev, &renesas_usb3_role_switch_desc); -- 2.7.4
WARNING: multiple messages have this Message-ID (diff)
From: Biju Das <biju.das@bp.renesas.com> To: Felipe Balbi <balbi@kernel.org>, Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> Cc: Biju Das <biju.das@bp.renesas.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Heikki Krogerus <heikki.krogerus@linux.intel.com>, Simon Horman <horms+renesas@verge.net.au>, Fabrizio Castro <fabrizio.castro@bp.renesas.com>, Kees Cook <keescook@chromium.org>, linux-usb@vger.kernel.org, Simon Horman <horms@verge.net.au>, Geert Uytterhoeven <geert+renesas@glider.be>, Chris Paterson <Chris.Paterson2@renesas.com>, linux-renesas-soc@vger.kernel.org Subject: [V5,6/9] usb: gadget: udc: renesas_usb3: Use usb_role_switch framework Date: Wed, 24 Apr 2019 10:22:20 +0100 [thread overview] Message-ID: <1556097743-12717-7-git-send-email-biju.das@bp.renesas.com> (raw) RZ/G2E cat874 board is capable of detecting cable connect and disconnect events. Add support for renesas_usb3 to receive connect and disconnect events and support dual-role switch using usb-role-switch framework. Signed-off-by: Biju Das <biju.das@bp.renesas.com> --- V4-->V5 * Incorporated Shimoda-san's review comment (https://patchwork.kernel.org/patch/10902537/) V3-->V4 * No Change V2-->V3 * Incorporated Shimoda-san's review comment (https://patchwork.kernel.org/patch/10852507/) * Used renesas,usb-role-switch property for differentiating USB role switch associated with Type-C port controller driver. V1-->V2 * Driver uses usb role clas for handling dual role switch and handling connect/disconnect events instead of extcon. --- drivers/usb/gadget/udc/renesas_usb3.c | 92 ++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index 7dc2485..230f5a5 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -351,6 +351,8 @@ struct renesas_usb3 { int disabled_count; struct usb_request *ep0_req; + + enum usb_role connection_state; u16 test_mode; u8 ep0_buf[USB3_EP0_BUF_SIZE]; bool softconnect; @@ -359,6 +361,7 @@ struct renesas_usb3 { bool extcon_usb; /* check vbus and set EXTCON_USB */ bool forced_b_device; bool start_to_connect; + bool usb_role_switch_property; }; #define gadget_to_renesas_usb3(_gadget) \ @@ -699,8 +702,11 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev) unsigned long flags; spin_lock_irqsave(&usb3->lock, flags); - usb3_set_mode_by_role_sw(usb3, host); - usb3_vbus_out(usb3, a_dev); + if (!usb3->usb_role_switch_property || + usb3->connection_state != USB_ROLE_NONE) { + usb3_set_mode_by_role_sw(usb3, host); + usb3_vbus_out(usb3, a_dev); + } /* for A-Peripheral or forced B-device mode */ if ((!host && a_dev) || usb3->start_to_connect) usb3_connect(usb3); @@ -716,7 +722,9 @@ static void usb3_check_id(struct renesas_usb3 *usb3) { usb3->extcon_host = usb3_is_a_device(usb3); - if (usb3->extcon_host && !usb3->forced_b_device) + if ((!usb3->usb_role_switch_property && + usb3->extcon_host && !usb3->forced_b_device) || + usb3->connection_state == USB_ROLE_HOST) usb3_mode_config(usb3, true, true); else usb3_mode_config(usb3, false, false); @@ -2343,14 +2351,65 @@ static enum usb_role renesas_usb3_role_switch_get(struct device *dev) return cur_role; } -static int renesas_usb3_role_switch_set(struct device *dev, - enum usb_role role) +static void handle_ext_role_switch_states(struct device *dev, + enum usb_role role) +{ + struct renesas_usb3 *usb3 = dev_get_drvdata(dev); + struct device *host = usb3->host_dev; + enum usb_role cur_role = renesas_usb3_role_switch_get(dev); + + switch (role) { + case USB_ROLE_NONE: + usb3->connection_state = USB_ROLE_NONE; + if (usb3->driver) + usb3_disconnect(usb3); + usb3_vbus_out(usb3, false); + 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) + usb3_connect(usb3); + } else if (cur_role == USB_ROLE_HOST) { + device_release_driver(host); + usb3_set_mode(usb3, false); + if (usb3->driver) + usb3_connect(usb3); + } + usb3_vbus_out(usb3, false); + break; + case USB_ROLE_HOST: + if (usb3->connection_state == USB_ROLE_NONE) { + if (usb3->driver) + usb3_disconnect(usb3); + + usb3->connection_state = USB_ROLE_HOST; + usb3_set_mode(usb3, true); + usb3_vbus_out(usb3, true); + if (device_attach(host) < 0) + dev_err(dev, "device_attach(host) failed\n"); + } else if (cur_role == USB_ROLE_DEVICE) { + usb3_disconnect(usb3); + /* Must set the mode before device_attach of the host */ + usb3_set_mode(usb3, true); + /* This device_attach() might sleep */ + if (device_attach(host) < 0) + dev_err(dev, "device_attach(host) failed\n"); + } + break; + default: + break; + } +} + +static void handle_role_switch_states(struct device *dev, + enum usb_role role) { struct renesas_usb3 *usb3 = dev_get_drvdata(dev); struct device *host = usb3->host_dev; enum usb_role cur_role = renesas_usb3_role_switch_get(dev); - pm_runtime_get_sync(dev); if (cur_role == USB_ROLE_HOST && role == USB_ROLE_DEVICE) { device_release_driver(host); usb3_set_mode(usb3, false); @@ -2361,6 +2420,20 @@ static int renesas_usb3_role_switch_set(struct device *dev, if (device_attach(host) < 0) dev_err(dev, "device_attach(host) failed\n"); } +} + +static int renesas_usb3_role_switch_set(struct device *dev, + enum usb_role role) +{ + struct renesas_usb3 *usb3 = dev_get_drvdata(dev); + + pm_runtime_get_sync(dev); + + if (usb3->usb_role_switch_property) + handle_ext_role_switch_states(dev, role); + else + handle_role_switch_states(dev, role); + pm_runtime_put(dev); return 0; @@ -2650,7 +2723,7 @@ static const unsigned int renesas_usb3_cable[] = { EXTCON_NONE, }; -static const struct usb_role_switch_desc renesas_usb3_role_switch_desc = { +static struct usb_role_switch_desc renesas_usb3_role_switch_desc = { .set = renesas_usb3_role_switch_set, .get = renesas_usb3_role_switch_get, .allow_userspace_control = true, @@ -2741,6 +2814,11 @@ static int renesas_usb3_probe(struct platform_device *pdev) if (ret < 0) goto err_dev_create; + if (device_property_read_bool(&pdev->dev, "renesas,usb-role-switch")) { + usb3->usb_role_switch_property = true; + renesas_usb3_role_switch_desc.fwnode = dev_fwnode(&pdev->dev); + } + INIT_WORK(&usb3->role_work, renesas_usb3_role_work); usb3->role_sw = usb_role_switch_register(&pdev->dev, &renesas_usb3_role_switch_desc);
next prev parent reply other threads:[~2019-04-24 9:29 UTC|newest] Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-24 9:22 [PATCH V5 0/9] Add USB3.0 and TI HD3SS3220 driver support Biju Das 2019-04-24 9:22 ` [PATCH V5 1/9] usb: roles: Introduce stubs for the exiting functions in role.h Biju Das 2019-04-24 9:22 ` [V5,1/9] " Biju Das 2019-04-24 9:22 ` [PATCH V5 2/9] usb: roles: add API to get usb_role_switch by node Biju Das 2019-04-24 9:22 ` Biju Das 2019-04-24 9:22 ` Biju Das 2019-04-24 9:22 ` [V5,2/9] " Biju Das 2019-04-24 9:22 ` [PATCH V5 3/9] dt-bindings: usb: hd3ss3220 device tree binding document Biju Das 2019-04-24 9:22 ` [V5,3/9] " Biju Das 2019-04-24 9:22 ` [PATCH V5 4/9] dt-bindings: usb: renesas_usb3: Add renesas,usb-role-switch property Biju Das 2019-04-24 9:22 ` [V5,4/9] " Biju Das 2019-04-26 18:14 ` [PATCH V5 4/9] " Rob Herring 2019-04-26 18:14 ` [V5,4/9] " Rob Herring 2019-04-29 9:39 ` [PATCH V5 4/9] " Biju Das 2019-04-29 9:39 ` [V5,4/9] " Biju Das 2019-04-29 9:39 ` [PATCH V5 4/9] " Biju Das 2019-05-03 6:39 ` Biju Das 2019-05-03 6:39 ` [V5,4/9] " Biju Das 2019-05-03 6:39 ` [PATCH V5 4/9] " Biju Das 2019-04-24 9:22 ` [PATCH V5 5/9] usb: typec: driver for TI HD3SS3220 USB Type-C DRP port controller Biju Das 2019-04-24 9:22 ` [V5,5/9] " Biju Das 2019-04-24 9:22 ` Biju Das [this message] 2019-04-24 9:22 ` [V5,6/9] usb: gadget: udc: renesas_usb3: Use usb_role_switch framework Biju Das 2019-04-24 9:22 ` [PATCH V5 7/9] arm64: defconfig: enable TYPEC_HD3SS3220 config option Biju Das 2019-04-24 9:22 ` Biju Das 2019-04-24 9:22 ` [PATCH V5 8/9] arm64: dts: renesas: r8a774c0-cat874: Enable USB3.0 host/peripheral device node Biju Das 2019-04-24 9:22 ` [PATCH V5 9/9] arm64: dts: renesas: r8a774c0-cat874: Enable usb role switch support Biju Das
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1556097743-12717-7-git-send-email-biju.das@bp.renesas.com \ --to=biju.das@bp.renesas.com \ --cc=Chris.Paterson2@renesas.com \ --cc=balbi@kernel.org \ --cc=fabrizio.castro@bp.renesas.com \ --cc=geert+renesas@glider.be \ --cc=gregkh@linuxfoundation.org \ --cc=heikki.krogerus@linux.intel.com \ --cc=horms+renesas@verge.net.au \ --cc=horms@verge.net.au \ --cc=keescook@chromium.org \ --cc=linux-renesas-soc@vger.kernel.org \ --cc=linux-usb@vger.kernel.org \ --cc=yoshihiro.shimoda.uh@renesas.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.