diff mbox series

[10/16] phy: renesas: rcar-gen3-usb2: Add support to initialize the bus

Message ID 20240822152801.602318-11-claudiu.beznea.uj@bp.renesas.com
State New
Headers show
Series Add initial USB support for the Renesas RZ/G3S SoC | expand

Commit Message

Claudiu Aug. 22, 2024, 3:27 p.m. UTC
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>

The Renesas RZ/G3S need to initialize the USB BUS before transferring data
due to hardware limitation. As the register that need to be touched for
this is in the address space of the USB PHY, and the UBS PHY need to be
initialized before any other USB drivers handling data transfer, add
support to initialize the USB BUS.

As the USB PHY is probed before any other USB drivers that enables
clocks and de-assert the reset signals and the BUS initialization is done
in the probe phase, we need to add code to de-assert reset signal and
runtime resume the device (which enables its clocks) before accessing
the registers.

As the reset signals are not required by the USB PHY driver for the other
USB PHY hardware variants, the reset signals and runtime PM was handled
only in the function that initialize the USB BUS.

The PHY initialization was done right after runtime PM enable to have
all in place when the PHYs are registered.

Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
---
 drivers/phy/renesas/phy-rcar-gen3-usb2.c | 50 ++++++++++++++++++++++--
 1 file changed, 47 insertions(+), 3 deletions(-)

Comments

Claudiu Aug. 23, 2024, 8:57 a.m. UTC | #1
Hi, Biju,

On 23.08.2024 10:35, Biju Das wrote:
> Hi Claudiu,
> 
>> -----Original Message-----
>> From: Claudiu <claudiu.beznea@tuxon.dev>
>> Sent: Thursday, August 22, 2024 4:28 PM
>> Subject: [PATCH 10/16] phy: renesas: rcar-gen3-usb2: Add support to initialize the bus
>>
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The Renesas RZ/G3S need to initialize the USB BUS before transferring data due to hardware limitation.
>> As the register that need to be touched for this is in the address space of the USB PHY, and the UBS
>> PHY need to be initialized before any other USB drivers handling data transfer, add support to
>> initialize the USB BUS.
>>
>> As the USB PHY is probed before any other USB drivers that enables clocks and de-assert the reset
>> signals and the BUS initialization is done in the probe phase, we need to add code to de-assert reset
>> signal and runtime resume the device (which enables its clocks) before accessing the registers.
>>
>> As the reset signals are not required by the USB PHY driver for the other USB PHY hardware variants,
>> the reset signals and runtime PM was handled only in the function that initialize the USB BUS.
>>
>> The PHY initialization was done right after runtime PM enable to have all in place when the PHYs are
>> registered.
> 
> There is no user for this patch. The first user is RZ/G3S and you should merge this patch with
> next one.

I think this is a matter of taste... This is how I usually format the
patches (for scenarios like this) and got no request for squashing.

Anyway, I can do it your way, too.

Thank you,
Claudiu Beznea

