LKML Archive mirror
 help / color / mirror / Atom feed
From: Johan Hovold <johan@kernel.org>
To: Krishna Kurapati <quic_kriskura@quicinc.com>
Cc: Thinh Nguyen <Thinh.Nguyen@synopsys.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Philipp Zabel <p.zabel@pengutronix.de>,
	Andy Gross <agross@kernel.org>,
	Bjorn Andersson <andersson@kernel.org>,
	Konrad Dybcio <konrad.dybcio@linaro.org>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Felipe Balbi <balbi@kernel.org>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org,
	quic_pkondeti@quicinc.com, quic_ppratap@quicinc.com,
	quic_wcheng@quicinc.com, quic_jackp@quicinc.com,
	quic_harshq@quicinc.com, ahalaney@redhat.com
Subject: Re: [PATCH v8 5/9] usb: dwc3: core: Refactor PHY logic to support Multiport Controller
Date: Wed, 17 May 2023 18:17:47 +0200	[thread overview]
Message-ID: <ZGT-K1PW66kEEYIJ@hovoldconsulting.com> (raw)
In-Reply-To: <20230514054917.21318-6-quic_kriskura@quicinc.com>

On Sun, May 14, 2023 at 11:19:13AM +0530, Krishna Kurapati wrote:
> Currently the DWC3 driver supports only single port controller
> which requires at most one HS and one SS PHY.
> 
> But the DWC3 USB controller can be connected to multiple ports and
> each port can have their own PHYs. Each port of the multiport
> controller can either be HS+SS capable or HS only capable
> Proper quantification of them is required to modify GUSB2PHYCFG
> and GUSB3PIPECTL registers appropriately.
> 
> Add support for detecting, obtaining and configuring phy's supported
> by a multiport controller and limit the max number of ports
> supported to 4.
> 
> Co-developed-by: Harsh Agarwal <quic_harshq@quicinc.com>
> Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>

If Harsh is the primary author you need to add a From: line at the
beginning of the patch.

Either way, you need his SoB as well as your Co-developed-by tag.

All this is documented under Documentation/process/ somewhere.

