All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Théo Lebrun" <theo.lebrun@bootlin.com>
To: "Roger Quadros" <rogerq@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Krzysztof Kozlowski" <krzysztof.kozlowski+dt@linaro.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Peter Chen" <peter.chen@kernel.org>,
	"Pawel Laszczak" <pawell@cadence.com>,
	"Nishanth Menon" <nm@ti.com>,
	"Vignesh Raghavendra" <vigneshr@ti.com>,
	"Tero Kristo" <kristo@kernel.org>
Cc: "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
	"Grégory Clement" <gregory.clement@bootlin.com>,
	"Kevin Hilman" <khilman@kernel.org>,
	"Alan Stern" <stern@rowland.harvard.edu>,
	linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 3/9] usb: cdns3-ti: move reg writes from probe into ->runtime_resume()
Date: Thu, 07 Mar 2024 15:39:15 +0100	[thread overview]
Message-ID: <CZNLFUH8WWIA.MAUN8E53X7PK@bootlin.com> (raw)
In-Reply-To: <d1ca5d29-8ef4-4d7f-b1c8-bcb361e6c351@kernel.org>

Hello Roger,

On Thu Mar 7, 2024 at 1:31 PM CET, Roger Quadros wrote:
> Hi,
>
> On 07/03/2024 11:55, Théo Lebrun wrote:
> > The hardware initialisation register write sequence is only used at
> > probe. Move it from being done at explicitely at probe to being done
> > implicitely by pm_runtime_get_sync() that calls ->runtime_resume().
>
> explicitly / implicitly
>
> > 
> > Keep devicetree parsing in probe and add a new field in the private
> > struct to remember the USB2 refclk rate code computation result.
> > 
> > This opens the door to having the init sequence being executed later
> > down the road, at system-wide resume for example. This is NOT currently
> > happening because runtime PM is disabled at suspend without the
> > refcount being affected.
> > 
> > Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> > ---
> >  drivers/usb/cdns3/cdns3-ti.c | 90 +++++++++++++++++++++++++-------------------
> >  1 file changed, 52 insertions(+), 38 deletions(-)
> > 
> > diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
> > index 5945c4b1e11f..4c8a557e6a6f 100644
> > --- a/drivers/usb/cdns3/cdns3-ti.c
> > +++ b/drivers/usb/cdns3/cdns3-ti.c
> > @@ -57,6 +57,7 @@ struct cdns_ti {
> >  	unsigned vbus_divider:1;
> >  	struct clk *usb2_refclk;
> >  	struct clk *lpm_clk;
> > +	int usb2_refclk_rate_code;
> >  };
> >  
> >  static const int cdns_ti_rate_table[] = {	/* in KHZ */
> > @@ -90,10 +91,8 @@ static int cdns_ti_probe(struct platform_device *pdev)
> >  	struct device *dev = &pdev->dev;
> >  	struct device_node *node = pdev->dev.of_node;
> >  	struct cdns_ti *data;
> > -	int error;
> > -	u32 reg;
> > -	int rate_code, i;
> >  	unsigned long rate;
> > +	int error, i;
> >  
> >  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> >  	if (!data)
> > @@ -133,7 +132,9 @@ static int cdns_ti_probe(struct platform_device *pdev)
> >  		return -EINVAL;
> >  	}
> >  
> > -	rate_code = i;
> > +	data->usb2_refclk_rate_code = i;
> > +	data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
> > +	data->usb2_only = device_property_read_bool(dev, "ti,usb2-only");
> >  
> >  	pm_runtime_enable(dev);
> >  	error = pm_runtime_get_sync(dev);
> > @@ -142,40 +143,6 @@ static int cdns_ti_probe(struct platform_device *pdev)
> >  		goto err;
> >  	}
> >  
> > -	/* assert RESET */
> > -	reg = cdns_ti_readl(data, USBSS_W1);
> > -	reg &= ~USBSS_W1_PWRUP_RST;
> > -	cdns_ti_writel(data, USBSS_W1, reg);
> > -
> > -	/* set static config */
> > -	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > -	reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK;
> > -	reg |= rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT;
> > -
> > -	reg &= ~USBSS1_STATIC_VBUS_SEL_MASK;
> > -	data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
> > -	if (data->vbus_divider)
> > -		reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT;
> > -
> > -	cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg);
> > -	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > -
> > -	/* set USB2_ONLY mode if requested */
> > -	reg = cdns_ti_readl(data, USBSS_W1);
> > -	data->usb2_only = device_property_read_bool(dev, "ti,usb2-only");
> > -	if (data->usb2_only)
> > -		reg |= USBSS_W1_USB2_ONLY;
> > -
> > -	/* set default modestrap */
> > -	reg |= USBSS_W1_MODESTRAP_SEL;
> > -	reg &= ~USBSS_W1_MODESTRAP_MASK;
> > -	reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT;
> > -	cdns_ti_writel(data, USBSS_W1, reg);
> > -
> > -	/* de-assert RESET */
> > -	reg |= USBSS_W1_PWRUP_RST;
> > -	cdns_ti_writel(data, USBSS_W1, reg);
> > -
> >  	error = of_platform_populate(node, NULL, NULL, dev);
> >  	if (error) {
> >  		dev_err(dev, "failed to create children: %d\n", error);
> > @@ -211,6 +178,52 @@ static void cdns_ti_remove(struct platform_device *pdev)
> >  	platform_set_drvdata(pdev, NULL);
> >  }
> >  
> > +static int cdns_ti_runtime_resume(struct device *dev)
> > +{
> > +	struct cdns_ti *data = dev_get_drvdata(dev);
> > +	u32 reg;
> > +
> > +	/* assert RESET */
> > +	reg = cdns_ti_readl(data, USBSS_W1);
> > +	reg &= ~USBSS_W1_PWRUP_RST;
> > +	cdns_ti_writel(data, USBSS_W1, reg);
> > +
> > +	/* set static config */
> > +	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > +	reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK;
> > +	reg |= data->usb2_refclk_rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT;
> > +
> > +	reg &= ~USBSS1_STATIC_VBUS_SEL_MASK;
> > +
> > +	if (data->vbus_divider)
> > +		reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT;
> > +
> > +	cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg);
> > +	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > +
> > +	/* set USB2_ONLY mode if requested */
> > +	reg = cdns_ti_readl(data, USBSS_W1);
> > +
> > +	if (data->usb2_only)
> > +		reg |= USBSS_W1_USB2_ONLY;
> > +
> > +	/* set default modestrap */
> > +	reg |= USBSS_W1_MODESTRAP_SEL;
> > +	reg &= ~USBSS_W1_MODESTRAP_MASK;
> > +	reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT;
> > +	cdns_ti_writel(data, USBSS_W1, reg);
> > +
> > +	/* de-assert RESET */
> > +	reg |= USBSS_W1_PWRUP_RST;
> > +	cdns_ti_writel(data, USBSS_W1, reg);
>
> I don't think USB controller requires a reset and re-init between
> runtime suspend/resume.
>
> What you need is reset/re-init during system Resume on certain platforms.
> So you should move this part of code into a helper function and call it
> from .probe() and .system_resume()

