ARM: tegra: smmu: Save & restore correct SMMU registers
Hiro Sugawara [Tue, 8 May 2012 16:35:42 +0000 (09:35 -0700)]
Bug 981373

Change-Id: I8617ca0ffd7df570b8ee6f3cad524decf6c26437
Signed-off-by: Hiro Sugawara <hsugawara@nvidia.com>
Reviewed-on: http://git-master/r/101285
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>

arch/arm/mach-tegra/iovmm-smmu.c

index 31c7d48..7e815e2 100644 (file)
@@ -310,10 +310,14 @@ struct smmu_device {
        /*
         * Register image savers for suspend/resume
         */
-       unsigned long translation_enable_0_0;
-       unsigned long translation_enable_1_0;
-       unsigned long translation_enable_2_0;
-       unsigned long asid_security_0;
+       unsigned long config_0;         /* Secure reg */
+       unsigned long tlb_config_0;
+       unsigned long ptc_config_0;
+       unsigned long ptb_asid_0;
+       unsigned long translation_enable_0_0;   /* Secure reg */
+       unsigned long translation_enable_1_0;   /* Secure reg */
+       unsigned long translation_enable_2_0;   /* Secure reg */
+       unsigned long asid_security_0;  /* Secure reg */
 
        unsigned long lowest_asid;      /* Variables for hardware testing */
        unsigned long debug_asid;
@@ -341,7 +345,7 @@ struct smmu_device {
  * Flush all TLB entries and all PTC entries
  * Caller must lock smmu
  */
-static void smmu_flush_regs(struct smmu_device *smmu, int enable)
+static void smmu_flush_regs(struct smmu_device *smmu)
 {
        writel(MC_SMMU_PTC_FLUSH_0_PTC_FLUSH_TYPE_ALL,
                smmu->regs + MC_SMMU_PTC_FLUSH_0);
@@ -349,10 +353,6 @@ static void smmu_flush_regs(struct smmu_device *smmu, int enable)
        writel(MC_SMMU_TLB_FLUSH_0_TLB_FLUSH_VA_MATCH_ALL |
                        MC_SMMU_TLB_FLUSH_0_TLB_FLUSH_ASID_MATCH_disable,
                smmu->regs + MC_SMMU_TLB_FLUSH_0);
-
-       if (enable)
-               writel(MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE,
-                       smmu->regs + MC_SMMU_CONFIG_0);
        FLUSH_SMMU_REGS(smmu);
 }
 
@@ -388,14 +388,14 @@ static void smmu_setup_regs(struct smmu_device *smmu)
                smmu->regs + MC_SMMU_TRANSLATION_ENABLE_1_0);
        writel(smmu->translation_enable_2_0,
                smmu->regs + MC_SMMU_TRANSLATION_ENABLE_2_0);
-       writel(smmu->asid_security_0,
-               smmu->regs + MC_SMMU_ASID_SECURITY_0);
-       writel(MC_SMMU_TLB_CONFIG_0_RESET_VAL,
-               smmu->regs + MC_SMMU_TLB_CONFIG_0);
-       writel(MC_SMMU_PTC_CONFIG_0_RESET_VAL,
-               smmu->regs + MC_SMMU_PTC_CONFIG_0);
-
-       smmu_flush_regs(smmu, 1);
+       writel(smmu->asid_security_0, smmu->regs + MC_SMMU_ASID_SECURITY_0);
+       writel(smmu->ptb_asid_0,      smmu->regs + MC_SMMU_PTB_ASID_0);
+       writel(smmu->ptc_config_0,    smmu->regs + MC_SMMU_PTC_CONFIG_0);
+       writel(smmu->tlb_config_0,    smmu->regs + MC_SMMU_TLB_CONFIG_0);
+       writel(smmu->config_0,        smmu->regs + MC_SMMU_CONFIG_0);
+
+       smmu_flush_regs(smmu);
+
        writel(
                readl(smmu->regs_ahbarb + AHB_ARBITRATION_XBAR_CTRL_0) |
                (AHB_ARBITRATION_XBAR_CTRL_0_SMMU_INIT_DONE_DONE <<
@@ -408,6 +408,10 @@ static int smmu_suspend(struct tegra_iovmm_device *dev)
        struct smmu_device *smmu =
                container_of(dev, struct smmu_device, iovmm_dev);
 
+       smmu->config_0     = readl(smmu->regs + MC_SMMU_CONFIG_0);
+       smmu->tlb_config_0 = readl(smmu->regs + MC_SMMU_TLB_CONFIG_0);
+       smmu->ptc_config_0 = readl(smmu->regs + MC_SMMU_PTC_CONFIG_0);
+       smmu->ptb_asid_0   = readl(smmu->regs + MC_SMMU_PTB_ASID_0);
        smmu->translation_enable_0_0 =
                readl(smmu->regs + MC_SMMU_TRANSLATION_ENABLE_0_0);
        smmu->translation_enable_1_0 =
@@ -691,10 +695,8 @@ static void smmu_unmap(struct tegra_iovmm_domain *domain,
                                flush_ptc_and_tlb(as->smmu, as, addr, pte,
                                                page, 0);
                                kunmap(page);
-                               if (!--(*pte_counter) && decommit) {
+                               if (!--(*pte_counter) && decommit)
                                        free_ptbl(as, addr);
-                                       smmu_flush_regs(as->smmu, 0);
-                               }
                        }
                }
                addr += SMMU_PAGE_SIZE;
@@ -966,10 +968,14 @@ static int smmu_probe(struct platform_device *pdev)
                goto fail;
        }
 
+       smmu->config_0        = MC_SMMU_CONFIG_0_SMMU_ENABLE_ENABLE;
+       smmu->tlb_config_0    = MC_SMMU_TLB_CONFIG_0_RESET_VAL;
+       smmu->ptc_config_0    = MC_SMMU_PTC_CONFIG_0_RESET_VAL;
+       smmu->ptb_asid_0      = 0;
        smmu->translation_enable_0_0 = ~0;
        smmu->translation_enable_1_0 = ~0;
        smmu->translation_enable_2_0 = ~0;
-       smmu->asid_security_0        = 0;
+       smmu->asid_security_0 = 0;
 
        memcpy(smmu->hwc_state, smmu_hwc_state_init, sizeof(smmu->hwc_state));