FROMGIT: scsi: ufs: ufs-qcom: Add support for reinitializing the UFS device
Starting from Qualcomm UFS version 4, the UFS device needs to be reinitialized after switching to maximum gear by the UFS core. Hence, add support for it by enabling the UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH quirk, implementing reinit_notify() callback and using the agreed gear speed for setting the PHY mode. Suggested-by: Can Guo <quic_cang@quicinc.com> Tested-by: Andrew Halaney <ahalaney@redhat.com> # Qdrive3/sa8540p-ride Change-Id: I2caf0076bca06385e53e6f6cd4e05e81b1f016ea Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Bug: 258234315 (cherry picked from commit baf5ddac90dc1983bc376b7ca6fe1afde702ff29 git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git for-next) Signed-off-by: Bart Van Assche <bvanassche@google.com>
This commit is contained in:
committed by
Treehugger Robot
parent
022d55f476
commit
3ce7942d7b
@@ -293,7 +293,6 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
|
|||||||
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||||
struct phy *phy = host->generic_phy;
|
struct phy *phy = host->generic_phy;
|
||||||
int ret;
|
int ret;
|
||||||
bool is_rate_B = UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B;
|
|
||||||
|
|
||||||
/* Reset UFS Host Controller and PHY */
|
/* Reset UFS Host Controller and PHY */
|
||||||
ret = ufs_qcom_host_reset(hba);
|
ret = ufs_qcom_host_reset(hba);
|
||||||
@@ -301,9 +300,6 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
|
|||||||
dev_warn(hba->dev, "%s: host reset returned %d\n",
|
dev_warn(hba->dev, "%s: host reset returned %d\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
|
|
||||||
if (is_rate_B)
|
|
||||||
phy_set_mode(phy, PHY_MODE_UFS_HS_B);
|
|
||||||
|
|
||||||
/* phy initialization - calibrate the phy */
|
/* phy initialization - calibrate the phy */
|
||||||
ret = phy_init(phy);
|
ret = phy_init(phy);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -312,6 +308,8 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phy_set_mode_ext(phy, PHY_MODE_UFS_HS_B, host->hs_gear);
|
||||||
|
|
||||||
/* power on phy - start serdes and phy's power and clocks */
|
/* power on phy - start serdes and phy's power and clocks */
|
||||||
ret = phy_power_on(phy);
|
ret = phy_power_on(phy);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -714,6 +712,9 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Use the agreed gear */
|
||||||
|
host->hs_gear = dev_req_params->gear_tx;
|
||||||
|
|
||||||
/* enable the device ref clock before changing to HS mode */
|
/* enable the device ref clock before changing to HS mode */
|
||||||
if (!ufshcd_is_hs_mode(&hba->pwr_info) &&
|
if (!ufshcd_is_hs_mode(&hba->pwr_info) &&
|
||||||
ufshcd_is_hs_mode(dev_req_params))
|
ufshcd_is_hs_mode(dev_req_params))
|
||||||
@@ -827,6 +828,9 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
|
|||||||
| UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE
|
| UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE
|
||||||
| UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP);
|
| UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (host->hw_ver.major > 0x3)
|
||||||
|
hba->quirks |= UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ufs_qcom_set_caps(struct ufs_hba *hba)
|
static void ufs_qcom_set_caps(struct ufs_hba *hba)
|
||||||
@@ -1034,6 +1038,12 @@ static int ufs_qcom_init(struct ufs_hba *hba)
|
|||||||
dev_warn(dev, "%s: failed to configure the testbus %d\n",
|
dev_warn(dev, "%s: failed to configure the testbus %d\n",
|
||||||
__func__, err);
|
__func__, err);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Power up the PHY using the minimum supported gear (UFS_HS_G2).
|
||||||
|
* Switching to max gear will be performed during reinit if supported.
|
||||||
|
*/
|
||||||
|
host->hs_gear = UFS_HS_G2;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_variant_clear:
|
out_variant_clear:
|
||||||
@@ -1377,6 +1387,13 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void ufs_qcom_reinit_notify(struct ufs_hba *hba)
|
||||||
|
{
|
||||||
|
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
|
||||||
|
|
||||||
|
phy_power_off(host->generic_phy);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
|
* struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
|
||||||
*
|
*
|
||||||
@@ -1400,6 +1417,7 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
|
|||||||
.device_reset = ufs_qcom_device_reset,
|
.device_reset = ufs_qcom_device_reset,
|
||||||
.config_scaling_param = ufs_qcom_config_scaling_param,
|
.config_scaling_param = ufs_qcom_config_scaling_param,
|
||||||
.program_key = ufs_qcom_ice_program_key,
|
.program_key = ufs_qcom_ice_program_key,
|
||||||
|
.reinit_notify = ufs_qcom_reinit_notify,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -206,6 +206,8 @@ struct ufs_qcom_host {
|
|||||||
struct reset_controller_dev rcdev;
|
struct reset_controller_dev rcdev;
|
||||||
|
|
||||||
struct gpio_desc *device_reset;
|
struct gpio_desc *device_reset;
|
||||||
|
|
||||||
|
u32 hs_gear;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline u32
|
static inline u32
|
||||||
|
|||||||
Reference in New Issue
Block a user