Runtime resume is being called at probe() and system-wide resume. See
our runtime_resume() implementation as that helper function you are
describing.

A previous revision did what you are recommending. We leaned towards the
current version. See:
https://lore.kernel.org/lkml/7h34wxfmwn.fsf@baylibre.com/

Also, assuming we enable runtime PM, a reset and re-init after runtime
suspend would be the right thing to do anyways. My reading of
drivers/pmdomain/core.c tells me that if our device goes to runtime
suspend, domains will be shut down. Our controller will be reset and
we'll need to re-init it. The GENPD_FLAG_RPM_ALWAYS_ON flag is of
interest to avoid the PD to be shut down during runtime PM.

Regards,

--
Théo Lebrun, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


WARNING: multiple messages have this Message-ID (diff)
From: "Théo Lebrun" <theo.lebrun@bootlin.com>
To: "Roger Quadros" <rogerq@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Krzysztof Kozlowski" <krzysztof.kozlowski+dt@linaro.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Peter Chen" <peter.chen@kernel.org>,
	"Pawel Laszczak" <pawell@cadence.com>,
	"Nishanth Menon" <nm@ti.com>,
	"Vignesh Raghavendra" <vigneshr@ti.com>,
	"Tero Kristo" <kristo@kernel.org>
Cc: "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
	"Grégory Clement" <gregory.clement@bootlin.com>,
	"Kevin Hilman" <khilman@kernel.org>,
	"Alan Stern" <stern@rowland.harvard.edu>,
	linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v4 3/9] usb: cdns3-ti: move reg writes from probe into ->runtime_resume()
Date: Thu, 07 Mar 2024 15:39:15 +0100	[thread overview]
Message-ID: <CZNLFUH8WWIA.MAUN8E53X7PK@bootlin.com> (raw)
In-Reply-To: <d1ca5d29-8ef4-4d7f-b1c8-bcb361e6c351@kernel.org>

Hello Roger,

