Loading drivers/scsi/ufs/ufs.h +1 −0 Original line number Diff line number Diff line Loading @@ -535,6 +535,7 @@ struct ufs_vreg { int max_uV; bool low_voltage_sup; bool low_voltage_active; bool sys_suspend_pwr_off; int min_uA; int max_uA; }; Loading drivers/scsi/ufs/ufshcd-pltfrm.c +15 −0 Original line number Diff line number Diff line Loading @@ -217,9 +217,24 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, } else if (!strcmp(name, "vccq")) { vreg->min_uV = UFS_VREG_VCCQ_MIN_UV; vreg->max_uV = UFS_VREG_VCCQ_MAX_UV; /** * Only if the SoC supports turning off VCCQ or VCCQ2 power * supply source during power collapse, set a flag to turn off * the specified power supply to reduce the system power * consumption during system suspend events. The tradeoffs are: * - System resume time will increase due * to UFS device full re-initialization time. * - UFS device life may be affected due to multiple * UFS power on/off events. * The benefits vs tradeoff should be considered carefully. */ if (of_property_read_bool(np, "vccq-pwr-collapse-sup")) vreg->sys_suspend_pwr_off = true; } else if (!strcmp(name, "vccq2")) { vreg->min_uV = UFS_VREG_VCCQ2_MIN_UV; vreg->max_uV = UFS_VREG_VCCQ2_MAX_UV; if (of_property_read_bool(np, "vccq2-pwr-collapse-sup")) vreg->sys_suspend_pwr_off = true; } goto out; Loading drivers/scsi/ufs/ufshcd.c +55 −9 Original line number Diff line number Diff line Loading @@ -8864,6 +8864,22 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) goto out; } /** * UFS3.0 and newer devices use Vcc and Vccq(1.2V) * while UFS2.1 devices use Vcc and Vccq2(1.8V) power * supplies. If the system allows turning off the regulators * during power collapse event, turn off the regulators * during system suspend events. This will cause the UFS * device to re-initialize upon system resume events. */ if ((hba->dev_info.w_spec_version >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) || (hba->dev_info.w_spec_version < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off)) hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE); /* UFS device is also active now */ ufshcd_set_ufs_dev_active(hba); ufshcd_force_reset_auto_bkops(hba); Loading Loading @@ -10109,7 +10125,20 @@ 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); ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); if (hba->dev_info.w_spec_version >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq, false); else ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); if (hba->dev_info.w_spec_version < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off) ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq2, false); else ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); } else if (!ufshcd_is_ufs_dev_active(hba)) { ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); if (!ufshcd_is_link_active(hba)) { Loading @@ -10125,22 +10154,39 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) && !hba->dev_info.is_lu_power_on_wp) { ret = ufshcd_setup_vreg(hba, true); } else if (!ufshcd_is_ufs_dev_active(hba)) { if (!ret && !ufshcd_is_link_active(hba)) { ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (hba->dev_info.w_spec_version < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off) ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq2, true); else ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); if (ret) goto vcc_disable; if (hba->dev_info.w_spec_version >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq, true); else ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (ret) goto vccq2_lpm; ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true); } else if (!ufshcd_is_ufs_dev_active(hba)) { if (!ufshcd_is_link_active(hba)) { ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); if (ret) goto vccq_lpm; goto vcc_disable; ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (ret) goto vccq2_lpm; } ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true); } goto out; vccq_lpm: ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); vccq2_lpm: ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); vcc_disable: ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); out: Loading Loading
drivers/scsi/ufs/ufs.h +1 −0 Original line number Diff line number Diff line Loading @@ -535,6 +535,7 @@ struct ufs_vreg { int max_uV; bool low_voltage_sup; bool low_voltage_active; bool sys_suspend_pwr_off; int min_uA; int max_uA; }; Loading
drivers/scsi/ufs/ufshcd-pltfrm.c +15 −0 Original line number Diff line number Diff line Loading @@ -217,9 +217,24 @@ static int ufshcd_populate_vreg(struct device *dev, const char *name, } else if (!strcmp(name, "vccq")) { vreg->min_uV = UFS_VREG_VCCQ_MIN_UV; vreg->max_uV = UFS_VREG_VCCQ_MAX_UV; /** * Only if the SoC supports turning off VCCQ or VCCQ2 power * supply source during power collapse, set a flag to turn off * the specified power supply to reduce the system power * consumption during system suspend events. The tradeoffs are: * - System resume time will increase due * to UFS device full re-initialization time. * - UFS device life may be affected due to multiple * UFS power on/off events. * The benefits vs tradeoff should be considered carefully. */ if (of_property_read_bool(np, "vccq-pwr-collapse-sup")) vreg->sys_suspend_pwr_off = true; } else if (!strcmp(name, "vccq2")) { vreg->min_uV = UFS_VREG_VCCQ2_MIN_UV; vreg->max_uV = UFS_VREG_VCCQ2_MAX_UV; if (of_property_read_bool(np, "vccq2-pwr-collapse-sup")) vreg->sys_suspend_pwr_off = true; } goto out; Loading
drivers/scsi/ufs/ufshcd.c +55 −9 Original line number Diff line number Diff line Loading @@ -8864,6 +8864,22 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) goto out; } /** * UFS3.0 and newer devices use Vcc and Vccq(1.2V) * while UFS2.1 devices use Vcc and Vccq2(1.8V) power * supplies. If the system allows turning off the regulators * during power collapse event, turn off the regulators * during system suspend events. This will cause the UFS * device to re-initialize upon system resume events. */ if ((hba->dev_info.w_spec_version >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) || (hba->dev_info.w_spec_version < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off)) hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE); /* UFS device is also active now */ ufshcd_set_ufs_dev_active(hba); ufshcd_force_reset_auto_bkops(hba); Loading Loading @@ -10109,7 +10125,20 @@ 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); ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); if (hba->dev_info.w_spec_version >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq, false); else ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); if (hba->dev_info.w_spec_version < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off) ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq2, false); else ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); } else if (!ufshcd_is_ufs_dev_active(hba)) { ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); if (!ufshcd_is_link_active(hba)) { Loading @@ -10125,22 +10154,39 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba) if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba) && !hba->dev_info.is_lu_power_on_wp) { ret = ufshcd_setup_vreg(hba, true); } else if (!ufshcd_is_ufs_dev_active(hba)) { if (!ret && !ufshcd_is_link_active(hba)) { ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (hba->dev_info.w_spec_version < 0x300 && hba->vreg_info.vccq2->sys_suspend_pwr_off) ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq2, true); else ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); if (ret) goto vcc_disable; if (hba->dev_info.w_spec_version >= 0x300 && hba->vreg_info.vccq->sys_suspend_pwr_off) ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vccq, true); else ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (ret) goto vccq2_lpm; ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true); } else if (!ufshcd_is_ufs_dev_active(hba)) { if (!ufshcd_is_link_active(hba)) { ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq2); if (ret) goto vccq_lpm; goto vcc_disable; ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq); if (ret) goto vccq2_lpm; } ret = ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, true); } goto out; vccq_lpm: ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq); vccq2_lpm: ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2); vcc_disable: ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false); out: Loading