All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Cc: balbi@kernel.org, gregkh@linuxfoundation.org, agross@kernel.org,
	linux-usb@vger.kernel.org, linux-arm-msm@vger.kernel.org,
	wcheng@codeaurora.org
Subject: Re: [PATCH 1/2] usb: dwc3: dwc3-qcom: Find USB connector and register role switch
Date: Tue, 29 Jun 2021 10:48:07 -0500	[thread overview]
Message-ID: <YNtAt3dCGGyj5DU/@yoga> (raw)
In-Reply-To: <20210629144449.2550737-2-bryan.odonoghue@linaro.org>

On Tue 29 Jun 09:44 CDT 2021, Bryan O'Donoghue wrote:

> From: Wesley Cheng <wcheng@codeaurora.org>
> 
> If registering a USB typeC connector, the connector node may not be a child
> of the DWC3 QCOM device.  Utilize devcon graph search to lookup if any
> remote endpoints contain the connector.  If a connector is present, the
> DWC3 QCOM will register a USB role switch to receive role change events, as
> well as attain a reference to the DWC3 core role switch to pass the event
> down.
> 

What's wrong with the switch that dwc3_setup_role_switch() sets up?

That's what I've been using in my UCSI hacking on Snapdragon 888 and it
seems to work...

Regards,
Bjorn

> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
> Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
>  drivers/usb/dwc3/dwc3-qcom.c | 118 ++++++++++++++++++++++++++++++++++-
>  1 file changed, 116 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
> index 49e6ca94486d..4491704503ab 100644
> --- a/drivers/usb/dwc3/dwc3-qcom.c
> +++ b/drivers/usb/dwc3/dwc3-qcom.c
> @@ -20,6 +20,8 @@
>  #include <linux/usb/of.h>
>  #include <linux/reset.h>
>  #include <linux/iopoll.h>
> +#include <linux/fwnode.h>
> +#include <linux/usb/role.h>
>  
>  #include "core.h"
>  
> @@ -82,6 +84,9 @@ struct dwc3_qcom {
>  	struct notifier_block	vbus_nb;
>  	struct notifier_block	host_nb;
>  
> +	struct usb_role_switch *role_sw;
> +	struct usb_role_switch *dwc3_drd_sw;
> +
>  	const struct dwc3_acpi_pdata *acpi_pdata;
>  
>  	enum usb_dr_mode	mode;
> @@ -296,6 +301,73 @@ static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom)
>  	icc_put(qcom->icc_path_apps);
>  }
>  
> +static int dwc3_qcom_usb_role_switch_set(struct usb_role_switch *sw,
> +					 enum usb_role role)
> +{
> +	struct dwc3_qcom *qcom = usb_role_switch_get_drvdata(sw);
> +	struct fwnode_handle *child;
> +	bool enable = false;
> +
> +	if (!qcom->dwc3_drd_sw) {
> +		child = device_get_next_child_node(qcom->dev, NULL);
> +		if (child) {
> +			qcom->dwc3_drd_sw = usb_role_switch_find_by_fwnode(child);
> +			fwnode_handle_put(child);
> +			if (IS_ERR(qcom->dwc3_drd_sw)) {
> +				qcom->dwc3_drd_sw = NULL;
> +				return 0;
> +			}
> +		}
> +	}
> +
> +	usb_role_switch_set_role(qcom->dwc3_drd_sw, role);
> +
> +	if (role == USB_ROLE_DEVICE)
> +		enable = true;
> +	else
> +		enable = false;
> +
> +	qcom->mode = (role == USB_ROLE_HOST) ? USB_DR_MODE_HOST :
> +					       USB_DR_MODE_PERIPHERAL;
> +	dwc3_qcom_vbus_overrride_enable(qcom, enable);
> +	return 0;
> +}
> +
> +static enum usb_role dwc3_qcom_usb_role_switch_get(struct usb_role_switch *sw)
> +{
> +	struct dwc3_qcom *qcom = usb_role_switch_get_drvdata(sw);
> +	enum usb_role role;
> +
> +	switch (qcom->mode) {
> +	case USB_DR_MODE_HOST:
> +		role = USB_ROLE_HOST;
> +		break;
> +	case USB_DR_MODE_PERIPHERAL:
> +		role = USB_ROLE_DEVICE;
> +		break;
> +	default:
> +		role = USB_ROLE_DEVICE;
> +		break;
> +	}
> +
> +	return role;
> +}
> +
> +static int dwc3_qcom_setup_role_switch(struct dwc3_qcom *qcom)
> +{
> +	struct usb_role_switch_desc dwc3_role_switch = {NULL};
> +
> +	dwc3_role_switch.fwnode = dev_fwnode(qcom->dev);
> +	dwc3_role_switch.set = dwc3_qcom_usb_role_switch_set;
> +	dwc3_role_switch.get = dwc3_qcom_usb_role_switch_get;
> +	dwc3_role_switch.driver_data = qcom;
> +	qcom->role_sw = usb_role_switch_register(qcom->dev, &dwc3_role_switch);
> +	if (IS_ERR(qcom->role_sw))
> +		return PTR_ERR(qcom->role_sw);
> +
> +	return 0;
> +}
> +
>  static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
>  {
>  	if (qcom->hs_phy_irq) {
> @@ -698,6 +770,40 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev)
>  	return acpi_create_platform_device(adev, NULL);
>  }
>  
> +static int dwc3_qcom_connector_check(struct fwnode_handle *fwnode)
> +{
> +	if (fwnode && (!fwnode_property_match_string(fwnode, "compatible",
> +						     "gpio-usb-b-connector") ||
> +	    !fwnode_property_match_string(fwnode, "compatible",
> +					  "usb-c-connector")))
> +		return 1;
> +
> +	return 0;
> +}
> +
> +static void *dwc3_qcom_find_usb_connector_match(struct fwnode_handle *fwnode,
> +						const char *id, void *data)
> +{
> +	/* Check if the "connector" node is the parent of the remote endpoint */
> +	if (dwc3_qcom_connector_check(fwnode))
> +		return fwnode;
> +
> +	/* else, check if it is a child node */
> +	fwnode = fwnode_get_named_child_node(fwnode, "connector");
> +	if (dwc3_qcom_connector_check(fwnode))
> +		return fwnode;
> +
> +	return 0;
> +}
> +
> +static bool dwc3_qcom_find_usb_connector(struct platform_device *pdev)
> +{
> +	struct fwnode_handle *fwnode = pdev->dev.fwnode;
> +
> +	return fwnode_connection_find_match(fwnode, "connector", NULL,
> +					    dwc3_qcom_find_usb_connector_match);
> +}
> +
>  static int dwc3_qcom_probe(struct platform_device *pdev)
>  {
>  	struct device_node	*np = pdev->dev.of_node;
> @@ -813,8 +919,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
>  	if (qcom->mode == USB_DR_MODE_PERIPHERAL)
>  		dwc3_qcom_vbus_overrride_enable(qcom, true);
>  
> -	/* register extcon to override sw_vbus on Vbus change later */
> -	ret = dwc3_qcom_register_extcon(qcom);
> +	if (dwc3_qcom_find_usb_connector(pdev)) {
> +		ret = dwc3_qcom_setup_role_switch(qcom);
> +	} else {
> +		/* register extcon to override sw_vbus on Vbus change later */
> +		ret = dwc3_qcom_register_extcon(qcom);
> +	}
> +
>  	if (ret)
>  		goto interconnect_exit;
>  
> @@ -850,6 +961,9 @@ static int dwc3_qcom_remove(struct platform_device *pdev)
>  	struct device *dev = &pdev->dev;
>  	int i;
>  
> +	usb_role_switch_unregister(qcom->role_sw);
> +	usb_role_switch_put(qcom->dwc3_drd_sw);
> +
>  	device_remove_software_node(&qcom->dwc3->dev);
>  	of_platform_depopulate(dev);
>  
> -- 
> 2.30.1
> 

  reply	other threads:[~2021-06-29 15:48 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-29 14:44 [PATCH 0/2] dwc3-qcom: Prepare the ground for pm8150b tcpm Bryan O'Donoghue
2021-06-29 14:44 ` [PATCH 1/2] usb: dwc3: dwc3-qcom: Find USB connector and register role switch Bryan O'Donoghue
2021-06-29 15:48   ` Bjorn Andersson [this message]
2021-06-29 19:23     ` Bryan O'Donoghue
2021-06-29 20:02       ` Jack Pham
2021-06-29 20:16         ` Bryan O'Donoghue
2021-06-29 20:30         ` Bjorn Andersson
2021-06-29 21:57           ` Bryan O'Donoghue
2021-06-30  2:21             ` Bryan O'Donoghue
2021-07-01  1:12               ` Jack Pham
2021-07-01  2:08                 ` Bryan O'Donoghue
2021-06-29 20:18       ` Bjorn Andersson
2021-06-29 14:44 ` [PATCH 2/2] usb: dwc3: dwc3-qcom: Fix typo in the dwc3 vbus override API Bryan O'Donoghue
2021-06-29 15:51   ` Bjorn Andersson

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=YNtAt3dCGGyj5DU/@yoga \
    --to=bjorn.andersson@linaro.org \
    --cc=agross@kernel.org \
    --cc=balbi@kernel.org \
    --cc=bryan.odonoghue@linaro.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=wcheng@codeaurora.org \
    /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: link
Be 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.