On Thu Mar 7, 2024 at 1:31 PM CET, Roger Quadros wrote:
> Hi,
>
> On 07/03/2024 11:55, Théo Lebrun wrote:
> > The hardware initialisation register write sequence is only used at
> > probe. Move it from being done at explicitely at probe to being done
> > implicitely by pm_runtime_get_sync() that calls ->runtime_resume().
>
> explicitly / implicitly
>
> > 
> > Keep devicetree parsing in probe and add a new field in the private
> > struct to remember the USB2 refclk rate code computation result.
> > 
> > This opens the door to having the init sequence being executed later
> > down the road, at system-wide resume for example. This is NOT currently
> > happening because runtime PM is disabled at suspend without the
> > refcount being affected.
> > 
> > Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> > ---
> >  drivers/usb/cdns3/cdns3-ti.c | 90 +++++++++++++++++++++++++-------------------
> >  1 file changed, 52 insertions(+), 38 deletions(-)
> > 
> > diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
> > index 5945c4b1e11f..4c8a557e6a6f 100644
> > --- a/drivers/usb/cdns3/cdns3-ti.c
> > +++ b/drivers/usb/cdns3/cdns3-ti.c
> > @@ -57,6 +57,7 @@ struct cdns_ti {
> >  	unsigned vbus_divider:1;
> >  	struct clk *usb2_refclk;
> >  	struct clk *lpm_clk;
> > +	int usb2_refclk_rate_code;
> >  };
> >  
> >  static const int cdns_ti_rate_table[] = {	/* in KHZ */
> > @@ -90,10 +91,8 @@ static int cdns_ti_probe(struct platform_device *pdev)
> >  	struct device *dev = &pdev->dev;
> >  	struct device_node *node = pdev->dev.of_node;
> >  	struct cdns_ti *data;
> > -	int error;
> > -	u32 reg;
> > -	int rate_code, i;
> >  	unsigned long rate;
> > +	int error, i;
> >  
> >  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> >  	if (!data)
> > @@ -133,7 +132,9 @@ static int cdns_ti_probe(struct platform_device *pdev)
> >  		return -EINVAL;
> >  	}
> >  
> > -	rate_code = i;
> > +	data->usb2_refclk_rate_code = i;
> > +	data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
> > +	data->usb2_only = device_property_read_bool(dev, "ti,usb2-only");
> >  
> >  	pm_runtime_enable(dev);
> >  	error = pm_runtime_get_sync(dev);
> > @@ -142,40 +143,6 @@ static int cdns_ti_probe(struct platform_device *pdev)
> >  		goto err;
> >  	}
> >  
> > -	/* assert RESET */
> > -	reg = cdns_ti_readl(data, USBSS_W1);
> > -	reg &= ~USBSS_W1_PWRUP_RST;
> > -	cdns_ti_writel(data, USBSS_W1, reg);
> > -
> > -	/* set static config */
> > -	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > -	reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK;
> > -	reg |= rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT;
> > -
> > -	reg &= ~USBSS1_STATIC_VBUS_SEL_MASK;
> > -	data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
> > -	if (data->vbus_divider)
> > -		reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT;
> > -
> > -	cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg);
> > -	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > -
> > -	/* set USB2_ONLY mode if requested */
> > -	reg = cdns_ti_readl(data, USBSS_W1);
> > -	data->usb2_only = device_property_read_bool(dev, "ti,usb2-only");
> > -	if (data->usb2_only)
> > -		reg |= USBSS_W1_USB2_ONLY;
> > -
> > -	/* set default modestrap */
> > -	reg |= USBSS_W1_MODESTRAP_SEL;
> > -	reg &= ~USBSS_W1_MODESTRAP_MASK;
> > -	reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT;
> > -	cdns_ti_writel(data, USBSS_W1, reg);
> > -
> > -	/* de-assert RESET */
> > -	reg |= USBSS_W1_PWRUP_RST;
> > -	cdns_ti_writel(data, USBSS_W1, reg);
> > -
> >  	error = of_platform_populate(node, NULL, NULL, dev);
> >  	if (error) {
> >  		dev_err(dev, "failed to create children: %d\n", error);
> > @@ -211,6 +178,52 @@ static void cdns_ti_remove(struct platform_device *pdev)
> >  	platform_set_drvdata(pdev, NULL);
> >  }
> >  
> > +static int cdns_ti_runtime_resume(struct device *dev)
> > +{
> > +	struct cdns_ti *data = dev_get_drvdata(dev);
> > +	u32 reg;
> > +
> > +	/* assert RESET */
> > +	reg = cdns_ti_readl(data, USBSS_W1);
> > +	reg &= ~USBSS_W1_PWRUP_RST;
> > +	cdns_ti_writel(data, USBSS_W1, reg);
> > +
> > +	/* set static config */
> > +	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > +	reg &= ~USBSS1_STATIC_PLL_REF_SEL_MASK;
> > +	reg |= data->usb2_refclk_rate_code << USBSS1_STATIC_PLL_REF_SEL_SHIFT;
> > +
> > +	reg &= ~USBSS1_STATIC_VBUS_SEL_MASK;
> > +
> > +	if (data->vbus_divider)
> > +		reg |= 1 << USBSS1_STATIC_VBUS_SEL_SHIFT;
> > +
> > +	cdns_ti_writel(data, USBSS_STATIC_CONFIG, reg);
> > +	reg = cdns_ti_readl(data, USBSS_STATIC_CONFIG);
> > +
> > +	/* set USB2_ONLY mode if requested */
> > +	reg = cdns_ti_readl(data, USBSS_W1);
> > +
> > +	if (data->usb2_only)
> > +		reg |= USBSS_W1_USB2_ONLY;
> > +
> > +	/* set default modestrap */
> > +	reg |= USBSS_W1_MODESTRAP_SEL;
> > +	reg &= ~USBSS_W1_MODESTRAP_MASK;
> > +	reg |= USBSS_MODESTRAP_MODE_NONE << USBSS_W1_MODESTRAP_SHIFT;
> > +	cdns_ti_writel(data, USBSS_W1, reg);
> > +
> > +	/* de-assert RESET */
> > +	reg |= USBSS_W1_PWRUP_RST;
> > +	cdns_ti_writel(data, USBSS_W1, reg);
>
> I don't think USB controller requires a reset and re-init between
> runtime suspend/resume.
>
> What you need is reset/re-init during system Resume on certain platforms.
> So you should move this part of code into a helper function and call it
> from .probe() and .system_resume()

Runtime resume is being called at probe() and system-wide resume. See
our runtime_resume() implementation as that helper function you are
describing.

A previous revision did what you are recommending. We leaned towards the
current version. See:
https://lore.kernel.org/lkml/7h34wxfmwn.fsf@baylibre.com/

Also, assuming we enable runtime PM, a reset and re-init after runtime
suspend would be the right thing to do anyways. My reading of
drivers/pmdomain/core.c tells me that if our device goes to runtime
suspend, domains will be shut down. Our controller will be reset and
we'll need to re-init it. The GENPD_FLAG_RPM_ALWAYS_ON flag is of
interest to avoid the PD to be shut down during runtime PM.

Regards,

--
Théo Lebrun, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2024-03-07 14:39 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-07  9:55 [PATCH v4 0/9] usb: cdns: fix suspend on J7200 by assuming reset-on-resume Théo Lebrun
2024-03-07  9:55 ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 1/9] dt-bindings: usb: ti,j721e-usb: fix compatible list Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07 15:02   ` Rob Herring
2024-03-07 15:02     ` Rob Herring
2024-03-07 18:14   ` Conor Dooley
2024-03-07 18:14     ` Conor Dooley
2024-03-07  9:55 ` [PATCH v4 2/9] dt-bindings: usb: ti,j721e-usb: add ti,j7200-usb compatible Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07 14:21   ` Rob Herring
2024-03-07 14:21     ` Rob Herring
2024-03-07 14:50     ` Théo Lebrun
2024-03-07 14:50       ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 3/9] usb: cdns3-ti: move reg writes from probe into ->runtime_resume() Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07 12:31   ` Roger Quadros
2024-03-07 12:31     ` Roger Quadros
2024-03-07 14:39     ` Théo Lebrun [this message]
2024-03-07 14:39       ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 4/9] usb: cdns3-ti: support reset-on-resume behavior Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07 12:34   ` Roger Quadros
2024-03-07 12:34     ` Roger Quadros
2024-03-08 21:58   ` Kevin Hilman
2024-03-08 21:58     ` Kevin Hilman
2024-03-14 13:40     ` Théo Lebrun
2024-03-14 13:40       ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 5/9] usb: cdns3-ti: pass auxdata from match data to of_platform_populate() Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07 12:38   ` Roger Quadros
2024-03-07 12:38     ` Roger Quadros
2024-03-07 14:47     ` Théo Lebrun
2024-03-07 14:47       ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 6/9] usb: cdns3: add quirk to platform data for reset-on-resume Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 7/9] usb: cdns3-ti: add J7200 support with reset-on-resume behavior Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 8/9] arm64: dts: ti: k3-j7200: use J7200-specific USB compatible Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun
2024-03-07  9:55 ` [PATCH v4 9/9] arm64: dts: ti: k3-am64: add USB fallback compatible to J721E Théo Lebrun
2024-03-07  9:55   ` Théo Lebrun

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=CZNLFUH8WWIA.MAUN8E53X7PK@bootlin.com \
    --to=theo.lebrun@bootlin.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=gregory.clement@bootlin.com \
    --cc=khilman@kernel.org \
    --cc=kristo@kernel.org \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=nm@ti.com \
    --cc=pawell@cadence.com \
    --cc=peter.chen@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=rogerq@kernel.org \
    --cc=stern@rowland.harvard.edu \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=vigneshr@ti.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: 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.