* [PATCH V2 1/6] phy: qcom-qmp-ufs: Rename qmp_ufs_enable and qmp_ufs_power_on
2025-03-18 14:49 [PATCH V2 0/6] Refactor phy powerup sequence Nitin Rawat
@ 2025-03-18 14:49 ` Nitin Rawat
2025-03-18 15:05 ` neil.armstrong
2025-03-18 14:49 ` [PATCH V2 2/6] phy: qcom-qmp-ufs: Refactor phy_power_on and phy_calibrate callbacks Nitin Rawat
` (4 subsequent siblings)
5 siblings, 1 reply; 19+ messages in thread
From: Nitin Rawat @ 2025-03-18 14:49 UTC (permalink / raw)
To: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Nitin Rawat
Rename qmp_ufs_enable to qmp_ufs_power_on and qmp_ufs_power_on to
qmp_ufs_phy_calibrate to better reflect functionality. Also
update function calls and structure assignments accordingly.
Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
index 45b3b792696e..bb836bc0f736 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
@@ -1837,7 +1837,7 @@ static int qmp_ufs_init(struct phy *phy)
return 0;
}
-static int qmp_ufs_power_on(struct phy *phy)
+static int qmp_ufs_phy_calibrate(struct phy *phy)
{
struct qmp_ufs *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -1898,7 +1898,7 @@ static int qmp_ufs_exit(struct phy *phy)
return 0;
}
-static int qmp_ufs_enable(struct phy *phy)
+static int qmp_ufs_power_on(struct phy *phy)
{
int ret;
@@ -1906,7 +1906,7 @@ static int qmp_ufs_enable(struct phy *phy)
if (ret)
return ret;
- ret = qmp_ufs_power_on(phy);
+ ret = qmp_ufs_phy_calibrate(phy);
if (ret)
qmp_ufs_exit(phy);
@@ -1940,7 +1940,7 @@ static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
}
static const struct phy_ops qcom_qmp_ufs_phy_ops = {
- .power_on = qmp_ufs_enable,
+ .power_on = qmp_ufs_power_on,
.power_off = qmp_ufs_disable,
.set_mode = qmp_ufs_set_mode,
.owner = THIS_MODULE,
--
2.48.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH V2 1/6] phy: qcom-qmp-ufs: Rename qmp_ufs_enable and qmp_ufs_power_on
2025-03-18 14:49 ` [PATCH V2 1/6] phy: qcom-qmp-ufs: Rename qmp_ufs_enable and qmp_ufs_power_on Nitin Rawat
@ 2025-03-18 15:05 ` neil.armstrong
0 siblings, 0 replies; 19+ messages in thread
From: neil.armstrong @ 2025-03-18 15:05 UTC (permalink / raw)
To: Nitin Rawat, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi
On 18/03/2025 15:49, Nitin Rawat wrote:
> Rename qmp_ufs_enable to qmp_ufs_power_on and qmp_ufs_power_on to
> qmp_ufs_phy_calibrate to better reflect functionality. Also
> update function calls and structure assignments accordingly.
>
> Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> index 45b3b792696e..bb836bc0f736 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> @@ -1837,7 +1837,7 @@ static int qmp_ufs_init(struct phy *phy)
> return 0;
> }
>
> -static int qmp_ufs_power_on(struct phy *phy)
> +static int qmp_ufs_phy_calibrate(struct phy *phy)
> {
> struct qmp_ufs *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> @@ -1898,7 +1898,7 @@ static int qmp_ufs_exit(struct phy *phy)
> return 0;
> }
>
> -static int qmp_ufs_enable(struct phy *phy)
> +static int qmp_ufs_power_on(struct phy *phy)
> {
> int ret;
>
> @@ -1906,7 +1906,7 @@ static int qmp_ufs_enable(struct phy *phy)
> if (ret)
> return ret;
>
> - ret = qmp_ufs_power_on(phy);
> + ret = qmp_ufs_phy_calibrate(phy);
> if (ret)
> qmp_ufs_exit(phy);
>
> @@ -1940,7 +1940,7 @@ static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> }
>
> static const struct phy_ops qcom_qmp_ufs_phy_ops = {
> - .power_on = qmp_ufs_enable,
> + .power_on = qmp_ufs_power_on,
> .power_off = qmp_ufs_disable,
> .set_mode = qmp_ufs_set_mode,
> .owner = THIS_MODULE,
> --
> 2.48.1
>
>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH V2 2/6] phy: qcom-qmp-ufs: Refactor phy_power_on and phy_calibrate callbacks
2025-03-18 14:49 [PATCH V2 0/6] Refactor phy powerup sequence Nitin Rawat
2025-03-18 14:49 ` [PATCH V2 1/6] phy: qcom-qmp-ufs: Rename qmp_ufs_enable and qmp_ufs_power_on Nitin Rawat
@ 2025-03-18 14:49 ` Nitin Rawat
2025-03-18 15:09 ` neil.armstrong
2025-03-18 14:49 ` [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset Nitin Rawat
` (3 subsequent siblings)
5 siblings, 1 reply; 19+ messages in thread
From: Nitin Rawat @ 2025-03-18 14:49 UTC (permalink / raw)
To: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Nitin Rawat, Can Guo
Commit 052553af6a31 ("ufs/phy: qcom: Refactor to use phy_init call")
puts enabling regulators & clks, calibrating UFS PHY, starting serdes
and polling PCS ready status into phy_power_on.
In Current code regulators enable, clks enable, calibrating UFS PHY,
start_serdes and polling PCS_ready_status are part of phy_power_on.
UFS PHY registers are retained after power collapse, meaning calibrating
UFS PHY, start_serdes and polling PCS_ready_status can be done only when
hba is powered_on, and not needed every time when phy_power_on is called
during resume. Hence keep the code which enables PHY's regulators & clks
in phy_power_on and move the rest steps into phy_calibrate function.
Refactor the code to retain PHY regulators & clks in phy_power_on and
move out rest of the code to new phy_calibrate function.
Co-developed-by: Can Guo <quic_cang@quicinc.com>
Signed-off-by: Can Guo <quic_cang@quicinc.com>
Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
index bb836bc0f736..0089ee80f852 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
@@ -1796,7 +1796,7 @@ static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
return 0;
}
-static int qmp_ufs_init(struct phy *phy)
+static int qmp_ufs_power_on(struct phy *phy)
{
struct qmp_ufs *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -1898,21 +1898,6 @@ static int qmp_ufs_exit(struct phy *phy)
return 0;
}
-static int qmp_ufs_power_on(struct phy *phy)
-{
- int ret;
-
- ret = qmp_ufs_init(phy);
- if (ret)
- return ret;
-
- ret = qmp_ufs_phy_calibrate(phy);
- if (ret)
- qmp_ufs_exit(phy);
-
- return ret;
-}
-
static int qmp_ufs_disable(struct phy *phy)
{
int ret;
@@ -1942,6 +1927,7 @@ static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
static const struct phy_ops qcom_qmp_ufs_phy_ops = {
.power_on = qmp_ufs_power_on,
.power_off = qmp_ufs_disable,
+ .calibrate = qmp_ufs_phy_calibrate,
.set_mode = qmp_ufs_set_mode,
.owner = THIS_MODULE,
};
--
2.48.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH V2 2/6] phy: qcom-qmp-ufs: Refactor phy_power_on and phy_calibrate callbacks
2025-03-18 14:49 ` [PATCH V2 2/6] phy: qcom-qmp-ufs: Refactor phy_power_on and phy_calibrate callbacks Nitin Rawat
@ 2025-03-18 15:09 ` neil.armstrong
2025-04-10 9:13 ` Nitin Rawat
0 siblings, 1 reply; 19+ messages in thread
From: neil.armstrong @ 2025-03-18 15:09 UTC (permalink / raw)
To: Nitin Rawat, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Can Guo
On 18/03/2025 15:49, Nitin Rawat wrote:
> Commit 052553af6a31 ("ufs/phy: qcom: Refactor to use phy_init call")
> puts enabling regulators & clks, calibrating UFS PHY, starting serdes
> and polling PCS ready status into phy_power_on.
>
> In Current code regulators enable, clks enable, calibrating UFS PHY,
> start_serdes and polling PCS_ready_status are part of phy_power_on.
>
> UFS PHY registers are retained after power collapse, meaning calibrating
> UFS PHY, start_serdes and polling PCS_ready_status can be done only when
> hba is powered_on, and not needed every time when phy_power_on is called
> during resume. Hence keep the code which enables PHY's regulators & clks
> in phy_power_on and move the rest steps into phy_calibrate function.
>
> Refactor the code to retain PHY regulators & clks in phy_power_on and
> move out rest of the code to new phy_calibrate function.
>
> Co-developed-by: Can Guo <quic_cang@quicinc.com>
> Signed-off-by: Can Guo <quic_cang@quicinc.com>
> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 18 ++----------------
> 1 file changed, 2 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> index bb836bc0f736..0089ee80f852 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> @@ -1796,7 +1796,7 @@ static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
> return 0;
> }
>
> -static int qmp_ufs_init(struct phy *phy)
> +static int qmp_ufs_power_on(struct phy *phy)
> {
> struct qmp_ufs *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> @@ -1898,21 +1898,6 @@ static int qmp_ufs_exit(struct phy *phy)
> return 0;
> }
>
> -static int qmp_ufs_power_on(struct phy *phy)
> -{
> - int ret;
> -
> - ret = qmp_ufs_init(phy);
> - if (ret)
> - return ret;
> -
> - ret = qmp_ufs_phy_calibrate(phy);
> - if (ret)
> - qmp_ufs_exit(phy);
> -
> - return ret;
> -}
> -
> static int qmp_ufs_disable(struct phy *phy)
> {
> int ret;
> @@ -1942,6 +1927,7 @@ static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> static const struct phy_ops qcom_qmp_ufs_phy_ops = {
> .power_on = qmp_ufs_power_on,
> .power_off = qmp_ufs_disable,
> + .calibrate = qmp_ufs_phy_calibrate,
Ok so this will break the UFS until patch 5 is applied,
breaking bisectability.
Make sure UFS host driver calls calibrate first, and then
do the refactor in the PHY driver.
And either all would go in a single tree or either PHY
or SCSI maintainer would need to provide an immutable
branch for the final merge.
> .set_mode = qmp_ufs_set_mode,
> .owner = THIS_MODULE,
> };
> --
> 2.48.1
>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH V2 2/6] phy: qcom-qmp-ufs: Refactor phy_power_on and phy_calibrate callbacks
2025-03-18 15:09 ` neil.armstrong
@ 2025-04-10 9:13 ` Nitin Rawat
2025-04-10 20:00 ` Dmitry Baryshkov
0 siblings, 1 reply; 19+ messages in thread
From: Nitin Rawat @ 2025-04-10 9:13 UTC (permalink / raw)
To: neil.armstrong, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Can Guo
On 3/18/2025 8:39 PM, neil.armstrong@linaro.org wrote:
> On 18/03/2025 15:49, Nitin Rawat wrote:
>> Commit 052553af6a31 ("ufs/phy: qcom: Refactor to use phy_init call")
>> puts enabling regulators & clks, calibrating UFS PHY, starting serdes
>> and polling PCS ready status into phy_power_on.
>>
>> In Current code regulators enable, clks enable, calibrating UFS PHY,
>> start_serdes and polling PCS_ready_status are part of phy_power_on.
>>
>> UFS PHY registers are retained after power collapse, meaning calibrating
>> UFS PHY, start_serdes and polling PCS_ready_status can be done only when
>> hba is powered_on, and not needed every time when phy_power_on is called
>> during resume. Hence keep the code which enables PHY's regulators & clks
>> in phy_power_on and move the rest steps into phy_calibrate function.
>>
>> Refactor the code to retain PHY regulators & clks in phy_power_on and
>> move out rest of the code to new phy_calibrate function.
>>
>> Co-developed-by: Can Guo <quic_cang@quicinc.com>
>> Signed-off-by: Can Guo <quic_cang@quicinc.com>
>> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
>> ---
>> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 18 ++----------------
>> 1 file changed, 2 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/
>> qualcomm/phy-qcom-qmp-ufs.c
>> index bb836bc0f736..0089ee80f852 100644
>> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
>> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
>> @@ -1796,7 +1796,7 @@ static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
>> return 0;
>> }
>>
>> -static int qmp_ufs_init(struct phy *phy)
>> +static int qmp_ufs_power_on(struct phy *phy)
>> {
>> struct qmp_ufs *qmp = phy_get_drvdata(phy);
>> const struct qmp_phy_cfg *cfg = qmp->cfg;
>> @@ -1898,21 +1898,6 @@ static int qmp_ufs_exit(struct phy *phy)
>> return 0;
>> }
>>
>> -static int qmp_ufs_power_on(struct phy *phy)
>> -{
>> - int ret;
>> -
>> - ret = qmp_ufs_init(phy);
>> - if (ret)
>> - return ret;
>> -
>> - ret = qmp_ufs_phy_calibrate(phy);
>> - if (ret)
>> - qmp_ufs_exit(phy);
>> -
>> - return ret;
>> -}
>> -
>> static int qmp_ufs_disable(struct phy *phy)
>> {
>> int ret;
>> @@ -1942,6 +1927,7 @@ static int qmp_ufs_set_mode(struct phy *phy,
>> enum phy_mode mode, int submode)
>> static const struct phy_ops qcom_qmp_ufs_phy_ops = {
>> .power_on = qmp_ufs_power_on,
>> .power_off = qmp_ufs_disable,
>> + .calibrate = qmp_ufs_phy_calibrate,
>
> Ok so this will break the UFS until patch 5 is applied,
> breaking bisectability.
>
> Make sure UFS host driver calls calibrate first, and then
> do the refactor in the PHY driver.
Hi Neil.
Thanks for the review. I have taken care of bisecatablity
compliance by making UFS host driver calls calibrate first
in latest patch set.
Regards,
Nitin
>
> And either all would go in a single tree or either PHY
> or SCSI maintainer would need to provide an immutable
> branch for the final merge.
>
>> .set_mode = qmp_ufs_set_mode,
>> .owner = THIS_MODULE,
>> };
>> --
>> 2.48.1
>>
>>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH V2 2/6] phy: qcom-qmp-ufs: Refactor phy_power_on and phy_calibrate callbacks
2025-04-10 9:13 ` Nitin Rawat
@ 2025-04-10 20:00 ` Dmitry Baryshkov
0 siblings, 0 replies; 19+ messages in thread
From: Dmitry Baryshkov @ 2025-04-10 20:00 UTC (permalink / raw)
To: Nitin Rawat
Cc: neil.armstrong, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio, quic_rdwivedi,
linux-arm-msm, linux-phy, linux-kernel, linux-scsi, Can Guo
On Thu, Apr 10, 2025 at 02:43:52PM +0530, Nitin Rawat wrote:
>
>
> On 3/18/2025 8:39 PM, neil.armstrong@linaro.org wrote:
> > On 18/03/2025 15:49, Nitin Rawat wrote:
> > > Commit 052553af6a31 ("ufs/phy: qcom: Refactor to use phy_init call")
> > > puts enabling regulators & clks, calibrating UFS PHY, starting serdes
> > > and polling PCS ready status into phy_power_on.
> > >
> > > In Current code regulators enable, clks enable, calibrating UFS PHY,
> > > start_serdes and polling PCS_ready_status are part of phy_power_on.
> > >
> > > UFS PHY registers are retained after power collapse, meaning calibrating
> > > UFS PHY, start_serdes and polling PCS_ready_status can be done only when
> > > hba is powered_on, and not needed every time when phy_power_on is called
> > > during resume. Hence keep the code which enables PHY's regulators & clks
> > > in phy_power_on and move the rest steps into phy_calibrate function.
> > >
> > > Refactor the code to retain PHY regulators & clks in phy_power_on and
> > > move out rest of the code to new phy_calibrate function.
> > >
> > > Co-developed-by: Can Guo <quic_cang@quicinc.com>
> > > Signed-off-by: Can Guo <quic_cang@quicinc.com>
> > > Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
> > > ---
> > > drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 18 ++----------------
> > > 1 file changed, 2 insertions(+), 16 deletions(-)
> > >
> > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/
> > > qualcomm/phy-qcom-qmp-ufs.c
> > > index bb836bc0f736..0089ee80f852 100644
> > > --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> > > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> > > @@ -1796,7 +1796,7 @@ static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
> > > return 0;
> > > }
> > >
> > > -static int qmp_ufs_init(struct phy *phy)
> > > +static int qmp_ufs_power_on(struct phy *phy)
> > > {
> > > struct qmp_ufs *qmp = phy_get_drvdata(phy);
> > > const struct qmp_phy_cfg *cfg = qmp->cfg;
> > > @@ -1898,21 +1898,6 @@ static int qmp_ufs_exit(struct phy *phy)
> > > return 0;
> > > }
> > >
> > > -static int qmp_ufs_power_on(struct phy *phy)
> > > -{
> > > - int ret;
> > > -
> > > - ret = qmp_ufs_init(phy);
> > > - if (ret)
> > > - return ret;
> > > -
> > > - ret = qmp_ufs_phy_calibrate(phy);
> > > - if (ret)
> > > - qmp_ufs_exit(phy);
> > > -
> > > - return ret;
> > > -}
> > > -
> > > static int qmp_ufs_disable(struct phy *phy)
> > > {
> > > int ret;
> > > @@ -1942,6 +1927,7 @@ static int qmp_ufs_set_mode(struct phy *phy,
> > > enum phy_mode mode, int submode)
> > > static const struct phy_ops qcom_qmp_ufs_phy_ops = {
> > > .power_on = qmp_ufs_power_on,
> > > .power_off = qmp_ufs_disable,
> > > + .calibrate = qmp_ufs_phy_calibrate,
> >
> > Ok so this will break the UFS until patch 5 is applied,
> > breaking bisectability.
> >
> > Make sure UFS host driver calls calibrate first, and then
> > do the refactor in the PHY driver.
>
> Hi Neil.
>
> Thanks for the review. I have taken care of bisecatablity
> compliance by making UFS host driver calls calibrate first
> in latest patch set.
_latest_. So if this patch gets merged first, UFS support will be
broken.
>
> Regards,
> Nitin
>
>
>
> >
> > And either all would go in a single tree or either PHY
> > or SCSI maintainer would need to provide an immutable
> > branch for the final merge.
> >
> > > .set_mode = qmp_ufs_set_mode,
> > > .owner = THIS_MODULE,
> > > };
> > > --
> > > 2.48.1
> > >
> > >
> >
>
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset
2025-03-18 14:49 [PATCH V2 0/6] Refactor phy powerup sequence Nitin Rawat
2025-03-18 14:49 ` [PATCH V2 1/6] phy: qcom-qmp-ufs: Rename qmp_ufs_enable and qmp_ufs_power_on Nitin Rawat
2025-03-18 14:49 ` [PATCH V2 2/6] phy: qcom-qmp-ufs: Refactor phy_power_on and phy_calibrate callbacks Nitin Rawat
@ 2025-03-18 14:49 ` Nitin Rawat
2025-03-18 15:13 ` neil.armstrong
2025-03-18 19:46 ` Bjorn Andersson
2025-03-18 14:49 ` [PATCH V2 4/6] phy: qcom-qmp-ufs: Refactor qmp_ufs_exit callback Nitin Rawat
` (2 subsequent siblings)
5 siblings, 2 replies; 19+ messages in thread
From: Nitin Rawat @ 2025-03-18 14:49 UTC (permalink / raw)
To: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Nitin Rawat
Refactor the UFS PHY reset handling to parse the reset logic only once
during probe, instead of every resume.
Move the UFS PHY reset parsing logic from qmp_phy_power_on to
qmp_ufs_probe to avoid unnecessary parsing during resume.
Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 104 ++++++++++++------------
1 file changed, 50 insertions(+), 54 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
index 0089ee80f852..3a80c2c110d2 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
@@ -1757,32 +1757,6 @@ static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg
qmp_ufs_init_all(qmp, &cfg->tbls_hs_b);
}
-static int qmp_ufs_com_init(struct qmp_ufs *qmp)
-{
- const struct qmp_phy_cfg *cfg = qmp->cfg;
- void __iomem *pcs = qmp->pcs;
- int ret;
-
- ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
- if (ret) {
- dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
- return ret;
- }
-
- ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
- if (ret)
- goto err_disable_regulators;
-
- qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
-
- return 0;
-
-err_disable_regulators:
- regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
-
- return ret;
-}
-
static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
{
const struct qmp_phy_cfg *cfg = qmp->cfg;
@@ -1800,41 +1774,27 @@ static int qmp_ufs_power_on(struct phy *phy)
{
struct qmp_ufs *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
+ void __iomem *pcs = qmp->pcs;
int ret;
- dev_vdbg(qmp->dev, "Initializing QMP phy\n");
-
- if (cfg->no_pcs_sw_reset) {
- /*
- * Get UFS reset, which is delayed until now to avoid a
- * circular dependency where UFS needs its PHY, but the PHY
- * needs this UFS reset.
- */
- if (!qmp->ufs_reset) {
- qmp->ufs_reset =
- devm_reset_control_get_exclusive(qmp->dev,
- "ufsphy");
-
- if (IS_ERR(qmp->ufs_reset)) {
- ret = PTR_ERR(qmp->ufs_reset);
- dev_err(qmp->dev,
- "failed to get UFS reset: %d\n",
- ret);
-
- qmp->ufs_reset = NULL;
- return ret;
- }
- }
- ret = reset_control_assert(qmp->ufs_reset);
- if (ret)
- return ret;
+ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
+ if (ret) {
+ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
+ return ret;
}
- ret = qmp_ufs_com_init(qmp);
+ ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
if (ret)
- return ret;
+ goto err_disable_regulators;
+
+ qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
return 0;
+
+err_disable_regulators:
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
+
+ return ret;
}
static int qmp_ufs_phy_calibrate(struct phy *phy)
@@ -1846,6 +1806,10 @@ static int qmp_ufs_phy_calibrate(struct phy *phy)
unsigned int val;
int ret;
+ ret = reset_control_assert(qmp->ufs_reset);
+ if (ret)
+ return ret;
+
qmp_ufs_init_registers(qmp, cfg);
ret = reset_control_deassert(qmp->ufs_reset);
@@ -2088,6 +2052,34 @@ static int qmp_ufs_parse_dt(struct qmp_ufs *qmp)
return 0;
}
+static int qmp_ufs_get_phy_reset(struct qmp_ufs *qmp)
+{
+ const struct qmp_phy_cfg *cfg = qmp->cfg;
+ int ret;
+
+ if (!cfg->no_pcs_sw_reset)
+ return 0;
+
+ /*
+ * Get UFS reset, which is delayed until now to avoid a
+ * circular dependency where UFS needs its PHY, but the PHY
+ * needs this UFS reset.
+ */
+ if (!qmp->ufs_reset) {
+ qmp->ufs_reset =
+ devm_reset_control_get_exclusive(qmp->dev, "ufsphy");
+
+ if (IS_ERR(qmp->ufs_reset)) {
+ ret = PTR_ERR(qmp->ufs_reset);
+ dev_err(qmp->dev, "failed to get PHY reset: %d\n", ret);
+ qmp->ufs_reset = NULL;
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int qmp_ufs_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -2114,6 +2106,10 @@ static int qmp_ufs_probe(struct platform_device *pdev)
if (ret)
return ret;
+ ret = qmp_ufs_get_phy_reset(qmp);
+ if (ret)
+ return ret;
+
/* Check for legacy binding with child node. */
np = of_get_next_available_child(dev->of_node, NULL);
if (np) {
--
2.48.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset
2025-03-18 14:49 ` [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset Nitin Rawat
@ 2025-03-18 15:13 ` neil.armstrong
2025-04-10 9:09 ` Nitin Rawat
2025-03-18 19:46 ` Bjorn Andersson
1 sibling, 1 reply; 19+ messages in thread
From: neil.armstrong @ 2025-03-18 15:13 UTC (permalink / raw)
To: Nitin Rawat, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi
On 18/03/2025 15:49, Nitin Rawat wrote:
> Refactor the UFS PHY reset handling to parse the reset logic only once
> during probe, instead of every resume.
>
> Move the UFS PHY reset parsing logic from qmp_phy_power_on to
> qmp_ufs_probe to avoid unnecessary parsing during resume.
>
> Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 104 ++++++++++++------------
> 1 file changed, 50 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> index 0089ee80f852..3a80c2c110d2 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> @@ -1757,32 +1757,6 @@ static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg
> qmp_ufs_init_all(qmp, &cfg->tbls_hs_b);
> }
>
> -static int qmp_ufs_com_init(struct qmp_ufs *qmp)
> -{
> - const struct qmp_phy_cfg *cfg = qmp->cfg;
> - void __iomem *pcs = qmp->pcs;
> - int ret;
> -
> - ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
> - if (ret) {
> - dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
> - return ret;
> - }
> -
> - ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
> - if (ret)
> - goto err_disable_regulators;
> -
> - qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
> -
> - return 0;
> -
> -err_disable_regulators:
> - regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
> -
> - return ret;
> -}
> -
> static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
> {
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> @@ -1800,41 +1774,27 @@ static int qmp_ufs_power_on(struct phy *phy)
> {
> struct qmp_ufs *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> + void __iomem *pcs = qmp->pcs;
> int ret;
> - dev_vdbg(qmp->dev, "Initializing QMP phy\n");
> -
> - if (cfg->no_pcs_sw_reset) {
> - /*
> - * Get UFS reset, which is delayed until now to avoid a
> - * circular dependency where UFS needs its PHY, but the PHY
> - * needs this UFS reset.
> - */
> - if (!qmp->ufs_reset) {
> - qmp->ufs_reset =
> - devm_reset_control_get_exclusive(qmp->dev,
> - "ufsphy");
> -
> - if (IS_ERR(qmp->ufs_reset)) {
> - ret = PTR_ERR(qmp->ufs_reset);
> - dev_err(qmp->dev,
> - "failed to get UFS reset: %d\n",
> - ret);
> -
> - qmp->ufs_reset = NULL;
> - return ret;
> - }
> - }
>
> - ret = reset_control_assert(qmp->ufs_reset);
> - if (ret)
> - return ret;
> + ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
> + if (ret) {
> + dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
> + return ret;
> }
>
> - ret = qmp_ufs_com_init(qmp);
> + ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
> if (ret)
> - return ret;
> + goto err_disable_regulators;
> +
> + qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
>
> return 0;
> +
> +err_disable_regulators:
> + regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
> +
> + return ret;
> }
This change is too fuzzy, please introduce qmp_ufs_get_phy_reset()
in a patch, move qmp_ufs_com_init() inline in qmp_ufs_power_on()
in a second time, and finally move reset_control_assert() to
calibrate in a third patch (and explain why).
Thanks,
Neil
>
> static int qmp_ufs_phy_calibrate(struct phy *phy)
> @@ -1846,6 +1806,10 @@ static int qmp_ufs_phy_calibrate(struct phy *phy)
> unsigned int val;
> int ret;
>
> + ret = reset_control_assert(qmp->ufs_reset);
> + if (ret)
> + return ret;
> +
> qmp_ufs_init_registers(qmp, cfg);
>
> ret = reset_control_deassert(qmp->ufs_reset);
> @@ -2088,6 +2052,34 @@ static int qmp_ufs_parse_dt(struct qmp_ufs *qmp)
> return 0;
> }
>
> +static int qmp_ufs_get_phy_reset(struct qmp_ufs *qmp)
> +{
> + const struct qmp_phy_cfg *cfg = qmp->cfg;
> + int ret;
> +
> + if (!cfg->no_pcs_sw_reset)
> + return 0;
> +
> + /*
> + * Get UFS reset, which is delayed until now to avoid a
> + * circular dependency where UFS needs its PHY, but the PHY
> + * needs this UFS reset.
> + */
> + if (!qmp->ufs_reset) {
> + qmp->ufs_reset =
> + devm_reset_control_get_exclusive(qmp->dev, "ufsphy");
> +
> + if (IS_ERR(qmp->ufs_reset)) {
> + ret = PTR_ERR(qmp->ufs_reset);
> + dev_err(qmp->dev, "failed to get PHY reset: %d\n", ret);
> + qmp->ufs_reset = NULL;
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> static int qmp_ufs_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -2114,6 +2106,10 @@ static int qmp_ufs_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> + ret = qmp_ufs_get_phy_reset(qmp);
> + if (ret)
> + return ret;
> +
> /* Check for legacy binding with child node. */
> np = of_get_next_available_child(dev->of_node, NULL);
> if (np) {
> --
> 2.48.1
>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset
2025-03-18 15:13 ` neil.armstrong
@ 2025-04-10 9:09 ` Nitin Rawat
0 siblings, 0 replies; 19+ messages in thread
From: Nitin Rawat @ 2025-04-10 9:09 UTC (permalink / raw)
To: neil.armstrong, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi
On 3/18/2025 8:43 PM, neil.armstrong@linaro.org wrote:
> On 18/03/2025 15:49, Nitin Rawat wrote:
>> Refactor the UFS PHY reset handling to parse the reset logic only once
>> during probe, instead of every resume.
>>
>> Move the UFS PHY reset parsing logic from qmp_phy_power_on to
>> qmp_ufs_probe to avoid unnecessary parsing during resume.
>>
>> Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
>> ---
>> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 104 ++++++++++++------------
>> 1 file changed, 50 insertions(+), 54 deletions(-)
>>
>> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/
>> qualcomm/phy-qcom-qmp-ufs.c
>> index 0089ee80f852..3a80c2c110d2 100644
>> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
>> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
>> @@ -1757,32 +1757,6 @@ static void qmp_ufs_init_registers(struct
>> qmp_ufs *qmp, const struct qmp_phy_cfg
>> qmp_ufs_init_all(qmp, &cfg->tbls_hs_b);
>> }
>>
>> -static int qmp_ufs_com_init(struct qmp_ufs *qmp)
>> -{
>> - const struct qmp_phy_cfg *cfg = qmp->cfg;
>> - void __iomem *pcs = qmp->pcs;
>> - int ret;
>> -
>> - ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
>> - if (ret) {
>> - dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
>> - return ret;
>> - }
>> -
>> - ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
>> - if (ret)
>> - goto err_disable_regulators;
>> -
>> - qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
>> -
>> - return 0;
>> -
>> -err_disable_regulators:
>> - regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
>> -
>> - return ret;
>> -}
>> -
>> static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
>> {
>> const struct qmp_phy_cfg *cfg = qmp->cfg;
>> @@ -1800,41 +1774,27 @@ static int qmp_ufs_power_on(struct phy *phy)
>> {
>> struct qmp_ufs *qmp = phy_get_drvdata(phy);
>> const struct qmp_phy_cfg *cfg = qmp->cfg;
>> + void __iomem *pcs = qmp->pcs;
>> int ret;
>> - dev_vdbg(qmp->dev, "Initializing QMP phy\n");
>> -
>> - if (cfg->no_pcs_sw_reset) {
>> - /*
>> - * Get UFS reset, which is delayed until now to avoid a
>> - * circular dependency where UFS needs its PHY, but the PHY
>> - * needs this UFS reset.
>> - */
>> - if (!qmp->ufs_reset) {
>> - qmp->ufs_reset =
>> - devm_reset_control_get_exclusive(qmp->dev,
>> - "ufsphy");
>> -
>> - if (IS_ERR(qmp->ufs_reset)) {
>> - ret = PTR_ERR(qmp->ufs_reset);
>> - dev_err(qmp->dev,
>> - "failed to get UFS reset: %d\n",
>> - ret);
>> -
>> - qmp->ufs_reset = NULL;
>> - return ret;
>> - }
>> - }
>>
>> - ret = reset_control_assert(qmp->ufs_reset);
>> - if (ret)
>> - return ret;
>> + ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
>> + if (ret) {
>> + dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
>> + return ret;
>> }
>>
>> - ret = qmp_ufs_com_init(qmp);
>> + ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
>> if (ret)
>> - return ret;
>> + goto err_disable_regulators;
>> +
>> + qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
>>
>> return 0;
>> +
>> +err_disable_regulators:
>> + regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
>> +
>> + return ret;
>> }
>
> This change is too fuzzy, please introduce qmp_ufs_get_phy_reset()
> in a patch, move qmp_ufs_com_init() inline in qmp_ufs_power_on()
> in a second time, and finally move reset_control_assert() to
> calibrate in a third patch (and explain why).
Thanks for the comment. I have taken care of this by separating
qmp_ufs_get_phy_reset and inlining qmp_ufs_com_init in 2 separate patches.
Thanks,
Nitin
>
> Thanks,
> Neil
>
>>
>> static int qmp_ufs_phy_calibrate(struct phy *phy)
>> @@ -1846,6 +1806,10 @@ static int qmp_ufs_phy_calibrate(struct phy *phy)
>> unsigned int val;
>> int ret;
>>
>> + ret = reset_control_assert(qmp->ufs_reset);
>> + if (ret)
>> + return ret;
>> +
>> qmp_ufs_init_registers(qmp, cfg);
>>
>> ret = reset_control_deassert(qmp->ufs_reset);
>> @@ -2088,6 +2052,34 @@ static int qmp_ufs_parse_dt(struct qmp_ufs *qmp)
>> return 0;
>> }
>>
>> +static int qmp_ufs_get_phy_reset(struct qmp_ufs *qmp)
>> +{
>> + const struct qmp_phy_cfg *cfg = qmp->cfg;
>> + int ret;
>> +
>> + if (!cfg->no_pcs_sw_reset)
>> + return 0;
>> +
>> + /*
>> + * Get UFS reset, which is delayed until now to avoid a
>> + * circular dependency where UFS needs its PHY, but the PHY
>> + * needs this UFS reset.
>> + */
>> + if (!qmp->ufs_reset) {
>> + qmp->ufs_reset =
>> + devm_reset_control_get_exclusive(qmp->dev, "ufsphy");
>> +
>> + if (IS_ERR(qmp->ufs_reset)) {
>> + ret = PTR_ERR(qmp->ufs_reset);
>> + dev_err(qmp->dev, "failed to get PHY reset: %d\n", ret);
>> + qmp->ufs_reset = NULL;
>> + return ret;
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> static int qmp_ufs_probe(struct platform_device *pdev)
>> {
>> struct device *dev = &pdev->dev;
>> @@ -2114,6 +2106,10 @@ static int qmp_ufs_probe(struct platform_device
>> *pdev)
>> if (ret)
>> return ret;
>>
>> + ret = qmp_ufs_get_phy_reset(qmp);
>> + if (ret)
>> + return ret;
>> +
>> /* Check for legacy binding with child node. */
>> np = of_get_next_available_child(dev->of_node, NULL);
>> if (np) {
>> --
>> 2.48.1
>>
>>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset
2025-03-18 14:49 ` [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset Nitin Rawat
2025-03-18 15:13 ` neil.armstrong
@ 2025-03-18 19:46 ` Bjorn Andersson
2025-04-10 15:37 ` Nitin Rawat
1 sibling, 1 reply; 19+ messages in thread
From: Bjorn Andersson @ 2025-03-18 19:46 UTC (permalink / raw)
To: Nitin Rawat
Cc: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio, quic_rdwivedi, linux-arm-msm,
linux-phy, linux-kernel, linux-scsi
On Tue, Mar 18, 2025 at 08:19:41PM +0530, Nitin Rawat wrote:
> Refactor the UFS PHY reset handling to parse the reset logic only once
> during probe, instead of every resume.
>
This looks very reasonable! But it would be preferred to see the commit
messages following the what format outlines in
https://docs.kernel.org/process/submitting-patches.html#describe-your-changes
with a clear problem description followed by a description of the
technical solution.
> Move the UFS PHY reset parsing logic from qmp_phy_power_on to
> qmp_ufs_probe to avoid unnecessary parsing during resume.
Please add ()-suffix to function names in your commit messages.
Also, this series moves things around a lot, can you confirm that UFS is
working inbetween each one of this patches, so that the branch is
bisectable when this is being picked up?
>
> Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 104 ++++++++++++------------
> 1 file changed, 50 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> index 0089ee80f852..3a80c2c110d2 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> @@ -1757,32 +1757,6 @@ static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg
> qmp_ufs_init_all(qmp, &cfg->tbls_hs_b);
> }
>
> -static int qmp_ufs_com_init(struct qmp_ufs *qmp)
> -{
> - const struct qmp_phy_cfg *cfg = qmp->cfg;
> - void __iomem *pcs = qmp->pcs;
> - int ret;
> -
> - ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
> - if (ret) {
> - dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
> - return ret;
> - }
> -
> - ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
> - if (ret)
> - goto err_disable_regulators;
> -
> - qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
> -
> - return 0;
> -
> -err_disable_regulators:
> - regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
> -
> - return ret;
> -}
> -
> static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
> {
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> @@ -1800,41 +1774,27 @@ static int qmp_ufs_power_on(struct phy *phy)
> {
> struct qmp_ufs *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
> + void __iomem *pcs = qmp->pcs;
This is only used once, perhaps not worth a local variable to save 5
characters on that line?
> int ret;
> - dev_vdbg(qmp->dev, "Initializing QMP phy\n");
> -
> - if (cfg->no_pcs_sw_reset) {
> - /*
> - * Get UFS reset, which is delayed until now to avoid a
> - * circular dependency where UFS needs its PHY, but the PHY
> - * needs this UFS reset.
> - */
> - if (!qmp->ufs_reset) {
> - qmp->ufs_reset =
> - devm_reset_control_get_exclusive(qmp->dev,
> - "ufsphy");
> -
> - if (IS_ERR(qmp->ufs_reset)) {
> - ret = PTR_ERR(qmp->ufs_reset);
> - dev_err(qmp->dev,
> - "failed to get UFS reset: %d\n",
> - ret);
> -
> - qmp->ufs_reset = NULL;
> - return ret;
> - }
> - }
>
> - ret = reset_control_assert(qmp->ufs_reset);
> - if (ret)
> - return ret;
> + ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
> + if (ret) {
> + dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
regulator_bulk_enable() will already have printed a more useful error
message, letting you know which of the vregs[] it was that failed to
enable.
> + return ret;
> }
>
> - ret = qmp_ufs_com_init(qmp);
> + ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
> if (ret)
> - return ret;
> + goto err_disable_regulators;
> +
> + qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
>
> return 0;
> +
> +err_disable_regulators:
> + regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
> +
> + return ret;
> }
>
> static int qmp_ufs_phy_calibrate(struct phy *phy)
> @@ -1846,6 +1806,10 @@ static int qmp_ufs_phy_calibrate(struct phy *phy)
> unsigned int val;
> int ret;
>
> + ret = reset_control_assert(qmp->ufs_reset);
> + if (ret)
> + return ret;
> +
> qmp_ufs_init_registers(qmp, cfg);
>
> ret = reset_control_deassert(qmp->ufs_reset);
> @@ -2088,6 +2052,34 @@ static int qmp_ufs_parse_dt(struct qmp_ufs *qmp)
> return 0;
> }
>
> +static int qmp_ufs_get_phy_reset(struct qmp_ufs *qmp)
> +{
> + const struct qmp_phy_cfg *cfg = qmp->cfg;
> + int ret;
> +
> + if (!cfg->no_pcs_sw_reset)
> + return 0;
> +
> + /*
> + * Get UFS reset, which is delayed until now to avoid a
> + * circular dependency where UFS needs its PHY, but the PHY
> + * needs this UFS reset.
This is invoked only once, from qcom_ufs_probe(), so it doesn't seem
accurate anymore. How come this is no longer needed? Please describe
what changed int he commit message.
> + */
> + if (!qmp->ufs_reset) {
> + qmp->ufs_reset =
> + devm_reset_control_get_exclusive(qmp->dev, "ufsphy");
The line break here is really weird, are you sure checkpatch --strict
didn't complain about this one?
> +
> + if (IS_ERR(qmp->ufs_reset)) {
> + ret = PTR_ERR(qmp->ufs_reset);
> + dev_err(qmp->dev, "failed to get PHY reset: %d\n", ret);
return dev_err_probe(qmp->dev, PTR_ERR(qmp->ufs_reset), "failed to...: %pe\n", qmp->ufs_reset);
While being more succinct, it also stores the reason for failing the
probe so that you can find it in /sys/kernel/debug/devices_deferred
> + qmp->ufs_reset = NULL;
Use a local variable if you're worried about someone accessing the stale
error code after returning here.
Regards,
Bjorn
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> static int qmp_ufs_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -2114,6 +2106,10 @@ static int qmp_ufs_probe(struct platform_device *pdev)
> if (ret)
> return ret;
>
> + ret = qmp_ufs_get_phy_reset(qmp);
> + if (ret)
> + return ret;
> +
> /* Check for legacy binding with child node. */
> np = of_get_next_available_child(dev->of_node, NULL);
> if (np) {
> --
> 2.48.1
>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset
2025-03-18 19:46 ` Bjorn Andersson
@ 2025-04-10 15:37 ` Nitin Rawat
0 siblings, 0 replies; 19+ messages in thread
From: Nitin Rawat @ 2025-04-10 15:37 UTC (permalink / raw)
To: Bjorn Andersson
Cc: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio, quic_rdwivedi, linux-arm-msm,
linux-phy, linux-kernel, linux-scsi
On 3/19/2025 1:16 AM, Bjorn Andersson wrote:
> On Tue, Mar 18, 2025 at 08:19:41PM +0530, Nitin Rawat wrote:
>> Refactor the UFS PHY reset handling to parse the reset logic only once
>> during probe, instead of every resume.
>>
>
> This looks very reasonable! But it would be preferred to see the commit
> messages following the what format outlines in
> https://docs.kernel.org/process/submitting-patches.html#describe-your-changes
> with a clear problem description followed by a description of the
> technical solution.
>
>> Move the UFS PHY reset parsing logic from qmp_phy_power_on to
>> qmp_ufs_probe to avoid unnecessary parsing during resume.
>
> Please add ()-suffix to function names in your commit messages.
>
> Also, this series moves things around a lot, can you confirm that UFS is
> working inbetween each one of this patches, so that the branch is
> bisectable when this is being picked up?
Hi Bjorn,
Thanks for the review. I've addressed the bisectability compliance in my
latest patch set (patchset #3) that I posted today. I just realized I
missed your other comments about adding the ()-suffix to function names
in commit messages. Sorry about that. I'll make sure to include this in
my next patch set.
Thanks,
Nitin
>
>>
>> Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
>> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
>> ---
>> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 104 ++++++++++++------------
>> 1 file changed, 50 insertions(+), 54 deletions(-)
>>
>> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
>> index 0089ee80f852..3a80c2c110d2 100644
>> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
>> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
>> @@ -1757,32 +1757,6 @@ static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg
>> qmp_ufs_init_all(qmp, &cfg->tbls_hs_b);
>> }
>>
>> -static int qmp_ufs_com_init(struct qmp_ufs *qmp)
>> -{
>> - const struct qmp_phy_cfg *cfg = qmp->cfg;
>> - void __iomem *pcs = qmp->pcs;
>> - int ret;
>> -
>> - ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
>> - if (ret) {
>> - dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
>> - return ret;
>> - }
>> -
>> - ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
>> - if (ret)
>> - goto err_disable_regulators;
>> -
>> - qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
>> -
>> - return 0;
>> -
>> -err_disable_regulators:
>> - regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
>> -
>> - return ret;
>> -}
>> -
>> static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
>> {
>> const struct qmp_phy_cfg *cfg = qmp->cfg;
>> @@ -1800,41 +1774,27 @@ static int qmp_ufs_power_on(struct phy *phy)
>> {
>> struct qmp_ufs *qmp = phy_get_drvdata(phy);
>> const struct qmp_phy_cfg *cfg = qmp->cfg;
>> + void __iomem *pcs = qmp->pcs;
>
> This is only used once, perhaps not worth a local variable to save 5
> characters on that line?
>
>> int ret;
>> - dev_vdbg(qmp->dev, "Initializing QMP phy\n");
>> -
>> - if (cfg->no_pcs_sw_reset) {
>> - /*
>> - * Get UFS reset, which is delayed until now to avoid a
>> - * circular dependency where UFS needs its PHY, but the PHY
>> - * needs this UFS reset.
>> - */
>> - if (!qmp->ufs_reset) {
>> - qmp->ufs_reset =
>> - devm_reset_control_get_exclusive(qmp->dev,
>> - "ufsphy");
>> -
>> - if (IS_ERR(qmp->ufs_reset)) {
>> - ret = PTR_ERR(qmp->ufs_reset);
>> - dev_err(qmp->dev,
>> - "failed to get UFS reset: %d\n",
>> - ret);
>> -
>> - qmp->ufs_reset = NULL;
>> - return ret;
>> - }
>> - }
>>
>> - ret = reset_control_assert(qmp->ufs_reset);
>> - if (ret)
>> - return ret;
>> + ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
>> + if (ret) {
>> + dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
>
> regulator_bulk_enable() will already have printed a more useful error
> message, letting you know which of the vregs[] it was that failed to
> enable.
>
>> + return ret;
>> }
>>
>> - ret = qmp_ufs_com_init(qmp);
>> + ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
>> if (ret)
>> - return ret;
>> + goto err_disable_regulators;
>> +
>> + qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
>>
>> return 0;
>> +
>> +err_disable_regulators:
>> + regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
>> +
>> + return ret;
>> }
>>
>> static int qmp_ufs_phy_calibrate(struct phy *phy)
>> @@ -1846,6 +1806,10 @@ static int qmp_ufs_phy_calibrate(struct phy *phy)
>> unsigned int val;
>> int ret;
>>
>> + ret = reset_control_assert(qmp->ufs_reset);
>> + if (ret)
>> + return ret;
>> +
>> qmp_ufs_init_registers(qmp, cfg);
>>
>> ret = reset_control_deassert(qmp->ufs_reset);
>> @@ -2088,6 +2052,34 @@ static int qmp_ufs_parse_dt(struct qmp_ufs *qmp)
>> return 0;
>> }
>>
>> +static int qmp_ufs_get_phy_reset(struct qmp_ufs *qmp)
>> +{
>> + const struct qmp_phy_cfg *cfg = qmp->cfg;
>> + int ret;
>> +
>> + if (!cfg->no_pcs_sw_reset)
>> + return 0;
>> +
>> + /*
>> + * Get UFS reset, which is delayed until now to avoid a
>> + * circular dependency where UFS needs its PHY, but the PHY
>> + * needs this UFS reset.
>
> This is invoked only once, from qcom_ufs_probe(), so it doesn't seem
> accurate anymore. How come this is no longer needed? Please describe
> what changed int he commit message.
>
>> + */
>> + if (!qmp->ufs_reset) {
>> + qmp->ufs_reset =
>> + devm_reset_control_get_exclusive(qmp->dev, "ufsphy");
>
> The line break here is really weird, are you sure checkpatch --strict
> didn't complain about this one?
>
>> +
>> + if (IS_ERR(qmp->ufs_reset)) {
>> + ret = PTR_ERR(qmp->ufs_reset);
>> + dev_err(qmp->dev, "failed to get PHY reset: %d\n", ret);
>
> return dev_err_probe(qmp->dev, PTR_ERR(qmp->ufs_reset), "failed to...: %pe\n", qmp->ufs_reset);
>
> While being more succinct, it also stores the reason for failing the
> probe so that you can find it in /sys/kernel/debug/devices_deferred
>
>> + qmp->ufs_reset = NULL;
>
> Use a local variable if you're worried about someone accessing the stale
> error code after returning here.
>
> Regards,
> Bjorn
>
>> + return ret;
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> static int qmp_ufs_probe(struct platform_device *pdev)
>> {
>> struct device *dev = &pdev->dev;
>> @@ -2114,6 +2106,10 @@ static int qmp_ufs_probe(struct platform_device *pdev)
>> if (ret)
>> return ret;
>>
>> + ret = qmp_ufs_get_phy_reset(qmp);
>> + if (ret)
>> + return ret;
>> +
>> /* Check for legacy binding with child node. */
>> np = of_get_next_available_child(dev->of_node, NULL);
>> if (np) {
>> --
>> 2.48.1
>>
>>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH V2 4/6] phy: qcom-qmp-ufs: Refactor qmp_ufs_exit callback.
2025-03-18 14:49 [PATCH V2 0/6] Refactor phy powerup sequence Nitin Rawat
` (2 preceding siblings ...)
2025-03-18 14:49 ` [PATCH V2 3/6] phy: qcom-qmp-ufs: Refactor UFS PHY reset Nitin Rawat
@ 2025-03-18 14:49 ` Nitin Rawat
2025-03-18 15:15 ` neil.armstrong
2025-03-18 14:49 ` [PATCH V2 5/6] scsi: ufs: qcom : Refactor phy_power_on/off calls Nitin Rawat
2025-03-18 14:49 ` [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function Nitin Rawat
5 siblings, 1 reply; 19+ messages in thread
From: Nitin Rawat @ 2025-03-18 14:49 UTC (permalink / raw)
To: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Nitin Rawat
Rename qmp_ufs_disable to qmp_ufs_power_off and refactor
the code to move all the power off sequence to qmp_ufs_power_off.
Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 41 ++-----------------------
1 file changed, 3 insertions(+), 38 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
index 3a80c2c110d2..675fef106d3b 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
@@ -1757,19 +1757,6 @@ static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg
qmp_ufs_init_all(qmp, &cfg->tbls_hs_b);
}
-static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
-{
- const struct qmp_phy_cfg *cfg = qmp->cfg;
-
- reset_control_assert(qmp->ufs_reset);
-
- clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
-
- regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
-
- return 0;
-}
-
static int qmp_ufs_power_on(struct phy *phy)
{
struct qmp_ufs *qmp = phy_get_drvdata(phy);
@@ -1839,39 +1826,17 @@ static int qmp_ufs_power_off(struct phy *phy)
struct qmp_ufs *qmp = phy_get_drvdata(phy);
const struct qmp_phy_cfg *cfg = qmp->cfg;
- /* PHY reset */
- if (!cfg->no_pcs_sw_reset)
- qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
-
- /* stop SerDes */
- qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], SERDES_START);
-
/* Put PHY into POWER DOWN state: active low */
qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
SW_PWRDN);
- return 0;
-}
-
-static int qmp_ufs_exit(struct phy *phy)
-{
- struct qmp_ufs *qmp = phy_get_drvdata(phy);
+ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
- qmp_ufs_com_exit(qmp);
+ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
return 0;
}
-static int qmp_ufs_disable(struct phy *phy)
-{
- int ret;
-
- ret = qmp_ufs_power_off(phy);
- if (ret)
- return ret;
- return qmp_ufs_exit(phy);
-}
-
static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
{
struct qmp_ufs *qmp = phy_get_drvdata(phy);
@@ -1890,7 +1855,7 @@ static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
static const struct phy_ops qcom_qmp_ufs_phy_ops = {
.power_on = qmp_ufs_power_on,
- .power_off = qmp_ufs_disable,
+ .power_off = qmp_ufs_power_off,
.calibrate = qmp_ufs_phy_calibrate,
.set_mode = qmp_ufs_set_mode,
.owner = THIS_MODULE,
--
2.48.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH V2 4/6] phy: qcom-qmp-ufs: Refactor qmp_ufs_exit callback.
2025-03-18 14:49 ` [PATCH V2 4/6] phy: qcom-qmp-ufs: Refactor qmp_ufs_exit callback Nitin Rawat
@ 2025-03-18 15:15 ` neil.armstrong
0 siblings, 0 replies; 19+ messages in thread
From: neil.armstrong @ 2025-03-18 15:15 UTC (permalink / raw)
To: Nitin Rawat, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi
On 18/03/2025 15:49, Nitin Rawat wrote:
> Rename qmp_ufs_disable to qmp_ufs_power_off and refactor
> the code to move all the power off sequence to qmp_ufs_power_off.
>
> Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
> ---
> drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 41 ++-----------------------
> 1 file changed, 3 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> index 3a80c2c110d2..675fef106d3b 100644
> --- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> +++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c
> @@ -1757,19 +1757,6 @@ static void qmp_ufs_init_registers(struct qmp_ufs *qmp, const struct qmp_phy_cfg
> qmp_ufs_init_all(qmp, &cfg->tbls_hs_b);
> }
>
> -static int qmp_ufs_com_exit(struct qmp_ufs *qmp)
> -{
> - const struct qmp_phy_cfg *cfg = qmp->cfg;
> -
> - reset_control_assert(qmp->ufs_reset);
> -
> - clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
> -
> - regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
> -
> - return 0;
> -}
> -
> static int qmp_ufs_power_on(struct phy *phy)
> {
> struct qmp_ufs *qmp = phy_get_drvdata(phy);
> @@ -1839,39 +1826,17 @@ static int qmp_ufs_power_off(struct phy *phy)
> struct qmp_ufs *qmp = phy_get_drvdata(phy);
> const struct qmp_phy_cfg *cfg = qmp->cfg;
>
> - /* PHY reset */
> - if (!cfg->no_pcs_sw_reset)
> - qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
> -
> - /* stop SerDes */
> - qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], SERDES_START);
> -
> /* Put PHY into POWER DOWN state: active low */
> qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
> SW_PWRDN);
So where goes this code ? I think it should go in a new exit PHY op.
>
> - return 0;
> -}
> -
> -static int qmp_ufs_exit(struct phy *phy)
> -{
> - struct qmp_ufs *qmp = phy_get_drvdata(phy);
> + clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
>
> - qmp_ufs_com_exit(qmp);
> + regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
>
> return 0;
> }
>
> -static int qmp_ufs_disable(struct phy *phy)
> -{
> - int ret;
> -
> - ret = qmp_ufs_power_off(phy);
> - if (ret)
> - return ret;
> - return qmp_ufs_exit(phy);
> -}
> -
> static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> {
> struct qmp_ufs *qmp = phy_get_drvdata(phy);
> @@ -1890,7 +1855,7 @@ static int qmp_ufs_set_mode(struct phy *phy, enum phy_mode mode, int submode)
>
> static const struct phy_ops qcom_qmp_ufs_phy_ops = {
> .power_on = qmp_ufs_power_on,
> - .power_off = qmp_ufs_disable,
> + .power_off = qmp_ufs_power_off,
> .calibrate = qmp_ufs_phy_calibrate,
> .set_mode = qmp_ufs_set_mode,
> .owner = THIS_MODULE,
> --
> 2.48.1
>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH V2 5/6] scsi: ufs: qcom : Refactor phy_power_on/off calls
2025-03-18 14:49 [PATCH V2 0/6] Refactor phy powerup sequence Nitin Rawat
` (3 preceding siblings ...)
2025-03-18 14:49 ` [PATCH V2 4/6] phy: qcom-qmp-ufs: Refactor qmp_ufs_exit callback Nitin Rawat
@ 2025-03-18 14:49 ` Nitin Rawat
2025-03-18 14:49 ` [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function Nitin Rawat
5 siblings, 0 replies; 19+ messages in thread
From: Nitin Rawat @ 2025-03-18 14:49 UTC (permalink / raw)
To: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Nitin Rawat, Can Guo
Commit 3f6d1767b1a0 ("phy: ufs-qcom: Refactor all init steps into
phy_poweron") removes the phy_power_on/off from ufs_qcom_setup_clocks
to suspend/resume func.
To have a better power saving, remove the phy_power_on/off calls from
resume/suspend path and put them back to ufs_qcom_setup_clocks, so that
PHY regulators & clks can be turned on/off along with UFS's clocks.
Since phy phy_power_on is separated out from phy calibrate, make
separate calls to phy_power_on and phy_calibrate calls from ufs qcom
driver.
Co-developed-by: Can Guo <quic_cang@quicinc.com>
Signed-off-by: Can Guo <quic_cang@quicinc.com>
Co-developed-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Ram Kumar Dwivedi <quic_rdwivedi@quicinc.com>
Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
---
drivers/ufs/host/ufs-qcom.c | 58 +++++++++++++++++--------------------
1 file changed, 26 insertions(+), 32 deletions(-)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 1b37449fbffc..5c7b6c75d669 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -473,6 +473,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
goto out_disable_phy;
}
+ ret = phy_calibrate(phy);
+ if (ret) {
+ dev_err(hba->dev, "Failed to calibrate PHY %d\n", ret);
+ goto out_disable_phy;
+ }
ufs_qcom_select_unipro_mode(host);
return 0;
@@ -633,26 +638,17 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
enum ufs_notify_change_status status)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- struct phy *phy = host->generic_phy;
if (status == PRE_CHANGE)
return 0;
- if (ufs_qcom_is_link_off(hba)) {
- /*
- * Disable the tx/rx lane symbol clocks before PHY is
- * powered down as the PLL source should be disabled
- * after downstream clocks are disabled.
- */
+ if (!ufs_qcom_is_link_active(hba))
ufs_qcom_disable_lane_clks(host);
- phy_power_off(phy);
- /* reset the connected UFS device during power down */
- ufs_qcom_device_reset_ctrl(hba, true);
- } else if (!ufs_qcom_is_link_active(hba)) {
- ufs_qcom_disable_lane_clks(host);
- }
+ /* reset the connected UFS device during power down */
+ if (ufs_qcom_is_link_off(hba) && host->device_reset)
+ ufs_qcom_device_reset_ctrl(hba, true);
return ufs_qcom_ice_suspend(host);
}
@@ -660,26 +656,11 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op,
static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- struct phy *phy = host->generic_phy;
int err;
- if (ufs_qcom_is_link_off(hba)) {
- err = phy_power_on(phy);
- if (err) {
- dev_err(hba->dev, "%s: failed PHY power on: %d\n",
- __func__, err);
- return err;
- }
-
- err = ufs_qcom_enable_lane_clks(host);
- if (err)
- return err;
-
- } else if (!ufs_qcom_is_link_active(hba)) {
- err = ufs_qcom_enable_lane_clks(host);
- if (err)
- return err;
- }
+ err = ufs_qcom_enable_lane_clks(host);
+ if (err)
+ return err;
return ufs_qcom_ice_resume(host);
}
@@ -1036,6 +1017,8 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
enum ufs_notify_change_status status)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct phy *phy = host->generic_phy;
+ int err;
/*
* In case ufs_qcom_init() is not yet done, simply ignore.
@@ -1054,10 +1037,20 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
/* disable device ref_clk */
ufs_qcom_dev_ref_clk_ctrl(host, false);
}
+ err = phy_power_off(phy);
+ if (err) {
+ dev_err(hba->dev, "phy power off failed, ret=%d\n", err);
+ return err;
+ }
}
break;
case POST_CHANGE:
if (on) {
+ err = phy_power_on(phy);
+ if (err) {
+ dev_err(hba->dev, "phy power on failed, ret = %d\n", err);
+ return err;
+ }
/* enable the device ref clock for HS mode*/
if (ufshcd_is_hs_mode(&hba->pwr_info))
ufs_qcom_dev_ref_clk_ctrl(host, true);
@@ -1240,9 +1233,10 @@ static int ufs_qcom_init(struct ufs_hba *hba)
static void ufs_qcom_exit(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct phy *phy = host->generic_phy;
ufs_qcom_disable_lane_clks(host);
- phy_power_off(host->generic_phy);
+ phy_power_off(phy);
phy_exit(host->generic_phy);
}
--
2.48.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function
2025-03-18 14:49 [PATCH V2 0/6] Refactor phy powerup sequence Nitin Rawat
` (4 preceding siblings ...)
2025-03-18 14:49 ` [PATCH V2 5/6] scsi: ufs: qcom : Refactor phy_power_on/off calls Nitin Rawat
@ 2025-03-18 14:49 ` Nitin Rawat
2025-03-18 17:46 ` Bart Van Assche
2025-03-18 19:50 ` Bjorn Andersson
5 siblings, 2 replies; 19+ messages in thread
From: Nitin Rawat @ 2025-03-18 14:49 UTC (permalink / raw)
To: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Nitin Rawat, Can Guo
Introduce ufs_qcom_phy_power_on and ufs_qcom_phy_power_off wrapper
functions with mutex protection to ensure safe usage of is_phy_pwr_on
and prevent possible race conditions.
Co-developed-by: Can Guo <quic_cang@quicinc.com>
Signed-off-by: Can Guo <quic_cang@quicinc.com>
Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
---
drivers/ufs/host/ufs-qcom.c | 44 +++++++++++++++++++++++++++++++------
drivers/ufs/host/ufs-qcom.h | 4 ++++
2 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 5c7b6c75d669..8f80724e64b9 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -421,6 +421,38 @@ static u32 ufs_qcom_get_hs_gear(struct ufs_hba *hba)
return UFS_HS_G3;
}
+static int ufs_qcom_phy_power_on(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct phy *phy = host->generic_phy;
+ int ret = 0;
+
+ guard(mutex)(&host->phy_mutex);
+ if (!host->is_phy_pwr_on) {
+ ret = phy_power_on(phy);
+ if (!ret)
+ host->is_phy_pwr_on = true;
+ }
+
+ return ret;
+}
+
+static int ufs_qcom_phy_power_off(struct ufs_hba *hba)
+{
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct phy *phy = host->generic_phy;
+ int ret = 0;
+
+ guard(mutex)(&host->phy_mutex);
+ if (host->is_phy_pwr_on) {
+ ret = phy_power_off(phy);
+ if (!ret)
+ host->is_phy_pwr_on = false;
+ }
+
+ return ret;
+}
+
static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -449,7 +481,7 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
return ret;
if (phy->power_count) {
- phy_power_off(phy);
+ ufs_qcom_phy_power_off(hba);
phy_exit(phy);
}
@@ -466,7 +498,7 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
goto out_disable_phy;
/* power on phy - start serdes and phy's power and clocks */
- ret = phy_power_on(phy);
+ ret = ufs_qcom_phy_power_on(hba);
if (ret) {
dev_err(hba->dev, "%s: phy power on failed, ret = %d\n",
__func__, ret);
@@ -1017,7 +1049,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
enum ufs_notify_change_status status)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- struct phy *phy = host->generic_phy;
int err;
/*
@@ -1037,7 +1068,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
/* disable device ref_clk */
ufs_qcom_dev_ref_clk_ctrl(host, false);
}
- err = phy_power_off(phy);
+ err = ufs_qcom_phy_power_off(hba);
if (err) {
dev_err(hba->dev, "phy power off failed, ret=%d\n", err);
return err;
@@ -1046,7 +1077,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
break;
case POST_CHANGE:
if (on) {
- err = phy_power_on(phy);
+ err = ufs_qcom_phy_power_on(hba);
if (err) {
dev_err(hba->dev, "phy power on failed, ret = %d\n", err);
return err;
@@ -1233,10 +1264,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
static void ufs_qcom_exit(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- struct phy *phy = host->generic_phy;
ufs_qcom_disable_lane_clks(host);
- phy_power_off(phy);
+ ufs_qcom_phy_power_off(hba);
phy_exit(host->generic_phy);
}
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index d0e6ec9128e7..3db29fbcd40b 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -252,6 +252,10 @@ struct ufs_qcom_host {
u32 phy_gear;
bool esi_enabled;
+ /* flag to check if phy is powered on */
+ bool is_phy_pwr_on;
+ /* Protect the usage of is_phy_pwr_on against racing */
+ struct mutex phy_mutex;
};
struct ufs_qcom_drvdata {
--
2.48.1
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related [flat|nested] 19+ messages in thread* Re: [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function
2025-03-18 14:49 ` [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function Nitin Rawat
@ 2025-03-18 17:46 ` Bart Van Assche
2025-03-18 19:50 ` Bjorn Andersson
1 sibling, 0 replies; 19+ messages in thread
From: Bart Van Assche @ 2025-03-18 17:46 UTC (permalink / raw)
To: Nitin Rawat, vkoul, kishon, manivannan.sadhasivam,
James.Bottomley, martin.petersen, konrad.dybcio
Cc: quic_rdwivedi, linux-arm-msm, linux-phy, linux-kernel, linux-scsi,
Can Guo
On 3/18/25 7:49 AM, Nitin Rawat wrote:
Just like the other patches in this series, the subject of this patch
should have the prefix "scsi: ufs: qcom:" instead of "scsi: ufs: host:"
> diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
> index d0e6ec9128e7..3db29fbcd40b 100644
> --- a/drivers/ufs/host/ufs-qcom.h
> +++ b/drivers/ufs/host/ufs-qcom.h
> @@ -252,6 +252,10 @@ struct ufs_qcom_host {
> u32 phy_gear;
>
> bool esi_enabled;
> + /* flag to check if phy is powered on */
> + bool is_phy_pwr_on;
> + /* Protect the usage of is_phy_pwr_on against racing */
> + struct mutex phy_mutex;
> };
Please reorder the above two structure members. Synchronization objects
should occur before the data members protected by these synchronization
objects in structure definitions.
It seems to me that phy_mutex not only serializes is_phy_pwr_on accesses
but that it also serializes phy_power_on() / phy_power_off() calls. If
this is the case, please mention this.
Thanks,
Bart.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function
2025-03-18 14:49 ` [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function Nitin Rawat
2025-03-18 17:46 ` Bart Van Assche
@ 2025-03-18 19:50 ` Bjorn Andersson
2025-04-10 15:41 ` Nitin Rawat
1 sibling, 1 reply; 19+ messages in thread
From: Bjorn Andersson @ 2025-03-18 19:50 UTC (permalink / raw)
To: Nitin Rawat
Cc: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio, quic_rdwivedi, linux-arm-msm,
linux-phy, linux-kernel, linux-scsi, Can Guo
On Tue, Mar 18, 2025 at 08:19:44PM +0530, Nitin Rawat wrote:
> Introduce ufs_qcom_phy_power_on and ufs_qcom_phy_power_off wrapper
> functions with mutex protection to ensure safe usage of is_phy_pwr_on
> and prevent possible race conditions.
>
Please describe the problem properly here. Are you introducing the mutex
because there is a problem, or because you want to be "safe"?
Why is it "refcounted", is the calling code paths no longer in sync? How
long has the current implementation been broken?
Regards,
Bjorn
> Co-developed-by: Can Guo <quic_cang@quicinc.com>
> Signed-off-by: Can Guo <quic_cang@quicinc.com>
> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
> ---
> drivers/ufs/host/ufs-qcom.c | 44 +++++++++++++++++++++++++++++++------
> drivers/ufs/host/ufs-qcom.h | 4 ++++
> 2 files changed, 41 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
> index 5c7b6c75d669..8f80724e64b9 100644
> --- a/drivers/ufs/host/ufs-qcom.c
> +++ b/drivers/ufs/host/ufs-qcom.c
> @@ -421,6 +421,38 @@ static u32 ufs_qcom_get_hs_gear(struct ufs_hba *hba)
> return UFS_HS_G3;
> }
>
> +static int ufs_qcom_phy_power_on(struct ufs_hba *hba)
> +{
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> + struct phy *phy = host->generic_phy;
> + int ret = 0;
> +
> + guard(mutex)(&host->phy_mutex);
> + if (!host->is_phy_pwr_on) {
> + ret = phy_power_on(phy);
> + if (!ret)
> + host->is_phy_pwr_on = true;
> + }
> +
> + return ret;
> +}
> +
> +static int ufs_qcom_phy_power_off(struct ufs_hba *hba)
> +{
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> + struct phy *phy = host->generic_phy;
> + int ret = 0;
> +
> + guard(mutex)(&host->phy_mutex);
> + if (host->is_phy_pwr_on) {
> + ret = phy_power_off(phy);
> + if (!ret)
> + host->is_phy_pwr_on = false;
> + }
> +
> + return ret;
> +}
> +
> static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
> {
> struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> @@ -449,7 +481,7 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
> return ret;
>
> if (phy->power_count) {
> - phy_power_off(phy);
> + ufs_qcom_phy_power_off(hba);
> phy_exit(phy);
> }
>
> @@ -466,7 +498,7 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
> goto out_disable_phy;
>
> /* power on phy - start serdes and phy's power and clocks */
> - ret = phy_power_on(phy);
> + ret = ufs_qcom_phy_power_on(hba);
> if (ret) {
> dev_err(hba->dev, "%s: phy power on failed, ret = %d\n",
> __func__, ret);
> @@ -1017,7 +1049,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
> enum ufs_notify_change_status status)
> {
> struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> - struct phy *phy = host->generic_phy;
> int err;
>
> /*
> @@ -1037,7 +1068,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
> /* disable device ref_clk */
> ufs_qcom_dev_ref_clk_ctrl(host, false);
> }
> - err = phy_power_off(phy);
> + err = ufs_qcom_phy_power_off(hba);
> if (err) {
> dev_err(hba->dev, "phy power off failed, ret=%d\n", err);
> return err;
> @@ -1046,7 +1077,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
> break;
> case POST_CHANGE:
> if (on) {
> - err = phy_power_on(phy);
> + err = ufs_qcom_phy_power_on(hba);
> if (err) {
> dev_err(hba->dev, "phy power on failed, ret = %d\n", err);
> return err;
> @@ -1233,10 +1264,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
> static void ufs_qcom_exit(struct ufs_hba *hba)
> {
> struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> - struct phy *phy = host->generic_phy;
>
> ufs_qcom_disable_lane_clks(host);
> - phy_power_off(phy);
> + ufs_qcom_phy_power_off(hba);
> phy_exit(host->generic_phy);
> }
>
> diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
> index d0e6ec9128e7..3db29fbcd40b 100644
> --- a/drivers/ufs/host/ufs-qcom.h
> +++ b/drivers/ufs/host/ufs-qcom.h
> @@ -252,6 +252,10 @@ struct ufs_qcom_host {
> u32 phy_gear;
>
> bool esi_enabled;
> + /* flag to check if phy is powered on */
> + bool is_phy_pwr_on;
> + /* Protect the usage of is_phy_pwr_on against racing */
> + struct mutex phy_mutex;
> };
>
> struct ufs_qcom_drvdata {
> --
> 2.48.1
>
>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [PATCH V2 6/6] scsi: ufs: host : Introduce phy_power_on/off wrapper function
2025-03-18 19:50 ` Bjorn Andersson
@ 2025-04-10 15:41 ` Nitin Rawat
0 siblings, 0 replies; 19+ messages in thread
From: Nitin Rawat @ 2025-04-10 15:41 UTC (permalink / raw)
To: Bjorn Andersson
Cc: vkoul, kishon, manivannan.sadhasivam, James.Bottomley,
martin.petersen, konrad.dybcio, quic_rdwivedi, linux-arm-msm,
linux-phy, linux-kernel, linux-scsi, Can Guo
On 3/19/2025 1:20 AM, Bjorn Andersson wrote:
> On Tue, Mar 18, 2025 at 08:19:44PM +0530, Nitin Rawat wrote:
>> Introduce ufs_qcom_phy_power_on and ufs_qcom_phy_power_off wrapper
>> functions with mutex protection to ensure safe usage of is_phy_pwr_on
>> and prevent possible race conditions.
>>
>
> Please describe the problem properly here. Are you introducing the mutex
> because there is a problem, or because you want to be "safe"?
>
> Why is it "refcounted", is the calling code paths no longer in sync? How
> long has the current implementation been broken?
>
> Regards,
> Bjorn
>
Hi Bjorn,
Thanks for the review. There are scenarios where ufshcd_link_startup()
can call ufshcd_vops_link_startup_notify() multiple times during
retries. This leads to the PHY reference count increasing continuously,
preventing proper re-initialization of the PHY.
Recently, this issue was addressed with patch 7bac65687510 ("scsi: ufs:
qcom: Power off the PHY if it was already powered on in
ufs_qcom_power_up_sequence()"). However, I still want to maintain a
reference count (ref_cnt) to safeguard against similar conditions in the
code. Additionally, this approach helps avoid unnecessary phy_power_on
and phy_power_off calls. Please let me know your thoughts.
Regrads,
Nitin
>> Co-developed-by: Can Guo <quic_cang@quicinc.com>
>> Signed-off-by: Can Guo <quic_cang@quicinc.com>
>> Signed-off-by: Nitin Rawat <quic_nitirawa@quicinc.com>
>> ---
>> drivers/ufs/host/ufs-qcom.c | 44 +++++++++++++++++++++++++++++++------
>> drivers/ufs/host/ufs-qcom.h | 4 ++++
>> 2 files changed, 41 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
>> index 5c7b6c75d669..8f80724e64b9 100644
>> --- a/drivers/ufs/host/ufs-qcom.c
>> +++ b/drivers/ufs/host/ufs-qcom.c
>> @@ -421,6 +421,38 @@ static u32 ufs_qcom_get_hs_gear(struct ufs_hba *hba)
>> return UFS_HS_G3;
>> }
>>
>> +static int ufs_qcom_phy_power_on(struct ufs_hba *hba)
>> +{
>> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> + struct phy *phy = host->generic_phy;
>> + int ret = 0;
>> +
>> + guard(mutex)(&host->phy_mutex);
>> + if (!host->is_phy_pwr_on) {
>> + ret = phy_power_on(phy);
>> + if (!ret)
>> + host->is_phy_pwr_on = true;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static int ufs_qcom_phy_power_off(struct ufs_hba *hba)
>> +{
>> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> + struct phy *phy = host->generic_phy;
>> + int ret = 0;
>> +
>> + guard(mutex)(&host->phy_mutex);
>> + if (host->is_phy_pwr_on) {
>> + ret = phy_power_off(phy);
>> + if (!ret)
>> + host->is_phy_pwr_on = false;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
>> {
>> struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> @@ -449,7 +481,7 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
>> return ret;
>>
>> if (phy->power_count) {
>> - phy_power_off(phy);
>> + ufs_qcom_phy_power_off(hba);
>> phy_exit(phy);
>> }
>>
>> @@ -466,7 +498,7 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
>> goto out_disable_phy;
>>
>> /* power on phy - start serdes and phy's power and clocks */
>> - ret = phy_power_on(phy);
>> + ret = ufs_qcom_phy_power_on(hba);
>> if (ret) {
>> dev_err(hba->dev, "%s: phy power on failed, ret = %d\n",
>> __func__, ret);
>> @@ -1017,7 +1049,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
>> enum ufs_notify_change_status status)
>> {
>> struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> - struct phy *phy = host->generic_phy;
>> int err;
>>
>> /*
>> @@ -1037,7 +1068,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
>> /* disable device ref_clk */
>> ufs_qcom_dev_ref_clk_ctrl(host, false);
>> }
>> - err = phy_power_off(phy);
>> + err = ufs_qcom_phy_power_off(hba);
>> if (err) {
>> dev_err(hba->dev, "phy power off failed, ret=%d\n", err);
>> return err;
>> @@ -1046,7 +1077,7 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on,
>> break;
>> case POST_CHANGE:
>> if (on) {
>> - err = phy_power_on(phy);
>> + err = ufs_qcom_phy_power_on(hba);
>> if (err) {
>> dev_err(hba->dev, "phy power on failed, ret = %d\n", err);
>> return err;
>> @@ -1233,10 +1264,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
>> static void ufs_qcom_exit(struct ufs_hba *hba)
>> {
>> struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>> - struct phy *phy = host->generic_phy;
>>
>> ufs_qcom_disable_lane_clks(host);
>> - phy_power_off(phy);
>> + ufs_qcom_phy_power_off(hba);
>> phy_exit(host->generic_phy);
>> }
>>
>> diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
>> index d0e6ec9128e7..3db29fbcd40b 100644
>> --- a/drivers/ufs/host/ufs-qcom.h
>> +++ b/drivers/ufs/host/ufs-qcom.h
>> @@ -252,6 +252,10 @@ struct ufs_qcom_host {
>> u32 phy_gear;
>>
>> bool esi_enabled;
>> + /* flag to check if phy is powered on */
>> + bool is_phy_pwr_on;
>> + /* Protect the usage of is_phy_pwr_on against racing */
>> + struct mutex phy_mutex;
>> };
>>
>> struct ufs_qcom_drvdata {
>> --
>> 2.48.1
>>
>>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply [flat|nested] 19+ messages in thread