diff mbox series

[v1,1/2] scsi: ufs: Introduce device quirk "DELAY_AFTER_LPM"

Message ID 20200729051840.31318-2-stanley.chu@mediatek.com (mailing list archive)
State New, archived
Headers show
Series scsi: ufs: Introduce and apply DELAY_AFTER_LPM device quirk | expand

Commit Message

Stanley Chu July 29, 2020, 5:18 a.m. UTC
Some UFS devices require delay after VCC power rail is turned-off.
Introduce a device quirk "DELAY_AFTER_LPM" to add 5ms delays after
VCC power-off during suspend flow.

Signed-off-by: Andy Teng <andy.teng@mediatek.com>
Signed-off-by: Peter Wang <peter.wang@mediatek.com>
Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
---
 drivers/scsi/ufs/ufs_quirks.h |  7 +++++++
 drivers/scsi/ufs/ufshcd.c     | 11 +++++++++++
 2 files changed, 18 insertions(+)

Comments

Can Guo July 29, 2020, 5:31 a.m. UTC | #1
Hi Stanley,

On 2020-07-29 13:18, Stanley Chu wrote:
> Some UFS devices require delay after VCC power rail is turned-off.
> Introduce a device quirk "DELAY_AFTER_LPM" to add 5ms delays after
> VCC power-off during suspend flow.
> 

Just curious, I can understand if you want to add some delays before
turnning off VCC/VCCQ/VCCQ2, but what is the delay AFTER turnning
them off for? I mean the power has been cut by host from PMIC, how
can the delay benefit the UFS device?

Thanks,

Can Guo.

