iommu: msm: Ensure clocks are on for PMU
Ensure that clocks are turned on before accessing the Performance
Monitor Unit (PMU) registers or device will crash due to unclocked
access.
Change-Id: Ie1ca42eb24bb874d30ca7a4d7b661812d798fc56
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/iommu_perfmon.h b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
index dcae83b..dc4671c 100644
--- a/arch/arm/mach-msm/include/mach/iommu_perfmon.h
+++ b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
@@ -63,6 +63,7 @@
* @iommu_dev: pointer to iommu device
* @ops: iommu access operations pointer.
* @hw_ops: iommu pm hw access operations pointer.
+ * @always_on: 1 if iommu is always on, 0 otherwise.
*/
struct iommu_info {
const char *iommu_name;
@@ -71,6 +72,7 @@
struct device *iommu_dev;
struct iommu_access_ops *ops;
struct iommu_pm_hw_ops *hw_ops;
+ unsigned int always_on;
};
/**
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 549800f..7ae0b21 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -414,6 +414,7 @@
pmon_info->iommu.ops = &iommu_access_ops_v0;
pmon_info->iommu.hw_ops = iommu_pm_get_hw_ops_v0();
pmon_info->iommu.iommu_name = drvdata->name;
+ pmon_info->iommu.always_on = 1;
ret = msm_iommu_pm_iommu_register(pmon_info);
if (ret) {
pr_err("%s iommu register fail\n",
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index 9265706..a11d794 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -503,14 +503,17 @@
rv = kstrtoul(buf, 10, &cmd);
if (!rv && (cmd < 2)) {
if (pmon->enabled == 1 && cmd == 0) {
- if (pmon->iommu_attach_count > 0)
+ if (pmon->iommu.always_on ||
+ pmon->iommu_attach_count > 0)
iommu_pm_off(pmon);
} else if (pmon->enabled == 0 && cmd == 1) {
/* We can only turn on perf. monitoring if
- * iommu is attached. Delay turning on perf.
- * monitoring until we are attached.
+ * iommu is attached (if not always on).
+ * Delay turning on perf. monitoring until
+ * we are attached.
*/
- if (pmon->iommu_attach_count > 0)
+ if (pmon->iommu.always_on ||
+ pmon->iommu_attach_count > 0)
iommu_pm_on(pmon);
else
pmon->enabled = 1;
@@ -803,9 +806,9 @@
++pmon->iommu_attach_count;
if (pmon->iommu_attach_count == 1) {
/* If perf. mon was enabled before we attached we do
- * the actual after we attach.
+ * the actual enabling after we attach.
*/
- if (pmon->enabled)
+ if (pmon->enabled && !pmon->iommu.always_on)
iommu_pm_on(pmon);
}
mutex_unlock(&pmon->lock);
@@ -820,9 +823,9 @@
mutex_lock(&pmon->lock);
if (pmon->iommu_attach_count == 1) {
/* If perf. mon is still enabled we have to disable
- * before we do the detach.
+ * before we do the detach if iommu is not always on.
*/
- if (pmon->enabled)
+ if (pmon->enabled && !pmon->iommu.always_on)
iommu_pm_off(pmon);
}
BUG_ON(pmon->iommu_attach_count == 0);