|
@@ -195,6 +195,7 @@ static int ufshcd_probe_hba(struct ufs_hba *hba);
|
|
|
static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
|
|
|
bool skip_ref_clk);
|
|
|
static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on);
|
|
|
+static int ufshcd_set_vccq_rail_unused(struct ufs_hba *hba, bool unused);
|
|
|
static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba);
|
|
|
static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba);
|
|
|
static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba);
|
|
@@ -4662,6 +4663,12 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
|
|
|
goto out;
|
|
|
|
|
|
ufs_advertise_fixup_device(hba);
|
|
|
+
|
|
|
+ ret = ufshcd_set_vccq_rail_unused(hba,
|
|
|
+ (hba->dev_quirks & UFS_DEVICE_NO_VCCQ) ? true : false);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
+
|
|
|
/* UFS device is also active now */
|
|
|
ufshcd_set_ufs_dev_active(hba);
|
|
|
ufshcd_force_reset_auto_bkops(hba);
|
|
@@ -4812,13 +4819,24 @@ static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg,
|
|
|
static inline int ufshcd_config_vreg_lpm(struct ufs_hba *hba,
|
|
|
struct ufs_vreg *vreg)
|
|
|
{
|
|
|
- return ufshcd_config_vreg_load(hba->dev, vreg, UFS_VREG_LPM_LOAD_UA);
|
|
|
+ if (!vreg)
|
|
|
+ return 0;
|
|
|
+ else if (vreg->unused)
|
|
|
+ return 0;
|
|
|
+ else
|
|
|
+ return ufshcd_config_vreg_load(hba->dev, vreg,
|
|
|
+ UFS_VREG_LPM_LOAD_UA);
|
|
|
}
|
|
|
|
|
|
static inline int ufshcd_config_vreg_hpm(struct ufs_hba *hba,
|
|
|
struct ufs_vreg *vreg)
|
|
|
{
|
|
|
- return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
|
|
|
+ if (!vreg)
|
|
|
+ return 0;
|
|
|
+ else if (vreg->unused)
|
|
|
+ return 0;
|
|
|
+ else
|
|
|
+ return ufshcd_config_vreg_load(hba->dev, vreg, vreg->max_uA);
|
|
|
}
|
|
|
|
|
|
static int ufshcd_config_vreg(struct device *dev,
|
|
@@ -4853,7 +4871,9 @@ static int ufshcd_enable_vreg(struct device *dev, struct ufs_vreg *vreg)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
|
|
|
- if (!vreg || vreg->enabled)
|
|
|
+ if (!vreg)
|
|
|
+ goto out;
|
|
|
+ else if (vreg->enabled || vreg->unused)
|
|
|
goto out;
|
|
|
|
|
|
ret = ufshcd_config_vreg(dev, vreg, true);
|
|
@@ -4873,7 +4893,9 @@ static int ufshcd_disable_vreg(struct device *dev, struct ufs_vreg *vreg)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
|
|
|
- if (!vreg || !vreg->enabled)
|
|
|
+ if (!vreg)
|
|
|
+ goto out;
|
|
|
+ else if (!vreg->enabled || vreg->unused)
|
|
|
goto out;
|
|
|
|
|
|
ret = regulator_disable(vreg->reg);
|
|
@@ -4979,6 +5001,36 @@ static int ufshcd_init_hba_vreg(struct ufs_hba *hba)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int ufshcd_set_vccq_rail_unused(struct ufs_hba *hba, bool unused)
|
|
|
+{
|
|
|
+ int ret = 0;
|
|
|
+ struct ufs_vreg_info *info = &hba->vreg_info;
|
|
|
+
|
|
|
+ if (!info)
|
|
|
+ goto out;
|
|
|
+ else if (!info->vccq)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (unused) {
|
|
|
+ /* shut off the rail here */
|
|
|
+ ret = ufshcd_toggle_vreg(hba->dev, info->vccq, false);
|
|
|
+ /*
|
|
|
+ * Mark this rail as no longer used, so it doesn't get enabled
|
|
|
+ * later by mistake
|
|
|
+ */
|
|
|
+ if (!ret)
|
|
|
+ info->vccq->unused = true;
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * rail should have been already enabled hence just make sure
|
|
|
+ * that unused flag is cleared.
|
|
|
+ */
|
|
|
+ info->vccq->unused = false;
|
|
|
+ }
|
|
|
+out:
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
|
|
|
bool skip_ref_clk)
|
|
|
{
|