> 
> Cheers,
> Biju
> 
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>> ---
>>  drivers/phy/renesas/phy-rcar-gen3-usb2.c | 50 ++++++++++++++++++++++--
>>  1 file changed, 47 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
>> index 7594f64eb737..cf4299cea579 100644
>> --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
>> +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
>> @@ -19,12 +19,14 @@
>>  #include <linux/platform_device.h>
>>  #include <linux/pm_runtime.h>
>>  #include <linux/regulator/consumer.h>
>> +#include <linux/reset.h>
>>  #include <linux/string.h>
>>  #include <linux/usb/of.h>
>>  #include <linux/workqueue.h>
>>
>>  /******* USB2.0 Host registers (original offset is +0x200) *******/
>>  #define USB2_INT_ENABLE		0x000
>> +#define USB2_AHB_BUS_CTR	0x008
>>  #define USB2_USBCTR		0x00c
>>  #define USB2_SPD_RSM_TIMSET	0x10c
>>  #define USB2_OC_TIMSET		0x110
>> @@ -40,6 +42,10 @@
>>  #define USB2_INT_ENABLE_USBH_INTB_EN	BIT(2)	/* For EHCI */
>>  #define USB2_INT_ENABLE_USBH_INTA_EN	BIT(1)	/* For OHCI */
>>
>> +/* AHB_BUS_CTR */
>> +#define USB2_AHB_BUS_CTR_MBL_MASK	GENMASK(1, 0)
>> +#define USB2_AHB_BUS_CTR_MBL_INCR4	2
>> +
>>  /* USBCTR */
>>  #define USB2_USBCTR_DIRPD	BIT(2)
>>  #define USB2_USBCTR_PLL_RST	BIT(1)
>> @@ -111,6 +117,7 @@ struct rcar_gen3_chan {
>>  	struct extcon_dev *extcon;
>>  	struct rcar_gen3_phy rphys[NUM_OF_PHYS];
>>  	struct regulator *vbus;
>> +	struct reset_control *rstc;
>>  	struct work_struct work;
>>  	struct mutex lock;	/* protects rphys[...].powered */
>>  	enum usb_dr_mode dr_mode;
>> @@ -125,6 +132,7 @@ struct rcar_gen3_chan {  struct rcar_gen3_phy_drv_data {
>>  	const struct phy_ops *phy_usb2_ops;
>>  	bool no_adp_ctrl;
>> +	bool init_bus;
>>  };
>>
>>  /*
>> @@ -650,6 +658,35 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np)
>>  	return candidate;
>>  }
>>
>> +static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
>> +{
>> +	struct device *dev = channel->dev;
>> +	int ret;
>> +	u32 val;
>> +
>> +	channel->rstc = devm_reset_control_array_get_shared(dev);
>> +	if (IS_ERR(channel->rstc))
>> +		return PTR_ERR(channel->rstc);
>> +
>> +	ret = pm_runtime_resume_and_get(dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = reset_control_deassert(channel->rstc);
>> +	if (ret)
>> +		goto rpm_put;
>> +
>> +	val = readl(channel->base + USB2_AHB_BUS_CTR);
>> +	val &= ~USB2_AHB_BUS_CTR_MBL_MASK;
>> +	val |= USB2_AHB_BUS_CTR_MBL_INCR4;
>> +	writel(val, channel->base + USB2_AHB_BUS_CTR);
>> +
>> +rpm_put:
>> +	pm_runtime_put(dev);
>> +
>> +	return ret;
>> +}
>> +
>>  static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)  {
>>  	const struct rcar_gen3_phy_drv_data *phy_data; @@ -703,6 +740,15 @@ static int
>> rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
>>  		goto error;
>>  	}
>>
>> +	platform_set_drvdata(pdev, channel);
>> +	channel->dev = dev;
>> +
>> +	if (phy_data->init_bus) {
>> +		ret = rcar_gen3_phy_usb2_init_bus(channel);
>> +		if (ret)
>> +			goto error;
>> +	}
>> +
>>  	channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
>>  	if (phy_data->no_adp_ctrl)
>>  		channel->obint_enable_bits = USB2_OBINT_IDCHG_EN; @@ -733,9 +779,6 @@ static int
>> rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
>>  		channel->vbus = NULL;
>>  	}
>>
>> -	platform_set_drvdata(pdev, channel);
>> -	channel->dev = dev;
>> -
>>  	provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
>>  	if (IS_ERR(provider)) {
>>  		dev_err(dev, "Failed to register PHY provider\n"); @@ -762,6 +805,7 @@ static void
>> rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
>>  	if (channel->is_otg_channel)
>>  		device_remove_file(&pdev->dev, &dev_attr_role);
>>
>> +	reset_control_assert(channel->rstc);
>>  	pm_runtime_disable(&pdev->dev);
>>  };
>>
>> --
>> 2.39.2
>
Vinod Koul Aug. 30, 2024, 8:02 a.m. UTC | #2
On 23-08-24, 09:01, Biju Das wrote:
> > >> The Renesas RZ/G3S need to initialize the USB BUS before transferring data due to hardware
> > limitation.
> > >> As the register that need to be touched for this is in the address
> > >> space of the USB PHY, and the UBS PHY need to be initialized before
> > >> any other USB drivers handling data transfer, add support to initialize the USB BUS.
> > >>
> > >> As the USB PHY is probed before any other USB drivers that enables
> > >> clocks and de-assert the reset signals and the BUS initialization is
> > >> done in the probe phase, we need to add code to de-assert reset signal and runtime resume the
> > device (which enables its clocks) before accessing the registers.
> > >>
> > >> As the reset signals are not required by the USB PHY driver for the
> > >> other USB PHY hardware variants, the reset signals and runtime PM was handled only in the function
> > that initialize the USB BUS.
> > >>
> > >> The PHY initialization was done right after runtime PM enable to have
> > >> all in place when the PHYs are registered.
> > >
> > > There is no user for this patch. The first user is RZ/G3S and you
> > > should merge this patch with next one.
> > 
> > I think this is a matter of taste... This is how I usually format the patches (for scenarios like
> > this) and got no request for squashing.
> 
> That is strange for trivial patches like this.

Splitting is better, this patch does one thing whereas the next one uses
it adds in new device, i would say quite a clean approach

NOTE: Don't quote the not required context while replying, it is good
mail list hygiene
Biju Das Aug. 30, 2024, 8:06 a.m. UTC | #3
Hi Vinod,

> -----Original Message-----
> From: Vinod Koul <vkoul@kernel.org>
> Sent: Friday, August 30, 2024 9:03 AM
> Subject: Re: [PATCH 10/16] phy: renesas: rcar-gen3-usb2: Add support to initialize the bus
> 
> On 23-08-24, 09:01, Biju Das wrote:
> > > >> The Renesas RZ/G3S need to initialize the USB BUS before
> > > >> transferring data due to hardware
> > > limitation.
> > > >> As the register that need to be touched for this is in the
> > > >> address space of the USB PHY, and the UBS PHY need to be
> > > >> initialized before any other USB drivers handling data transfer, add support to initialize the
> USB BUS.
> > > >>
> > > >> As the USB PHY is probed before any other USB drivers that
> > > >> enables clocks and de-assert the reset signals and the BUS
> > > >> initialization is done in the probe phase, we need to add code to
> > > >> de-assert reset signal and runtime resume the
> > > device (which enables its clocks) before accessing the registers.
> > > >>
> > > >> As the reset signals are not required by the USB PHY driver for
> > > >> the other USB PHY hardware variants, the reset signals and
> > > >> runtime PM was handled only in the function
> > > that initialize the USB BUS.
> > > >>
> > > >> The PHY initialization was done right after runtime PM enable to
> > > >> have all in place when the PHYs are registered.
> > > >
> > > > There is no user for this patch. The first user is RZ/G3S and you
> > > > should merge this patch with next one.
> > >
> > > I think this is a matter of taste... This is how I usually format
> > > the patches (for scenarios like
> > > this) and got no request for squashing.
> >
> > That is strange for trivial patches like this.
> 
> Splitting is better, this patch does one thing whereas the next one uses it adds in new device, i
> would say quite a clean approach
> 
> NOTE: Don't quote the not required context while replying, it is good mail list hygiene

Agreed. I was wrong then. To support a new device, bus initialization is required.
So I thought it should go together.

Cheers,
Biju
Claudiu Oct. 9, 2024, 8:31 a.m. UTC | #4
Hi, Geert,

On 08.10.2024 17:57, Geert Uytterhoeven wrote:
> Hi Claudiu,
> 
> On Thu, Aug 22, 2024 at 5:28 PM Claudiu <claudiu.beznea@tuxon.dev> wrote:
>>
>> From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
>>
>> The Renesas RZ/G3S need to initialize the USB BUS before transferring data
>> due to hardware limitation. As the register that need to be touched for
>> this is in the address space of the USB PHY, and the UBS PHY need to be
>> initialized before any other USB drivers handling data transfer, add
>> support to initialize the USB BUS.
>>
>> As the USB PHY is probed before any other USB drivers that enables
>> clocks and de-assert the reset signals and the BUS initialization is done
>> in the probe phase, we need to add code to de-assert reset signal and
>> runtime resume the device (which enables its clocks) before accessing
>> the registers.
>>
>> As the reset signals are not required by the USB PHY driver for the other
>> USB PHY hardware variants, the reset signals and runtime PM was handled
>> only in the function that initialize the USB BUS.
>>
>> The PHY initialization was done right after runtime PM enable to have
>> all in place when the PHYs are registered.
>>
>> Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
> 
> Thanks for your patch, which is now commit 4eae16375357a2a7 ("phy:
> renesas: rcar-gen3-usb2: Add support to initialize the bus") in
> v6.12-rc1.
> 
>> --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
>> +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
>> @@ -650,6 +658,35 @@ static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np)
>>         return candidate;
>>  }
>>
>> +static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
>> +{
>> +       struct device *dev = channel->dev;
>> +       int ret;
>> +       u32 val;
>> +
>> +       channel->rstc = devm_reset_control_array_get_shared(dev);
>> +       if (IS_ERR(channel->rstc))
>> +               return PTR_ERR(channel->rstc);
>> +
>> +       ret = pm_runtime_resume_and_get(dev);
>> +       if (ret)
>> +               return ret;
>> +
>> +       ret = reset_control_deassert(channel->rstc);
>> +       if (ret)
>> +               goto rpm_put;
>> +
>> +       val = readl(channel->base + USB2_AHB_BUS_CTR);
>> +       val &= ~USB2_AHB_BUS_CTR_MBL_MASK;
>> +       val |= USB2_AHB_BUS_CTR_MBL_INCR4;
>> +       writel(val, channel->base + USB2_AHB_BUS_CTR);
>> +
>> +rpm_put:
>> +       pm_runtime_put(dev);
>> +
>> +       return ret;
>> +}
>> +
>>  static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
>>  {
>>         const struct rcar_gen3_phy_drv_data *phy_data;
>> @@ -703,6 +740,15 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
>>                 goto error;
>>         }
>>
>> +       platform_set_drvdata(pdev, channel);
>> +       channel->dev = dev;
> 
> Unrelated change?

That's a leftover from the removal of the suspend to RAM support from the
initial work (internal only) of this series. I'll keep it in mid to remove
it on the following patches, if needed.

> 
>> +
>> +       if (phy_data->init_bus) {
>> +               ret = rcar_gen3_phy_usb2_init_bus(channel);
>> +               if (ret)
>> +                       goto error;
>> +       }
>> +
>>         channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
>>         if (phy_data->no_adp_ctrl)
>>                 channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
>> @@ -733,9 +779,6 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
>>                 channel->vbus = NULL;
>>         }
>>
>> -       platform_set_drvdata(pdev, channel);
>> -       channel->dev = dev;
>> -
>>         provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
>>         if (IS_ERR(provider)) {
>>                 dev_err(dev, "Failed to register PHY provider\n");
> 
> The reset is not asserted in the error path, only in .remove().
> 
> Oh, Christophe already sent a fix for that...
> "[PATCH v3] phy: renesas: rcar-gen3-usb2: Fix an error handling path
> in rcar_gen3_phy_usb2_probe()"
> https://lore.kernel.org/all/290b25827e3f0742808940719455ff0c5cb9d01d.1726329925.git.christophe.jaillet@wanadoo.fr

Yes, I messed this when removing the suspend to RAM from my initial work on
this (internal only). Thanks Christophe for handling it.

Thank you,
Claudiu Beznea

> 
>> @@ -762,6 +805,7 @@ static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
>>         if (channel->is_otg_channel)
>>                 device_remove_file(&pdev->dev, &dev_attr_role);
>>
>> +       reset_control_assert(channel->rstc);
>>         pm_runtime_disable(&pdev->dev);
>>  };
> 
> The rest LGTM.
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
>
diff mbox series

Patch

diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
index 7594f64eb737..cf4299cea579 100644
--- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -19,12 +19,14 @@ 
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/reset.h>
 #include <linux/string.h>
 #include <linux/usb/of.h>
 #include <linux/workqueue.h>
 
 /******* USB2.0 Host registers (original offset is +0x200) *******/
 #define USB2_INT_ENABLE		0x000
+#define USB2_AHB_BUS_CTR	0x008
 #define USB2_USBCTR		0x00c
 #define USB2_SPD_RSM_TIMSET	0x10c
 #define USB2_OC_TIMSET		0x110
@@ -40,6 +42,10 @@ 
 #define USB2_INT_ENABLE_USBH_INTB_EN	BIT(2)	/* For EHCI */
 #define USB2_INT_ENABLE_USBH_INTA_EN	BIT(1)	/* For OHCI */
 
+/* AHB_BUS_CTR */
+#define USB2_AHB_BUS_CTR_MBL_MASK	GENMASK(1, 0)
+#define USB2_AHB_BUS_CTR_MBL_INCR4	2
+
 /* USBCTR */
 #define USB2_USBCTR_DIRPD	BIT(2)
 #define USB2_USBCTR_PLL_RST	BIT(1)
@@ -111,6 +117,7 @@  struct rcar_gen3_chan {
 	struct extcon_dev *extcon;
 	struct rcar_gen3_phy rphys[NUM_OF_PHYS];
 	struct regulator *vbus;
+	struct reset_control *rstc;
 	struct work_struct work;
 	struct mutex lock;	/* protects rphys[...].powered */
 	enum usb_dr_mode dr_mode;
@@ -125,6 +132,7 @@  struct rcar_gen3_chan {
 struct rcar_gen3_phy_drv_data {
 	const struct phy_ops *phy_usb2_ops;
 	bool no_adp_ctrl;
+	bool init_bus;
 };
 
 /*
@@ -650,6 +658,35 @@  static enum usb_dr_mode rcar_gen3_get_dr_mode(struct device_node *np)
 	return candidate;
 }
 
+static int rcar_gen3_phy_usb2_init_bus(struct rcar_gen3_chan *channel)
+{
+	struct device *dev = channel->dev;
+	int ret;
+	u32 val;
+
+	channel->rstc = devm_reset_control_array_get_shared(dev);
+	if (IS_ERR(channel->rstc))
+		return PTR_ERR(channel->rstc);
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret)
+		return ret;
+
+	ret = reset_control_deassert(channel->rstc);
+	if (ret)
+		goto rpm_put;
+
+	val = readl(channel->base + USB2_AHB_BUS_CTR);
+	val &= ~USB2_AHB_BUS_CTR_MBL_MASK;
+	val |= USB2_AHB_BUS_CTR_MBL_INCR4;
+	writel(val, channel->base + USB2_AHB_BUS_CTR);
+
+rpm_put:
+	pm_runtime_put(dev);
+
+	return ret;
+}
+
 static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 {
 	const struct rcar_gen3_phy_drv_data *phy_data;
@@ -703,6 +740,15 @@  static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 		goto error;
 	}
 
+	platform_set_drvdata(pdev, channel);
+	channel->dev = dev;
+
+	if (phy_data->init_bus) {
+		ret = rcar_gen3_phy_usb2_init_bus(channel);
+		if (ret)
+			goto error;
+	}
+
 	channel->soc_no_adp_ctrl = phy_data->no_adp_ctrl;
 	if (phy_data->no_adp_ctrl)
 		channel->obint_enable_bits = USB2_OBINT_IDCHG_EN;
@@ -733,9 +779,6 @@  static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 		channel->vbus = NULL;
 	}
 
-	platform_set_drvdata(pdev, channel);
-	channel->dev = dev;
-
 	provider = devm_of_phy_provider_register(dev, rcar_gen3_phy_usb2_xlate);
 	if (IS_ERR(provider)) {
 		dev_err(dev, "Failed to register PHY provider\n");
@@ -762,6 +805,7 @@  static void rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
 	if (channel->is_otg_channel)
 		device_remove_file(&pdev->dev, &dev_attr_role);
 
+	reset_control_assert(channel->rstc);
 	pm_runtime_disable(&pdev->dev);
 };