aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/vp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2/vp.c')
-rw-r--r--arch/arm/mach-omap2/vp.c65
1 files changed, 56 insertions, 9 deletions
diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
index 4677921..4202701 100644
--- a/arch/arm/mach-omap2/vp.c
+++ b/arch/arm/mach-omap2/vp.c
@@ -1,5 +1,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/ratelimit.h>
#include <plat/common.h>
@@ -117,6 +118,21 @@ int omap_vp_update_errorgain(struct voltagedomain *voltdm,
return 0;
}
+#define _MAX_COUNT_ERR 10
+static u8 __vp_debug_error_message_count = _MAX_COUNT_ERR;
+/* Dump with stack the first few messages, tone down severity for the rest */
+#define _vp_controlled_err(ARGS...) \
+{ \
+ if (__vp_debug_error_message_count) { \
+ pr_err(ARGS); \
+ dump_stack(); \
+ __vp_debug_error_message_count--; \
+ } else { \
+ pr_err_ratelimited(ARGS); \
+ } \
+}
+
+
/* VP force update method of voltage scaling */
int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
unsigned long target_volt)
@@ -126,6 +142,18 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
u8 target_vsel, current_vsel;
int ret, timeout = 0;
+ /*
+ * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+ * This is an additional allowance to ensure we are in proper state
+ * to enter into forceupdate state transition.
+ */
+ omap_test_timeout((voltdm->read(vp->vstatus)), VP_IDLE_TIMEOUT,
+ timeout);
+
+ if (timeout >= VP_IDLE_TIMEOUT)
+ _vp_controlled_err("%s:vdd_%s idletimdout forceupdate(v=%ld)\n",
+ __func__, voltdm->name, target_volt);
+
ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
if (ret)
return ret;
@@ -141,8 +169,11 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
udelay(1);
}
if (timeout >= VP_TRANXDONE_TIMEOUT) {
- pr_warning("%s: vdd_%s TRANXDONE timeout exceeded."
- "Voltage change aborted", __func__, voltdm->name);
+ _vp_controlled_err("%s: vdd_%s TRANXDONE timeout exceeded."
+ "Voltage change aborted target volt=%ld,"
+ "target vsel=0x%02x, current_vsel=0x%02x\n",
+ __func__, voltdm->name, target_volt,
+ target_vsel, current_vsel);
return -ETIMEDOUT;
}
@@ -171,9 +202,12 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
omap_test_timeout(vp->common->ops->check_txdone(vp->id),
VP_TRANXDONE_TIMEOUT, timeout);
if (timeout >= VP_TRANXDONE_TIMEOUT)
- pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
- "TRANXDONE never got set after the voltage update\n",
- __func__, voltdm->name);
+ _vp_controlled_err("%s: vdd_%s TRANXDONE timeout exceeded. "
+ "TRANXDONE never got set after the voltage update. "
+ "target volt=%ld, target vsel=0x%02x, "
+ "current_vsel=0x%02x\n",
+ __func__, voltdm->name, target_volt,
+ target_vsel, current_vsel);
omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
@@ -190,9 +224,11 @@ int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
}
if (timeout >= VP_TRANXDONE_TIMEOUT)
- pr_warning("%s: vdd_%s TRANXDONE timeout exceeded while trying"
- "to clear the TRANXDONE status\n",
- __func__, voltdm->name);
+ _vp_controlled_err("%s: vdd_%s TRANXDONE timeout exceeded while"
+ "trying to clear the TRANXDONE status. target volt=%ld,"
+ "target vsel=0x%02x, current_vsel=0x%02x\n",
+ __func__, voltdm->name, target_volt,
+ target_vsel, current_vsel);
vpconfig = voltdm->read(vp->vpconfig);
/* Clear initVDD copy trigger bit */
@@ -308,6 +344,17 @@ void omap_vp_disable(struct voltagedomain *voltdm)
return;
}
+ /*
+ * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
+ * Depending on if we catch VP in the middle of an SR operation.
+ */
+ omap_test_timeout((voltdm->read(vp->vstatus)),
+ VP_IDLE_TIMEOUT, timeout);
+
+ if (timeout >= VP_IDLE_TIMEOUT)
+ pr_warning("%s: vdd_%s idle timedout before disable\n",
+ __func__, voltdm->name);
+
/* Disable VP */
vpconfig = voltdm->read(vp->vpconfig);
vpconfig &= ~vp->common->vpconfig_vpenable;
@@ -320,7 +367,7 @@ void omap_vp_disable(struct voltagedomain *voltdm)
VP_IDLE_TIMEOUT, timeout);
if (timeout >= VP_IDLE_TIMEOUT)
- pr_warning("%s: vdd_%s idle timedout\n",
+ pr_warning("%s: vdd_%s idle timedout after disable\n",
__func__, voltdm->name);
vp->enabled = false;