iommu: msm: Add decoding to PAR when fault occurs

Add decoding of the PAR register when a VA2PA translation fault
occurs to help in debugging.

Change-Id: Ie3c442d29c3c10f7437acbb63262eb51bc9cc9ab
Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v1.h b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
index 1c20d04..04cd441 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
@@ -19,6 +19,8 @@
 #define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
 #define GET_CTX_REG(reg, base, ctx) \
 	(readl_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
+#define GET_CTX_REG_L(reg, base, ctx) \
+	(readll_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
 
 #define SET_GLOBAL_REG(reg, base, val)	writel_relaxed((val), ((base) + (reg)))
 
@@ -196,7 +198,7 @@
 #define GET_CONTEXTIDR(b, c)     GET_CTX_REG(CB_CONTEXTIDR, (b), (c))
 #define GET_PRRR(b, c)           GET_CTX_REG(CB_PRRR, (b), (c))
 #define GET_NMRR(b, c)           GET_CTX_REG(CB_NMRR, (b), (c))
-#define GET_PAR(b, c)            GET_CTX_REG(CB_PAR, (b), (c))
+#define GET_PAR(b, c)            GET_CTX_REG_L(CB_PAR, (b), (c))
 #define GET_FSR(b, c)            GET_CTX_REG(CB_FSR, (b), (c))
 #define GET_FSRRESTORE(b, c)     GET_CTX_REG(CB_FSRRESTORE, (b), (c))
 #define GET_FAR(b, c)            GET_CTX_REG(CB_FAR, (b), (c))
@@ -1307,6 +1309,7 @@
 #define CB_PAR_TF          (CB_PAR_TF_MASK     << CB_PAR_TF_SHIFT)
 #define CB_PAR_AFF         (CB_PAR_AFF_MASK    << CB_PAR_AFF_SHIFT)
 #define CB_PAR_PF          (CB_PAR_PF_MASK     << CB_PAR_PF_SHIFT)
+#define CB_PAR_EF          (CB_PAR_EF_MASK     << CB_PAR_EF_SHIFT)
 #define CB_PAR_TLBMCF      (CB_PAR_TLBMCF_MASK << CB_PAR_TLBMCF_SHIFT)
 #define CB_PAR_TLBLKF      (CB_PAR_TLBLKF_MASK << CB_PAR_TLBLKF_SHIFT)
 #define CB_PAR_ATOT        (CB_PAR_ATOT_MASK   << CB_PAR_ATOT_SHIFT)
@@ -1682,11 +1685,12 @@
 #define CB_PAR_TF_MASK          0x01
 #define CB_PAR_AFF_MASK         0x01
 #define CB_PAR_PF_MASK          0x01
+#define CB_PAR_EF_MASK          0x01
 #define CB_PAR_TLBMCF_MASK      0x01
 #define CB_PAR_TLBLKF_MASK      0x01
-#define CB_PAR_ATOT_MASK        0x01
-#define CB_PAR_PLVL_MASK        0x03
-#define CB_PAR_STAGE_MASK       0x01
+#define CB_PAR_ATOT_MASK        0x01ULL
+#define CB_PAR_PLVL_MASK        0x03ULL
+#define CB_PAR_STAGE_MASK       0x01ULL
 
 /* Primary Region Remap Register: CB_PRRR */
 #define CB_PRRR_TR0_MASK        0x03
@@ -2052,11 +2056,12 @@
 #define CB_PAR_TF_SHIFT            1
 #define CB_PAR_AFF_SHIFT           2
 #define CB_PAR_PF_SHIFT            3
+#define CB_PAR_EF_SHIFT            4
 #define CB_PAR_TLBMCF_SHIFT        5
 #define CB_PAR_TLBLKF_SHIFT        6
 #define CB_PAR_ATOT_SHIFT          31
-#define CB_PAR_PLVL_SHIFT          0
-#define CB_PAR_STAGE_SHIFT         3
+#define CB_PAR_PLVL_SHIFT          32
+#define CB_PAR_STAGE_SHIFT         35
 
 /* Primary Region Remap Register: CB_PRRR */
 #define CB_PRRR_TR0_SHIFT          0
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index a400b58..aed2b47 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -769,7 +769,7 @@
 	struct msm_iommu_priv *priv;
 	struct msm_iommu_drvdata *iommu_drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata;
-	unsigned int par;
+	u64 par;
 	void __iomem *base;
 	phys_addr_t ret = 0;
 	int ctx;
@@ -802,6 +802,23 @@
 	__disable_clocks(iommu_drvdata);
 
 	if (par & CB_PAR_F) {
+		unsigned int level = (par & CB_PAR_PLVL) >> CB_PAR_PLVL_SHIFT;
+		pr_err("IOMMU translation fault!\n");
+		pr_err("name = %s\n", iommu_drvdata->name);
+		pr_err("context = %s (%d)\n", ctx_drvdata->name,
+						ctx_drvdata->num);
+		pr_err("Interesting registers:\n");
+		pr_err("PAR = %16llx [%s%s%s%s%s%s%s%sPLVL%u %s]\n", par,
+			(par & CB_PAR_F) ? "F " : "",
+			(par & CB_PAR_TF) ? "TF " : "",
+			(par & CB_PAR_AFF) ? "AFF " : "",
+			(par & CB_PAR_PF) ? "PF " : "",
+			(par & CB_PAR_EF) ? "EF " : "",
+			(par & CB_PAR_TLBMCF) ? "TLBMCF " : "",
+			(par & CB_PAR_TLBLKF) ? "TLBLKF " : "",
+			(par & CB_PAR_ATOT) ? "ATOT " : "",
+			level,
+			(par & CB_PAR_STAGE) ? "S2 " : "S1 ");
 		ret = 0;
 	} else {
 		/* We are dealing with a supersection */