msm: spm-v2: Disable AVS operations on unsupported targets
Do not enable/disable AVS on targets where it is not enabled at boot.
Enabling it on targets when AVS isn't enabled and the AVS control
parameters aren't configured, causes undefined behavior and random
crashes.
Change-Id: Id0c4e10618437eed1b383145a6a4f25bbd901647
Signed-off-by: Anji Jonnala <anjir@codeaurora.org>
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index f0d3d06..5684082 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -311,6 +311,15 @@
}
#ifdef CONFIG_MSM_AVS_HW
+static bool msm_spm_drv_is_avs_enabled(struct msm_spm_driver_data *dev)
+{
+ msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
+ if (dev->major == SAW2_MAJOR_2)
+ return dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] & BIT(0);
+ else
+ return dev->reg_shadow[MSM_SPM_REG_SAW2_AVS_CTL] & BIT(27);
+}
+
static void msm_spm_drv_disable_avs(struct msm_spm_driver_data *dev)
{
msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_AVS_CTL);
@@ -335,6 +344,10 @@
}
#else
+static bool msm_spm_drv_is_avs_enabled(struct msm_spm_driver_data *dev)
+{
+ return false;
+}
static void msm_spm_drv_disable_avs(struct msm_spm_driver_data *dev) { }
@@ -347,6 +360,7 @@
int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel)
{
uint32_t timeout_us, new_level;
+ bool avs_enabled = msm_spm_drv_is_avs_enabled(dev);
if (!dev)
return -EINVAL;
@@ -357,7 +371,8 @@
if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
pr_info("%s: requesting vlevel %#x\n", __func__, vlevel);
- msm_spm_drv_disable_avs(dev);
+ if (avs_enabled)
+ msm_spm_drv_disable_avs(dev);
/* Kick the state machine back to idle */
dev->reg_shadow[MSM_SPM_REG_SAW2_RST] = 1;
@@ -381,18 +396,22 @@
goto set_vdd_bail;
}
- /* Set AVS min/max */
- msm_spm_drv_set_avs_vlevel(dev, vlevel);
-
if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
pr_info("%s: done, remaining timeout %uus\n",
__func__, timeout_us);
- msm_spm_drv_enable_avs(dev);
+ /* Set AVS min/max */
+ if (avs_enabled) {
+ msm_spm_drv_set_avs_vlevel(dev, vlevel);
+ msm_spm_drv_enable_avs(dev);
+ }
+
return 0;
set_vdd_bail:
- msm_spm_drv_enable_avs(dev);
+ if (avs_enabled)
+ msm_spm_drv_enable_avs(dev);
+
pr_err("%s: failed %#x, remaining timeout %uus, vlevel %#x\n",
__func__, vlevel, timeout_us, new_level);
return -EIO;