> +/**
> + * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core
> + * @dwc: Pointer to our controller context structure
> + *
> + * Returns 0 on success. The USB PHY interfaces are configured but not
> + * initialized. The PHY interfaces and the PHYs get initialized together with
> + * the core in dwc3_core_init.
> + */
> +static int dwc3_phy_setup(struct dwc3 *dwc)
> +{
> +	int i;
> +	int ret;

Please try to use reverse xmas style for declaration throughout (i.e.
place the longest declarations first).

> +
> +	for (i = 0; i < dwc->num_usb3_ports; i++) {
> +		ret = dwc3_ss_phy_setup(dwc, i);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	for (i = 0; i < dwc->num_usb2_ports; i++) {
> +		ret = dwc3_hs_phy_setup(dwc, i);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	return 0;
>  }
> @@ -744,22 +777,38 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
>  static int dwc3_phy_init(struct dwc3 *dwc)
>  {
>  	int ret;
> +	int i;
> +	int j;
>  
>  	usb_phy_init(dwc->usb2_phy);
>  	usb_phy_init(dwc->usb3_phy);
>  
> -	ret = phy_init(dwc->usb2_generic_phy);
> -	if (ret < 0)
> -		goto err_shutdown_usb3_phy;
> +	for (i = 0; i < dwc->num_usb2_ports; i++) {
> +		ret = phy_init(dwc->usb2_generic_phy[i]);
> +		if (ret < 0) {
> +			/* clean up prior initialized HS PHYs */
> +			for (j = 0; j < i; j++)
> +				phy_exit(dwc->usb2_generic_phy[j]);
> +			goto err_shutdown_usb3_phy;
> +		}
> +	}
>  
> -	ret = phy_init(dwc->usb3_generic_phy);
> -	if (ret < 0)
> -		goto err_exit_usb2_phy;
> +	for (i = 0; i < dwc->num_usb2_ports; i++) {
> +		ret = phy_init(dwc->usb3_generic_phy[i]);
> +		if (ret < 0) {
> +			/* clean up prior initialized SS PHYs */
> +			for (j = 0; j < i; j++)
> +				phy_exit(dwc->usb3_generic_phy[j]);
> +			goto err_exit_usb2_phy;
> +		}
> +	}

The above is probably better implemented as a single loop over
num_usb2_ports where you enable each USB2 and USB3 PHY. On errors you
use the loop index to disable the already enabled PHYs in reverse
order below (after disabling the USB2 PHY if USB3 phy init fails).

>  	return 0;
>  
>  err_exit_usb2_phy:
> -	phy_exit(dwc->usb2_generic_phy);
> +	for (i = 0; i < dwc->num_usb2_ports; i++)
> +		phy_exit(dwc->usb2_generic_phy[i]);
> +

No need for a newline separator.

>  err_shutdown_usb3_phy:
>  	usb_phy_shutdown(dwc->usb3_phy);
>  	usb_phy_shutdown(dwc->usb2_phy);
> @@ -769,8 +818,12 @@ static int dwc3_phy_init(struct dwc3 *dwc)
>  
>  static void dwc3_phy_exit(struct dwc3 *dwc)
>  {
> -	phy_exit(dwc->usb3_generic_phy);
> -	phy_exit(dwc->usb2_generic_phy);
> +	int i;
> +
> +	for (i = 0; i < dwc->num_usb2_ports; i++) {
> +		phy_exit(dwc->usb3_generic_phy[i]);
> +		phy_exit(dwc->usb2_generic_phy[i]);
> +	}

For symmetry, I'd probably do this in reverse order to.

>  	usb_phy_shutdown(dwc->usb3_phy);
>  	usb_phy_shutdown(dwc->usb2_phy);
> @@ -779,22 +832,38 @@ static void dwc3_phy_exit(struct dwc3 *dwc)
>  static int dwc3_phy_power_on(struct dwc3 *dwc)
>  {
>  	int ret;
> +	int i;
> +	int j;
>  
>  	usb_phy_set_suspend(dwc->usb2_phy, 0);
>  	usb_phy_set_suspend(dwc->usb3_phy, 0);
>  
> -	ret = phy_power_on(dwc->usb2_generic_phy);
> -	if (ret < 0)
> -		goto err_suspend_usb3_phy;
> +	for (i = 0; i < dwc->num_usb2_ports; i++) {
> +		ret = phy_power_on(dwc->usb2_generic_phy[i]);
> +		if (ret < 0) {
> +			/* Turn off prior ON'ed HS Phy's */
> +			for (j = 0; j < i; j++)
> +				phy_power_off(dwc->usb2_generic_phy[j]);
> +			goto err_suspend_usb3_phy;
> +		}
> +	}
>  
> -	ret = phy_power_on(dwc->usb3_generic_phy);
> -	if (ret < 0)
> -		goto err_power_off_usb2_phy;
> +	for (i = 0; i < dwc->num_usb2_ports; i++) {
> +		ret = phy_power_on(dwc->usb3_generic_phy[i]);
> +		if (ret < 0) {
> +			/* Turn of prior ON'ed SS Phy's */
> +			for (j = 0; j < i; j++)
> +				phy_power_off(dwc->usb3_generic_phy[j]);
> +			goto err_power_off_usb2_phy;
> +		}
> +	}

These loops should be merged too as for phy_init.

>  	return 0;
>  
>  err_power_off_usb2_phy:
> -	phy_power_off(dwc->usb2_generic_phy);
> +	for (i = 0; i < dwc->num_usb2_ports; i++)
> +		phy_power_off(dwc->usb2_generic_phy[i]);
> +
>  err_suspend_usb3_phy:
>  	usb_phy_set_suspend(dwc->usb3_phy, 1);
>  	usb_phy_set_suspend(dwc->usb2_phy, 1);

> +static int dwc3_get_multiport_phys(struct dwc3 *dwc)
> +{
> +	int ret;
> +	struct device *dev = dwc->dev;
> +	int i;
> +	char phy_name[11];

As an example, for reverse xmas style this should be

	struct device *dev = dwc->dev;
	char phy_name[11];
	int ret;
	int i;

which tends to be more readable.

> +
> +	/*
> +	 * Each port is at least HS capable. So loop over num_usb2_ports
> +	 * to get available phy's.
> +	 */
> +	for (i = 0; i < dwc->num_usb2_ports; i++) {
> +		sprintf(phy_name, "usb2-port%d", i);
> +		dwc->usb2_generic_phy[i] = devm_phy_get(dev, phy_name);
> +		if (IS_ERR(dwc->usb2_generic_phy[i])) {
> +			ret = PTR_ERR(dwc->usb2_generic_phy[i]);
> +			if (ret == -ENOSYS || ret == -ENODEV)
> +				dwc->usb2_generic_phy[i] = NULL;
> +			else
> +				return dev_err_probe(dev, ret, "usb2 phy: %s not configured\n", phy_name);

This can just be

	"phy %s not configured"

or perhaps better

	"failed to lookup phy %s"

> +		}
> +
> +		sprintf(phy_name, "usb3-port%d", i);
> +		dwc->usb3_generic_phy[i] = devm_phy_get(dev, phy_name);
> +		if (IS_ERR(dwc->usb3_generic_phy[i])) {
> +			ret = PTR_ERR(dwc->usb3_generic_phy[i]);
> +			if (ret == -ENOSYS || ret == -ENODEV)
> +				dwc->usb3_generic_phy[i] = NULL;
> +			else
> +				return dev_err_probe(dev, ret, "usb3 phy: %s not configured\n", phy_name);
> +		}
> +	}
> +
> +	return 0;
> +}

I think you should drop this helper and use the same loop for both
single and multiport controllers below.

Just use the old phy names if num_usb2_ports is 1, for example:

	if (dwc->num_usb2_ports == 1)
		sprintf(phy_name, "usb2-phy");
	else
		sprintf(phy_name, "usb2-port%d", i);

> +
>  static int dwc3_core_get_phy(struct dwc3 *dwc)
>  {
>  	struct device		*dev = dwc->dev;
> @@ -1314,20 +1428,23 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
>  			return dev_err_probe(dev, ret, "no usb3 phy configured\n");
>  	}
>  
> -	dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy");
> -	if (IS_ERR(dwc->usb2_generic_phy)) {
> -		ret = PTR_ERR(dwc->usb2_generic_phy);
> +	if (dwc->num_usb2_ports > 1)
> +		return dwc3_get_multiport_phys(dwc);
> +
> +	dwc->usb2_generic_phy[0] = devm_phy_get(dev, "usb2-phy");
> +	if (IS_ERR(dwc->usb2_generic_phy[0])) {
> +		ret = PTR_ERR(dwc->usb2_generic_phy[0]);
>  		if (ret == -ENOSYS || ret == -ENODEV)
> -			dwc->usb2_generic_phy = NULL;
> +			dwc->usb2_generic_phy[0] = NULL;
>  		else
>  			return dev_err_probe(dev, ret, "no usb2 phy configured\n");
>  	}
>  
> -	dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy");
> -	if (IS_ERR(dwc->usb3_generic_phy)) {
> -		ret = PTR_ERR(dwc->usb3_generic_phy);
> +	dwc->usb3_generic_phy[0] = devm_phy_get(dev, "usb3-phy");
> +	if (IS_ERR(dwc->usb3_generic_phy[0])) {
> +		ret = PTR_ERR(dwc->usb3_generic_phy[0]);
>  		if (ret == -ENOSYS || ret == -ENODEV)
> -			dwc->usb3_generic_phy = NULL;
> +			dwc->usb3_generic_phy[0] = NULL;
>  		else
>  			return dev_err_probe(dev, ret, "no usb3 phy configured\n");
>  	}
 
>  static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
>  {
> +	int i;

Add this declaration last instead (and similar throughout).

>  	unsigned long	flags;
>  	u32 reg;

> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index d3401963bc27..84f6303922aa 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -35,6 +35,9 @@
>  
>  #define DWC3_MSG_MAX	500
>  
> +/* Number of ports supported by a multiport controller */
> +#define MAX_PORTS_SUPPORTED	4

This define should have a DWC3 prefix (e.g. DWC3_MAX_PORTS, "SUPPORTED"
doesn't seem to add much).

Is this just an arbitrary implementation limit?

> +
>  /* Define XHCI Extcap register offsets for getting multiport info */
>  #define XHCI_HCC_PARAMS_OFFSET	0x10
>  #define DWC3_XHCI_HCSPARAMS1	0x04
> @@ -1038,8 +1041,8 @@ struct dwc3_scratchpad_array {
>   * @usb3_phy: pointer to USB3 PHY
>   * @num_usb2_ports: number of usb2 ports.
>   * @num_usb3_ports: number of usb3 ports.
> - * @usb2_generic_phy: pointer to USB2 PHY
> - * @usb3_generic_phy: pointer to USB3 PHY
> + * @usb2_generic_phy: pointer to array of USB2 PHY
> + * @usb3_generic_phy: pointer to array of USB3 PHY
>   * @phys_ready: flag to indicate that PHYs are ready
>   * @ulpi: pointer to ulpi interface
>   * @ulpi_ready: flag to indicate that ULPI is initialized
> @@ -1178,8 +1181,8 @@ struct dwc3 {
>  	u8			num_usb2_ports;
>  	u8			num_usb3_ports;
>  
> -	struct phy		*usb2_generic_phy;
> -	struct phy		*usb3_generic_phy;
> +	struct phy		*usb2_generic_phy[MAX_PORTS_SUPPORTED];
> +	struct phy		*usb3_generic_phy[MAX_PORTS_SUPPORTED];

As I mentioned in a comment to one of the earlier patches, you need to
add a sanity check when parsing the port counts to avoid accessing data
beyond these arrays when looping over the PHYs.

>  
>  	bool			phys_ready;

Johan

  parent reply	other threads:[~2023-05-17 16:19 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-14  5:49 [PATCH v8 0/9] Add multiport support for DWC3 controllers Krishna Kurapati
2023-05-14  5:49 ` [PATCH v8 1/9] dt-bindings: usb: qcom,dwc3: Add bindings for SC8280 Multiport Krishna Kurapati
2023-05-14  9:46   ` Krzysztof Kozlowski
2023-05-16 10:59   ` Johan Hovold
2023-05-17 11:10     ` Krishna Kurapati PSSNV
2023-05-17 11:44       ` Johan Hovold
2023-05-17 12:19         ` Krishna Kurapati PSSNV
2023-05-17 12:55           ` Johan Hovold
2023-05-14  5:49 ` [PATCH v8 2/9] dt-bindings: usb: Add bindings for multiport properties on DWC3 controller Krishna Kurapati
2023-05-14  5:49 ` [PATCH v8 3/9] usb: dwc3: core: Access XHCI address space temporarily to read port info Krishna Kurapati
2023-05-15 21:08   ` Bjorn Andersson
2023-05-16  2:12     ` Krishna Kurapati PSSNV
2023-05-16 22:39       ` Thinh Nguyen
2023-05-16 12:11   ` Johan Hovold
2023-05-16 15:02     ` Krishna Kurapati PSSNV
2023-05-17  3:10       ` Krishna Kurapati PSSNV
2023-05-17  3:21         ` Thinh Nguyen
2023-05-17  7:46           ` Johan Hovold
2023-05-17 23:21             ` Thinh Nguyen
2023-06-07 11:56               ` Johan Hovold
2023-05-17  7:35       ` Johan Hovold
2023-05-17 12:21         ` Krishna Kurapati PSSNV
2023-05-17 15:10           ` Johan Hovold
2023-05-14  5:49 ` [PATCH v8 4/9] usb: dwc3: core: Skip setting event buffers for host only controllers Krishna Kurapati
2023-05-15 21:19   ` Bjorn Andersson
2023-05-16 12:17   ` Johan Hovold
2023-05-16 14:28     ` Krishna Kurapati PSSNV
2023-05-14  5:49 ` [PATCH v8 5/9] usb: dwc3: core: Refactor PHY logic to support Multiport Controller Krishna Kurapati
2023-05-15 21:47   ` Bjorn Andersson
2023-05-16  2:31     ` Krishna Kurapati PSSNV
2023-05-17 16:17   ` Johan Hovold [this message]
2023-05-14  5:49 ` [PATCH v8 6/9] usb: dwc3: qcom: Add multiport controller support for qcom wrapper Krishna Kurapati
2023-05-15 22:27   ` Bjorn Andersson
2023-05-16  2:19     ` Krishna Kurapati PSSNV
2023-05-17 16:37       ` Johan Hovold
2023-05-20 17:48         ` Krishna Kurapati PSSNV
2023-06-07 11:37           ` Johan Hovold
2023-06-07 19:51             ` Krishna Kurapati PSSNV
2023-06-08  9:42               ` Johan Hovold
2023-06-08 15:23                 ` Krishna Kurapati PSSNV
2023-06-08 17:57                   ` Thinh Nguyen
2023-06-09  8:18                     ` Johan Hovold
2023-06-09 18:16                       ` Thinh Nguyen
2023-06-15  4:20                         ` Krishna Kurapati PSSNV
2023-06-15 21:08                           ` Thinh Nguyen
2023-06-21  7:38                             ` Johan Hovold
2023-06-22  4:39                               ` Krishna Kurapati PSSNV
2023-06-21  7:34                         ` Johan Hovold
2023-06-22 22:41                           ` Thinh Nguyen
2023-05-26  2:55     ` Bjorn Andersson
2023-05-26 15:25       ` Krishna Kurapati PSSNV
2023-06-07 11:44         ` Johan Hovold
2023-06-07 19:55           ` Krishna Kurapati PSSNV
2023-06-08  9:44             ` Johan Hovold
2023-06-07 12:16   ` Johan Hovold
2023-06-27 15:43     ` Johan Hovold
2023-07-02 19:05       ` Krishna Kurapati PSSNV
2023-07-14  9:00         ` Johan Hovold
2023-07-14 10:38           ` Krishna Kurapati PSSNV
2023-07-21 11:16             ` Johan Hovold
2023-07-21 12:10               ` Konrad Dybcio
2023-07-21 12:54                 ` Johan Hovold
2023-08-11 16:48                   ` Konrad Dybcio
2023-08-12  8:58                     ` Krishna Kurapati PSSNV
2023-05-14  5:49 ` [PATCH v8 7/9] arm64: dts: qcom: sc8280xp: Add multiport controller node for SC8280 Krishna Kurapati
2023-05-15 14:26   ` Johan Hovold
2023-05-15 15:32     ` Krishna Kurapati PSSNV
2023-05-16 10:54       ` Johan Hovold
2023-05-16 14:24         ` Krishna Kurapati PSSNV
2023-05-16 14:42           ` Johan Hovold
2023-05-16 14:44             ` Krishna Kurapati PSSNV
2023-05-14  5:49 ` [PATCH v8 8/9] arm64: dts: qcom: sa8295p: Enable tertiary controller and its 4 USB ports Krishna Kurapati
2023-05-14  5:49 ` [PATCH v8 9/9] arm64: dts: qcom: sa8540-ride: Enable first port of tertiary usb controller Krishna Kurapati
2023-05-15  2:40 ` [PATCH v8 0/9] Add multiport support for DWC3 controllers 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=ZGT-K1PW66kEEYIJ@hovoldconsulting.com \
    --to=johan@kernel.org \
    --cc=Thinh.Nguyen@synopsys.com \
    --cc=agross@kernel.org \
    --cc=ahalaney@redhat.com \
    --cc=andersson@kernel.org \
    --cc=balbi@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=konrad.dybcio@linaro.org \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=quic_harshq@quicinc.com \
    --cc=quic_jackp@quicinc.com \
    --cc=quic_kriskura@quicinc.com \
    --cc=quic_pkondeti@quicinc.com \
    --cc=quic_ppratap@quicinc.com \
    --cc=quic_wcheng@quicinc.com \
    --cc=robh+dt@kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).