[COMMON] iommu/exynos: add condition for no_rpm_control
authorJanghyuck Kim <janghyuck.kim@samsung.com>
Tue, 31 Oct 2017 02:15:16 +0000 (11:15 +0900)
committerYoungmin Nam <youngmin.nam@samsung.com>
Tue, 3 Jul 2018 07:01:02 +0000 (16:01 +0900)
If device has no_rpm_control attribute, it is not controlled by runtime
pm and controlled explicitly by exynos_sysmmu_control() API.
However, no_rpm_control attribute is also used for condition checking of
TLB invalidation or showing status API. It always made condition false,
and TLB invalidation or showing status API were skipped.

This patch added condition to prcess these operation if SysMMU has
no_rpm_control attribute and it is enabled by explicit API.

Change-Id: Idaa5789b1616227eae5c162330d3ff41c5cde761
Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
drivers/iommu/exynos-iommu.c
drivers/iommu/exynos-iommu.h

index 13acf336240f23f0da222e825b65cd89f65d359f..c38f2a1525ea7bc6a5b0dffdb85b342659faaa2e 100644 (file)
@@ -112,8 +112,8 @@ void exynos_sysmmu_tlb_invalidate(struct iommu_domain *iommu_domain,
                        struct sysmmu_drvdata *drvdata = dev_get_drvdata(list->sysmmu);
 
                        spin_lock(&drvdata->lock);
-                       if (!is_sysmmu_active(drvdata) ||
-                                       !is_sysmmu_runtime_active(drvdata)) {
+                       if (!is_runtime_active_or_enabled(drvdata) ||
+                                       !is_sysmmu_active(drvdata)) {
                                spin_unlock(&drvdata->lock);
                                dev_dbg(drvdata->sysmmu,
                                        "Skip TLB invalidation %#zx@%#x\n",
@@ -467,7 +467,7 @@ static int __init sysmmu_parse_dt(struct device *sysmmu,
                drvdata->hold_rpm_on_boot = true;
 
        if (of_property_read_bool(sysmmu->of_node, "sysmmu,no-rpm-control"))
-               drvdata->no_rpm_control = true;
+               drvdata->no_rpm_control = SYSMMU_STATE_DISABLED;
 
        if (IS_TLB_WAY_TYPE(drvdata)) {
                ret = sysmmu_parse_tlb_way_dt(sysmmu, drvdata);
@@ -700,12 +700,19 @@ void exynos_sysmmu_control(struct device *master, bool enable)
        spin_lock_irqsave(&owner->lock, flags);
        list_for_each_entry(list, &owner->sysmmu_list, node) {
                drvdata = dev_get_drvdata(list->sysmmu);
-               if (!drvdata->no_rpm_control)
+               spin_lock(&drvdata->lock);
+               if (!drvdata->no_rpm_control) {
+                       spin_unlock(&drvdata->lock);
                        continue;
-               if (enable)
+               }
+               if (enable) {
                        __sysmmu_enable_nocount(drvdata);
-               else
+                       drvdata->no_rpm_control = SYSMMU_STATE_ENABLED;
+               } else {
                        __sysmmu_disable_nocount(drvdata);
+                       drvdata->no_rpm_control = SYSMMU_STATE_DISABLED;
+               }
+               spin_unlock(&drvdata->lock);
        }
        spin_unlock_irqrestore(&owner->lock, flags);
 }
@@ -1309,7 +1316,7 @@ void exynos_sysmmu_show_status(struct device *master)
 
                spin_lock_irqsave(&drvdata->lock, flags);
                if (!is_sysmmu_active(drvdata) ||
-                               !is_sysmmu_runtime_active(drvdata)) {
+                               !is_runtime_active_or_enabled(drvdata)) {
                        dev_info(drvdata->sysmmu,
                                "%s: SysMMU is not active\n", __func__);
                        spin_unlock_irqrestore(&drvdata->lock, flags);
index 998aa3411d31b9380493a23b4154d93b9c94e737..583ec0c0b500d59dadaedefe94706da3e3a453bc 100644 (file)
@@ -324,6 +324,12 @@ struct tlb_props {
        };
 };
 
+enum {
+       SYSMMU_USE_RUNTIME_ACTIVE = 0,
+       SYSMMU_STATE_DISABLED,
+       SYSMMU_STATE_ENABLED,
+};
+
 /*
  * This structure hold all data of a single SYSMMU controller, this includes
  * hw resources like registers and clocks, pointers and list nodes to connect
@@ -402,6 +408,12 @@ static inline bool is_sysmmu_runtime_active(struct sysmmu_drvdata *data)
        return data->runtime_active > 0 && !data->no_rpm_control;
 }
 
+static inline bool is_runtime_active_or_enabled(struct sysmmu_drvdata *data)
+{
+       return is_sysmmu_runtime_active(data) ||
+               data->no_rpm_control == SYSMMU_STATE_ENABLED;
+}
+
 static inline bool set_sysmmu_active(struct sysmmu_drvdata *data)
 {
        /* return true if the System MMU was not active previously