> Signed-off-by: Andy Teng <andy.teng@mediatek.com>
> Signed-off-by: Peter Wang <peter.wang@mediatek.com>
> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> ---
>  drivers/scsi/ufs/ufs_quirks.h |  7 +++++++
>  drivers/scsi/ufs/ufshcd.c     | 11 +++++++++++
>  2 files changed, 18 insertions(+)
> 
> diff --git a/drivers/scsi/ufs/ufs_quirks.h 
> b/drivers/scsi/ufs/ufs_quirks.h
> index 2a0041493e30..07f559ac5883 100644
> --- a/drivers/scsi/ufs/ufs_quirks.h
> +++ b/drivers/scsi/ufs/ufs_quirks.h
> @@ -109,4 +109,11 @@ struct ufs_dev_fix {
>   */
>  #define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10)
> 
> +/*
> + * Some UFS devices require delay after VCC power rail is turned-off.
> + * Enable this quirk to introduce 5ms delays after VCC power-off 
> during
> + * suspend flow.
> + */
> +#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM        (1 << 11)
> +
>  #endif /* UFS_QUIRKS_H_ */
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index acba2271c5d3..63f4e2f75aa1 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -8111,6 +8111,8 @@ static int ufshcd_link_state_transition(struct
> ufs_hba *hba,
> 
>  static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
>  {
> +	bool vcc_off = false;
> +
>  	/*
>  	 * It seems some UFS devices may keep drawing more than sleep current
>  	 * (atleast for 500us) from UFS rails (especially from VCCQ rail).
> @@ -8139,13 +8141,22 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba 
> *hba)
>  	if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
>  	    !hba->dev_info.is_lu_power_on_wp) {
>  		ufshcd_setup_vreg(hba, false);
> +		vcc_off = true;
>  	} else if (!ufshcd_is_ufs_dev_active(hba)) {
>  		ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
> +		vcc_off = true;
>  		if (!ufshcd_is_link_active(hba)) {
>  			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
>  			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
>  		}
>  	}
> +
> +	/*
> +	 * Some UFS devices require delay after VCC power rail is turned-off.
> +	 */
> +	if (vcc_off && hba->vreg_info.vcc &&
> +		hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM)
> +		usleep_range(5000, 5100);
>  }
> 
>  static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
Stanley Chu July 29, 2020, 6:17 a.m. UTC | #2
Hi Can,

On Wed, 2020-07-29 at 13:31 +0800, Can Guo wrote:
> Hi Stanley,
> 
> On 2020-07-29 13:18, Stanley Chu wrote:
> > Some UFS devices require delay after VCC power rail is turned-off.
> > Introduce a device quirk "DELAY_AFTER_LPM" to add 5ms delays after
> > VCC power-off during suspend flow.
> > 
> 
> Just curious, I can understand if you want to add some delays before
> turnning off VCC/VCCQ/VCCQ2, but what is the delay AFTER turnning
> them off for? I mean the power has been cut by host from PMIC, how
> can the delay benefit the UFS device?
> 

The problem comes from both sides,
1. VCC power rail design by SoC vendors, and
2. Device strategy according to VCC changes

Take Micron UFS devices on MediaTek platform as example, our VCC drop
rate may be too slow and lead to incorrect resume strategy by device.
Without this delay, device may not resume successfully.

Thanks,
Stanley Chu
Can Guo July 29, 2020, 9:21 a.m. UTC | #3
On 2020-07-29 13:18, Stanley Chu wrote:
> Some UFS devices require delay after VCC power rail is turned-off.
> Introduce a device quirk "DELAY_AFTER_LPM" to add 5ms delays after
> VCC power-off during suspend flow.
> 
> Signed-off-by: Andy Teng <andy.teng@mediatek.com>
> Signed-off-by: Peter Wang <peter.wang@mediatek.com>
> Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
> ---
>  drivers/scsi/ufs/ufs_quirks.h |  7 +++++++
>  drivers/scsi/ufs/ufshcd.c     | 11 +++++++++++
>  2 files changed, 18 insertions(+)
> 
> diff --git a/drivers/scsi/ufs/ufs_quirks.h 
> b/drivers/scsi/ufs/ufs_quirks.h
> index 2a0041493e30..07f559ac5883 100644
> --- a/drivers/scsi/ufs/ufs_quirks.h
> +++ b/drivers/scsi/ufs/ufs_quirks.h
> @@ -109,4 +109,11 @@ struct ufs_dev_fix {
>   */
>  #define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10)
> 
> +/*
> + * Some UFS devices require delay after VCC power rail is turned-off.
> + * Enable this quirk to introduce 5ms delays after VCC power-off 
> during
> + * suspend flow.
> + */
> +#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM        (1 << 11)
> +
>  #endif /* UFS_QUIRKS_H_ */
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index acba2271c5d3..63f4e2f75aa1 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -8111,6 +8111,8 @@ static int ufshcd_link_state_transition(struct
> ufs_hba *hba,
> 
>  static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
>  {
> +	bool vcc_off = false;
> +
>  	/*
>  	 * It seems some UFS devices may keep drawing more than sleep current
>  	 * (atleast for 500us) from UFS rails (especially from VCCQ rail).
> @@ -8139,13 +8141,22 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba 
> *hba)
>  	if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
>  	    !hba->dev_info.is_lu_power_on_wp) {
>  		ufshcd_setup_vreg(hba, false);
> +		vcc_off = true;
>  	} else if (!ufshcd_is_ufs_dev_active(hba)) {
>  		ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
> +		vcc_off = true;
>  		if (!ufshcd_is_link_active(hba)) {
>  			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
>  			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
>  		}
>  	}
> +
> +	/*
> +	 * Some UFS devices require delay after VCC power rail is turned-off.
> +	 */
> +	if (vcc_off && hba->vreg_info.vcc &&
> +		hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM)
> +		usleep_range(5000, 5100);
>  }
> 
>  static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)

Reviewed-by: Can Guo <cang@codeaurora.org>
diff mbox series

Patch

diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h
index 2a0041493e30..07f559ac5883 100644
--- a/drivers/scsi/ufs/ufs_quirks.h
+++ b/drivers/scsi/ufs/ufs_quirks.h
@@ -109,4 +109,11 @@  struct ufs_dev_fix {
  */
 #define UFS_DEVICE_QUIRK_SUPPORT_EXTENDED_FEATURES (1 << 10)
 
+/*
+ * Some UFS devices require delay after VCC power rail is turned-off.
+ * Enable this quirk to introduce 5ms delays after VCC power-off during
+ * suspend flow.
+ */
+#define UFS_DEVICE_QUIRK_DELAY_AFTER_LPM        (1 << 11)
+
 #endif /* UFS_QUIRKS_H_ */
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index acba2271c5d3..63f4e2f75aa1 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -8111,6 +8111,8 @@  static int ufshcd_link_state_transition(struct ufs_hba *hba,
 
 static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
 {
+	bool vcc_off = false;
+
 	/*
 	 * It seems some UFS devices may keep drawing more than sleep current
 	 * (atleast for 500us) from UFS rails (especially from VCCQ rail).
@@ -8139,13 +8141,22 @@  static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
 	if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) &&
 	    !hba->dev_info.is_lu_power_on_wp) {
 		ufshcd_setup_vreg(hba, false);
+		vcc_off = true;
 	} else if (!ufshcd_is_ufs_dev_active(hba)) {
 		ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
+		vcc_off = true;
 		if (!ufshcd_is_link_active(hba)) {
 			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
 			ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
 		}
 	}
+
+	/*
+	 * Some UFS devices require delay after VCC power rail is turned-off.
+	 */
+	if (vcc_off && hba->vreg_info.vcc &&
+		hba->dev_quirks & UFS_DEVICE_QUIRK_DELAY_AFTER_LPM)
+		usleep_range(5000, 5100);
 }
 
 static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)